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*67732Smckusick * @(#)init_main.c 8.10 (Berkeley) 08/22/94 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> 3447654Skarels 3556934Smckusick #include <ufs/ufs/quota.h> 3626Sbill 3756934Smckusick #include <machine/cpu.h> 3837522Smckusick 3956934Smckusick #include <vm/vm.h> 4045724Smckusick 4155399Smckusick #ifdef HPFPLIB 4249382Skarels char copyright[] = 4360928Smckusick "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"; 4455399Smckusick #else 4555399Smckusick char copyright[] = 4660928Smckusick "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n"; 4755399Smckusick #endif 4849382Skarels 4964405Sbostic /* Components of the first process -- never freed. */ 5047543Skarels struct session session0; 5147543Skarels struct pgrp pgrp0; 5247543Skarels struct proc proc0; 5347543Skarels struct pcred cred0; 5447654Skarels struct filedesc0 filedesc0; 5547543Skarels struct plimit limit0; 5647543Skarels struct vmspace vmspace0; 5747654Skarels struct proc *curproc = &proc0; 5847543Skarels struct proc *initproc, *pageproc; 5947543Skarels 6016807Skarels int cmask = CMASK; 6148981Skarels extern struct user *proc0paddr; 6245880Swilliam 6349382Skarels struct vnode *rootvp, *swapdev_vp; 6449382Skarels int boothowto; 6553009Ssklower struct timeval boottime; 6654781Storek struct timeval runtime; 6749382Skarels 6865076Smckusick static void start_init __P((struct proc *p, void *framep)); 6964540Smckusick 7026Sbill /* 7164405Sbostic * System startup; initialize the world, create process 0, mount root 7264405Sbostic * filesystem, and fork to create init and pagedaemon. Most of the 7364405Sbostic * hard work is done in the lower-level initialization routines including 7464405Sbostic * startup(), which does memory initialization and autoconfiguration. 7526Sbill */ 7665076Smckusick main(framep) 7765076Smckusick void *framep; 7826Sbill { 792451Swnj register struct proc *p; 8047654Skarels register struct filedesc0 *fdp; 8159118Storek register struct pdevinit *pdev; 8264405Sbostic register int i; 8347543Skarels int s, rval[2]; 8464405Sbostic extern int (*mountroot) __P((void)); 8559118Storek extern struct pdevinit pdevinit[]; 8654781Storek extern void roundrobin __P((void *)); 8754781Storek extern void schedcpu __P((void *)); 8826Sbill 8945880Swilliam /* 9064405Sbostic * Initialize the current process pointer (curproc) before 9164405Sbostic * any possible traps/probes to simplify trap processing. 9245880Swilliam */ 9347543Skarels p = &proc0; 9447543Skarels curproc = p; 9545724Smckusick /* 9647543Skarels * Attempt to find console and initialize 9747543Skarels * in case of early panic or other messages. 9845724Smckusick */ 9947543Skarels consinit(); 10049382Skarels printf(copyright); 10147543Skarels 10245724Smckusick vm_mem_init(); 10345724Smckusick kmeminit(); 10449533Skarels cpu_startup(); 10526Sbill 10665114Smckusick /* 107*67732Smckusick * Initialize process and pgrp structures. 108*67732Smckusick */ 109*67732Smckusick procinit(); 110*67732Smckusick 111*67732Smckusick /* 11265114Smckusick * Create process 0 (the swapper). 11365114Smckusick */ 114*67732Smckusick LIST_INSERT_HEAD(&allproc, p, p_list); 11547543Skarels p->p_pgrp = &pgrp0; 116*67732Smckusick LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash); 117*67732Smckusick LIST_INIT(&pgrp0.pg_members); 118*67732Smckusick LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist); 119*67732Smckusick 12047543Skarels pgrp0.pg_session = &session0; 12147543Skarels session0.s_count = 1; 12247543Skarels session0.s_leader = p; 12347543Skarels 12464571Sbostic p->p_flag = P_INMEM | P_SYSTEM; 1252451Swnj p->p_stat = SRUN; 1262451Swnj p->p_nice = NZERO; 12747543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 12847543Skarels 12964405Sbostic /* Create credentials. */ 13049745Smckusick cred0.p_refcnt = 1; 13147543Skarels p->p_cred = &cred0; 13247543Skarels p->p_ucred = crget(); 13347543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 13429946Skarels 13564405Sbostic /* Create the file descriptor table. */ 13647543Skarels fdp = &filedesc0; 13747654Skarels p->p_fd = &fdp->fd_fd; 13847654Skarels fdp->fd_fd.fd_refcnt = 1; 13947654Skarels fdp->fd_fd.fd_cmask = cmask; 14047654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 14147654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 14247654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 14347543Skarels 14464405Sbostic /* Create the limits structures. */ 14547543Skarels p->p_limit = &limit0; 14647543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 14747543Skarels limit0.pl_rlimit[i].rlim_cur = 14847543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 14956935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 15047543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 15159488Smckusick i = ptoa(cnt.v_free_count); 15259488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 15359488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 15459488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 15547543Skarels limit0.p_refcnt = 1; 15647543Skarels 15764405Sbostic /* Allocate a prototype map so we have something to fork. */ 15847543Skarels p->p_vmspace = &vmspace0; 15947543Skarels vmspace0.vm_refcnt = 1; 16047543Skarels pmap_pinit(&vmspace0.vm_pmap); 16147543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 16247543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 16347543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 16447543Skarels p->p_addr = proc0paddr; /* XXX */ 16547543Skarels 16647543Skarels /* 16764405Sbostic * We continue to place resource usage info and signal 16864405Sbostic * actions in the user struct so they're pageable. 16947543Skarels */ 17048981Skarels p->p_stats = &p->p_addr->u_stats; 17148981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 17247543Skarels 17355406Smckusick /* 174*67732Smckusick * Charge root for one process. 17555406Smckusick */ 17655406Smckusick (void)chgproccnt(0, 1); 17755406Smckusick 17847543Skarels rqinit(); 17947543Skarels 18059118Storek /* Configure virtual memory system, set vm rlimits. */ 18147543Skarels vm_init_limits(p); 18223534Skarels 18359118Storek /* Initialize the file systems. */ 18439431Smckusick vfsinit(); 18537610Smckusick 18659118Storek /* Start real time and statistics clocks. */ 18754781Storek initclocks(); 18826Sbill 18964405Sbostic /* Initialize mbuf's. */ 1904821Swnj mbinit(); 19164405Sbostic 19264405Sbostic /* Initialize clists. */ 19364405Sbostic clist_init(); 19464405Sbostic 19541565Smckusick #ifdef SYSVSHM 19664405Sbostic /* Initialize System V style shared memory. */ 19741565Smckusick shminit(); 19841565Smckusick #endif 19959118Storek 20059118Storek /* Attach pseudo-devices. */ 20159118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 20259118Storek (*pdev->pdev_attach)(pdev->pdev_count); 20359118Storek 2049156Ssam /* 20559118Storek * Initialize protocols. Block reception of incoming packets 20659118Storek * until everything is ready. 2079156Ssam */ 2089156Ssam s = splimp(); 2095227Swnj ifinit(); 2108969Sroot domaininit(); 2119156Ssam splx(s); 21247543Skarels 2137419Sroot #ifdef GPROF 21464405Sbostic /* Initialize kernel profiling. */ 2157419Sroot kmstartup(); 2167419Sroot #endif 2177189Sroot 21864405Sbostic /* Kick off timeout driven events by calling first time. */ 21954781Storek roundrobin(NULL); 22054781Storek schedcpu(NULL); 2218096Sroot 22264405Sbostic /* Mount the root file system. */ 22337610Smckusick if ((*mountroot)()) 22437610Smckusick panic("cannot mount root"); 22564405Sbostic 22664405Sbostic /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 22765255Smckusick if (VFS_ROOT(mountlist.tqh_first, &rootvnode)) 22837610Smckusick panic("cannot find root vnode"); 22964405Sbostic fdp->fd_fd.fd_cdir = rootvnode; 23047654Skarels VREF(fdp->fd_fd.fd_cdir); 23164405Sbostic VOP_UNLOCK(rootvnode); 23247654Skarels fdp->fd_fd.fd_rdir = NULL; 23347543Skarels swapinit(); 23426Sbill 23526Sbill /* 23655796Smckusick * Now can look at time, having had a chance to verify the time 23755796Smckusick * from the file system. Reset p->p_rtime as it may have been 23864571Sbostic * munched in mi_switch() after the time got set. 23947543Skarels */ 24054943Storek p->p_stats->p_start = runtime = mono_time = boottime = time; 24155796Smckusick p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 24247543Skarels 24364405Sbostic /* Initialize signal state for process 0. */ 24447543Skarels siginit(p); 24564405Sbostic 24664405Sbostic /* Create process 1 (init(8)). */ 24752504Sbostic if (fork(p, NULL, rval)) 24847543Skarels panic("fork init"); 24947543Skarels if (rval[1]) { 25065076Smckusick start_init(curproc, framep); 25164540Smckusick return; 25216807Skarels } 25347543Skarels 25464405Sbostic /* Create process 2 (the pageout daemon). */ 25552504Sbostic if (fork(p, NULL, rval)) 25647543Skarels panic("fork pager"); 25747543Skarels if (rval[1]) { 25847543Skarels /* 25947543Skarels * Now in process 2. 26047543Skarels */ 26147543Skarels p = curproc; 26247543Skarels pageproc = p; 26364571Sbostic p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ 26447543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 26545724Smckusick vm_pageout(); 26664405Sbostic /* NOTREACHED */ 26726Sbill } 26826Sbill 26964405Sbostic /* The scheduler is an infinite loop. */ 27064405Sbostic scheduler(); 27164405Sbostic /* NOTREACHED */ 27226Sbill } 27364540Smckusick 27464540Smckusick /* 27564540Smckusick * List of paths to try when searching for "init". 27664540Smckusick */ 27764540Smckusick static char *initpaths[] = { 27864540Smckusick "/sbin/init", 27964540Smckusick "/sbin/oinit", 28064540Smckusick "/sbin/init.bak", 28164540Smckusick NULL, 28264540Smckusick }; 28364540Smckusick 28464540Smckusick /* 28564540Smckusick * Start the initial user process; try exec'ing each pathname in "initpaths". 28664540Smckusick * The program is invoked with one argument containing the boot flags. 28764540Smckusick */ 28864540Smckusick static void 28965076Smckusick start_init(p, framep) 29064540Smckusick struct proc *p; 29165076Smckusick void *framep; 29264540Smckusick { 29364540Smckusick vm_offset_t addr; 29464540Smckusick struct execve_args args; 29564540Smckusick int options, i, retval[2], error; 29664540Smckusick char **pathp, *path, *ucp, **uap, *arg0, *arg1; 29764540Smckusick 29864830Shibler initproc = p; 29964830Shibler 30064540Smckusick /* 30165076Smckusick * We need to set the system call frame as if we were entered through 30265076Smckusick * a syscall() so that when we call execve() below, it will be able 30365076Smckusick * to set the entry point (see setregs) when it tries to exec. The 30465076Smckusick * startup code in "locore.s" has allocated space for the frame and 30565076Smckusick * passed a pointer to that space as main's argument. 30664540Smckusick */ 30765076Smckusick cpu_set_init_frame(p, framep); 30864540Smckusick 30964540Smckusick /* 31064540Smckusick * Need just enough stack to hold the faked-up "execve()" arguments. 31164540Smckusick */ 31264540Smckusick addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 31364540Smckusick if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0) 31464540Smckusick panic("init: couldn't allocate argument space"); 31564540Smckusick p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 31664540Smckusick 31764540Smckusick for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { 31864540Smckusick /* 31964540Smckusick * Move out the boot flag argument. 32064540Smckusick */ 32164540Smckusick options = 0; 32264540Smckusick ucp = (char *)USRSTACK; 32364571Sbostic (void)subyte(--ucp, 0); /* trailing zero */ 32464540Smckusick if (boothowto & RB_SINGLE) { 32564571Sbostic (void)subyte(--ucp, 's'); 32664540Smckusick options = 1; 32764540Smckusick } 32864540Smckusick #ifdef notyet 32964540Smckusick if (boothowto & RB_FASTBOOT) { 33064571Sbostic (void)subyte(--ucp, 'f'); 33164540Smckusick options = 1; 33264540Smckusick } 33364540Smckusick #endif 33464540Smckusick if (options == 0) 33564571Sbostic (void)subyte(--ucp, '-'); 33664571Sbostic (void)subyte(--ucp, '-'); /* leading hyphen */ 33764540Smckusick arg1 = ucp; 33864540Smckusick 33964540Smckusick /* 34064540Smckusick * Move out the file name (also arg 0). 34164540Smckusick */ 34264540Smckusick for (i = strlen(path) + 1; i >= 0; i--) 34364571Sbostic (void)subyte(--ucp, path[i]); 34464540Smckusick arg0 = ucp; 34564540Smckusick 34664540Smckusick /* 34764540Smckusick * Move out the arg pointers. 34864540Smckusick */ 34964540Smckusick uap = (char **)((int)ucp & ~(NBPW-1)); 35064571Sbostic (void)suword((caddr_t)--uap, 0); /* terminator */ 35164571Sbostic (void)suword((caddr_t)--uap, (int)arg1); 35264571Sbostic (void)suword((caddr_t)--uap, (int)arg0); 35364540Smckusick 35464540Smckusick /* 35564540Smckusick * Point at the arguments. 35664540Smckusick */ 35764540Smckusick args.fname = arg0; 35864540Smckusick args.argp = uap; 35964540Smckusick args.envp = NULL; 36064540Smckusick 36164540Smckusick /* 36264571Sbostic * Now try to exec the program. If can't for any reason 36364571Sbostic * other than it doesn't exist, complain. 36464540Smckusick */ 36564540Smckusick if ((error = execve(p, &args, &retval)) == 0) 36664540Smckusick return; 36764571Sbostic if (error != ENOENT) 36864571Sbostic printf("exec %s: error %d\n", path, error); 36964540Smckusick } 37064540Smckusick printf("init: not found\n"); 37164540Smckusick panic("no init"); 37264540Smckusick } 373