123364Smckusick /* 247543Skarels * 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*47689Skarels * @(#)init_main.c 7.36 (Berkeley) 03/31/91 723364Smckusick */ 826Sbill 917087Sbloom #include "param.h" 1045914Smckusick #include "filedesc.h" 1117087Sbloom #include "kernel.h" 1217087Sbloom #include "mount.h" 1317087Sbloom #include "map.h" 1417087Sbloom #include "proc.h" 1547654Skarels #include "resourcevar.h" 1647654Skarels #include "signalvar.h" 1747654Skarels #include "systm.h" 1837610Smckusick #include "vnode.h" 1917087Sbloom #include "seg.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 2847543Skarels #include "ufs/quota.h" 2926Sbill 3037522Smckusick #include "machine/cpu.h" 3137522Smckusick 3247543Skarels #include "vm/vm.h" 3345724Smckusick 3447543Skarels /* 3547543Skarels * Components of process 0; 3647543Skarels * never freed. 3747543Skarels */ 3847543Skarels struct session session0; 3947543Skarels struct pgrp pgrp0; 4047543Skarels struct proc proc0; 4147543Skarels struct pcred cred0; 4247654Skarels struct filedesc0 filedesc0; 4347543Skarels struct plimit limit0; 4447543Skarels struct vmspace vmspace0; 4547654Skarels struct proc *curproc = &proc0; 4647543Skarels struct proc *initproc, *pageproc; 4747543Skarels 4816807Skarels int cmask = CMASK; 4945724Smckusick extern caddr_t proc0paddr; 5037610Smckusick extern int (*mountroot)(); 5145880Swilliam 5226Sbill /* 5347543Skarels * System startup; initialize the world, create process 0, 5447543Skarels * mount root filesystem, and fork to create init and pagedaemon. 5547543Skarels * Most of the hard work is done in the lower-level initialization 5647543Skarels * routines including startup(), which does memory initialization 5747543Skarels * and autoconfiguration. 5826Sbill */ 5926Sbill main(firstaddr) 608969Sroot int firstaddr; 6126Sbill { 62361Sbill register int i; 632451Swnj register struct proc *p; 6447654Skarels register struct filedesc0 *fdp; 6547543Skarels int s, rval[2]; 6626Sbill 6745880Swilliam /* 6847543Skarels * Initialize curproc before any possible traps/probes 6947543Skarels * to simplify trap processing. 7045880Swilliam */ 7147543Skarels p = &proc0; 7247543Skarels curproc = p; 7345724Smckusick /* 7447543Skarels * Attempt to find console and initialize 7547543Skarels * in case of early panic or other messages. 7645724Smckusick */ 7747543Skarels consinit(); 7847543Skarels 7945724Smckusick vm_mem_init(); 8045724Smckusick kmeminit(); 8126Sbill startup(firstaddr); 8226Sbill 8326Sbill /* 8426Sbill * set up system process 0 (swapper) 8526Sbill */ 8647543Skarels p = &proc0; 8747543Skarels curproc = p; 8847543Skarels 8947543Skarels allproc = p; 9047543Skarels p->p_prev = &allproc; 9147543Skarels p->p_pgrp = &pgrp0; 9247543Skarels pgrphash[0] = &pgrp0; 9347543Skarels pgrp0.pg_mem = p; 9447543Skarels pgrp0.pg_session = &session0; 9547543Skarels session0.s_count = 1; 9647543Skarels session0.s_leader = p; 9747543Skarels 9847543Skarels p->p_flag = SLOAD|SSYS; 992451Swnj p->p_stat = SRUN; 1002451Swnj p->p_nice = NZERO; 10147543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 10247543Skarels 10345724Smckusick /* 10447543Skarels * Setup credentials 10545724Smckusick */ 10647543Skarels p->p_cred = &cred0; 10747543Skarels p->p_ucred = crget(); 10847543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 10929946Skarels 11045914Smckusick /* 11145914Smckusick * Create the file descriptor table for process 0. 11245914Smckusick */ 11347543Skarels fdp = &filedesc0; 11447654Skarels p->p_fd = &fdp->fd_fd; 11547654Skarels fdp->fd_fd.fd_refcnt = 1; 11647654Skarels fdp->fd_fd.fd_cmask = cmask; 11747654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 11847654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 11947654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 12047543Skarels 12118278Smckusick /* 12247543Skarels * Set initial limits 12347543Skarels */ 12447543Skarels p->p_limit = &limit0; 12547543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 12647543Skarels limit0.pl_rlimit[i].rlim_cur = 12747543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 12847543Skarels limit0.pl_rlimit[RLIMIT_OFILE].rlim_cur = NOFILE; 12947543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 13047543Skarels limit0.p_refcnt = 1; 13147543Skarels 13247543Skarels /* 13347543Skarels * Allocate a prototype map so we have something to fork 13447543Skarels */ 13547543Skarels p->p_vmspace = &vmspace0; 13647543Skarels vmspace0.vm_refcnt = 1; 13747543Skarels pmap_pinit(&vmspace0.vm_pmap); 13847543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 13947543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 14047543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 14147543Skarels p->p_addr = proc0paddr; /* XXX */ 14247543Skarels 14347543Skarels /* 14447543Skarels * We continue to place resource usage info 14547543Skarels * and signal actions in the user struct so they're pageable. 14647543Skarels */ 14747654Skarels p->p_stats = &((struct user *)p->p_addr)->u_stats; 14847654Skarels p->p_sigacts = &((struct user *)p->p_addr)->u_sigacts; 14947543Skarels 15047543Skarels rqinit(); 15147543Skarels 15247543Skarels /* 15323534Skarels * configure virtual memory system, 15423534Skarels * set vm rlimits 15518278Smckusick */ 15647543Skarels vm_init_limits(p); 15723534Skarels 15837610Smckusick /* 15939431Smckusick * Initialize the file systems. 16039431Smckusick * 16137610Smckusick * Get vnodes for swapdev, argdev, and rootdev. 16237610Smckusick */ 16339431Smckusick vfsinit(); 16437610Smckusick if (bdevvp(swapdev, &swapdev_vp) || 16537610Smckusick bdevvp(argdev, &argdev_vp) || 16637610Smckusick bdevvp(rootdev, &rootvp)) 16737610Smckusick panic("can't setup bdevvp's"); 16837610Smckusick 16930256Ssam startrtclock(); 17029946Skarels #if defined(vax) 17112823Ssam #include "kg.h" 17212823Ssam #if NKG > 0 17311356Smckusick startkgclock(); 17411356Smckusick #endif 17529946Skarels #endif 17626Sbill 17726Sbill /* 1784821Swnj * Initialize tables, protocols, and set up well-known inodes. 17926Sbill */ 1804821Swnj mbinit(); 18121103Skarels cinit(); 18241565Smckusick #ifdef SYSVSHM 18341565Smckusick shminit(); 18441565Smckusick #endif 18526137Skarels #include "sl.h" 18626137Skarels #if NSL > 0 18726137Skarels slattach(); /* XXX */ 18826137Skarels #endif 18941565Smckusick #include "loop.h" 1905855Swnj #if NLOOP > 0 1915855Swnj loattach(); /* XXX */ 1925855Swnj #endif 1939156Ssam /* 1949156Ssam * Block reception of incoming packets 1959156Ssam * until protocols have been initialized. 1969156Ssam */ 1979156Ssam s = splimp(); 1985227Swnj ifinit(); 1998969Sroot domaininit(); 2009156Ssam splx(s); 20147543Skarels 2027419Sroot #ifdef GPROF 2037419Sroot kmstartup(); 2047419Sroot #endif 2057189Sroot 20647543Skarels /* kick off timeout driven events by calling first time */ 2078096Sroot roundrobin(); 2088096Sroot schedcpu(); 20945880Swilliam enablertclock(); /* enable realtime clock interrupts */ 2108096Sroot 21147543Skarels /* 21247543Skarels * Set up the root file system and vnode. 21347543Skarels */ 21437610Smckusick if ((*mountroot)()) 21537610Smckusick panic("cannot mount root"); 21637610Smckusick /* 21737610Smckusick * Get vnode for '/'. 21847654Skarels * Setup rootdir and fdp->fd_fd.fd_cdir to point to it. 21937610Smckusick */ 22037610Smckusick if (VFS_ROOT(rootfs, &rootdir)) 22137610Smckusick panic("cannot find root vnode"); 22247654Skarels fdp->fd_fd.fd_cdir = rootdir; 22347654Skarels VREF(fdp->fd_fd.fd_cdir); 22437726Smckusick VOP_UNLOCK(rootdir); 22547654Skarels fdp->fd_fd.fd_rdir = NULL; 22647543Skarels swapinit(); 22726Sbill 22826Sbill /* 22947543Skarels * Now can look at time, having had a chance 23047543Skarels * to verify the time from the file system. 23147543Skarels */ 23247543Skarels boottime = p->p_stats->p_start = time; 23347543Skarels 23447543Skarels /* 23516807Skarels * make init process 23616807Skarels */ 23747543Skarels siginit(p); 23847543Skarels if (fork(p, (void *) NULL, rval)) 23947543Skarels panic("fork init"); 24047543Skarels if (rval[1]) { 241*47689Skarels static char initflags[] = "-sf"; 242*47689Skarels char *ip = initflags + 1; 24345724Smckusick vm_offset_t addr = 0; 24445724Smckusick 24547543Skarels /* 24647543Skarels * Now in process 1. Set init flags into icode, 24747543Skarels * get a minimal address space, copy out "icode", 24847543Skarels * and return to it to do an exec of init. 24947543Skarels */ 25047543Skarels p = curproc; 25147543Skarels initproc = p; 25247543Skarels if (boothowto&RB_SINGLE) 25347543Skarels *ip++ = 's'; 25447543Skarels #ifdef notyet 25547543Skarels if (boothowto&RB_FASTBOOT) 25647543Skarels *ip++ = 'f'; 257*47689Skarels #endif 25847543Skarels *ip++ = '\0'; 25947543Skarels 26047543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 261*47689Skarels round_page(szicode + sizeof(initflags)), FALSE) != 0 || 262*47689Skarels 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); 26747543Skarels if (vm_allocate(&p->p_vmspace->vm_map, &addr, 26847543Skarels PAGE_SIZE, FALSE) != KERN_SUCCESS) 26947543Skarels panic("vm_allocate init stack"); 27047543Skarels p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 27116807Skarels (void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode); 272*47689Skarels (void) copyout(initflags, (caddr_t)szicode, sizeof(initflags)); 27347543Skarels return; /* returns to icode */ 27416807Skarels } 27547543Skarels 27616807Skarels /* 27745724Smckusick * Start up pageout daemon (process 2). 27826Sbill */ 27947543Skarels if (fork(p, (void *) NULL, rval)) 28047543Skarels panic("fork pager"); 28147543Skarels if (rval[1]) { 28247543Skarels /* 28347543Skarels * Now in process 2. 28447543Skarels */ 28547543Skarels p = curproc; 28647543Skarels pageproc = p; 28747543Skarels p->p_flag |= SLOAD|SSYS; /* XXX */ 28847543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 28945724Smckusick vm_pageout(); 2909025Sroot /*NOTREACHED*/ 29126Sbill } 29226Sbill 29326Sbill /* 29426Sbill * enter scheduling loop 29526Sbill */ 29626Sbill sched(); 29726Sbill } 29826Sbill 29947543Skarels /* MOVE TO vfs_bio.c (bufinit) XXX */ 30026Sbill /* 30147543Skarels * Initialize buffers and hash links for buffers. 3027001Smckusick */ 30347543Skarels bufinit() 3047001Smckusick { 3057001Smckusick register int i; 3068554Sroot register struct buf *bp, *dp; 30747543Skarels register struct bufhd *hp; 30810336Smckusick int base, residual; 30926Sbill 31047543Skarels for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++) 31147543Skarels hp->b_forw = hp->b_back = (struct buf *)hp; 31247543Skarels 3132322Swnj for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) { 3142322Swnj dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp; 3152322Swnj dp->b_flags = B_HEAD; 3162322Swnj } 31710336Smckusick base = bufpages / nbuf; 31810336Smckusick residual = bufpages % nbuf; 3196570Smckusic for (i = 0; i < nbuf; i++) { 32026Sbill bp = &buf[i]; 32126Sbill bp->b_dev = NODEV; 3229156Ssam bp->b_bcount = 0; 32338774Smckusick bp->b_rcred = NOCRED; 32438774Smckusick bp->b_wcred = NOCRED; 32538774Smckusick bp->b_dirtyoff = 0; 32638774Smckusick bp->b_dirtyend = 0; 3276570Smckusic bp->b_un.b_addr = buffers + i * MAXBSIZE; 32810336Smckusick if (i < residual) 32910336Smckusick bp->b_bufsize = (base + 1) * CLBYTES; 33010336Smckusick else 33110336Smckusick bp->b_bufsize = base * CLBYTES; 3329750Ssam binshash(bp, &bfreelist[BQ_AGE]); 3332322Swnj bp->b_flags = B_BUSY|B_INVAL; 33426Sbill brelse(bp); 33526Sbill } 33630531Skarels } 337