Home | History | Annotate | Line # | Download | only in kern
init_main.c revision 1.133
      1 /*	$NetBSD: init_main.c,v 1.133 1998/10/19 11:51:53 pk 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 #ifndef curproc
    125 struct	proc *curproc = &proc0;
    126 #endif
    127 struct	proc *initproc;
    128 
    129 int	cmask = CMASK;
    130 extern	struct user *proc0paddr;
    131 
    132 struct	vnode *rootvp, *swapdev_vp;
    133 int	boothowto;
    134 struct	timeval boottime;
    135 struct	timeval runtime;
    136 
    137 static void check_console __P((struct proc *p));
    138 static void start_init __P((struct proc *));
    139 static void start_pagedaemon __P((struct proc *));
    140 static void start_reaper __P((struct proc *));
    141 void main __P((void));
    142 
    143 extern char sigcode[], esigcode[];
    144 #ifdef SYSCALL_DEBUG
    145 extern char *syscallnames[];
    146 #endif
    147 
    148 struct emul emul_netbsd = {
    149 	"netbsd",
    150 	NULL,
    151 	sendsig,
    152 	SYS_syscall,
    153 	SYS_MAXSYSCALL,
    154 	sysent,
    155 #ifdef SYSCALL_DEBUG
    156 	syscallnames,
    157 #else
    158 	NULL,
    159 #endif
    160 	0,
    161 	copyargs,
    162 	setregs,
    163 	sigcode,
    164 	esigcode,
    165 };
    166 
    167 /*
    168  * System startup; initialize the world, create process 0, mount root
    169  * filesystem, and fork to create init and pagedaemon.  Most of the
    170  * hard work is done in the lower-level initialization routines including
    171  * startup(), which does memory initialization and autoconfiguration.
    172  */
    173 void
    174 main()
    175 {
    176 	struct proc *p, *p2;
    177 	struct pdevinit *pdev;
    178 	int i, s, error;
    179 	extern struct pdevinit pdevinit[];
    180 	extern void roundrobin __P((void *));
    181 	extern void schedcpu __P((void *));
    182 	extern void disk_init __P((void));
    183 #if defined(NFSSERVER) || defined(NFS)
    184 	extern void nfs_init __P((void));
    185 #endif
    186 
    187 	/*
    188 	 * Initialize the current process pointer (curproc) before
    189 	 * any possible traps/probes to simplify trap processing.
    190 	 */
    191 	p = &proc0;
    192 	curproc = p;
    193 	/*
    194 	 * Attempt to find console and initialize
    195 	 * in case of early panic or other messages.
    196 	 */
    197 	consinit();
    198 	printf(copyright);
    199 
    200 #if defined(UVM)
    201 	uvm_init();
    202 #else
    203 	vm_mem_init();
    204 	kmeminit();
    205 #if defined(MACHINE_NEW_NONCONTIG)
    206 	vm_page_physrehash();
    207 #endif
    208 #endif /* UVM */
    209 
    210 	/*
    211 	 * Initialize mbuf's.  Do this now because we might attempt to
    212 	 * allocate mbufs or mbuf clusters during autoconfiguration.
    213 	 */
    214 	mbinit();
    215 
    216 	/* Initialize sockets. */
    217 	soinit();
    218 
    219 	disk_init();		/* must come before autoconfiguration */
    220 	tty_init();		/* initialise tty list */
    221 #if NRND > 0
    222 	rnd_init();
    223 #endif
    224 	config_init();		/* init autoconfiguration data structures */
    225 	cpu_startup();
    226 
    227 	/*
    228 	 * Initialize process and pgrp structures.
    229 	 */
    230 	procinit();
    231 
    232 	/*
    233 	 * Create process 0 (the swapper).
    234 	 */
    235 	LIST_INSERT_HEAD(&allproc, p, p_list);
    236 	p->p_pgrp = &pgrp0;
    237 	LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
    238 	LIST_INIT(&pgrp0.pg_members);
    239 	LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
    240 
    241 	pgrp0.pg_session = &session0;
    242 	session0.s_count = 1;
    243 	session0.s_sid = p->p_pid;
    244 	session0.s_leader = p;
    245 
    246 	p->p_flag = P_INMEM | P_SYSTEM;
    247 	p->p_stat = SRUN;
    248 	p->p_nice = NZERO;
    249 	p->p_emul = &emul_netbsd;
    250 	memcpy(p->p_comm, "swapper", sizeof("swapper"));
    251 
    252 	/* Create credentials. */
    253 	cred0.p_refcnt = 1;
    254 	p->p_cred = &cred0;
    255 	p->p_ucred = crget();
    256 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
    257 
    258 	/* Create the file descriptor table. */
    259 	finit();
    260 	p->p_fd = &filedesc0.fd_fd;
    261 	fdinit1(&filedesc0);
    262 
    263 	/* Create the limits structures. */
    264 	p->p_limit = &limit0;
    265 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
    266 		limit0.pl_rlimit[i].rlim_cur =
    267 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
    268 	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
    269 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
    270 #if defined(UVM)
    271 	i = ptoa(uvmexp.free);
    272 #else
    273 	i = ptoa(cnt.v_free_count);
    274 #endif
    275 	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
    276 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
    277 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
    278 	limit0.p_refcnt = 1;
    279 
    280 	/*
    281 	 * Initialize proc0's vmspace, which uses the kernel pmap.
    282 	 * All kernel processes (which never have user space mappings)
    283 	 * share proc0's vmspace, and thus, the kernel pmap.
    284 	 */
    285 #if defined(UVM)
    286 	uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
    287 	    trunc_page(VM_MAX_ADDRESS), TRUE);
    288 #else
    289 	vmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
    290 	    trunc_page(VM_MAX_ADDRESS), TRUE);
    291 #endif
    292 	p->p_vmspace = &vmspace0;
    293 
    294 	p->p_addr = proc0paddr;				/* XXX */
    295 
    296 	/*
    297 	 * We continue to place resource usage info and signal
    298 	 * actions in the user struct so they're pageable.
    299 	 */
    300 	p->p_stats = &p->p_addr->u_stats;
    301 	p->p_sigacts = &p->p_addr->u_sigacts;
    302 
    303 	/*
    304 	 * Charge root for one process.
    305 	 */
    306 	(void)chgproccnt(0, 1);
    307 
    308 	rqinit();
    309 
    310 	/* Configure virtual memory system, set vm rlimits. */
    311 #if defined(UVM)
    312 	uvm_init_limits(p);
    313 #else
    314 	vm_init_limits(p);
    315 #endif
    316 
    317 	/* Initialize the file systems. */
    318 #if defined(NFSSERVER) || defined(NFS)
    319 	nfs_init();			/* initialize server/shared data */
    320 #endif
    321 	vfsinit();
    322 
    323 	/* Start real time and statistics clocks. */
    324 	initclocks();
    325 
    326 #ifdef REAL_CLISTS
    327 	/* Initialize clists. */
    328 	clist_init();
    329 #endif
    330 
    331 #ifdef SYSVSHM
    332 	/* Initialize System V style shared memory. */
    333 	shminit();
    334 #endif
    335 
    336 #ifdef SYSVSEM
    337 	/* Initialize System V style semaphores. */
    338 	seminit();
    339 #endif
    340 
    341 #ifdef SYSVMSG
    342 	/* Initialize System V style message queues. */
    343 	msginit();
    344 #endif
    345 
    346 	/* Attach pseudo-devices. */
    347 	for (pdev = pdevinit; pdev->pdev_attach != NULL; pdev++)
    348 		(*pdev->pdev_attach)(pdev->pdev_count);
    349 
    350 	/*
    351 	 * Initialize protocols.  Block reception of incoming packets
    352 	 * until everything is ready.
    353 	 */
    354 	s = splimp();
    355 	ifinit();
    356 	domaininit();
    357 	splx(s);
    358 
    359 #ifdef GPROF
    360 	/* Initialize kernel profiling. */
    361 	kmstartup();
    362 #endif
    363 
    364 	/* Kick off timeout driven events by calling first time. */
    365 	roundrobin(NULL);
    366 	schedcpu(NULL);
    367 
    368 	/* Determine the root and dump devices. */
    369 	cpu_rootconf();
    370 	cpu_dumpconf();
    371 
    372 	/* Mount the root file system. */
    373 	do {
    374 		domountroothook();
    375 		if ((error = vfs_mountroot())) {
    376 			printf("cannot mount root, error = %d\n", error);
    377 			boothowto |= RB_ASKNAME;
    378 			setroot(root_device,
    379 			    (rootdev != NODEV) ? DISKPART(rootdev) : 0, NULL);
    380 		}
    381 	} while (error != 0);
    382 	mountroothook_destroy();
    383 
    384 	mountlist.cqh_first->mnt_flag |= MNT_ROOTFS;
    385 	mountlist.cqh_first->mnt_op->vfs_refcount++;
    386 
    387 	/*
    388 	 * Get the vnode for '/'.  Set filedesc0.fd_fd.fd_cdir to
    389 	 * reference it.
    390 	 */
    391 	if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
    392 		panic("cannot find root vnode");
    393 	filedesc0.fd_fd.fd_cdir = rootvnode;
    394 	VREF(filedesc0.fd_fd.fd_cdir);
    395 	VOP_UNLOCK(rootvnode, 0);
    396 	filedesc0.fd_fd.fd_rdir = NULL;
    397 #if defined(UVM)
    398 	uvm_swap_init();
    399 #else
    400 	swapinit();
    401 #endif
    402 
    403 	/*
    404 	 * Now can look at time, having had a chance to verify the time
    405 	 * from the file system.  Reset p->p_rtime as it may have been
    406 	 * munched in mi_switch() after the time got set.
    407 	 */
    408 	p->p_stats->p_start = runtime = mono_time = boottime = time;
    409 	p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
    410 
    411 	/* Initialize signal state for process 0. */
    412 	siginit(p);
    413 
    414 	/* Create process 1 (init(8)). */
    415 	if (fork1(p, 0, NULL, &p2))
    416 		panic("fork init");
    417 	cpu_set_kpc(p2, start_init);
    418 
    419 	/* Create process 2 (the pageout daemon). */
    420 	if (fork1(p, FORK_SHAREVM, NULL, &p2))
    421 		panic("fork pager");
    422 	cpu_set_kpc(p2, start_pagedaemon);
    423 
    424 	/* Create process 3 (the process reaper). */
    425 	if (fork1(p, FORK_SHAREVM, NULL, &p2))
    426 		panic("fork reaper");
    427 	cpu_set_kpc(p2, start_reaper);
    428 
    429 	/* The scheduler is an infinite loop. */
    430 #if defined(UVM)
    431 	uvm_scheduler();
    432 #else
    433 	scheduler();
    434 #endif
    435 	/* NOTREACHED */
    436 }
    437 
    438 static void
    439 check_console(p)
    440 	struct proc *p;
    441 {
    442 	struct nameidata nd;
    443 	int error;
    444 
    445 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
    446 	error = namei(&nd);
    447 	if (error == 0)
    448 		vrele(nd.ni_vp);
    449 	else if (error == ENOENT)
    450 		printf("warning: no /dev/console\n");
    451 	else
    452 		printf("warning: lookup /dev/console: error %d\n", error);
    453 }
    454 
    455 /*
    456  * List of paths to try when searching for "init".
    457  */
    458 static char *initpaths[] = {
    459 	"/sbin/init",
    460 	"/sbin/oinit",
    461 	"/sbin/init.bak",
    462 	NULL,
    463 };
    464 
    465 /*
    466  * Start the initial user process; try exec'ing each pathname in "initpaths".
    467  * The program is invoked with one argument containing the boot flags.
    468  */
    469 static void
    470 start_init(p)
    471 	struct proc *p;
    472 {
    473 	vaddr_t addr;
    474 	struct sys_execve_args /* {
    475 		syscallarg(const char *) path;
    476 		syscallarg(char * const *) argp;
    477 		syscallarg(char * const *) envp;
    478 	} */ args;
    479 	int options, i, error;
    480 	register_t retval[2];
    481 	char flags[4], *flagsp;
    482 	char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
    483 
    484 	/*
    485 	 * Now in process 1.
    486 	 */
    487 	initproc = p;
    488 
    489 	/*
    490 	 * This is not the right way to do this.  We really should
    491 	 * hand-craft a descriptor onto /dev/console to hand to init,
    492 	 * but that's a _lot_ more work, and the benefit from this easy
    493 	 * hack makes up for the "good is the enemy of the best" effect.
    494 	 */
    495 	check_console(p);
    496 
    497 	/*
    498 	 * Need just enough stack to hold the faked-up "execve()" arguments.
    499 	 */
    500 	addr = USRSTACK - PAGE_SIZE;
    501 #if defined(UVM)
    502 	if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
    503                     NULL, UVM_UNKNOWN_OFFSET,
    504                     UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
    505 		    UVM_ADV_NORMAL,
    506                     UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW))
    507 		!= KERN_SUCCESS)
    508 		panic("init: couldn't allocate argument space");
    509 #else
    510 	if (vm_allocate(&p->p_vmspace->vm_map, &addr, (vsize_t)PAGE_SIZE,
    511 	    FALSE) != 0)
    512 		panic("init: couldn't allocate argument space");
    513 #endif
    514 	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
    515 
    516 	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
    517 		ucp = (char *)(addr + PAGE_SIZE);
    518 
    519 		/*
    520 		 * Construct the boot flag argument.
    521 		 */
    522 		flagsp = flags;
    523 		*flagsp++ = '-';
    524 		options = 0;
    525 
    526 		if (boothowto & RB_SINGLE) {
    527 			*flagsp++ = 's';
    528 			options = 1;
    529 		}
    530 #ifdef notyet
    531 		if (boothowto & RB_FASTBOOT) {
    532 			*flagsp++ = 'f';
    533 			options = 1;
    534 		}
    535 #endif
    536 
    537 		/*
    538 		 * Move out the flags (arg 1), if necessary.
    539 		 */
    540 		if (options != 0) {
    541 			*flagsp++ = '\0';
    542 			i = flagsp - flags;
    543 #ifdef DEBUG
    544 			printf("init: copying out flags `%s' %d\n", flags, i);
    545 #endif
    546 			(void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
    547 			arg1 = ucp;
    548 		}
    549 
    550 		/*
    551 		 * Move out the file name (also arg 0).
    552 		 */
    553 		i = strlen(path) + 1;
    554 #ifdef DEBUG
    555 		printf("init: copying out path `%s' %d\n", path, i);
    556 #endif
    557 		(void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
    558 		arg0 = ucp;
    559 
    560 		/*
    561 		 * Move out the arg pointers.
    562 		 */
    563 		uap = (char **)((long)ucp & ~ALIGNBYTES);
    564 		(void)suword((caddr_t)--uap, 0);	/* terminator */
    565 		if (options != 0)
    566 			(void)suword((caddr_t)--uap, (long)arg1);
    567 		(void)suword((caddr_t)--uap, (long)arg0);
    568 
    569 		/*
    570 		 * Point at the arguments.
    571 		 */
    572 		SCARG(&args, path) = arg0;
    573 		SCARG(&args, argp) = uap;
    574 		SCARG(&args, envp) = NULL;
    575 
    576 		/*
    577 		 * Now try to exec the program.  If can't for any reason
    578 		 * other than it doesn't exist, complain.
    579 		 */
    580 		error = sys_execve(p, &args, retval);
    581 		if (error == 0 || error == EJUSTRETURN)
    582 			return;
    583 		if (error != ENOENT)
    584 			printf("exec %s: error %d\n", path, error);
    585 	}
    586 	printf("init: not found\n");
    587 	panic("no init");
    588 }
    589 
    590 static void
    591 start_pagedaemon(p)
    592 	struct proc *p;
    593 {
    594 
    595 	/*
    596 	 * Now in process 2.
    597 	 */
    598 	p->p_flag |= P_INMEM | P_SYSTEM;	/* XXX */
    599 	memcpy(curproc->p_comm, "pagedaemon", sizeof("pagedaemon"));
    600 #if defined(UVM)
    601 	uvm_pageout();
    602 #else
    603 	vm_pageout();
    604 #endif
    605 	/* NOTREACHED */
    606 }
    607 
    608 static void
    609 start_reaper(p)
    610 	struct proc *p;
    611 {
    612 
    613 	/*
    614 	 * Now in process 3.
    615 	 */
    616 	p->p_flag |= P_INMEM | P_SYSTEM;	/* XXX */
    617 	memcpy(curproc->p_comm, "reaper", sizeof("reaper"));
    618 	reaper();
    619 	/* NOTREACHED */
    620 }
    621