123364Smckusick /* 263170Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 363170Sbostic * The Regents of the University of California. All rights reserved. 423364Smckusick * 547817Skarels * %sccs.include.redist.c% 647817Skarels * 7*64405Sbostic * @(#)init_main.c 8.2 (Berkeley) 09/05/93 823364Smckusick */ 926Sbill 1056934Smckusick #include <sys/param.h> 1156934Smckusick #include <sys/filedesc.h> 1256934Smckusick #include <sys/kernel.h> 1356934Smckusick #include <sys/mount.h> 1456934Smckusick #include <sys/map.h> 1556934Smckusick #include <sys/proc.h> 1656934Smckusick #include <sys/resourcevar.h> 1756934Smckusick #include <sys/signalvar.h> 1856934Smckusick #include <sys/systm.h> 1956934Smckusick #include <sys/vnode.h> 2056934Smckusick #include <sys/conf.h> 2156934Smckusick #include <sys/buf.h> 2256934Smckusick #include <sys/clist.h> 2359118Storek #include <sys/device.h> 2456934Smckusick #include <sys/protosw.h> 2556934Smckusick #include <sys/reboot.h> 2656934Smckusick #include <sys/user.h> 2747654Skarels 2856934Smckusick #include <ufs/ufs/quota.h> 2926Sbill 3056934Smckusick #include <machine/cpu.h> 3137522Smckusick 3256934Smckusick #include <vm/vm.h> 3345724Smckusick 3455399Smckusick #ifdef HPFPLIB 3549382Skarels char copyright[] = 3660928Smckusick "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n"; 3755399Smckusick #else 3855399Smckusick char copyright[] = 3960928Smckusick "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; 4055399Smckusick #endif 4149382Skarels 42*64405Sbostic /* Components of the first process -- never freed. */ 4347543Skarels struct session session0; 4447543Skarels struct pgrp pgrp0; 4547543Skarels struct proc proc0; 4647543Skarels struct pcred cred0; 4747654Skarels struct filedesc0 filedesc0; 4847543Skarels struct plimit limit0; 4947543Skarels struct vmspace vmspace0; 5047654Skarels struct proc *curproc = &proc0; 5147543Skarels struct proc *initproc, *pageproc; 5247543Skarels 5316807Skarels int cmask = CMASK; 5448981Skarels extern struct user *proc0paddr; 5545880Swilliam 5649382Skarels struct vnode *rootvp, *swapdev_vp; 5749382Skarels int boothowto; 5853009Ssklower struct timeval boottime; 5954781Storek struct timeval runtime; 6049382Skarels 6126Sbill /* 62*64405Sbostic * System startup; initialize the world, create process 0, mount root 63*64405Sbostic * filesystem, and fork to create init and pagedaemon. Most of the 64*64405Sbostic * hard work is done in the lower-level initialization routines including 65*64405Sbostic * startup(), which does memory initialization and autoconfiguration. 6626Sbill */ 6749533Skarels main() 6826Sbill { 692451Swnj register struct proc *p; 7047654Skarels register struct filedesc0 *fdp; 7159118Storek register struct pdevinit *pdev; 72*64405Sbostic register int i; 7347543Skarels int s, rval[2]; 74*64405Sbostic extern int (*mountroot) __P((void)); 7559118Storek extern struct pdevinit pdevinit[]; 7654781Storek extern void roundrobin __P((void *)); 7754781Storek extern void schedcpu __P((void *)); 7826Sbill 7945880Swilliam /* 80*64405Sbostic * Initialize the current process pointer (curproc) before 81*64405Sbostic * any possible traps/probes to simplify trap processing. 8245880Swilliam */ 8347543Skarels p = &proc0; 8447543Skarels curproc = p; 8545724Smckusick /* 8647543Skarels * Attempt to find console and initialize 8747543Skarels * in case of early panic or other messages. 8845724Smckusick */ 8947543Skarels consinit(); 9049382Skarels printf(copyright); 9147543Skarels 9245724Smckusick vm_mem_init(); 9345724Smckusick kmeminit(); 9449533Skarels cpu_startup(); 9526Sbill 96*64405Sbostic /* Create process 0 (the swapper). */ 9747543Skarels p = &proc0; 9847543Skarels curproc = p; 9947543Skarels 10054781Storek allproc = (volatile struct proc *)p; 10154781Storek p->p_prev = (struct proc **)&allproc; 10247543Skarels p->p_pgrp = &pgrp0; 10347543Skarels pgrphash[0] = &pgrp0; 10447543Skarels pgrp0.pg_mem = p; 10547543Skarels pgrp0.pg_session = &session0; 10647543Skarels session0.s_count = 1; 10747543Skarels session0.s_leader = p; 10847543Skarels 10947543Skarels p->p_flag = SLOAD|SSYS; 1102451Swnj p->p_stat = SRUN; 1112451Swnj p->p_nice = NZERO; 11247543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 11347543Skarels 114*64405Sbostic /* Create credentials. */ 11549745Smckusick cred0.p_refcnt = 1; 11647543Skarels p->p_cred = &cred0; 11747543Skarels p->p_ucred = crget(); 11847543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 11929946Skarels 120*64405Sbostic /* Create the file descriptor table. */ 12147543Skarels fdp = &filedesc0; 12247654Skarels p->p_fd = &fdp->fd_fd; 12347654Skarels fdp->fd_fd.fd_refcnt = 1; 12447654Skarels fdp->fd_fd.fd_cmask = cmask; 12547654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 12647654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 12747654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 12847543Skarels 129*64405Sbostic /* Create the limits structures. */ 13047543Skarels p->p_limit = &limit0; 13147543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 13247543Skarels limit0.pl_rlimit[i].rlim_cur = 13347543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 13456935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 13547543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 13659488Smckusick i = ptoa(cnt.v_free_count); 13759488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 13859488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 13959488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 14047543Skarels limit0.p_refcnt = 1; 14147543Skarels 142*64405Sbostic /* Allocate a prototype map so we have something to fork. */ 14347543Skarels p->p_vmspace = &vmspace0; 14447543Skarels vmspace0.vm_refcnt = 1; 14547543Skarels pmap_pinit(&vmspace0.vm_pmap); 14647543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 14747543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 14847543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 14947543Skarels p->p_addr = proc0paddr; /* XXX */ 15047543Skarels 15147543Skarels /* 152*64405Sbostic * We continue to place resource usage info and signal 153*64405Sbostic * actions in the user struct so they're pageable. 15447543Skarels */ 15548981Skarels p->p_stats = &p->p_addr->u_stats; 15648981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 15747543Skarels 15855406Smckusick /* 15955406Smckusick * Initialize per uid information structure and charge 16055406Smckusick * root for one process. 16155406Smckusick */ 16255406Smckusick usrinfoinit(); 16355406Smckusick (void)chgproccnt(0, 1); 16455406Smckusick 16547543Skarels rqinit(); 16647543Skarels 16759118Storek /* Configure virtual memory system, set vm rlimits. */ 16847543Skarels vm_init_limits(p); 16923534Skarels 17059118Storek /* Initialize the file systems. */ 17139431Smckusick vfsinit(); 17237610Smckusick 17359118Storek /* Start real time and statistics clocks. */ 17454781Storek initclocks(); 17526Sbill 176*64405Sbostic /* Initialize mbuf's. */ 1774821Swnj mbinit(); 178*64405Sbostic 179*64405Sbostic /* Initialize clists. */ 180*64405Sbostic clist_init(); 181*64405Sbostic 18241565Smckusick #ifdef SYSVSHM 183*64405Sbostic /* Initialize System V style shared memory. */ 18441565Smckusick shminit(); 18541565Smckusick #endif 18659118Storek 18759118Storek /* Attach pseudo-devices. */ 18859118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 18959118Storek (*pdev->pdev_attach)(pdev->pdev_count); 19059118Storek 1919156Ssam /* 19259118Storek * Initialize protocols. Block reception of incoming packets 19359118Storek * until everything is ready. 1949156Ssam */ 1959156Ssam s = splimp(); 1965227Swnj ifinit(); 1978969Sroot domaininit(); 1989156Ssam splx(s); 19947543Skarels 2007419Sroot #ifdef GPROF 201*64405Sbostic /* Initialize kernel profiling. */ 2027419Sroot kmstartup(); 2037419Sroot #endif 2047189Sroot 205*64405Sbostic /* Kick off timeout driven events by calling first time. */ 20654781Storek roundrobin(NULL); 20754781Storek schedcpu(NULL); 2088096Sroot 209*64405Sbostic /* Mount the root file system. */ 21037610Smckusick if ((*mountroot)()) 21137610Smckusick panic("cannot mount root"); 212*64405Sbostic 213*64405Sbostic /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 214*64405Sbostic if (VFS_ROOT(rootfs, &rootvnode)) 21537610Smckusick panic("cannot find root vnode"); 216*64405Sbostic fdp->fd_fd.fd_cdir = rootvnode; 21747654Skarels VREF(fdp->fd_fd.fd_cdir); 218*64405Sbostic VOP_UNLOCK(rootvnode); 21947654Skarels fdp->fd_fd.fd_rdir = NULL; 22047543Skarels swapinit(); 22126Sbill 22226Sbill /* 22355796Smckusick * Now can look at time, having had a chance to verify the time 22455796Smckusick * from the file system. Reset p->p_rtime as it may have been 22555796Smckusick * munched in swtch() after the time got set. 22647543Skarels */ 22754943Storek p->p_stats->p_start = runtime = mono_time = boottime = time; 22855796Smckusick p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 22947543Skarels 230*64405Sbostic /* Initialize signal state for process 0. */ 23147543Skarels siginit(p); 232*64405Sbostic 233*64405Sbostic /* Create process 1 (init(8)). */ 23452504Sbostic if (fork(p, NULL, rval)) 23547543Skarels panic("fork init"); 23647543Skarels if (rval[1]) { 23749382Skarels extern int icode[]; /* user init code */ 23849382Skarels extern int szicode; /* size of icode */ 23952504Sbostic static char initflags[] = "-sf"; 24052504Sbostic vm_offset_t addr; 24152504Sbostic char *ip; 24245724Smckusick 24347543Skarels /* 24452504Sbostic * Now in process 1. Set init flags into icode, get a minimal 24552504Sbostic * address space, copy out "icode", and return to it to do an 24652504Sbostic * exec of init. 24747543Skarels */ 24852504Sbostic ip = initflags + 1; 24947543Skarels if (boothowto&RB_SINGLE) 25047543Skarels *ip++ = 's'; 25147543Skarels #ifdef notyet 25247543Skarels if (boothowto&RB_FASTBOOT) 25347543Skarels *ip++ = 'f'; 25447689Skarels #endif 25552504Sbostic if (ip == initflags + 1) 25652504Sbostic *ip++ = '-'; 25747543Skarels *ip++ = '\0'; 25847543Skarels 25952505Storek addr = VM_MIN_ADDRESS; 26052504Sbostic initproc = p = curproc; 26147543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 26247689Skarels round_page(szicode + sizeof(initflags)), FALSE) != 0 || 26352505Storek addr != VM_MIN_ADDRESS) 26445724Smckusick panic("init: couldn't allocate at zero"); 26545724Smckusick 266*64405Sbostic /* Need just enough stack from which to exec. */ 26748981Skarels addr = trunc_page(USRSTACK - PAGE_SIZE); 26847543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 26947543Skarels PAGE_SIZE, FALSE) != KERN_SUCCESS) 27047543Skarels panic("vm_allocate init stack"); 27147543Skarels p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 27252505Storek (void)copyout((caddr_t)icode, (caddr_t)VM_MIN_ADDRESS, 27352505Storek (u_int)szicode); 27452505Storek (void)copyout(initflags, (caddr_t)(VM_MIN_ADDRESS + szicode), 27552505Storek sizeof(initflags)); 27647543Skarels return; /* returns to icode */ 27716807Skarels } 27847543Skarels 279*64405Sbostic /* Create process 2 (the pageout daemon). */ 28052504Sbostic if (fork(p, NULL, rval)) 28147543Skarels panic("fork pager"); 28247543Skarels if (rval[1]) { 28347543Skarels /* 28447543Skarels * Now in process 2. 28547543Skarels */ 28647543Skarels p = curproc; 28747543Skarels pageproc = p; 28847543Skarels p->p_flag |= SLOAD|SSYS; /* XXX */ 28947543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 29045724Smckusick vm_pageout(); 291*64405Sbostic /* NOTREACHED */ 29226Sbill } 29326Sbill 294*64405Sbostic /* The scheduler is an infinite loop. */ 295*64405Sbostic scheduler(); 296*64405Sbostic /* NOTREACHED */ 29726Sbill } 298