123364Smckusick /* 247543Skarels * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. 347817Skarels * All rights reserved. 423364Smckusick * 547817Skarels * %sccs.include.redist.c% 647817Skarels * 7*54781Storek * @(#)init_main.c 7.50 (Berkeley) 07/08/92 823364Smckusick */ 926Sbill 1017087Sbloom #include "param.h" 1145914Smckusick #include "filedesc.h" 1217087Sbloom #include "kernel.h" 1317087Sbloom #include "mount.h" 1417087Sbloom #include "map.h" 1517087Sbloom #include "proc.h" 1647654Skarels #include "resourcevar.h" 1747654Skarels #include "signalvar.h" 1847654Skarels #include "systm.h" 1937610Smckusick #include "vnode.h" 2017087Sbloom #include "conf.h" 2117087Sbloom #include "buf.h" 2217087Sbloom #include "clist.h" 2337611Smckusick #include "malloc.h" 2417087Sbloom #include "protosw.h" 2530570Skarels #include "reboot.h" 2647654Skarels #include "user.h" 2747654Skarels 2851453Sbostic #include "ufs/ufs/quota.h" 2926Sbill 3037522Smckusick #include "machine/cpu.h" 3137522Smckusick 3247543Skarels #include "vm/vm.h" 3345724Smckusick 3449382Skarels char copyright[] = 3549382Skarels "Copyright (c) 1982,1986,1989,1991 The Regents of the University of California.\nAll rights reserved.\n\n"; 3649382Skarels 3747543Skarels /* 3847543Skarels * Components of process 0; 3947543Skarels * never freed. 4047543Skarels */ 4147543Skarels struct session session0; 4247543Skarels struct pgrp pgrp0; 4347543Skarels struct proc proc0; 4447543Skarels struct pcred cred0; 4547654Skarels struct filedesc0 filedesc0; 4647543Skarels struct plimit limit0; 4747543Skarels struct vmspace vmspace0; 4847654Skarels struct proc *curproc = &proc0; 4947543Skarels struct proc *initproc, *pageproc; 5047543Skarels 5116807Skarels int cmask = CMASK; 5248981Skarels extern struct user *proc0paddr; 5337610Smckusick extern int (*mountroot)(); 5445880Swilliam 5549382Skarels struct vnode *rootvp, *swapdev_vp; 5649382Skarels int boothowto; 5753009Ssklower struct timeval boottime; 58*54781Storek struct timeval runtime; 5949382Skarels 6026Sbill /* 6147543Skarels * System startup; initialize the world, create process 0, 6247543Skarels * mount root filesystem, and fork to create init and pagedaemon. 6347543Skarels * Most of the hard work is done in the lower-level initialization 6447543Skarels * routines including startup(), which does memory initialization 6547543Skarels * and autoconfiguration. 6626Sbill */ 6749533Skarels main() 6826Sbill { 69361Sbill register int i; 702451Swnj register struct proc *p; 7147654Skarels register struct filedesc0 *fdp; 7247543Skarels int s, rval[2]; 73*54781Storek extern void roundrobin __P((void *)); 74*54781Storek extern void schedcpu __P((void *)); 7526Sbill 7645880Swilliam /* 7747543Skarels * Initialize curproc before any possible traps/probes 7847543Skarels * to simplify trap processing. 7945880Swilliam */ 8047543Skarels p = &proc0; 8147543Skarels curproc = p; 8245724Smckusick /* 8347543Skarels * Attempt to find console and initialize 8447543Skarels * in case of early panic or other messages. 8545724Smckusick */ 8647543Skarels consinit(); 8749382Skarels printf(copyright); 8847543Skarels 8945724Smckusick vm_mem_init(); 9045724Smckusick kmeminit(); 9149533Skarels cpu_startup(); 9226Sbill 9326Sbill /* 9426Sbill * set up system process 0 (swapper) 9526Sbill */ 9647543Skarels p = &proc0; 9747543Skarels curproc = p; 9847543Skarels 99*54781Storek allproc = (volatile struct proc *)p; 100*54781Storek p->p_prev = (struct proc **)&allproc; 10147543Skarels p->p_pgrp = &pgrp0; 10247543Skarels pgrphash[0] = &pgrp0; 10347543Skarels pgrp0.pg_mem = p; 10447543Skarels pgrp0.pg_session = &session0; 10547543Skarels session0.s_count = 1; 10647543Skarels session0.s_leader = p; 10747543Skarels 10847543Skarels p->p_flag = SLOAD|SSYS; 1092451Swnj p->p_stat = SRUN; 1102451Swnj p->p_nice = NZERO; 11147543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 11247543Skarels 11345724Smckusick /* 11447543Skarels * Setup credentials 11545724Smckusick */ 11649745Smckusick cred0.p_refcnt = 1; 11747543Skarels p->p_cred = &cred0; 11847543Skarels p->p_ucred = crget(); 11947543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 12029946Skarels 12145914Smckusick /* 12245914Smckusick * Create the file descriptor table for process 0. 12345914Smckusick */ 12447543Skarels fdp = &filedesc0; 12547654Skarels p->p_fd = &fdp->fd_fd; 12647654Skarels fdp->fd_fd.fd_refcnt = 1; 12747654Skarels fdp->fd_fd.fd_cmask = cmask; 12847654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 12947654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 13047654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 13147543Skarels 13218278Smckusick /* 13347543Skarels * Set initial limits 13447543Skarels */ 13547543Skarels p->p_limit = &limit0; 13647543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 13747543Skarels limit0.pl_rlimit[i].rlim_cur = 13847543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 13947543Skarels limit0.pl_rlimit[RLIMIT_OFILE].rlim_cur = NOFILE; 14047543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 14147543Skarels limit0.p_refcnt = 1; 14247543Skarels 14347543Skarels /* 14447543Skarels * Allocate a prototype map so we have something to fork 14547543Skarels */ 14647543Skarels p->p_vmspace = &vmspace0; 14747543Skarels vmspace0.vm_refcnt = 1; 14847543Skarels pmap_pinit(&vmspace0.vm_pmap); 14947543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 15047543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 15147543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 15247543Skarels p->p_addr = proc0paddr; /* XXX */ 15347543Skarels 15447543Skarels /* 15547543Skarels * We continue to place resource usage info 15647543Skarels * and signal actions in the user struct so they're pageable. 15747543Skarels */ 15848981Skarels p->p_stats = &p->p_addr->u_stats; 15948981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 16047543Skarels 16147543Skarels rqinit(); 16247543Skarels 16347543Skarels /* 16423534Skarels * configure virtual memory system, 16523534Skarels * set vm rlimits 16618278Smckusick */ 16747543Skarels vm_init_limits(p); 16823534Skarels 16937610Smckusick /* 17039431Smckusick * Initialize the file systems. 17139431Smckusick * 17249382Skarels * Get vnodes for swapdev and rootdev. 17337610Smckusick */ 17439431Smckusick vfsinit(); 17549382Skarels if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp)) 17637610Smckusick panic("can't setup bdevvp's"); 17737610Smckusick 178*54781Storek /* 179*54781Storek * Start real time and statistics clocks. 180*54781Storek */ 181*54781Storek initclocks(); 18226Sbill 18326Sbill /* 1844821Swnj * Initialize tables, protocols, and set up well-known inodes. 18526Sbill */ 1864821Swnj mbinit(); 18721103Skarels cinit(); 18841565Smckusick #ifdef SYSVSHM 18941565Smckusick shminit(); 19041565Smckusick #endif 19126137Skarels #include "sl.h" 19226137Skarels #if NSL > 0 19326137Skarels slattach(); /* XXX */ 19426137Skarels #endif 19541565Smckusick #include "loop.h" 1965855Swnj #if NLOOP > 0 1975855Swnj loattach(); /* XXX */ 1985855Swnj #endif 1999156Ssam /* 2009156Ssam * Block reception of incoming packets 2019156Ssam * until protocols have been initialized. 2029156Ssam */ 2039156Ssam s = splimp(); 2045227Swnj ifinit(); 2058969Sroot domaininit(); 2069156Ssam splx(s); 20747543Skarels 2087419Sroot #ifdef GPROF 2097419Sroot kmstartup(); 2107419Sroot #endif 2117189Sroot 21247543Skarels /* kick off timeout driven events by calling first time */ 213*54781Storek roundrobin(NULL); 214*54781Storek schedcpu(NULL); 2158096Sroot 21647543Skarels /* 21747543Skarels * Set up the root file system and vnode. 21847543Skarels */ 21937610Smckusick if ((*mountroot)()) 22037610Smckusick panic("cannot mount root"); 22137610Smckusick /* 22237610Smckusick * Get vnode for '/'. 22347654Skarels * Setup rootdir and fdp->fd_fd.fd_cdir to point to it. 22437610Smckusick */ 22537610Smckusick if (VFS_ROOT(rootfs, &rootdir)) 22637610Smckusick panic("cannot find root vnode"); 22747654Skarels fdp->fd_fd.fd_cdir = rootdir; 22847654Skarels VREF(fdp->fd_fd.fd_cdir); 22937726Smckusick VOP_UNLOCK(rootdir); 23047654Skarels fdp->fd_fd.fd_rdir = NULL; 23147543Skarels swapinit(); 23226Sbill 23326Sbill /* 23447543Skarels * Now can look at time, having had a chance 23547543Skarels * to verify the time from the file system. 23647543Skarels */ 237*54781Storek runtime = mono_time = boottime = time; 238*54781Storek p->p_stats->p_start = p->p_rtime = runtime; 23947543Skarels 24047543Skarels /* 24116807Skarels * make init process 24216807Skarels */ 24347543Skarels siginit(p); 24452504Sbostic if (fork(p, NULL, rval)) 24547543Skarels panic("fork init"); 24647543Skarels if (rval[1]) { 24749382Skarels extern int icode[]; /* user init code */ 24849382Skarels extern int szicode; /* size of icode */ 24952504Sbostic static char initflags[] = "-sf"; 25052504Sbostic vm_offset_t addr; 25152504Sbostic char *ip; 25245724Smckusick 25347543Skarels /* 25452504Sbostic * Now in process 1. Set init flags into icode, get a minimal 25552504Sbostic * address space, copy out "icode", and return to it to do an 25652504Sbostic * exec of init. 25747543Skarels */ 25852504Sbostic ip = initflags + 1; 25947543Skarels if (boothowto&RB_SINGLE) 26047543Skarels *ip++ = 's'; 26147543Skarels #ifdef notyet 26247543Skarels if (boothowto&RB_FASTBOOT) 26347543Skarels *ip++ = 'f'; 26447689Skarels #endif 26552504Sbostic if (ip == initflags + 1) 26652504Sbostic *ip++ = '-'; 26747543Skarels *ip++ = '\0'; 26847543Skarels 26952505Storek addr = VM_MIN_ADDRESS; 27052504Sbostic initproc = p = curproc; 27147543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 27247689Skarels round_page(szicode + sizeof(initflags)), FALSE) != 0 || 27352505Storek addr != VM_MIN_ADDRESS) 27445724Smckusick panic("init: couldn't allocate at zero"); 27545724Smckusick 27645724Smckusick /* need just enough stack to exec from */ 27748981Skarels addr = trunc_page(USRSTACK - PAGE_SIZE); 27847543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 27947543Skarels PAGE_SIZE, FALSE) != KERN_SUCCESS) 28047543Skarels panic("vm_allocate init stack"); 28147543Skarels p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 28252505Storek (void)copyout((caddr_t)icode, (caddr_t)VM_MIN_ADDRESS, 28352505Storek (u_int)szicode); 28452505Storek (void)copyout(initflags, (caddr_t)(VM_MIN_ADDRESS + szicode), 28552505Storek sizeof(initflags)); 28647543Skarels return; /* returns to icode */ 28716807Skarels } 28847543Skarels 28916807Skarels /* 29045724Smckusick * Start up pageout daemon (process 2). 29126Sbill */ 29252504Sbostic if (fork(p, NULL, rval)) 29347543Skarels panic("fork pager"); 29447543Skarels if (rval[1]) { 29547543Skarels /* 29647543Skarels * Now in process 2. 29747543Skarels */ 29847543Skarels p = curproc; 29947543Skarels pageproc = p; 30047543Skarels p->p_flag |= SLOAD|SSYS; /* XXX */ 30147543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 30245724Smckusick vm_pageout(); 3039025Sroot /*NOTREACHED*/ 30426Sbill } 30526Sbill 30626Sbill /* 30726Sbill * enter scheduling loop 30826Sbill */ 30926Sbill sched(); 31026Sbill } 311