123364Smckusick /* 2*63170Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 3*63170Sbostic * The Regents of the University of California. All rights reserved. 423364Smckusick * 547817Skarels * %sccs.include.redist.c% 647817Skarels * 7*63170Sbostic * @(#)init_main.c 8.1 (Berkeley) 06/10/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 4247543Skarels /* 4347543Skarels * Components of process 0; 4447543Skarels * never freed. 4547543Skarels */ 4647543Skarels struct session session0; 4747543Skarels struct pgrp pgrp0; 4847543Skarels struct proc proc0; 4947543Skarels struct pcred cred0; 5047654Skarels struct filedesc0 filedesc0; 5147543Skarels struct plimit limit0; 5247543Skarels struct vmspace vmspace0; 5347654Skarels struct proc *curproc = &proc0; 5447543Skarels struct proc *initproc, *pageproc; 5547543Skarels 5616807Skarels int cmask = CMASK; 5748981Skarels extern struct user *proc0paddr; 5837610Smckusick extern int (*mountroot)(); 5945880Swilliam 6049382Skarels struct vnode *rootvp, *swapdev_vp; 6149382Skarels int boothowto; 6253009Ssklower struct timeval boottime; 6354781Storek struct timeval runtime; 6449382Skarels 6526Sbill /* 6647543Skarels * System startup; initialize the world, create process 0, 6747543Skarels * mount root filesystem, and fork to create init and pagedaemon. 6847543Skarels * Most of the hard work is done in the lower-level initialization 6947543Skarels * routines including startup(), which does memory initialization 7047543Skarels * and autoconfiguration. 7126Sbill */ 7249533Skarels main() 7326Sbill { 74361Sbill register int i; 752451Swnj register struct proc *p; 7647654Skarels register struct filedesc0 *fdp; 7759118Storek register struct pdevinit *pdev; 7847543Skarels int s, rval[2]; 7959118Storek extern struct pdevinit pdevinit[]; 8054781Storek extern void roundrobin __P((void *)); 8154781Storek extern void schedcpu __P((void *)); 8226Sbill 8345880Swilliam /* 8447543Skarels * Initialize curproc before any possible traps/probes 8547543Skarels * to simplify trap processing. 8645880Swilliam */ 8747543Skarels p = &proc0; 8847543Skarels curproc = p; 8945724Smckusick /* 9047543Skarels * Attempt to find console and initialize 9147543Skarels * in case of early panic or other messages. 9245724Smckusick */ 9347543Skarels consinit(); 9449382Skarels printf(copyright); 9547543Skarels 9645724Smckusick vm_mem_init(); 9745724Smckusick kmeminit(); 9849533Skarels cpu_startup(); 9926Sbill 10026Sbill /* 10126Sbill * set up system process 0 (swapper) 10226Sbill */ 10347543Skarels p = &proc0; 10447543Skarels curproc = p; 10547543Skarels 10654781Storek allproc = (volatile struct proc *)p; 10754781Storek p->p_prev = (struct proc **)&allproc; 10847543Skarels p->p_pgrp = &pgrp0; 10947543Skarels pgrphash[0] = &pgrp0; 11047543Skarels pgrp0.pg_mem = p; 11147543Skarels pgrp0.pg_session = &session0; 11247543Skarels session0.s_count = 1; 11347543Skarels session0.s_leader = p; 11447543Skarels 11547543Skarels p->p_flag = SLOAD|SSYS; 1162451Swnj p->p_stat = SRUN; 1172451Swnj p->p_nice = NZERO; 11847543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 11947543Skarels 12045724Smckusick /* 12147543Skarels * Setup credentials 12245724Smckusick */ 12349745Smckusick cred0.p_refcnt = 1; 12447543Skarels p->p_cred = &cred0; 12547543Skarels p->p_ucred = crget(); 12647543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 12729946Skarels 12845914Smckusick /* 12945914Smckusick * Create the file descriptor table for process 0. 13045914Smckusick */ 13147543Skarels fdp = &filedesc0; 13247654Skarels p->p_fd = &fdp->fd_fd; 13347654Skarels fdp->fd_fd.fd_refcnt = 1; 13447654Skarels fdp->fd_fd.fd_cmask = cmask; 13547654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 13647654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 13747654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 13847543Skarels 13918278Smckusick /* 14047543Skarels * Set initial limits 14147543Skarels */ 14247543Skarels p->p_limit = &limit0; 14347543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 14447543Skarels limit0.pl_rlimit[i].rlim_cur = 14547543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 14656935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 14747543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 14859488Smckusick i = ptoa(cnt.v_free_count); 14959488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 15059488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 15159488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 15247543Skarels limit0.p_refcnt = 1; 15347543Skarels 15447543Skarels /* 15547543Skarels * Allocate a prototype map so we have something to fork 15647543Skarels */ 15747543Skarels p->p_vmspace = &vmspace0; 15847543Skarels vmspace0.vm_refcnt = 1; 15947543Skarels pmap_pinit(&vmspace0.vm_pmap); 16047543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 16147543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 16247543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 16347543Skarels p->p_addr = proc0paddr; /* XXX */ 16447543Skarels 16547543Skarels /* 16647543Skarels * We continue to place resource usage info 16747543Skarels * and signal actions in the user struct so they're pageable. 16847543Skarels */ 16948981Skarels p->p_stats = &p->p_addr->u_stats; 17048981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 17147543Skarels 17255406Smckusick /* 17355406Smckusick * Initialize per uid information structure and charge 17455406Smckusick * root for one process. 17555406Smckusick */ 17655406Smckusick usrinfoinit(); 17755406Smckusick (void)chgproccnt(0, 1); 17855406Smckusick 17947543Skarels rqinit(); 18047543Skarels 18159118Storek /* Configure virtual memory system, set vm rlimits. */ 18247543Skarels vm_init_limits(p); 18323534Skarels 18459118Storek /* Initialize the file systems. */ 18539431Smckusick vfsinit(); 18637610Smckusick 18759118Storek /* Start real time and statistics clocks. */ 18854781Storek initclocks(); 18926Sbill 19059118Storek /* Initialize tables. */ 1914821Swnj mbinit(); 19221103Skarels cinit(); 19341565Smckusick #ifdef SYSVSHM 19441565Smckusick shminit(); 19541565Smckusick #endif 19659118Storek 19759118Storek /* Attach pseudo-devices. */ 19859118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 19959118Storek (*pdev->pdev_attach)(pdev->pdev_count); 20059118Storek 2019156Ssam /* 20259118Storek * Initialize protocols. Block reception of incoming packets 20359118Storek * until everything is ready. 2049156Ssam */ 2059156Ssam s = splimp(); 2065227Swnj ifinit(); 2078969Sroot domaininit(); 2089156Ssam splx(s); 20947543Skarels 2107419Sroot #ifdef GPROF 2117419Sroot kmstartup(); 2127419Sroot #endif 2137189Sroot 21447543Skarels /* kick off timeout driven events by calling first time */ 21554781Storek roundrobin(NULL); 21654781Storek schedcpu(NULL); 2178096Sroot 21847543Skarels /* 21947543Skarels * Set up the root file system and vnode. 22047543Skarels */ 22137610Smckusick if ((*mountroot)()) 22237610Smckusick panic("cannot mount root"); 22337610Smckusick /* 22437610Smckusick * Get vnode for '/'. 22547654Skarels * Setup rootdir and fdp->fd_fd.fd_cdir to point to it. 22637610Smckusick */ 22737610Smckusick if (VFS_ROOT(rootfs, &rootdir)) 22837610Smckusick panic("cannot find root vnode"); 22947654Skarels fdp->fd_fd.fd_cdir = rootdir; 23047654Skarels VREF(fdp->fd_fd.fd_cdir); 23137726Smckusick VOP_UNLOCK(rootdir); 23247654Skarels fdp->fd_fd.fd_rdir = NULL; 23347543Skarels swapinit(); 23426Sbill 23526Sbill /* 23655796Smckusick * Now can look at time, having had a chance to verify the time 23755796Smckusick * from the file system. Reset p->p_rtime as it may have been 23855796Smckusick * munched in swtch() after the time got set. 23947543Skarels */ 24054943Storek p->p_stats->p_start = runtime = mono_time = boottime = time; 24155796Smckusick p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 24247543Skarels 24347543Skarels /* 24416807Skarels * make init process 24516807Skarels */ 24647543Skarels siginit(p); 24752504Sbostic if (fork(p, NULL, rval)) 24847543Skarels panic("fork init"); 24947543Skarels if (rval[1]) { 25049382Skarels extern int icode[]; /* user init code */ 25149382Skarels extern int szicode; /* size of icode */ 25252504Sbostic static char initflags[] = "-sf"; 25352504Sbostic vm_offset_t addr; 25452504Sbostic char *ip; 25545724Smckusick 25647543Skarels /* 25752504Sbostic * Now in process 1. Set init flags into icode, get a minimal 25852504Sbostic * address space, copy out "icode", and return to it to do an 25952504Sbostic * exec of init. 26047543Skarels */ 26152504Sbostic ip = initflags + 1; 26247543Skarels if (boothowto&RB_SINGLE) 26347543Skarels *ip++ = 's'; 26447543Skarels #ifdef notyet 26547543Skarels if (boothowto&RB_FASTBOOT) 26647543Skarels *ip++ = 'f'; 26747689Skarels #endif 26852504Sbostic if (ip == initflags + 1) 26952504Sbostic *ip++ = '-'; 27047543Skarels *ip++ = '\0'; 27147543Skarels 27252505Storek addr = VM_MIN_ADDRESS; 27352504Sbostic initproc = p = curproc; 27447543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 27547689Skarels round_page(szicode + sizeof(initflags)), FALSE) != 0 || 27652505Storek addr != VM_MIN_ADDRESS) 27745724Smckusick panic("init: couldn't allocate at zero"); 27845724Smckusick 27945724Smckusick /* need just enough stack to exec from */ 28048981Skarels addr = trunc_page(USRSTACK - PAGE_SIZE); 28147543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 28247543Skarels PAGE_SIZE, FALSE) != KERN_SUCCESS) 28347543Skarels panic("vm_allocate init stack"); 28447543Skarels p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 28552505Storek (void)copyout((caddr_t)icode, (caddr_t)VM_MIN_ADDRESS, 28652505Storek (u_int)szicode); 28752505Storek (void)copyout(initflags, (caddr_t)(VM_MIN_ADDRESS + szicode), 28852505Storek sizeof(initflags)); 28947543Skarels return; /* returns to icode */ 29016807Skarels } 29147543Skarels 29216807Skarels /* 29345724Smckusick * Start up pageout daemon (process 2). 29426Sbill */ 29552504Sbostic if (fork(p, NULL, rval)) 29647543Skarels panic("fork pager"); 29747543Skarels if (rval[1]) { 29847543Skarels /* 29947543Skarels * Now in process 2. 30047543Skarels */ 30147543Skarels p = curproc; 30247543Skarels pageproc = p; 30347543Skarels p->p_flag |= SLOAD|SSYS; /* XXX */ 30447543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 30545724Smckusick vm_pageout(); 3069025Sroot /*NOTREACHED*/ 30726Sbill } 30826Sbill 30926Sbill /* 31026Sbill * enter scheduling loop 31126Sbill */ 31226Sbill sched(); 31326Sbill } 314