123364Smckusick /* 263170Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 363170Sbostic * The Regents of the University of California. All rights reserved. 465771Sbostic * (c) UNIX System Laboratories, Inc. 565771Sbostic * All or some portions of this file are derived from material licensed 665771Sbostic * to the University of California by American Telephone and Telegraph 765771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 865771Sbostic * the permission of UNIX System Laboratories, Inc. 923364Smckusick * 1047817Skarels * %sccs.include.redist.c% 1147817Skarels * 12*69138Smckusick * @(#)init_main.c 8.12 (Berkeley) 05/01/95 1323364Smckusick */ 1426Sbill 1556934Smckusick #include <sys/param.h> 1656934Smckusick #include <sys/filedesc.h> 1764540Smckusick #include <sys/errno.h> 1864540Smckusick #include <sys/exec.h> 1956934Smckusick #include <sys/kernel.h> 2056934Smckusick #include <sys/mount.h> 2156934Smckusick #include <sys/map.h> 2256934Smckusick #include <sys/proc.h> 2356934Smckusick #include <sys/resourcevar.h> 2456934Smckusick #include <sys/signalvar.h> 2556934Smckusick #include <sys/systm.h> 2656934Smckusick #include <sys/vnode.h> 2756934Smckusick #include <sys/conf.h> 2856934Smckusick #include <sys/buf.h> 2956934Smckusick #include <sys/clist.h> 3059118Storek #include <sys/device.h> 3156934Smckusick #include <sys/protosw.h> 3256934Smckusick #include <sys/reboot.h> 3356934Smckusick #include <sys/user.h> 3468299Scgd #include <sys/syscallargs.h> 3547654Skarels 3656934Smckusick #include <ufs/ufs/quota.h> 3726Sbill 3856934Smckusick #include <machine/cpu.h> 3937522Smckusick 4056934Smckusick #include <vm/vm.h> 4145724Smckusick 4255399Smckusick #ifdef HPFPLIB 4349382Skarels char copyright[] = 4460928Smckusick "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"; 4555399Smckusick #else 4655399Smckusick char copyright[] = 4760928Smckusick "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; 4855399Smckusick #endif 4949382Skarels 5064405Sbostic /* Components of the first process -- never freed. */ 5147543Skarels struct session session0; 5247543Skarels struct pgrp pgrp0; 5347543Skarels struct proc proc0; 5447543Skarels struct pcred cred0; 5547654Skarels struct filedesc0 filedesc0; 5647543Skarels struct plimit limit0; 5747543Skarels struct vmspace vmspace0; 5847654Skarels struct proc *curproc = &proc0; 5947543Skarels struct proc *initproc, *pageproc; 6047543Skarels 6116807Skarels int cmask = CMASK; 6248981Skarels extern struct user *proc0paddr; 6345880Swilliam 6449382Skarels struct vnode *rootvp, *swapdev_vp; 6549382Skarels int boothowto; 6653009Ssklower struct timeval boottime; 6754781Storek struct timeval runtime; 6849382Skarels 6965076Smckusick static void start_init __P((struct proc *p, void *framep)); 7064540Smckusick 7126Sbill /* 7264405Sbostic * System startup; initialize the world, create process 0, mount root 7364405Sbostic * filesystem, and fork to create init and pagedaemon. Most of the 7464405Sbostic * hard work is done in the lower-level initialization routines including 7564405Sbostic * startup(), which does memory initialization and autoconfiguration. 7626Sbill */ 7765076Smckusick main(framep) 7865076Smckusick void *framep; 7926Sbill { 802451Swnj register struct proc *p; 8147654Skarels register struct filedesc0 *fdp; 8259118Storek register struct pdevinit *pdev; 8364405Sbostic register int i; 8468299Scgd int s; 8568299Scgd register_t rval[2]; 8664405Sbostic extern int (*mountroot) __P((void)); 8759118Storek extern struct pdevinit pdevinit[]; 8854781Storek extern void roundrobin __P((void *)); 8954781Storek extern void schedcpu __P((void *)); 9026Sbill 9145880Swilliam /* 9264405Sbostic * Initialize the current process pointer (curproc) before 9364405Sbostic * any possible traps/probes to simplify trap processing. 9445880Swilliam */ 9547543Skarels p = &proc0; 9647543Skarels curproc = p; 9745724Smckusick /* 9847543Skarels * Attempt to find console and initialize 9947543Skarels * in case of early panic or other messages. 10045724Smckusick */ 10147543Skarels consinit(); 10249382Skarels printf(copyright); 10347543Skarels 10445724Smckusick vm_mem_init(); 10545724Smckusick kmeminit(); 10649533Skarels cpu_startup(); 10726Sbill 10865114Smckusick /* 10967732Smckusick * Initialize process and pgrp structures. 11067732Smckusick */ 11167732Smckusick procinit(); 11267732Smckusick 11367732Smckusick /* 11465114Smckusick * Create process 0 (the swapper). 11565114Smckusick */ 11667732Smckusick LIST_INSERT_HEAD(&allproc, p, p_list); 11747543Skarels p->p_pgrp = &pgrp0; 11867732Smckusick LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 11967732Smckusick LIST_INIT(&pgrp0.pg_members); 12067732Smckusick LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 12167732Smckusick 12247543Skarels pgrp0.pg_session = &session0; 12347543Skarels session0.s_count = 1; 12447543Skarels session0.s_leader = p; 12547543Skarels 12664571Sbostic p->p_flag = P_INMEM | P_SYSTEM; 1272451Swnj p->p_stat = SRUN; 1282451Swnj p->p_nice = NZERO; 12947543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 13047543Skarels 13164405Sbostic /* Create credentials. */ 13249745Smckusick cred0.p_refcnt = 1; 13347543Skarels p->p_cred = &cred0; 13447543Skarels p->p_ucred = crget(); 13547543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 13629946Skarels 13764405Sbostic /* Create the file descriptor table. */ 13847543Skarels fdp = &filedesc0; 13947654Skarels p->p_fd = &fdp->fd_fd; 14047654Skarels fdp->fd_fd.fd_refcnt = 1; 14147654Skarels fdp->fd_fd.fd_cmask = cmask; 14247654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 14347654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 14447654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 14547543Skarels 14664405Sbostic /* Create the limits structures. */ 14747543Skarels p->p_limit = &limit0; 14847543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 14947543Skarels limit0.pl_rlimit[i].rlim_cur = 15047543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 15156935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 15247543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 15359488Smckusick i = ptoa(cnt.v_free_count); 15459488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 15559488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 15659488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 15747543Skarels limit0.p_refcnt = 1; 15847543Skarels 15964405Sbostic /* Allocate a prototype map so we have something to fork. */ 16047543Skarels p->p_vmspace = &vmspace0; 16147543Skarels vmspace0.vm_refcnt = 1; 16247543Skarels pmap_pinit(&vmspace0.vm_pmap); 16347543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 16447543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 16547543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 16647543Skarels p->p_addr = proc0paddr; /* XXX */ 16747543Skarels 16847543Skarels /* 16964405Sbostic * We continue to place resource usage info and signal 17064405Sbostic * actions in the user struct so they're pageable. 17147543Skarels */ 17248981Skarels p->p_stats = &p->p_addr->u_stats; 17348981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 17447543Skarels 17555406Smckusick /* 17667732Smckusick * Charge root for one process. 17755406Smckusick */ 17855406Smckusick (void)chgproccnt(0, 1); 17955406Smckusick 18047543Skarels rqinit(); 18147543Skarels 18259118Storek /* Configure virtual memory system, set vm rlimits. */ 18347543Skarels vm_init_limits(p); 18423534Skarels 18559118Storek /* Initialize the file systems. */ 18639431Smckusick vfsinit(); 18737610Smckusick 18859118Storek /* Start real time and statistics clocks. */ 18954781Storek initclocks(); 19026Sbill 19164405Sbostic /* Initialize mbuf's. */ 1924821Swnj mbinit(); 19364405Sbostic 19464405Sbostic /* Initialize clists. */ 19564405Sbostic clist_init(); 19664405Sbostic 19741565Smckusick #ifdef SYSVSHM 19864405Sbostic /* Initialize System V style shared memory. */ 19941565Smckusick shminit(); 20041565Smckusick #endif 20159118Storek 20259118Storek /* Attach pseudo-devices. */ 20359118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 20459118Storek (*pdev->pdev_attach)(pdev->pdev_count); 20559118Storek 2069156Ssam /* 20759118Storek * Initialize protocols. Block reception of incoming packets 20859118Storek * until everything is ready. 2099156Ssam */ 2109156Ssam s = splimp(); 2115227Swnj ifinit(); 2128969Sroot domaininit(); 2139156Ssam splx(s); 21447543Skarels 2157419Sroot #ifdef GPROF 21664405Sbostic /* Initialize kernel profiling. */ 2177419Sroot kmstartup(); 2187419Sroot #endif 2197189Sroot 22064405Sbostic /* Kick off timeout driven events by calling first time. */ 22154781Storek roundrobin(NULL); 22254781Storek schedcpu(NULL); 2238096Sroot 22464405Sbostic /* Mount the root file system. */ 22537610Smckusick if ((*mountroot)()) 22637610Smckusick panic("cannot mount root"); 22764405Sbostic 22864405Sbostic /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 22965255Smckusick if (VFS_ROOT(mountlist.tqh_first, &rootvnode)) 23037610Smckusick panic("cannot find root vnode"); 23164405Sbostic fdp->fd_fd.fd_cdir = rootvnode; 23247654Skarels VREF(fdp->fd_fd.fd_cdir); 23364405Sbostic VOP_UNLOCK(rootvnode); 23447654Skarels fdp->fd_fd.fd_rdir = NULL; 23547543Skarels swapinit(); 23626Sbill 23726Sbill /* 23855796Smckusick * Now can look at time, having had a chance to verify the time 23955796Smckusick * from the file system. Reset p->p_rtime as it may have been 24064571Sbostic * munched in mi_switch() after the time got set. 24147543Skarels */ 24254943Storek p->p_stats->p_start = runtime = mono_time = boottime = time; 24355796Smckusick p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 24447543Skarels 24564405Sbostic /* Initialize signal state for process 0. */ 24647543Skarels siginit(p); 24764405Sbostic 24864405Sbostic /* Create process 1 (init(8)). */ 24952504Sbostic if (fork(p, NULL, rval)) 25047543Skarels panic("fork init"); 25147543Skarels if (rval[1]) { 25265076Smckusick start_init(curproc, framep); 25364540Smckusick return; 25416807Skarels } 25547543Skarels 25664405Sbostic /* Create process 2 (the pageout daemon). */ 25752504Sbostic if (fork(p, NULL, rval)) 25847543Skarels panic("fork pager"); 25947543Skarels if (rval[1]) { 26047543Skarels /* 26147543Skarels * Now in process 2. 26247543Skarels */ 26347543Skarels p = curproc; 26447543Skarels pageproc = p; 26564571Sbostic p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ 26647543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 26745724Smckusick vm_pageout(); 26864405Sbostic /* NOTREACHED */ 26926Sbill } 27026Sbill 27164405Sbostic /* The scheduler is an infinite loop. */ 27264405Sbostic scheduler(); 27364405Sbostic /* NOTREACHED */ 27426Sbill } 27564540Smckusick 27664540Smckusick /* 27764540Smckusick * List of paths to try when searching for "init". 27864540Smckusick */ 27964540Smckusick static char *initpaths[] = { 28064540Smckusick "/sbin/init", 28164540Smckusick "/sbin/oinit", 28264540Smckusick "/sbin/init.bak", 28364540Smckusick NULL, 28464540Smckusick }; 28564540Smckusick 28664540Smckusick /* 28764540Smckusick * Start the initial user process; try exec'ing each pathname in "initpaths". 28864540Smckusick * The program is invoked with one argument containing the boot flags. 28964540Smckusick */ 29064540Smckusick static void 29165076Smckusick start_init(p, framep) 29264540Smckusick struct proc *p; 29365076Smckusick void *framep; 29464540Smckusick { 29564540Smckusick vm_offset_t addr; 29668299Scgd struct execve_args /* { 29768299Scgd syscallarg(char *) path; 29868299Scgd syscallarg(char **) argp; 29968299Scgd syscallarg(char **) envp; 30068299Scgd } */ args; 30168299Scgd int options, i, error; 30268299Scgd register_t retval[2]; 303*69138Smckusick char flags[4] = "-", *flagsp; 30464540Smckusick char **pathp, *path, *ucp, **uap, *arg0, *arg1; 30564540Smckusick 30664830Shibler initproc = p; 30764830Shibler 30864540Smckusick /* 30965076Smckusick * We need to set the system call frame as if we were entered through 31065076Smckusick * a syscall() so that when we call execve() below, it will be able 31165076Smckusick * to set the entry point (see setregs) when it tries to exec. The 31265076Smckusick * startup code in "locore.s" has allocated space for the frame and 31365076Smckusick * passed a pointer to that space as main's argument. 31464540Smckusick */ 31565076Smckusick cpu_set_init_frame(p, framep); 31664540Smckusick 31764540Smckusick /* 31864540Smckusick * Need just enough stack to hold the faked-up "execve()" arguments. 31964540Smckusick */ 32064540Smckusick addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 32164540Smckusick if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0) 32264540Smckusick panic("init: couldn't allocate argument space"); 32364540Smckusick p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 32464540Smckusick 32564540Smckusick for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { 32664540Smckusick /* 327*69138Smckusick * Construct the boot flag argument. 32864540Smckusick */ 32964540Smckusick options = 0; 330*69138Smckusick flagsp = flags + 1; 33164540Smckusick ucp = (char *)USRSTACK; 33264540Smckusick if (boothowto & RB_SINGLE) { 333*69138Smckusick *flagsp++ = 's'; 33464540Smckusick options = 1; 33564540Smckusick } 33664540Smckusick #ifdef notyet 33764540Smckusick if (boothowto & RB_FASTBOOT) { 338*69138Smckusick *flagsp++ = 'f'; 33964540Smckusick options = 1; 34064540Smckusick } 34164540Smckusick #endif 342*69138Smckusick /* 343*69138Smckusick * Move out the flags (arg 1), if necessary. 344*69138Smckusick */ 345*69138Smckusick if (options != 0) { 346*69138Smckusick *flagsp++ = '\0'; 347*69138Smckusick i = flagsp - flags; 348*69138Smckusick (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i); 349*69138Smckusick arg1 = ucp; 350*69138Smckusick } 35164540Smckusick 35264540Smckusick /* 35364540Smckusick * Move out the file name (also arg 0). 35464540Smckusick */ 355*69138Smckusick i = strlen(path) + 1; 356*69138Smckusick (void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i); 35764540Smckusick arg0 = ucp; 35864540Smckusick 35964540Smckusick /* 36064540Smckusick * Move out the arg pointers. 36164540Smckusick */ 36268299Scgd uap = (char **)((long)ucp & ~ALIGNBYTES); 36364571Sbostic (void)suword((caddr_t)--uap, 0); /* terminator */ 364*69138Smckusick if (options != 0) 365*69138Smckusick (void)suword((caddr_t)--uap, (long)arg1); 36668299Scgd (void)suword((caddr_t)--uap, (long)arg0); 36764540Smckusick 36864540Smckusick /* 36964540Smckusick * Point at the arguments. 37064540Smckusick */ 37168299Scgd SCARG(&args, path) = arg0; 37268299Scgd SCARG(&args, argp) = uap; 37368299Scgd SCARG(&args, envp) = NULL; 37464540Smckusick 37564540Smckusick /* 37664571Sbostic * Now try to exec the program. If can't for any reason 37764571Sbostic * other than it doesn't exist, complain. 37864540Smckusick */ 37968299Scgd if ((error = execve(p, &args, retval)) == 0) 38064540Smckusick return; 38164571Sbostic if (error != ENOENT) 38264571Sbostic printf("exec %s: error %d\n", path, error); 38364540Smckusick } 38464540Smckusick printf("init: not found\n"); 38564540Smckusick panic("no init"); 38664540Smckusick } 387