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*69376Smckusick * @(#)init_main.c 8.15 (Berkeley) 05/10/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]; 8659118Storek extern struct pdevinit pdevinit[]; 8754781Storek extern void roundrobin __P((void *)); 8854781Storek extern void schedcpu __P((void *)); 8926Sbill 9045880Swilliam /* 9164405Sbostic * Initialize the current process pointer (curproc) before 9264405Sbostic * any possible traps/probes to simplify trap processing. 9345880Swilliam */ 9447543Skarels p = &proc0; 9547543Skarels curproc = p; 9645724Smckusick /* 9747543Skarels * Attempt to find console and initialize 9847543Skarels * in case of early panic or other messages. 9945724Smckusick */ 10047543Skarels consinit(); 10149382Skarels printf(copyright); 10247543Skarels 10345724Smckusick vm_mem_init(); 10445724Smckusick kmeminit(); 10549533Skarels cpu_startup(); 10626Sbill 10765114Smckusick /* 10867732Smckusick * Initialize process and pgrp structures. 10967732Smckusick */ 11067732Smckusick procinit(); 11167732Smckusick 11267732Smckusick /* 11365114Smckusick * Create process 0 (the swapper). 11465114Smckusick */ 11567732Smckusick LIST_INSERT_HEAD(&allproc, p, p_list); 11647543Skarels p->p_pgrp = &pgrp0; 11767732Smckusick LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 11867732Smckusick LIST_INIT(&pgrp0.pg_members); 11967732Smckusick LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 12067732Smckusick 12147543Skarels pgrp0.pg_session = &session0; 12247543Skarels session0.s_count = 1; 12347543Skarels session0.s_leader = p; 12447543Skarels 12564571Sbostic p->p_flag = P_INMEM | P_SYSTEM; 1262451Swnj p->p_stat = SRUN; 1272451Swnj p->p_nice = NZERO; 12847543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 12947543Skarels 13064405Sbostic /* Create credentials. */ 13149745Smckusick cred0.p_refcnt = 1; 13247543Skarels p->p_cred = &cred0; 13347543Skarels p->p_ucred = crget(); 13447543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 13529946Skarels 13664405Sbostic /* Create the file descriptor table. */ 13747543Skarels fdp = &filedesc0; 13847654Skarels p->p_fd = &fdp->fd_fd; 13947654Skarels fdp->fd_fd.fd_refcnt = 1; 14047654Skarels fdp->fd_fd.fd_cmask = cmask; 14147654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 14247654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 14347654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 14447543Skarels 14564405Sbostic /* Create the limits structures. */ 14647543Skarels p->p_limit = &limit0; 14747543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 14847543Skarels limit0.pl_rlimit[i].rlim_cur = 14947543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 15056935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 15147543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 15259488Smckusick i = ptoa(cnt.v_free_count); 15359488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 15459488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 15559488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 15647543Skarels limit0.p_refcnt = 1; 15747543Skarels 15864405Sbostic /* Allocate a prototype map so we have something to fork. */ 15947543Skarels p->p_vmspace = &vmspace0; 16047543Skarels vmspace0.vm_refcnt = 1; 16147543Skarels pmap_pinit(&vmspace0.vm_pmap); 16247543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 16347543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 16447543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 16547543Skarels p->p_addr = proc0paddr; /* XXX */ 16647543Skarels 16747543Skarels /* 16864405Sbostic * We continue to place resource usage info and signal 16964405Sbostic * actions in the user struct so they're pageable. 17047543Skarels */ 17148981Skarels p->p_stats = &p->p_addr->u_stats; 17248981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 17347543Skarels 17455406Smckusick /* 17567732Smckusick * Charge root for one process. 17655406Smckusick */ 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 19064405Sbostic /* Initialize mbuf's. */ 1914821Swnj mbinit(); 19264405Sbostic 19364405Sbostic /* Initialize clists. */ 19464405Sbostic clist_init(); 19564405Sbostic 19641565Smckusick #ifdef SYSVSHM 19764405Sbostic /* Initialize System V style shared memory. */ 19841565Smckusick shminit(); 19941565Smckusick #endif 20059118Storek 20159118Storek /* Attach pseudo-devices. */ 20259118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 20359118Storek (*pdev->pdev_attach)(pdev->pdev_count); 20459118Storek 2059156Ssam /* 20659118Storek * Initialize protocols. Block reception of incoming packets 20759118Storek * until everything is ready. 2089156Ssam */ 2099156Ssam s = splimp(); 2105227Swnj ifinit(); 2118969Sroot domaininit(); 2129156Ssam splx(s); 21347543Skarels 2147419Sroot #ifdef GPROF 21564405Sbostic /* Initialize kernel profiling. */ 2167419Sroot kmstartup(); 2177419Sroot #endif 2187189Sroot 21964405Sbostic /* Kick off timeout driven events by calling first time. */ 22054781Storek roundrobin(NULL); 22154781Storek schedcpu(NULL); 2228096Sroot 22364405Sbostic /* Mount the root file system. */ 224*69376Smckusick if (vfs_mountroot()) 22537610Smckusick panic("cannot mount root"); 22669348Smckusick mountlist.cqh_first->mnt_flag |= MNT_ROOTFS; 22764405Sbostic 22864405Sbostic /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 22969325Smckusick if (VFS_ROOT(mountlist.cqh_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]; 30369138Smckusick 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 /* 32769138Smckusick * Construct the boot flag argument. 32864540Smckusick */ 32964540Smckusick options = 0; 33069138Smckusick flagsp = flags + 1; 33164540Smckusick ucp = (char *)USRSTACK; 33264540Smckusick if (boothowto & RB_SINGLE) { 33369138Smckusick *flagsp++ = 's'; 33464540Smckusick options = 1; 33564540Smckusick } 33664540Smckusick #ifdef notyet 33764540Smckusick if (boothowto & RB_FASTBOOT) { 33869138Smckusick *flagsp++ = 'f'; 33964540Smckusick options = 1; 34064540Smckusick } 34164540Smckusick #endif 34269138Smckusick /* 34369138Smckusick * Move out the flags (arg 1), if necessary. 34469138Smckusick */ 34569138Smckusick if (options != 0) { 34669138Smckusick *flagsp++ = '\0'; 34769138Smckusick i = flagsp - flags; 34869138Smckusick (void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i); 34969138Smckusick arg1 = ucp; 35069138Smckusick } 35164540Smckusick 35264540Smckusick /* 35364540Smckusick * Move out the file name (also arg 0). 35464540Smckusick */ 35569138Smckusick i = strlen(path) + 1; 35669138Smckusick (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 */ 36469138Smckusick if (options != 0) 36569138Smckusick (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