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