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*65255Smckusick * @(#)init_main.c 8.8 (Berkeley) 12/30/93 823364Smckusick */ 926Sbill 1056934Smckusick #include <sys/param.h> 1156934Smckusick #include <sys/filedesc.h> 1264540Smckusick #include <sys/errno.h> 1364540Smckusick #include <sys/exec.h> 1456934Smckusick #include <sys/kernel.h> 1556934Smckusick #include <sys/mount.h> 1656934Smckusick #include <sys/map.h> 1756934Smckusick #include <sys/proc.h> 1856934Smckusick #include <sys/resourcevar.h> 1956934Smckusick #include <sys/signalvar.h> 2056934Smckusick #include <sys/systm.h> 2156934Smckusick #include <sys/vnode.h> 2256934Smckusick #include <sys/conf.h> 2356934Smckusick #include <sys/buf.h> 2456934Smckusick #include <sys/clist.h> 2559118Storek #include <sys/device.h> 2656934Smckusick #include <sys/protosw.h> 2756934Smckusick #include <sys/reboot.h> 2856934Smckusick #include <sys/user.h> 2947654Skarels 3056934Smckusick #include <ufs/ufs/quota.h> 3126Sbill 3256934Smckusick #include <machine/cpu.h> 3337522Smckusick 3456934Smckusick #include <vm/vm.h> 3545724Smckusick 3655399Smckusick #ifdef HPFPLIB 3749382Skarels char copyright[] = 3860928Smckusick "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"; 3955399Smckusick #else 4055399Smckusick char copyright[] = 4160928Smckusick "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; 4255399Smckusick #endif 4349382Skarels 4464405Sbostic /* Components of the first process -- never freed. */ 4547543Skarels struct session session0; 4647543Skarels struct pgrp pgrp0; 4747543Skarels struct proc proc0; 4847543Skarels struct pcred cred0; 4947654Skarels struct filedesc0 filedesc0; 5047543Skarels struct plimit limit0; 5147543Skarels struct vmspace vmspace0; 5247654Skarels struct proc *curproc = &proc0; 5347543Skarels struct proc *initproc, *pageproc; 5447543Skarels 5516807Skarels int cmask = CMASK; 5648981Skarels extern struct user *proc0paddr; 5745880Swilliam 5849382Skarels struct vnode *rootvp, *swapdev_vp; 5949382Skarels int boothowto; 6053009Ssklower struct timeval boottime; 6154781Storek struct timeval runtime; 6249382Skarels 6365076Smckusick static void start_init __P((struct proc *p, void *framep)); 6464540Smckusick 6526Sbill /* 6664405Sbostic * System startup; initialize the world, create process 0, mount root 6764405Sbostic * filesystem, and fork to create init and pagedaemon. Most of the 6864405Sbostic * hard work is done in the lower-level initialization routines including 6964405Sbostic * startup(), which does memory initialization and autoconfiguration. 7026Sbill */ 7165076Smckusick main(framep) 7265076Smckusick void *framep; 7326Sbill { 742451Swnj register struct proc *p; 7547654Skarels register struct filedesc0 *fdp; 7659118Storek register struct pdevinit *pdev; 7764405Sbostic register int i; 7847543Skarels int s, rval[2]; 7964405Sbostic extern int (*mountroot) __P((void)); 8059118Storek extern struct pdevinit pdevinit[]; 8154781Storek extern void roundrobin __P((void *)); 8254781Storek extern void schedcpu __P((void *)); 8326Sbill 8445880Swilliam /* 8564405Sbostic * Initialize the current process pointer (curproc) before 8664405Sbostic * any possible traps/probes to simplify trap processing. 8745880Swilliam */ 8847543Skarels p = &proc0; 8947543Skarels curproc = p; 9045724Smckusick /* 9147543Skarels * Attempt to find console and initialize 9247543Skarels * in case of early panic or other messages. 9345724Smckusick */ 9447543Skarels consinit(); 9549382Skarels printf(copyright); 9647543Skarels 9745724Smckusick vm_mem_init(); 9845724Smckusick kmeminit(); 9949533Skarels cpu_startup(); 10026Sbill 10165114Smckusick /* 10265114Smckusick * Create process 0 (the swapper). 10365114Smckusick */ 10454781Storek allproc = (volatile struct proc *)p; 10554781Storek p->p_prev = (struct proc **)&allproc; 10647543Skarels p->p_pgrp = &pgrp0; 10747543Skarels pgrphash[0] = &pgrp0; 10847543Skarels pgrp0.pg_mem = p; 10947543Skarels pgrp0.pg_session = &session0; 11047543Skarels session0.s_count = 1; 11147543Skarels session0.s_leader = p; 11247543Skarels 11364571Sbostic p->p_flag = P_INMEM | P_SYSTEM; 1142451Swnj p->p_stat = SRUN; 1152451Swnj p->p_nice = NZERO; 11647543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 11747543Skarels 11864405Sbostic /* Create credentials. */ 11949745Smckusick cred0.p_refcnt = 1; 12047543Skarels p->p_cred = &cred0; 12147543Skarels p->p_ucred = crget(); 12247543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 12329946Skarels 12464405Sbostic /* Create the file descriptor table. */ 12547543Skarels fdp = &filedesc0; 12647654Skarels p->p_fd = &fdp->fd_fd; 12747654Skarels fdp->fd_fd.fd_refcnt = 1; 12847654Skarels fdp->fd_fd.fd_cmask = cmask; 12947654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 13047654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 13147654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 13247543Skarels 13364405Sbostic /* Create the limits structures. */ 13447543Skarels p->p_limit = &limit0; 13547543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 13647543Skarels limit0.pl_rlimit[i].rlim_cur = 13747543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 13856935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 13947543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 14059488Smckusick i = ptoa(cnt.v_free_count); 14159488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 14259488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 14359488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 14447543Skarels limit0.p_refcnt = 1; 14547543Skarels 14664405Sbostic /* Allocate a prototype map so we have something to fork. */ 14747543Skarels p->p_vmspace = &vmspace0; 14847543Skarels vmspace0.vm_refcnt = 1; 14947543Skarels pmap_pinit(&vmspace0.vm_pmap); 15047543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 15147543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 15247543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 15347543Skarels p->p_addr = proc0paddr; /* XXX */ 15447543Skarels 15547543Skarels /* 15664405Sbostic * We continue to place resource usage info and signal 15764405Sbostic * actions in the user struct so they're pageable. 15847543Skarels */ 15948981Skarels p->p_stats = &p->p_addr->u_stats; 16048981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 16147543Skarels 16255406Smckusick /* 16355406Smckusick * Initialize per uid information structure and charge 16455406Smckusick * root for one process. 16555406Smckusick */ 16655406Smckusick usrinfoinit(); 16755406Smckusick (void)chgproccnt(0, 1); 16855406Smckusick 16947543Skarels rqinit(); 17047543Skarels 17159118Storek /* Configure virtual memory system, set vm rlimits. */ 17247543Skarels vm_init_limits(p); 17323534Skarels 17459118Storek /* Initialize the file systems. */ 17539431Smckusick vfsinit(); 17637610Smckusick 17759118Storek /* Start real time and statistics clocks. */ 17854781Storek initclocks(); 17926Sbill 18064405Sbostic /* Initialize mbuf's. */ 1814821Swnj mbinit(); 18264405Sbostic 18364405Sbostic /* Initialize clists. */ 18464405Sbostic clist_init(); 18564405Sbostic 18641565Smckusick #ifdef SYSVSHM 18764405Sbostic /* Initialize System V style shared memory. */ 18841565Smckusick shminit(); 18941565Smckusick #endif 19059118Storek 19159118Storek /* Attach pseudo-devices. */ 19259118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 19359118Storek (*pdev->pdev_attach)(pdev->pdev_count); 19459118Storek 1959156Ssam /* 19659118Storek * Initialize protocols. Block reception of incoming packets 19759118Storek * until everything is ready. 1989156Ssam */ 1999156Ssam s = splimp(); 2005227Swnj ifinit(); 2018969Sroot domaininit(); 2029156Ssam splx(s); 20347543Skarels 2047419Sroot #ifdef GPROF 20564405Sbostic /* Initialize kernel profiling. */ 2067419Sroot kmstartup(); 2077419Sroot #endif 2087189Sroot 20964405Sbostic /* Kick off timeout driven events by calling first time. */ 21054781Storek roundrobin(NULL); 21154781Storek schedcpu(NULL); 2128096Sroot 21364405Sbostic /* Mount the root file system. */ 21437610Smckusick if ((*mountroot)()) 21537610Smckusick panic("cannot mount root"); 21664405Sbostic 21764405Sbostic /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 218*65255Smckusick if (VFS_ROOT(mountlist.tqh_first, &rootvnode)) 21937610Smckusick panic("cannot find root vnode"); 22064405Sbostic fdp->fd_fd.fd_cdir = rootvnode; 22147654Skarels VREF(fdp->fd_fd.fd_cdir); 22264405Sbostic VOP_UNLOCK(rootvnode); 22347654Skarels fdp->fd_fd.fd_rdir = NULL; 22447543Skarels swapinit(); 22526Sbill 22626Sbill /* 22755796Smckusick * Now can look at time, having had a chance to verify the time 22855796Smckusick * from the file system. Reset p->p_rtime as it may have been 22964571Sbostic * munched in mi_switch() after the time got set. 23047543Skarels */ 23154943Storek p->p_stats->p_start = runtime = mono_time = boottime = time; 23255796Smckusick p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 23347543Skarels 23464405Sbostic /* Initialize signal state for process 0. */ 23547543Skarels siginit(p); 23664405Sbostic 23764405Sbostic /* Create process 1 (init(8)). */ 23852504Sbostic if (fork(p, NULL, rval)) 23947543Skarels panic("fork init"); 24047543Skarels if (rval[1]) { 24165076Smckusick start_init(curproc, framep); 24264540Smckusick return; 24316807Skarels } 24447543Skarels 24564405Sbostic /* Create process 2 (the pageout daemon). */ 24652504Sbostic if (fork(p, NULL, rval)) 24747543Skarels panic("fork pager"); 24847543Skarels if (rval[1]) { 24947543Skarels /* 25047543Skarels * Now in process 2. 25147543Skarels */ 25247543Skarels p = curproc; 25347543Skarels pageproc = p; 25464571Sbostic p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ 25547543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 25645724Smckusick vm_pageout(); 25764405Sbostic /* NOTREACHED */ 25826Sbill } 25926Sbill 26064405Sbostic /* The scheduler is an infinite loop. */ 26164405Sbostic scheduler(); 26264405Sbostic /* NOTREACHED */ 26326Sbill } 26464540Smckusick 26564540Smckusick /* 26664540Smckusick * List of paths to try when searching for "init". 26764540Smckusick */ 26864540Smckusick static char *initpaths[] = { 26964540Smckusick "/sbin/init", 27064540Smckusick "/sbin/oinit", 27164540Smckusick "/sbin/init.bak", 27264540Smckusick NULL, 27364540Smckusick }; 27464540Smckusick 27564540Smckusick /* 27664540Smckusick * Start the initial user process; try exec'ing each pathname in "initpaths". 27764540Smckusick * The program is invoked with one argument containing the boot flags. 27864540Smckusick */ 27964540Smckusick static void 28065076Smckusick start_init(p, framep) 28164540Smckusick struct proc *p; 28265076Smckusick void *framep; 28364540Smckusick { 28464540Smckusick vm_offset_t addr; 28564540Smckusick struct execve_args args; 28664540Smckusick int options, i, retval[2], error; 28764540Smckusick char **pathp, *path, *ucp, **uap, *arg0, *arg1; 28864540Smckusick 28964830Shibler initproc = p; 29064830Shibler 29164540Smckusick /* 29265076Smckusick * We need to set the system call frame as if we were entered through 29365076Smckusick * a syscall() so that when we call execve() below, it will be able 29465076Smckusick * to set the entry point (see setregs) when it tries to exec. The 29565076Smckusick * startup code in "locore.s" has allocated space for the frame and 29665076Smckusick * passed a pointer to that space as main's argument. 29764540Smckusick */ 29865076Smckusick cpu_set_init_frame(p, framep); 29964540Smckusick 30064540Smckusick /* 30164540Smckusick * Need just enough stack to hold the faked-up "execve()" arguments. 30264540Smckusick */ 30364540Smckusick addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 30464540Smckusick if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0) 30564540Smckusick panic("init: couldn't allocate argument space"); 30664540Smckusick p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 30764540Smckusick 30864540Smckusick for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { 30964540Smckusick /* 31064540Smckusick * Move out the boot flag argument. 31164540Smckusick */ 31264540Smckusick options = 0; 31364540Smckusick ucp = (char *)USRSTACK; 31464571Sbostic (void)subyte(--ucp, 0); /* trailing zero */ 31564540Smckusick if (boothowto & RB_SINGLE) { 31664571Sbostic (void)subyte(--ucp, 's'); 31764540Smckusick options = 1; 31864540Smckusick } 31964540Smckusick #ifdef notyet 32064540Smckusick if (boothowto & RB_FASTBOOT) { 32164571Sbostic (void)subyte(--ucp, 'f'); 32264540Smckusick options = 1; 32364540Smckusick } 32464540Smckusick #endif 32564540Smckusick if (options == 0) 32664571Sbostic (void)subyte(--ucp, '-'); 32764571Sbostic (void)subyte(--ucp, '-'); /* leading hyphen */ 32864540Smckusick arg1 = ucp; 32964540Smckusick 33064540Smckusick /* 33164540Smckusick * Move out the file name (also arg 0). 33264540Smckusick */ 33364540Smckusick for (i = strlen(path) + 1; i >= 0; i--) 33464571Sbostic (void)subyte(--ucp, path[i]); 33564540Smckusick arg0 = ucp; 33664540Smckusick 33764540Smckusick /* 33864540Smckusick * Move out the arg pointers. 33964540Smckusick */ 34064540Smckusick uap = (char **)((int)ucp & ~(NBPW-1)); 34164571Sbostic (void)suword((caddr_t)--uap, 0); /* terminator */ 34264571Sbostic (void)suword((caddr_t)--uap, (int)arg1); 34364571Sbostic (void)suword((caddr_t)--uap, (int)arg0); 34464540Smckusick 34564540Smckusick /* 34664540Smckusick * Point at the arguments. 34764540Smckusick */ 34864540Smckusick args.fname = arg0; 34964540Smckusick args.argp = uap; 35064540Smckusick args.envp = NULL; 35164540Smckusick 35264540Smckusick /* 35364571Sbostic * Now try to exec the program. If can't for any reason 35464571Sbostic * other than it doesn't exist, complain. 35564540Smckusick */ 35664540Smckusick if ((error = execve(p, &args, &retval)) == 0) 35764540Smckusick return; 35864571Sbostic if (error != ENOENT) 35964571Sbostic printf("exec %s: error %d\n", path, error); 36064540Smckusick } 36164540Smckusick printf("init: not found\n"); 36264540Smckusick panic("no init"); 36364540Smckusick } 364