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*64830Shibler * @(#)init_main.c 8.5 (Berkeley) 11/11/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 6364540Smckusick static void start_init __P((struct proc *p, int *regs)); 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 */ 7164540Smckusick main(regs) 7264540Smckusick int *regs; 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 10164405Sbostic /* Create process 0 (the swapper). */ 10247543Skarels p = &proc0; 10347543Skarels curproc = p; 10447543Skarels 10554781Storek allproc = (volatile struct proc *)p; 10654781Storek p->p_prev = (struct proc **)&allproc; 10747543Skarels p->p_pgrp = &pgrp0; 10847543Skarels pgrphash[0] = &pgrp0; 10947543Skarels pgrp0.pg_mem = p; 11047543Skarels pgrp0.pg_session = &session0; 11147543Skarels session0.s_count = 1; 11247543Skarels session0.s_leader = p; 11347543Skarels 11464571Sbostic p->p_flag = P_INMEM | P_SYSTEM; 1152451Swnj p->p_stat = SRUN; 1162451Swnj p->p_nice = NZERO; 11747543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 11847543Skarels 11964405Sbostic /* Create credentials. */ 12049745Smckusick cred0.p_refcnt = 1; 12147543Skarels p->p_cred = &cred0; 12247543Skarels p->p_ucred = crget(); 12347543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 12429946Skarels 12564405Sbostic /* Create the file descriptor table. */ 12647543Skarels fdp = &filedesc0; 12747654Skarels p->p_fd = &fdp->fd_fd; 12847654Skarels fdp->fd_fd.fd_refcnt = 1; 12947654Skarels fdp->fd_fd.fd_cmask = cmask; 13047654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 13147654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 13247654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 13347543Skarels 13464405Sbostic /* Create the limits structures. */ 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; 13956935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 14047543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 14159488Smckusick i = ptoa(cnt.v_free_count); 14259488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 14359488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 14459488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 14547543Skarels limit0.p_refcnt = 1; 14647543Skarels 14764405Sbostic /* Allocate a prototype map so we have something to fork. */ 14847543Skarels p->p_vmspace = &vmspace0; 14947543Skarels vmspace0.vm_refcnt = 1; 15047543Skarels pmap_pinit(&vmspace0.vm_pmap); 15147543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 15247543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 15347543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 15447543Skarels p->p_addr = proc0paddr; /* XXX */ 15547543Skarels 15647543Skarels /* 15764405Sbostic * We continue to place resource usage info and signal 15864405Sbostic * actions in the user struct so they're pageable. 15947543Skarels */ 16048981Skarels p->p_stats = &p->p_addr->u_stats; 16148981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 16247543Skarels 16355406Smckusick /* 16455406Smckusick * Initialize per uid information structure and charge 16555406Smckusick * root for one process. 16655406Smckusick */ 16755406Smckusick usrinfoinit(); 16855406Smckusick (void)chgproccnt(0, 1); 16955406Smckusick 17047543Skarels rqinit(); 17147543Skarels 17259118Storek /* Configure virtual memory system, set vm rlimits. */ 17347543Skarels vm_init_limits(p); 17423534Skarels 17559118Storek /* Initialize the file systems. */ 17639431Smckusick vfsinit(); 17737610Smckusick 17859118Storek /* Start real time and statistics clocks. */ 17954781Storek initclocks(); 18026Sbill 18164405Sbostic /* Initialize mbuf's. */ 1824821Swnj mbinit(); 18364405Sbostic 18464405Sbostic /* Initialize clists. */ 18564405Sbostic clist_init(); 18664405Sbostic 18741565Smckusick #ifdef SYSVSHM 18864405Sbostic /* Initialize System V style shared memory. */ 18941565Smckusick shminit(); 19041565Smckusick #endif 19159118Storek 19259118Storek /* Attach pseudo-devices. */ 19359118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 19459118Storek (*pdev->pdev_attach)(pdev->pdev_count); 19559118Storek 1969156Ssam /* 19759118Storek * Initialize protocols. Block reception of incoming packets 19859118Storek * until everything is ready. 1999156Ssam */ 2009156Ssam s = splimp(); 2015227Swnj ifinit(); 2028969Sroot domaininit(); 2039156Ssam splx(s); 20447543Skarels 2057419Sroot #ifdef GPROF 20664405Sbostic /* Initialize kernel profiling. */ 2077419Sroot kmstartup(); 2087419Sroot #endif 2097189Sroot 21064405Sbostic /* Kick off timeout driven events by calling first time. */ 21154781Storek roundrobin(NULL); 21254781Storek schedcpu(NULL); 2138096Sroot 21464405Sbostic /* Mount the root file system. */ 21537610Smckusick if ((*mountroot)()) 21637610Smckusick panic("cannot mount root"); 21764405Sbostic 21864405Sbostic /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 21964405Sbostic if (VFS_ROOT(rootfs, &rootvnode)) 22037610Smckusick panic("cannot find root vnode"); 22164405Sbostic fdp->fd_fd.fd_cdir = rootvnode; 22247654Skarels VREF(fdp->fd_fd.fd_cdir); 22364405Sbostic VOP_UNLOCK(rootvnode); 22447654Skarels fdp->fd_fd.fd_rdir = NULL; 22547543Skarels swapinit(); 22626Sbill 22726Sbill /* 22855796Smckusick * Now can look at time, having had a chance to verify the time 22955796Smckusick * from the file system. Reset p->p_rtime as it may have been 23064571Sbostic * munched in mi_switch() after the time got set. 23147543Skarels */ 23254943Storek p->p_stats->p_start = runtime = mono_time = boottime = time; 23355796Smckusick p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 23447543Skarels 23564405Sbostic /* Initialize signal state for process 0. */ 23647543Skarels siginit(p); 23764405Sbostic 23864405Sbostic /* Create process 1 (init(8)). */ 23952504Sbostic if (fork(p, NULL, rval)) 24047543Skarels panic("fork init"); 24147543Skarels if (rval[1]) { 24264540Smckusick start_init(curproc, regs); 24364540Smckusick return; 24416807Skarels } 24547543Skarels 24664405Sbostic /* Create process 2 (the pageout daemon). */ 24752504Sbostic if (fork(p, NULL, rval)) 24847543Skarels panic("fork pager"); 24947543Skarels if (rval[1]) { 25047543Skarels /* 25147543Skarels * Now in process 2. 25247543Skarels */ 25347543Skarels p = curproc; 25447543Skarels pageproc = p; 25564571Sbostic p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ 25647543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 25745724Smckusick vm_pageout(); 25864405Sbostic /* NOTREACHED */ 25926Sbill } 26026Sbill 26164405Sbostic /* The scheduler is an infinite loop. */ 26264405Sbostic scheduler(); 26364405Sbostic /* NOTREACHED */ 26426Sbill } 26564540Smckusick 26664540Smckusick /* 26764540Smckusick * List of paths to try when searching for "init". 26864540Smckusick */ 26964540Smckusick static char *initpaths[] = { 27064540Smckusick "/sbin/init", 27164540Smckusick "/sbin/oinit", 27264540Smckusick "/sbin/init.bak", 27364540Smckusick NULL, 27464540Smckusick }; 27564540Smckusick 27664540Smckusick /* 27764540Smckusick * Start the initial user process; try exec'ing each pathname in "initpaths". 27864540Smckusick * The program is invoked with one argument containing the boot flags. 27964540Smckusick */ 28064540Smckusick static void 28164540Smckusick start_init(p, regs) 28264540Smckusick struct proc *p; 28364540Smckusick int *regs; 28464540Smckusick { 28564540Smckusick vm_offset_t addr; 28664540Smckusick struct execve_args args; 28764540Smckusick int options, i, retval[2], error; 28864540Smckusick char **pathp, *path, *ucp, **uap, *arg0, *arg1; 28964540Smckusick 290*64830Shibler initproc = p; 291*64830Shibler 29264540Smckusick /* 29364540Smckusick * We need to set p->p_md.md_regs since start_init acts like a 29464540Smckusick * system call and references the regs to set the entry point 29564540Smckusick * (see setregs) when it tries to exec. On regular fork, the 29664540Smckusick * p->p_md.md_regs of the child is undefined since it is set on 29764540Smckusick * each system call. The startup code in "locore.s" has arranged 29864540Smckusick * that there be some place to set "p->p_md.md_regs" to, and 29964540Smckusick * passed a pointer to that place as main's argument. 30064540Smckusick */ 30164540Smckusick p->p_md.md_regs = regs; 30264540Smckusick 30364540Smckusick /* 30464540Smckusick * Need just enough stack to hold the faked-up "execve()" arguments. 30564540Smckusick */ 30664540Smckusick addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 30764540Smckusick if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0) 30864540Smckusick panic("init: couldn't allocate argument space"); 30964540Smckusick p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 31064540Smckusick 31164540Smckusick for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { 31264540Smckusick /* 31364540Smckusick * Move out the boot flag argument. 31464540Smckusick */ 31564540Smckusick options = 0; 31664540Smckusick ucp = (char *)USRSTACK; 31764571Sbostic (void)subyte(--ucp, 0); /* trailing zero */ 31864540Smckusick if (boothowto & RB_SINGLE) { 31964571Sbostic (void)subyte(--ucp, 's'); 32064540Smckusick options = 1; 32164540Smckusick } 32264540Smckusick #ifdef notyet 32364540Smckusick if (boothowto & RB_FASTBOOT) { 32464571Sbostic (void)subyte(--ucp, 'f'); 32564540Smckusick options = 1; 32664540Smckusick } 32764540Smckusick #endif 32864540Smckusick if (options == 0) 32964571Sbostic (void)subyte(--ucp, '-'); 33064571Sbostic (void)subyte(--ucp, '-'); /* leading hyphen */ 33164540Smckusick arg1 = ucp; 33264540Smckusick 33364540Smckusick /* 33464540Smckusick * Move out the file name (also arg 0). 33564540Smckusick */ 33664540Smckusick for (i = strlen(path) + 1; i >= 0; i--) 33764571Sbostic (void)subyte(--ucp, path[i]); 33864540Smckusick arg0 = ucp; 33964540Smckusick 34064540Smckusick /* 34164540Smckusick * Move out the arg pointers. 34264540Smckusick */ 34364540Smckusick uap = (char **)((int)ucp & ~(NBPW-1)); 34464571Sbostic (void)suword((caddr_t)--uap, 0); /* terminator */ 34564571Sbostic (void)suword((caddr_t)--uap, (int)arg1); 34664571Sbostic (void)suword((caddr_t)--uap, (int)arg0); 34764540Smckusick 34864540Smckusick /* 34964540Smckusick * Point at the arguments. 35064540Smckusick */ 35164540Smckusick args.fname = arg0; 35264540Smckusick args.argp = uap; 35364540Smckusick args.envp = NULL; 35464540Smckusick 35564540Smckusick /* 35664571Sbostic * Now try to exec the program. If can't for any reason 35764571Sbostic * other than it doesn't exist, complain. 35864540Smckusick */ 35964540Smckusick if ((error = execve(p, &args, &retval)) == 0) 36064540Smckusick return; 36164571Sbostic if (error != ENOENT) 36264571Sbostic printf("exec %s: error %d\n", path, error); 36364540Smckusick } 36464540Smckusick printf("init: not found\n"); 36564540Smckusick panic("no init"); 36664540Smckusick } 367