123364Smckusick /* 263170Sbostic * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993 363170Sbostic * The Regents of the University of California. All rights reserved. 4*65771Sbostic * (c) UNIX System Laboratories, Inc. 5*65771Sbostic * All or some portions of this file are derived from material licensed 6*65771Sbostic * to the University of California by American Telephone and Telegraph 7*65771Sbostic * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8*65771Sbostic * the permission of UNIX System Laboratories, Inc. 923364Smckusick * 1047817Skarels * %sccs.include.redist.c% 1147817Skarels * 12*65771Sbostic * @(#)init_main.c 8.9 (Berkeley) 01/21/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 /* 10765114Smckusick * Create process 0 (the swapper). 10865114Smckusick */ 10954781Storek allproc = (volatile struct proc *)p; 11054781Storek p->p_prev = (struct proc **)&allproc; 11147543Skarels p->p_pgrp = &pgrp0; 11247543Skarels pgrphash[0] = &pgrp0; 11347543Skarels pgrp0.pg_mem = p; 11447543Skarels pgrp0.pg_session = &session0; 11547543Skarels session0.s_count = 1; 11647543Skarels session0.s_leader = p; 11747543Skarels 11864571Sbostic p->p_flag = P_INMEM | P_SYSTEM; 1192451Swnj p->p_stat = SRUN; 1202451Swnj p->p_nice = NZERO; 12147543Skarels bcopy("swapper", p->p_comm, sizeof ("swapper")); 12247543Skarels 12364405Sbostic /* Create credentials. */ 12449745Smckusick cred0.p_refcnt = 1; 12547543Skarels p->p_cred = &cred0; 12647543Skarels p->p_ucred = crget(); 12747543Skarels p->p_ucred->cr_ngroups = 1; /* group 0 */ 12829946Skarels 12964405Sbostic /* Create the file descriptor table. */ 13047543Skarels fdp = &filedesc0; 13147654Skarels p->p_fd = &fdp->fd_fd; 13247654Skarels fdp->fd_fd.fd_refcnt = 1; 13347654Skarels fdp->fd_fd.fd_cmask = cmask; 13447654Skarels fdp->fd_fd.fd_ofiles = fdp->fd_dfiles; 13547654Skarels fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags; 13647654Skarels fdp->fd_fd.fd_nfiles = NDFILE; 13747543Skarels 13864405Sbostic /* Create the limits structures. */ 13947543Skarels p->p_limit = &limit0; 14047543Skarels for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++) 14147543Skarels limit0.pl_rlimit[i].rlim_cur = 14247543Skarels limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY; 14356935Smckusick limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE; 14447543Skarels limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC; 14559488Smckusick i = ptoa(cnt.v_free_count); 14659488Smckusick limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i; 14759488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i; 14859488Smckusick limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3; 14947543Skarels limit0.p_refcnt = 1; 15047543Skarels 15164405Sbostic /* Allocate a prototype map so we have something to fork. */ 15247543Skarels p->p_vmspace = &vmspace0; 15347543Skarels vmspace0.vm_refcnt = 1; 15447543Skarels pmap_pinit(&vmspace0.vm_pmap); 15547543Skarels vm_map_init(&p->p_vmspace->vm_map, round_page(VM_MIN_ADDRESS), 15647543Skarels trunc_page(VM_MAX_ADDRESS), TRUE); 15747543Skarels vmspace0.vm_map.pmap = &vmspace0.vm_pmap; 15847543Skarels p->p_addr = proc0paddr; /* XXX */ 15947543Skarels 16047543Skarels /* 16164405Sbostic * We continue to place resource usage info and signal 16264405Sbostic * actions in the user struct so they're pageable. 16347543Skarels */ 16448981Skarels p->p_stats = &p->p_addr->u_stats; 16548981Skarels p->p_sigacts = &p->p_addr->u_sigacts; 16647543Skarels 16755406Smckusick /* 16855406Smckusick * Initialize per uid information structure and charge 16955406Smckusick * root for one process. 17055406Smckusick */ 17155406Smckusick usrinfoinit(); 17255406Smckusick (void)chgproccnt(0, 1); 17355406Smckusick 17447543Skarels rqinit(); 17547543Skarels 17659118Storek /* Configure virtual memory system, set vm rlimits. */ 17747543Skarels vm_init_limits(p); 17823534Skarels 17959118Storek /* Initialize the file systems. */ 18039431Smckusick vfsinit(); 18137610Smckusick 18259118Storek /* Start real time and statistics clocks. */ 18354781Storek initclocks(); 18426Sbill 18564405Sbostic /* Initialize mbuf's. */ 1864821Swnj mbinit(); 18764405Sbostic 18864405Sbostic /* Initialize clists. */ 18964405Sbostic clist_init(); 19064405Sbostic 19141565Smckusick #ifdef SYSVSHM 19264405Sbostic /* Initialize System V style shared memory. */ 19341565Smckusick shminit(); 19441565Smckusick #endif 19559118Storek 19659118Storek /* Attach pseudo-devices. */ 19759118Storek for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++) 19859118Storek (*pdev->pdev_attach)(pdev->pdev_count); 19959118Storek 2009156Ssam /* 20159118Storek * Initialize protocols. Block reception of incoming packets 20259118Storek * until everything is ready. 2039156Ssam */ 2049156Ssam s = splimp(); 2055227Swnj ifinit(); 2068969Sroot domaininit(); 2079156Ssam splx(s); 20847543Skarels 2097419Sroot #ifdef GPROF 21064405Sbostic /* Initialize kernel profiling. */ 2117419Sroot kmstartup(); 2127419Sroot #endif 2137189Sroot 21464405Sbostic /* Kick off timeout driven events by calling first time. */ 21554781Storek roundrobin(NULL); 21654781Storek schedcpu(NULL); 2178096Sroot 21864405Sbostic /* Mount the root file system. */ 21937610Smckusick if ((*mountroot)()) 22037610Smckusick panic("cannot mount root"); 22164405Sbostic 22264405Sbostic /* Get the vnode for '/'. Set fdp->fd_fd.fd_cdir to reference it. */ 22365255Smckusick if (VFS_ROOT(mountlist.tqh_first, &rootvnode)) 22437610Smckusick panic("cannot find root vnode"); 22564405Sbostic fdp->fd_fd.fd_cdir = rootvnode; 22647654Skarels VREF(fdp->fd_fd.fd_cdir); 22764405Sbostic VOP_UNLOCK(rootvnode); 22847654Skarels fdp->fd_fd.fd_rdir = NULL; 22947543Skarels swapinit(); 23026Sbill 23126Sbill /* 23255796Smckusick * Now can look at time, having had a chance to verify the time 23355796Smckusick * from the file system. Reset p->p_rtime as it may have been 23464571Sbostic * munched in mi_switch() after the time got set. 23547543Skarels */ 23654943Storek p->p_stats->p_start = runtime = mono_time = boottime = time; 23755796Smckusick p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0; 23847543Skarels 23964405Sbostic /* Initialize signal state for process 0. */ 24047543Skarels siginit(p); 24164405Sbostic 24264405Sbostic /* Create process 1 (init(8)). */ 24352504Sbostic if (fork(p, NULL, rval)) 24447543Skarels panic("fork init"); 24547543Skarels if (rval[1]) { 24665076Smckusick start_init(curproc, framep); 24764540Smckusick return; 24816807Skarels } 24947543Skarels 25064405Sbostic /* Create process 2 (the pageout daemon). */ 25152504Sbostic if (fork(p, NULL, rval)) 25247543Skarels panic("fork pager"); 25347543Skarels if (rval[1]) { 25447543Skarels /* 25547543Skarels * Now in process 2. 25647543Skarels */ 25747543Skarels p = curproc; 25847543Skarels pageproc = p; 25964571Sbostic p->p_flag |= P_INMEM | P_SYSTEM; /* XXX */ 26047543Skarels bcopy("pagedaemon", curproc->p_comm, sizeof ("pagedaemon")); 26145724Smckusick vm_pageout(); 26264405Sbostic /* NOTREACHED */ 26326Sbill } 26426Sbill 26564405Sbostic /* The scheduler is an infinite loop. */ 26664405Sbostic scheduler(); 26764405Sbostic /* NOTREACHED */ 26826Sbill } 26964540Smckusick 27064540Smckusick /* 27164540Smckusick * List of paths to try when searching for "init". 27264540Smckusick */ 27364540Smckusick static char *initpaths[] = { 27464540Smckusick "/sbin/init", 27564540Smckusick "/sbin/oinit", 27664540Smckusick "/sbin/init.bak", 27764540Smckusick NULL, 27864540Smckusick }; 27964540Smckusick 28064540Smckusick /* 28164540Smckusick * Start the initial user process; try exec'ing each pathname in "initpaths". 28264540Smckusick * The program is invoked with one argument containing the boot flags. 28364540Smckusick */ 28464540Smckusick static void 28565076Smckusick start_init(p, framep) 28664540Smckusick struct proc *p; 28765076Smckusick void *framep; 28864540Smckusick { 28964540Smckusick vm_offset_t addr; 29064540Smckusick struct execve_args args; 29164540Smckusick int options, i, retval[2], error; 29264540Smckusick char **pathp, *path, *ucp, **uap, *arg0, *arg1; 29364540Smckusick 29464830Shibler initproc = p; 29564830Shibler 29664540Smckusick /* 29765076Smckusick * We need to set the system call frame as if we were entered through 29865076Smckusick * a syscall() so that when we call execve() below, it will be able 29965076Smckusick * to set the entry point (see setregs) when it tries to exec. The 30065076Smckusick * startup code in "locore.s" has allocated space for the frame and 30165076Smckusick * passed a pointer to that space as main's argument. 30264540Smckusick */ 30365076Smckusick cpu_set_init_frame(p, framep); 30464540Smckusick 30564540Smckusick /* 30664540Smckusick * Need just enough stack to hold the faked-up "execve()" arguments. 30764540Smckusick */ 30864540Smckusick addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 30964540Smckusick if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0) 31064540Smckusick panic("init: couldn't allocate argument space"); 31164540Smckusick p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 31264540Smckusick 31364540Smckusick for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { 31464540Smckusick /* 31564540Smckusick * Move out the boot flag argument. 31664540Smckusick */ 31764540Smckusick options = 0; 31864540Smckusick ucp = (char *)USRSTACK; 31964571Sbostic (void)subyte(--ucp, 0); /* trailing zero */ 32064540Smckusick if (boothowto & RB_SINGLE) { 32164571Sbostic (void)subyte(--ucp, 's'); 32264540Smckusick options = 1; 32364540Smckusick } 32464540Smckusick #ifdef notyet 32564540Smckusick if (boothowto & RB_FASTBOOT) { 32664571Sbostic (void)subyte(--ucp, 'f'); 32764540Smckusick options = 1; 32864540Smckusick } 32964540Smckusick #endif 33064540Smckusick if (options == 0) 33164571Sbostic (void)subyte(--ucp, '-'); 33264571Sbostic (void)subyte(--ucp, '-'); /* leading hyphen */ 33364540Smckusick arg1 = ucp; 33464540Smckusick 33564540Smckusick /* 33664540Smckusick * Move out the file name (also arg 0). 33764540Smckusick */ 33864540Smckusick for (i = strlen(path) + 1; i >= 0; i--) 33964571Sbostic (void)subyte(--ucp, path[i]); 34064540Smckusick arg0 = ucp; 34164540Smckusick 34264540Smckusick /* 34364540Smckusick * Move out the arg pointers. 34464540Smckusick */ 34564540Smckusick uap = (char **)((int)ucp & ~(NBPW-1)); 34664571Sbostic (void)suword((caddr_t)--uap, 0); /* terminator */ 34764571Sbostic (void)suword((caddr_t)--uap, (int)arg1); 34864571Sbostic (void)suword((caddr_t)--uap, (int)arg0); 34964540Smckusick 35064540Smckusick /* 35164540Smckusick * Point at the arguments. 35264540Smckusick */ 35364540Smckusick args.fname = arg0; 35464540Smckusick args.argp = uap; 35564540Smckusick args.envp = NULL; 35664540Smckusick 35764540Smckusick /* 35864571Sbostic * Now try to exec the program. If can't for any reason 35964571Sbostic * other than it doesn't exist, complain. 36064540Smckusick */ 36164540Smckusick if ((error = execve(p, &args, &retval)) == 0) 36264540Smckusick return; 36364571Sbostic if (error != ENOENT) 36464571Sbostic printf("exec %s: error %d\n", path, error); 36564540Smckusick } 36664540Smckusick printf("init: not found\n"); 36764540Smckusick panic("no init"); 36864540Smckusick } 369