Home | History | Annotate | Line # | Download | only in kern
init_main.c revision 1.132
      1 /*	$NetBSD: init_main.c,v 1.132 1998/09/08 23:57:58 thorpej Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995 Christopher G. Demetriou.  All rights reserved.
      5  * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
      6  *	The Regents of the University of California.  All rights reserved.
      7  * (c) UNIX System Laboratories, Inc.
      8  * All or some portions of this file are derived from material licensed
      9  * to the University of California by American Telephone and Telegraph
     10  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     11  * the permission of UNIX System Laboratories, Inc.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted provided that the following conditions
     15  * are met:
     16  * 1. Redistributions of source code must retain the above copyright
     17  *    notice, this list of conditions and the following disclaimer.
     18  * 2. Redistributions in binary form must reproduce the above copyright
     19  *    notice, this list of conditions and the following disclaimer in the
     20  *    documentation and/or other materials provided with the distribution.
     21  * 3. All advertising materials mentioning features or use of this software
     22  *    must display the following acknowledgement:
     23  *	This product includes software developed by the University of
     24  *	California, Berkeley and its contributors.
     25  * 4. Neither the name of the University nor the names of its contributors
     26  *    may be used to endorse or promote products derived from this software
     27  *    without specific prior written permission.
     28  *
     29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     39  * SUCH DAMAGE.
     40  *
     41  *	@(#)init_main.c	8.16 (Berkeley) 5/14/95
     42  */
     43 
     44 #include "fs_nfs.h"
     45 #include "opt_nfsserver.h"
     46 #include "opt_uvm.h"
     47 
     48 #include "rnd.h"
     49 
     50 #include <sys/param.h>
     51 #include <sys/filedesc.h>
     52 #include <sys/file.h>
     53 #include <sys/errno.h>
     54 #include <sys/exec.h>
     55 #include <sys/kernel.h>
     56 #include <sys/mount.h>
     57 #include <sys/map.h>
     58 #include <sys/proc.h>
     59 #include <sys/resourcevar.h>
     60 #include <sys/signalvar.h>
     61 #include <sys/systm.h>
     62 #include <sys/vnode.h>
     63 #include <sys/tty.h>
     64 #include <sys/conf.h>
     65 #include <sys/disklabel.h>
     66 #include <sys/buf.h>
     67 #ifdef REAL_CLISTS
     68 #include <sys/clist.h>
     69 #endif
     70 #include <sys/device.h>
     71 #include <sys/socketvar.h>
     72 #include <sys/protosw.h>
     73 #include <sys/reboot.h>
     74 #include <sys/user.h>
     75 #ifdef SYSVSHM
     76 #include <sys/shm.h>
     77 #endif
     78 #ifdef SYSVSEM
     79 #include <sys/sem.h>
     80 #endif
     81 #ifdef SYSVMSG
     82 #include <sys/msg.h>
     83 #endif
     84 #include <sys/domain.h>
     85 #include <sys/mbuf.h>
     86 #include <sys/namei.h>
     87 #if NRND > 0
     88 #include <sys/rnd.h>
     89 #endif
     90 
     91 #include <sys/syscall.h>
     92 #include <sys/syscallargs.h>
     93 
     94 #include <ufs/ufs/quota.h>
     95 
     96 #include <machine/cpu.h>
     97 
     98 #include <vm/vm.h>
     99 #include <vm/vm_pageout.h>
    100 
    101 #if defined(UVM)
    102 #include <uvm/uvm.h>
    103 #endif
    104 
    105 #include <net/if.h>
    106 #include <net/raw_cb.h>
    107 
    108 char	copyright[] = "\
    109 Copyright (c) 1996, 1997, 1998
    110     The NetBSD Foundation, Inc.  All rights reserved.
    111 Copyright (c) 1982, 1986, 1989, 1991, 1993
    112     The Regents of the University of California.  All rights reserved.
    113 
    114 ";
    115 
    116 /* Components of the first process -- never freed. */
    117 struct	session session0;
    118 struct	pgrp pgrp0;
    119 struct	proc proc0;
    120 struct	pcred cred0;
    121 struct	filedesc0 filedesc0;
    122 struct	plimit limit0;
    123 struct	vmspace vmspace0;
    124 struct	proc *curproc = &proc0;
    125 struct	proc *initproc;
    126 
    127 int	cmask = CMASK;
    128 extern	struct user *proc0paddr;
    129 
    130 struct	vnode *rootvp, *swapdev_vp;
    131 int	boothowto;
    132 struct	timeval boottime;
    133 struct	timeval runtime;
    134 
    135 static void check_console __P((struct proc *p));
    136 static void start_init __P((struct proc *));
    137 static void start_pagedaemon __P((struct proc *));
    138 static void start_reaper __P((struct proc *));
    139 void main __P((void));
    140 
    141 extern char sigcode[], esigcode[];
    142 #ifdef SYSCALL_DEBUG
    143 extern char *syscallnames[];
    144 #endif
    145 
    146 struct emul emul_netbsd = {
    147 	"netbsd",
    148 	NULL,
    149 	sendsig,
    150 	SYS_syscall,
    151 	SYS_MAXSYSCALL,
    152 	sysent,
    153 #ifdef SYSCALL_DEBUG
    154 	syscallnames,
    155 #else
    156 	NULL,
    157 #endif
    158 	0,
    159 	copyargs,
    160 	setregs,
    161 	sigcode,
    162 	esigcode,
    163 };
    164 
    165 /*
    166  * System startup; initialize the world, create process 0, mount root
    167  * filesystem, and fork to create init and pagedaemon.  Most of the
    168  * hard work is done in the lower-level initialization routines including
    169  * startup(), which does memory initialization and autoconfiguration.
    170  */
    171 void
    172 main()
    173 {
    174 	struct proc *p, *p2;
    175 	struct pdevinit *pdev;
    176 	int i, s, error;
    177 	extern struct pdevinit pdevinit[];
    178 	extern void roundrobin __P((void *));
    179 	extern void schedcpu __P((void *));
    180 	extern void disk_init __P((void));
    181 #if defined(NFSSERVER) || defined(NFS)
    182 	extern void nfs_init __P((void));
    183 #endif
    184 
    185 	/*
    186 	 * Initialize the current process pointer (curproc) before
    187 	 * any possible traps/probes to simplify trap processing.
    188 	 */
    189 	p = &proc0;
    190 	curproc = p;
    191 	/*
    192 	 * Attempt to find console and initialize
    193 	 * in case of early panic or other messages.
    194 	 */
    195 	consinit();
    196 	printf(copyright);
    197 
    198 #if defined(UVM)
    199 	uvm_init();
    200 #else
    201 	vm_mem_init();
    202 	kmeminit();
    203 #if defined(MACHINE_NEW_NONCONTIG)
    204 	vm_page_physrehash();
    205 #endif
    206 #endif /* UVM */
    207 
    208 	/*
    209 	 * Initialize mbuf's.  Do this now because we might attempt to
    210 	 * allocate mbufs or mbuf clusters during autoconfiguration.
    211 	 */
    212 	mbinit();
    213 
    214 	/* Initialize sockets. */
    215 	soinit();
    216 
    217 	disk_init();		/* must come before autoconfiguration */
    218 	tty_init();		/* initialise tty list */
    219 #if NRND > 0
    220 	rnd_init();
    221 #endif
    222 	config_init();		/* init autoconfiguration data structures */
    223 	cpu_startup();
    224 
    225 	/*
    226 	 * Initialize process and pgrp structures.
    227 	 */
    228 	procinit();
    229 
    230 	/*
    231 	 * Create process 0 (the swapper).
    232 	 */
    233 	LIST_INSERT_HEAD(&allproc, p, p_list);
    234 	p->p_pgrp = &pgrp0;
    235 	LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
    236 	LIST_INIT(&pgrp0.pg_members);
    237 	LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
    238 
    239 	pgrp0.pg_session = &session0;
    240 	session0.s_count = 1;
    241 	session0.s_sid = p->p_pid;
    242 	session0.s_leader = p;
    243 
    244 	p->p_flag = P_INMEM | P_SYSTEM;
    245 	p->p_stat = SRUN;
    246 	p->p_nice = NZERO;
    247 	p->p_emul = &emul_netbsd;
    248 	memcpy(p->p_comm, "swapper", sizeof("swapper"));
    249 
    250 	/* Create credentials. */
    251 	cred0.p_refcnt = 1;
    252 	p->p_cred = &cred0;
    253 	p->p_ucred = crget();
    254 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
    255 
    256 	/* Create the file descriptor table. */
    257 	finit();
    258 	p->p_fd = &filedesc0.fd_fd;
    259 	fdinit1(&filedesc0);
    260 
    261 	/* Create the limits structures. */
    262 	p->p_limit = &limit0;
    263 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
    264 		limit0.pl_rlimit[i].rlim_cur =
    265 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
    266 	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
    267 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
    268 #if defined(UVM)
    269 	i = ptoa(uvmexp.free);
    270 #else
    271 	i = ptoa(cnt.v_free_count);
    272 #endif
    273 	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
    274 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
    275 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
    276 	limit0.p_refcnt = 1;
    277 
    278 	/*
    279 	 * Initialize proc0's vmspace, which uses the kernel pmap.
    280 	 * All kernel processes (which never have user space mappings)
    281 	 * share proc0's vmspace, and thus, the kernel pmap.
    282 	 */
    283 #if defined(UVM)
    284 	uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
    285 	    trunc_page(VM_MAX_ADDRESS), TRUE);
    286 #else
    287 	vmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
    288 	    trunc_page(VM_MAX_ADDRESS), TRUE);
    289 #endif
    290 	p->p_vmspace = &vmspace0;
    291 
    292 	p->p_addr = proc0paddr;				/* XXX */
    293 
    294 	/*
    295 	 * We continue to place resource usage info and signal
    296 	 * actions in the user struct so they're pageable.
    297 	 */
    298 	p->p_stats = &p->p_addr->u_stats;
    299 	p->p_sigacts = &p->p_addr->u_sigacts;
    300 
    301 	/*
    302 	 * Charge root for one process.
    303 	 */
    304 	(void)chgproccnt(0, 1);
    305 
    306 	rqinit();
    307 
    308 	/* Configure virtual memory system, set vm rlimits. */
    309 #if defined(UVM)
    310 	uvm_init_limits(p);
    311 #else
    312 	vm_init_limits(p);
    313 #endif
    314 
    315 	/* Initialize the file systems. */
    316 #if defined(NFSSERVER) || defined(NFS)
    317 	nfs_init();			/* initialize server/shared data */
    318 #endif
    319 	vfsinit();
    320 
    321 	/* Start real time and statistics clocks. */
    322 	initclocks();
    323 
    324 #ifdef REAL_CLISTS
    325 	/* Initialize clists. */
    326 	clist_init();
    327 #endif
    328 
    329 #ifdef SYSVSHM
    330 	/* Initialize System V style shared memory. */
    331 	shminit();
    332 #endif
    333 
    334 #ifdef SYSVSEM
    335 	/* Initialize System V style semaphores. */
    336 	seminit();
    337 #endif
    338 
    339 #ifdef SYSVMSG
    340 	/* Initialize System V style message queues. */
    341 	msginit();
    342 #endif
    343 
    344 	/* Attach pseudo-devices. */
    345 	for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
    346 		(*pdev->pdev_attach)(pdev->pdev_count);
    347 
    348 	/*
    349 	 * Initialize protocols.  Block reception of incoming packets
    350 	 * until everything is ready.
    351 	 */
    352 	s = splimp();
    353 	ifinit();
    354 	domaininit();
    355 	splx(s);
    356 
    357 #ifdef GPROF
    358 	/* Initialize kernel profiling. */
    359 	kmstartup();
    360 #endif
    361 
    362 	/* Kick off timeout driven events by calling first time. */
    363 	roundrobin(NULL);
    364 	schedcpu(NULL);
    365 
    366 	/* Determine the root and dump devices. */
    367 	cpu_rootconf();
    368 	cpu_dumpconf();
    369 
    370 	/* Mount the root file system. */
    371 	do {
    372 		domountroothook();
    373 		if ((error = vfs_mountroot())) {
    374 			printf("cannot mount root, error = %d\n", error);
    375 			boothowto |= RB_ASKNAME;
    376 			setroot(root_device,
    377 			    (rootdev != NODEV) ? DISKPART(rootdev) : 0, NULL);
    378 		}
    379 	} while (error != 0);
    380 	mountroothook_destroy();
    381 
    382 	mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
    383 	mountlist.cqh_first->mnt_op->vfs_refcount++;
    384 
    385 	/*
    386 	 * Get the vnode for '/'.  Set filedesc0.fd_fd.fd_cdir to
    387 	 * reference it.
    388 	 */
    389 	if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
    390 		panic("cannot find root vnode");
    391 	filedesc0.fd_fd.fd_cdir = rootvnode;
    392 	VREF(filedesc0.fd_fd.fd_cdir);
    393 	VOP_UNLOCK(rootvnode, 0);
    394 	filedesc0.fd_fd.fd_rdir = NULL;
    395 #if defined(UVM)
    396 	uvm_swap_init();
    397 #else
    398 	swapinit();
    399 #endif
    400 
    401 	/*
    402 	 * Now can look at time, having had a chance to verify the time
    403 	 * from the file system.  Reset p->p_rtime as it may have been
    404 	 * munched in mi_switch() after the time got set.
    405 	 */
    406 	p->p_stats->p_start = runtime = mono_time = boottime = time;
    407 	p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
    408 
    409 	/* Initialize signal state for process 0. */
    410 	siginit(p);
    411 
    412 	/* Create process 1 (init(8)). */
    413 	if (fork1(p, 0, NULL, &p2))
    414 		panic("fork init");
    415 	cpu_set_kpc(p2, start_init);
    416 
    417 	/* Create process 2 (the pageout daemon). */
    418 	if (fork1(p, FORK_SHAREVM, NULL, &p2))
    419 		panic("fork pager");
    420 	cpu_set_kpc(p2, start_pagedaemon);
    421 
    422 	/* Create process 3 (the process reaper). */
    423 	if (fork1(p, FORK_SHAREVM, NULL, &p2))
    424 		panic("fork reaper");
    425 	cpu_set_kpc(p2, start_reaper);
    426 
    427 	/* The scheduler is an infinite loop. */
    428 #if defined(UVM)
    429 	uvm_scheduler();
    430 #else
    431 	scheduler();
    432 #endif
    433 	/* NOTREACHED */
    434 }
    435 
    436 static void
    437 check_console(p)
    438 	struct proc *p;
    439 {
    440 	struct nameidata nd;
    441 	int error;
    442 
    443 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
    444 	error = namei(&nd);
    445 	if (error == 0)
    446 		vrele(nd.ni_vp);
    447 	else if (error == ENOENT)
    448 		printf("warning: no /dev/console\n");
    449 	else
    450 		printf("warning: lookup /dev/console: error %d\n", error);
    451 }
    452 
    453 /*
    454  * List of paths to try when searching for "init".
    455  */
    456 static char *initpaths[] = {
    457 	"/sbin/init",
    458 	"/sbin/oinit",
    459 	"/sbin/init.bak",
    460 	NULL,
    461 };
    462 
    463 /*
    464  * Start the initial user process; try exec'ing each pathname in "initpaths".
    465  * The program is invoked with one argument containing the boot flags.
    466  */
    467 static void
    468 start_init(p)
    469 	struct proc *p;
    470 {
    471 	vaddr_t addr;
    472 	struct sys_execve_args /* {
    473 		syscallarg(const char *) path;
    474 		syscallarg(char * const *) argp;
    475 		syscallarg(char * const *) envp;
    476 	} */ args;
    477 	int options, i, error;
    478 	register_t retval[2];
    479 	char flags[4], *flagsp;
    480 	char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
    481 
    482 	/*
    483 	 * Now in process 1.
    484 	 */
    485 	initproc = p;
    486 
    487 	/*
    488 	 * This is not the right way to do this.  We really should
    489 	 * hand-craft a descriptor onto /dev/console to hand to init,
    490 	 * but that's a _lot_ more work, and the benefit from this easy
    491 	 * hack makes up for the "good is the enemy of the best" effect.
    492 	 */
    493 	check_console(p);
    494 
    495 	/*
    496 	 * Need just enough stack to hold the faked-up "execve()" arguments.
    497 	 */
    498 	addr = USRSTACK - PAGE_SIZE;
    499 #if defined(UVM)
    500 	if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
    501                     NULL, UVM_UNKNOWN_OFFSET,
    502                     UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
    503 		    UVM_ADV_NORMAL,
    504                     UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW))
    505 		!= KERN_SUCCESS)
    506 		panic("init: couldn't allocate argument space");
    507 #else
    508 	if (vm_allocate(&p->p_vmspace->vm_map, &addr, (vsize_t)PAGE_SIZE,
    509 	    FALSE) != 0)
    510 		panic("init: couldn't allocate argument space");
    511 #endif
    512 	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
    513 
    514 	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
    515 		ucp = (char *)(addr + PAGE_SIZE);
    516 
    517 		/*
    518 		 * Construct the boot flag argument.
    519 		 */
    520 		flagsp = flags;
    521 		*flagsp++ = '-';
    522 		options = 0;
    523 
    524 		if (boothowto & RB_SINGLE) {
    525 			*flagsp++ = 's';
    526 			options = 1;
    527 		}
    528 #ifdef notyet
    529 		if (boothowto & RB_FASTBOOT) {
    530 			*flagsp++ = 'f';
    531 			options = 1;
    532 		}
    533 #endif
    534 
    535 		/*
    536 		 * Move out the flags (arg 1), if necessary.
    537 		 */
    538 		if (options != 0) {
    539 			*flagsp++ = '\0';
    540 			i = flagsp - flags;
    541 #ifdef DEBUG
    542 			printf("init: copying out flags `%s' %d\n", flags, i);
    543 #endif
    544 			(void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
    545 			arg1 = ucp;
    546 		}
    547 
    548 		/*
    549 		 * Move out the file name (also arg 0).
    550 		 */
    551 		i = strlen(path) + 1;
    552 #ifdef DEBUG
    553 		printf("init: copying out path `%s' %d\n", path, i);
    554 #endif
    555 		(void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
    556 		arg0 = ucp;
    557 
    558 		/*
    559 		 * Move out the arg pointers.
    560 		 */
    561 		uap = (char **)((long)ucp & ~ALIGNBYTES);
    562 		(void)suword((caddr_t)--uap, 0);	/* terminator */
    563 		if (options != 0)
    564 			(void)suword((caddr_t)--uap, (long)arg1);
    565 		(void)suword((caddr_t)--uap, (long)arg0);
    566 
    567 		/*
    568 		 * Point at the arguments.
    569 		 */
    570 		SCARG(&args, path) = arg0;
    571 		SCARG(&args, argp) = uap;
    572 		SCARG(&args, envp) = NULL;
    573 
    574 		/*
    575 		 * Now try to exec the program.  If can't for any reason
    576 		 * other than it doesn't exist, complain.
    577 		 */
    578 		error = sys_execve(p, &args, retval);
    579 		if (error == 0 || error == EJUSTRETURN)
    580 			return;
    581 		if (error != ENOENT)
    582 			printf("exec %s: error %d\n", path, error);
    583 	}
    584 	printf("init: not found\n");
    585 	panic("no init");
    586 }
    587 
    588 static void
    589 start_pagedaemon(p)
    590 	struct proc *p;
    591 {
    592 
    593 	/*
    594 	 * Now in process 2.
    595 	 */
    596 	p->p_flag |= P_INMEM | P_SYSTEM;	/* XXX */
    597 	memcpy(curproc->p_comm, "pagedaemon", sizeof("pagedaemon"));
    598 #if defined(UVM)
    599 	uvm_pageout();
    600 #else
    601 	vm_pageout();
    602 #endif
    603 	/* NOTREACHED */
    604 }
    605 
    606 static void
    607 start_reaper(p)
    608 	struct proc *p;
    609 {
    610 
    611 	/*
    612 	 * Now in process 3.
    613 	 */
    614 	p->p_flag |= P_INMEM | P_SYSTEM;	/* XXX */
    615 	memcpy(curproc->p_comm, "reaper", sizeof("reaper"));
    616 	reaper();
    617 	/* NOTREACHED */
    618 }
    619