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*64540Smckusick * @(#)init_main.c 8.3 (Berkeley) 09/21/93 823364Smckusick */ 926Sbill 1056934Smckusick #include <sys/param.h> 1156934Smckusick #include <sys/filedesc.h> 12*64540Smckusick #include <sys/errno.h> 13*64540Smckusick #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 63*64540Smckusick static void start_init __P((struct proc *p, int *regs)); 64*64540Smckusick 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 */ 71*64540Smckusick main(regs) 72*64540Smckusick 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 11447543Skarels p->p_flag = SLOAD|SSYS; 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 23055796Smckusick * munched in swtch() 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]) { 242*64540Smckusick start_init(curproc, regs); 243*64540Smckusick 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; 25547543Skarels p->p_flag |= SLOAD|SSYS; /* 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 } 265*64540Smckusick 266*64540Smckusick /* 267*64540Smckusick * List of paths to try when searching for "init". 268*64540Smckusick */ 269*64540Smckusick static char *initpaths[] = { 270*64540Smckusick "/sbin/init", 271*64540Smckusick "/sbin/oinit", 272*64540Smckusick "/sbin/init.bak", 273*64540Smckusick NULL, 274*64540Smckusick }; 275*64540Smckusick 276*64540Smckusick /* 277*64540Smckusick * Start the initial user process; try exec'ing each pathname in "initpaths". 278*64540Smckusick * The program is invoked with one argument containing the boot flags. 279*64540Smckusick */ 280*64540Smckusick static void 281*64540Smckusick start_init(p, regs) 282*64540Smckusick struct proc *p; 283*64540Smckusick int *regs; 284*64540Smckusick { 285*64540Smckusick vm_offset_t addr; 286*64540Smckusick struct execve_args args; 287*64540Smckusick int options, i, retval[2], error; 288*64540Smckusick char **pathp, *path, *ucp, **uap, *arg0, *arg1; 289*64540Smckusick 290*64540Smckusick /* 291*64540Smckusick * We need to set p->p_md.md_regs since start_init acts like a 292*64540Smckusick * system call and references the regs to set the entry point 293*64540Smckusick * (see setregs) when it tries to exec. On regular fork, the 294*64540Smckusick * p->p_md.md_regs of the child is undefined since it is set on 295*64540Smckusick * each system call. The startup code in "locore.s" has arranged 296*64540Smckusick * that there be some place to set "p->p_md.md_regs" to, and 297*64540Smckusick * passed a pointer to that place as main's argument. 298*64540Smckusick */ 299*64540Smckusick p->p_md.md_regs = regs; 300*64540Smckusick 301*64540Smckusick /* 302*64540Smckusick * Need just enough stack to hold the faked-up "execve()" arguments. 303*64540Smckusick */ 304*64540Smckusick addr = trunc_page(VM_MAX_ADDRESS - PAGE_SIZE); 305*64540Smckusick if (vm_allocate(&p->p_vmspace->vm_map, &addr, PAGE_SIZE, FALSE) != 0) 306*64540Smckusick panic("init: couldn't allocate argument space"); 307*64540Smckusick p->p_vmspace->vm_maxsaddr = (caddr_t)addr; 308*64540Smckusick 309*64540Smckusick for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) { 310*64540Smckusick /* 311*64540Smckusick * Move out the boot flag argument. 312*64540Smckusick */ 313*64540Smckusick options = 0; 314*64540Smckusick ucp = (char *)USRSTACK; 315*64540Smckusick (void) subyte(--ucp, 0); /* trailing zero */ 316*64540Smckusick if (boothowto & RB_SINGLE) { 317*64540Smckusick (void) subyte(--ucp, 's'); 318*64540Smckusick options = 1; 319*64540Smckusick } 320*64540Smckusick #ifdef notyet 321*64540Smckusick if (boothowto & RB_FASTBOOT) { 322*64540Smckusick (void) subyte(--ucp, 'f'); 323*64540Smckusick options = 1; 324*64540Smckusick } 325*64540Smckusick #endif 326*64540Smckusick if (options == 0) 327*64540Smckusick (void) subyte(--ucp, '-'); 328*64540Smckusick (void) subyte(--ucp, '-'); /* leading hyphen */ 329*64540Smckusick arg1 = ucp; 330*64540Smckusick 331*64540Smckusick /* 332*64540Smckusick * Move out the file name (also arg 0). 333*64540Smckusick */ 334*64540Smckusick for (i = strlen(path) + 1; i >= 0; i--) 335*64540Smckusick (void) subyte(--ucp, path[i]); 336*64540Smckusick arg0 = ucp; 337*64540Smckusick 338*64540Smckusick /* 339*64540Smckusick * Move out the arg pointers. 340*64540Smckusick */ 341*64540Smckusick uap = (char **)((int)ucp & ~(NBPW-1)); 342*64540Smckusick (void) suword((caddr_t)--uap, 0); /* terminator */ 343*64540Smckusick (void) suword((caddr_t)--uap, (int)arg1); 344*64540Smckusick (void) suword((caddr_t)--uap, (int)arg0); 345*64540Smckusick 346*64540Smckusick /* 347*64540Smckusick * Point at the arguments. 348*64540Smckusick */ 349*64540Smckusick args.fname = arg0; 350*64540Smckusick args.argp = uap; 351*64540Smckusick args.envp = NULL; 352*64540Smckusick 353*64540Smckusick /* 354*64540Smckusick * Now try to exec the program. 355*64540Smckusick */ 356*64540Smckusick if ((error = execve(p, &args, &retval)) == 0) 357*64540Smckusick return; 358*64540Smckusick if (error != ENOENT) { 359*64540Smckusick /* 360*64540Smckusick * Found "init", but couldn't execute it. 361*64540Smckusick * Complain now. 362*64540Smckusick */ 363*64540Smckusick printf("Can't invoke %s: error %d\n", path, error); 364*64540Smckusick panic("init error"); 365*64540Smckusick } 366*64540Smckusick } 367*64540Smckusick printf("init: not found\n"); 368*64540Smckusick panic("no init"); 369*64540Smckusick } 370