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