123364Smckusick /* 2*47543Skarels * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 339480Smckusick * All rights reserved. The Berkeley software License Agreement 439480Smckusick * specifies the terms and conditions for redistribution. 523364Smckusick * 6*47543Skarels * @(#)init_main.c 7.34 (Berkeley) 03/17/91 723364Smckusick */ 826Sbill 917087Sbloom #include "param.h" 1017087Sbloom #include "systm.h" 1117087Sbloom #include "user.h" 1245914Smckusick #include "filedesc.h" 1317087Sbloom #include "kernel.h" 1417087Sbloom #include "mount.h" 1517087Sbloom #include "map.h" 1617087Sbloom #include "proc.h" 1737610Smckusick #include "vnode.h" 1817087Sbloom #include "seg.h" 1917087Sbloom #include "conf.h" 2017087Sbloom #include "buf.h" 2117087Sbloom #include "clist.h" 2237611Smckusick #include "malloc.h" 2317087Sbloom #include "protosw.h" 2430570Skarels #include "reboot.h" 25*47543Skarels #include "ufs/quota.h" 2626Sbill 2737522Smckusick #include "machine/cpu.h" 2837522Smckusick 29*47543Skarels #include "vm/vm.h" 30*47543Skarels #include "vm/vm_param.h" 31*47543Skarels #include "vm/vm_map.h" 3245724Smckusick 33*47543Skarels /* 34*47543Skarels * Components of process 0; 35*47543Skarels * never freed. 36*47543Skarels */ 37*47543Skarels struct session session0; 38*47543Skarels struct pgrp pgrp0; 39*47543Skarels struct proc proc0; 40*47543Skarels struct pcred cred0; 41*47543Skarels struct filedesc filedesc0; 42*47543Skarels struct file *fd0[NOEXTENT]; 43*47543Skarels char fdflags0[NOEXTENT]; 44*47543Skarels struct plimit limit0; 45*47543Skarels struct vmspace vmspace0; 46*47543Skarels struct proc *initproc, *pageproc; 47*47543Skarels 4816807Skarels int cmask = CMASK; 4945724Smckusick extern caddr_t proc0paddr; 5037610Smckusick extern int (*mountroot)(); 51*47543Skarels extern char initflags[]; 5245880Swilliam 5326Sbill /* 54*47543Skarels * System startup; initialize the world, create process 0, 55*47543Skarels * mount root filesystem, and fork to create init and pagedaemon. 56*47543Skarels * Most of the hard work is done in the lower-level initialization 57*47543Skarels * routines including startup(), which does memory initialization 58*47543Skarels * and autoconfiguration. 5926Sbill */ 6026Sbill main(firstaddr) 618969Sroot int firstaddr; 6226Sbill { 63361Sbill register int i; 642451Swnj register struct proc *p; 6545914Smckusick register struct filedesc *fdp; 66*47543Skarels int s, rval[2]; 6726Sbill 6845880Swilliam /* 69*47543Skarels * Initialize curproc before any possible traps/probes 70*47543Skarels * to simplify trap processing. 7145880Swilliam */ 72*47543Skarels p = &proc0; 73*47543Skarels curproc = p; 7445724Smckusick /* 75*47543Skarels * Attempt to find console and initialize 76*47543Skarels * in case of early panic or other messages. 7745724Smckusick */ 78*47543Skarels consinit(); 79*47543Skarels 8045724Smckusick vm_mem_init(); 8145724Smckusick kmeminit(); 8226Sbill startup(firstaddr); 8326Sbill 8426Sbill /* 8526Sbill * set up system process 0 (swapper) 8626Sbill */ 87*47543Skarels p = &proc0; 88*47543Skarels curproc = p; 89*47543Skarels 90*47543Skarels allproc = p; 91*47543Skarels p->p_prev = &allproc; 92*47543Skarels p->p_pgrp = &pgrp0; 93*47543Skarels pgrphash[0] = &pgrp0; 94*47543Skarels pgrp0.pg_mem = p; 95*47543Skarels pgrp0.pg_session = &session0; 96*47543Skarels session0.s_count = 1; 97*47543Skarels session0.s_leader = p; 98*47543Skarels 99*47543Skarels p->p_flag = SLOAD|SSYS; 1002451Swnj p->p_stat = SRUN; 1012451Swnj p->p_nice = NZERO; 102*47543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 103*47543Skarels 10445724Smckusick /* 105*47543Skarels * Setup credentials 10645724Smckusick */ 107*47543Skarels p->p_cred = &cred0; 108*47543Skarels p->p_ucred = crget(); 109*47543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 11029946Skarels 11145914Smckusick /* 11245914Smckusick * Create the file descriptor table for process 0. 11345914Smckusick */ 114*47543Skarels fdp = &filedesc0; 11545914Smckusick p->p_fd = fdp; 11645914Smckusick fdp->fd_refcnt = 1; 11745914Smckusick fdp->fd_cmask = cmask; 118*47543Skarels fdp->fd_ofiles = fd0; 119*47543Skarels fdp->fd_ofileflags = fdflags0; 120*47543Skarels fdp->fd_nfiles = NOEXTENT; 121*47543Skarels 12218278Smckusick /* 123*47543Skarels * Set initial limits 124*47543Skarels */ 125*47543Skarels p->p_limit = &limit0; 126*47543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 127*47543Skarels limit0.pl_rlimit[i].rlim_cur = 128*47543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 129*47543Skarels limit0.pl_rlimit[RLIMIT_OFILE].rlim_cur = NOFILE; 130*47543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 131*47543Skarels limit0.p_refcnt = 1; 132*47543Skarels 133*47543Skarels /* 134*47543Skarels * Allocate a prototype map so we have something to fork 135*47543Skarels */ 136*47543Skarels p->p_vmspace = &vmspace0; 137*47543Skarels vmspace0.vm_refcnt = 1; 138*47543Skarels pmap_pinit(&vmspace0.vm_pmap); 139*47543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 140*47543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 141*47543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 142*47543Skarels p->p_addr = proc0paddr; /* XXX */ 143*47543Skarels 144*47543Skarels /* 145*47543Skarels * We continue to place resource usage info 146*47543Skarels * and signal actions in the user struct so they're pageable. 147*47543Skarels */ 148*47543Skarels p->p_stats = &u.u_stats; 149*47543Skarels p->p_sigacts = &u.u_sigacts; 150*47543Skarels 151*47543Skarels rqinit(); 152*47543Skarels 153*47543Skarels /* 15423534Skarels * configure virtual memory system, 15523534Skarels * set vm rlimits 15618278Smckusick */ 157*47543Skarels vm_init_limits(p); 15823534Skarels 15937610Smckusick /* 16039431Smckusick * Initialize the file systems. 16139431Smckusick * 16237610Smckusick * Get vnodes for swapdev, argdev, and rootdev. 16337610Smckusick */ 16439431Smckusick vfsinit(); 16537610Smckusick if (bdevvp(swapdev, &swapdev_vp) || 16637610Smckusick bdevvp(argdev, &argdev_vp) || 16737610Smckusick bdevvp(rootdev, &rootvp)) 16837610Smckusick panic("can't setup bdevvp's"); 16937610Smckusick 17030256Ssam startrtclock(); 17129946Skarels #if defined(vax) 17212823Ssam #include "kg.h" 17312823Ssam #if NKG > 0 17411356Smckusick startkgclock(); 17511356Smckusick #endif 17629946Skarels #endif 17726Sbill 17826Sbill /* 1794821Swnj * Initialize tables, protocols, and set up well-known inodes. 18026Sbill */ 1814821Swnj mbinit(); 18221103Skarels cinit(); 18341565Smckusick #ifdef SYSVSHM 18441565Smckusick shminit(); 18541565Smckusick #endif 18626137Skarels #include "sl.h" 18726137Skarels #if NSL > 0 18826137Skarels slattach(); /* XXX */ 18926137Skarels #endif 19041565Smckusick #include "loop.h" 1915855Swnj #if NLOOP > 0 1925855Swnj loattach(); /* XXX */ 1935855Swnj #endif 1949156Ssam /* 1959156Ssam * Block reception of incoming packets 1969156Ssam * until protocols have been initialized. 1979156Ssam */ 1989156Ssam s = splimp(); 1995227Swnj ifinit(); 2008969Sroot domaininit(); 2019156Ssam splx(s); 202*47543Skarels 2037419Sroot #ifdef GPROF 2047419Sroot kmstartup(); 2057419Sroot #endif 2067189Sroot 207*47543Skarels /* kick off timeout driven events by calling first time */ 2088096Sroot roundrobin(); 2098096Sroot schedcpu(); 21045880Swilliam enablertclock(); /* enable realtime clock interrupts */ 2118096Sroot 212*47543Skarels /* 213*47543Skarels * Set up the root file system and vnode. 214*47543Skarels */ 21537610Smckusick if ((*mountroot)()) 21637610Smckusick panic("cannot mount root"); 21737610Smckusick /* 21837610Smckusick * Get vnode for '/'. 21945914Smckusick * Setup rootdir and fdp->fd_cdir to point to it. 22037610Smckusick */ 22137610Smckusick if (VFS_ROOT(rootfs, &rootdir)) 22237610Smckusick panic("cannot find root vnode"); 22345914Smckusick fdp->fd_cdir = rootdir; 22445914Smckusick VREF(fdp->fd_cdir); 22537726Smckusick VOP_UNLOCK(rootdir); 22645914Smckusick fdp->fd_rdir = NULL; 227*47543Skarels swapinit(); 22826Sbill 22926Sbill /* 230*47543Skarels * Now can look at time, having had a chance 231*47543Skarels * to verify the time from the file system. 232*47543Skarels */ 233*47543Skarels boottime = p->p_stats->p_start = time; 234*47543Skarels 235*47543Skarels /* 23616807Skarels * make init process 23716807Skarels */ 238*47543Skarels siginit(p); 239*47543Skarels if (fork(p, (void *) NULL, rval)) 240*47543Skarels panic("fork init"); 241*47543Skarels if (rval[1]) { 242*47543Skarels char *ip = initflags; 24345724Smckusick vm_offset_t addr = 0; 24445724Smckusick 245*47543Skarels /* 246*47543Skarels * Now in process 1. Set init flags into icode, 247*47543Skarels * get a minimal address space, copy out "icode", 248*47543Skarels * and return to it to do an exec of init. 249*47543Skarels */ 250*47543Skarels p = curproc; 251*47543Skarels initproc = p; 252*47543Skarels *ip++ = '-'; 253*47543Skarels if (boothowto&RB_SINGLE) 254*47543Skarels *ip++ = 's'; 255*47543Skarels #ifdef notyet 256*47543Skarels if (boothowto&RB_FASTBOOT) 257*47543Skarels *ip++ = 'f'; 258*47543Skarels *ip++ = '\0'; 259*47543Skarels #endif 260*47543Skarels 261*47543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 262*47543Skarels round_page(szicode), FALSE) != KERN_SUCCESS || addr != 0) 26345724Smckusick panic("init: couldn't allocate at zero"); 26445724Smckusick 26545724Smckusick /* need just enough stack to exec from */ 26645724Smckusick addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 267*47543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 268*47543Skarels PAGE_SIZE, FALSE) != KERN_SUCCESS) 269*47543Skarels panic("vm_allocate init stack"); 270*47543Skarels p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 27116807Skarels (void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode); 272*47543Skarels return; /* returns to icode */ 27316807Skarels } 274*47543Skarels 27516807Skarels /* 27645724Smckusick * Start up pageout daemon (process 2). 27726Sbill */ 278*47543Skarels if (fork(p, (void *) NULL, rval)) 279*47543Skarels panic("fork pager"); 280*47543Skarels if (rval[1]) { 281*47543Skarels /* 282*47543Skarels * Now in process 2. 283*47543Skarels */ 284*47543Skarels p = curproc; 285*47543Skarels pageproc = p; 286*47543Skarels p->p_flag |= SLOAD|SSYS; /* XXX */ 287*47543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 28845724Smckusick vm_pageout(); 2899025Sroot /*NOTREACHED*/ 29026Sbill } 29126Sbill 29226Sbill /* 29326Sbill * enter scheduling loop 29426Sbill */ 29526Sbill sched(); 29626Sbill } 29726Sbill 298*47543Skarels /* MOVE TO vfs_bio.c (bufinit) XXX */ 29926Sbill /* 300*47543Skarels * Initialize buffers and hash links for buffers. 3017001Smckusick */ 302*47543Skarels bufinit() 3037001Smckusick { 3047001Smckusick register int i; 3058554Sroot register struct buf *bp, *dp; 306*47543Skarels register struct bufhd *hp; 30710336Smckusick int base, residual; 30826Sbill 309*47543Skarels for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++) 310*47543Skarels hp->b_forw = hp->b_back = (struct buf *)hp; 311*47543Skarels 3122322Swnj for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) { 3132322Swnj dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp; 3142322Swnj dp->b_flags = B_HEAD; 3152322Swnj } 31610336Smckusick base = bufpages / nbuf; 31710336Smckusick residual = bufpages % nbuf; 3186570Smckusic for (i = 0; i < nbuf; i++) { 31926Sbill bp = &buf[i]; 32026Sbill bp->b_dev = NODEV; 3219156Ssam bp->b_bcount = 0; 32238774Smckusick bp->b_rcred = NOCRED; 32338774Smckusick bp->b_wcred = NOCRED; 32438774Smckusick bp->b_dirtyoff = 0; 32538774Smckusick bp->b_dirtyend = 0; 3266570Smckusic bp->b_un.b_addr = buffers + i * MAXBSIZE; 32710336Smckusick if (i < residual) 32810336Smckusick bp->b_bufsize = (base + 1) * CLBYTES; 32910336Smckusick else 33010336Smckusick bp->b_bufsize = base * CLBYTES; 3319750Ssam binshash(bp, &bfreelist[BQ_AGE]); 3322322Swnj bp->b_flags = B_BUSY|B_INVAL; 33326Sbill brelse(bp); 33426Sbill } 33530531Skarels } 336