Home | History | Annotate | Line # | Download | only in kern
init_main.c revision 1.127
      1 /*	$NetBSD: init_main.c,v 1.127 1998/08/01 01:36:35 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/errno.h>
     53 #include <sys/exec.h>
     54 #include <sys/kernel.h>
     55 #include <sys/mount.h>
     56 #include <sys/map.h>
     57 #include <sys/proc.h>
     58 #include <sys/resourcevar.h>
     59 #include <sys/signalvar.h>
     60 #include <sys/systm.h>
     61 #include <sys/vnode.h>
     62 #include <sys/tty.h>
     63 #include <sys/conf.h>
     64 #include <sys/disklabel.h>
     65 #include <sys/buf.h>
     66 #ifdef REAL_CLISTS
     67 #include <sys/clist.h>
     68 #endif
     69 #include <sys/device.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 #if defined(UVM)
    100 #include <uvm/uvm.h>
    101 #endif
    102 
    103 #include <net/if.h>
    104 #include <net/raw_cb.h>
    105 
    106 char	copyright[] = "\
    107 Copyright (c) 1996, 1997, 1998
    108     The NetBSD Foundation, Inc.  All rights reserved.
    109 Copyright (c) 1982, 1986, 1989, 1991, 1993
    110     The Regents of the University of California.  All rights reserved.
    111 
    112 ";
    113 
    114 /* Components of the first process -- never freed. */
    115 struct	session session0;
    116 struct	pgrp pgrp0;
    117 struct	proc proc0;
    118 struct	pcred cred0;
    119 struct	filedesc0 filedesc0;
    120 struct	plimit limit0;
    121 struct	vmspace vmspace0;
    122 struct	proc *curproc = &proc0;
    123 struct	proc *initproc;
    124 
    125 int	cmask = CMASK;
    126 extern	struct user *proc0paddr;
    127 
    128 struct	vnode *rootvp, *swapdev_vp;
    129 int	boothowto;
    130 struct	timeval boottime;
    131 struct	timeval runtime;
    132 
    133 static void check_console __P((struct proc *p));
    134 static void start_init __P((struct proc *));
    135 static void start_pagedaemon __P((struct proc *));
    136 void main __P((void));
    137 
    138 extern char sigcode[], esigcode[];
    139 #ifdef SYSCALL_DEBUG
    140 extern char *syscallnames[];
    141 #endif
    142 
    143 struct emul emul_netbsd = {
    144 	"netbsd",
    145 	NULL,
    146 	sendsig,
    147 	SYS_syscall,
    148 	SYS_MAXSYSCALL,
    149 	sysent,
    150 #ifdef SYSCALL_DEBUG
    151 	syscallnames,
    152 #else
    153 	NULL,
    154 #endif
    155 	0,
    156 	copyargs,
    157 	setregs,
    158 	sigcode,
    159 	esigcode,
    160 };
    161 
    162 /*
    163  * System startup; initialize the world, create process 0, mount root
    164  * filesystem, and fork to create init and pagedaemon.  Most of the
    165  * hard work is done in the lower-level initialization routines including
    166  * startup(), which does memory initialization and autoconfiguration.
    167  */
    168 void
    169 main()
    170 {
    171 	struct proc *p, *p2;
    172 	struct pdevinit *pdev;
    173 	int i, s, error;
    174 	extern struct pdevinit pdevinit[];
    175 	extern void roundrobin __P((void *));
    176 	extern void schedcpu __P((void *));
    177 	extern void disk_init __P((void));
    178 #if defined(NFSSERVER) || defined(NFS)
    179 	extern void nfs_init __P((void));
    180 #endif
    181 
    182 	/*
    183 	 * Initialize the current process pointer (curproc) before
    184 	 * any possible traps/probes to simplify trap processing.
    185 	 */
    186 	p = &proc0;
    187 	curproc = p;
    188 	/*
    189 	 * Attempt to find console and initialize
    190 	 * in case of early panic or other messages.
    191 	 */
    192 	consinit();
    193 	printf(copyright);
    194 
    195 #if defined(UVM)
    196 	uvm_init();
    197 #else
    198 	vm_mem_init();
    199 	kmeminit();
    200 #if defined(MACHINE_NEW_NONCONTIG)
    201 	vm_page_physrehash();
    202 #endif
    203 #endif /* UVM */
    204 
    205 	/*
    206 	 * Initialize mbuf's.  Do this now because we might attempt to
    207 	 * allocate mbufs or mbuf clusters during autoconfiguration.
    208 	 */
    209 	mbinit();
    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 	cpu_startup();
    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 	p->p_flag = P_INMEM | P_SYSTEM;
    239 	p->p_stat = SRUN;
    240 	p->p_nice = NZERO;
    241 	p->p_emul = &emul_netbsd;
    242 	bcopy("swapper", p->p_comm, sizeof("swapper"));
    243 
    244 	/* Create credentials. */
    245 	cred0.p_refcnt = 1;
    246 	p->p_cred = &cred0;
    247 	p->p_ucred = crget();
    248 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
    249 
    250 	/* Create the file descriptor table. */
    251 	p->p_fd = &filedesc0.fd_fd;
    252 	fdinit1(&filedesc0);
    253 
    254 	/* Create the limits structures. */
    255 	p->p_limit = &limit0;
    256 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
    257 		limit0.pl_rlimit[i].rlim_cur =
    258 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
    259 	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
    260 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
    261 #if defined(UVM)
    262 	i = ptoa(uvmexp.free);
    263 #else
    264 	i = ptoa(cnt.v_free_count);
    265 #endif
    266 	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
    267 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
    268 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
    269 	limit0.p_refcnt = 1;
    270 
    271 	/*
    272 	 * Initialize proc0's vmspace, which uses the kernel pmap.
    273 	 * All kernel processes (which never have user space mappings)
    274 	 * share proc0's vmspace, and thus, the kernel pmap.
    275 	 */
    276 #if defined(UVM)
    277 	uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
    278 	    trunc_page(VM_MAX_ADDRESS), TRUE);
    279 #else
    280 	vmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS),
    281 	    trunc_page(VM_MAX_ADDRESS), TRUE);
    282 #endif
    283 	p->p_vmspace = &vmspace0;
    284 
    285 	p->p_addr = proc0paddr;				/* XXX */
    286 
    287 	/*
    288 	 * We continue to place resource usage info and signal
    289 	 * actions in the user struct so they're pageable.
    290 	 */
    291 	p->p_stats = &p->p_addr->u_stats;
    292 	p->p_sigacts = &p->p_addr->u_sigacts;
    293 
    294 	/*
    295 	 * Charge root for one process.
    296 	 */
    297 	(void)chgproccnt(0, 1);
    298 
    299 	rqinit();
    300 
    301 	/* Configure virtual memory system, set vm rlimits. */
    302 #if defined(UVM)
    303 	uvm_init_limits(p);
    304 #else
    305 	vm_init_limits(p);
    306 #endif
    307 
    308 	/* Initialize the file systems. */
    309 #if defined(NFSSERVER) || defined(NFS)
    310 	nfs_init();			/* initialize server/shared data */
    311 #endif
    312 	vfsinit();
    313 
    314 	/* Start real time and statistics clocks. */
    315 	initclocks();
    316 
    317 #ifdef REAL_CLISTS
    318 	/* Initialize clists. */
    319 	clist_init();
    320 #endif
    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 	filedesc0.fd_fd.fd_cdir = rootvnode;
    385 	VREF(filedesc0.fd_fd.fd_cdir);
    386 	VOP_UNLOCK(rootvnode, 0);
    387 	filedesc0.fd_fd.fd_rdir = NULL;
    388 #if defined(UVM)
    389 	uvm_swap_init();
    390 #else
    391 	swapinit();
    392 #endif
    393 
    394 	/*
    395 	 * Now can look at time, having had a chance to verify the time
    396 	 * from the file system.  Reset p->p_rtime as it may have been
    397 	 * munched in mi_switch() after the time got set.
    398 	 */
    399 	p->p_stats->p_start = runtime = mono_time = boottime = time;
    400 	p->p_rtime.tv_sec = p->p_rtime.tv_usec = 0;
    401 
    402 	/* Initialize signal state for process 0. */
    403 	siginit(p);
    404 
    405 	/* Create process 1 (init(8)). */
    406 	if (fork1(p, 0, NULL, &p2))
    407 		panic("fork init");
    408 	cpu_set_kpc(p2, start_init);
    409 
    410 	/* Create process 2 (the pageout daemon). */
    411 	if (fork1(p, FORK_SHAREVM, NULL, &p2))
    412 		panic("fork pager");
    413 	cpu_set_kpc(p2, start_pagedaemon);
    414 
    415 	/* The scheduler is an infinite loop. */
    416 #if defined(UVM)
    417 	uvm_scheduler();
    418 #else
    419 	scheduler();
    420 #endif
    421 	/* NOTREACHED */
    422 }
    423 
    424 static void
    425 check_console(p)
    426 	struct proc *p;
    427 {
    428 	struct nameidata nd;
    429 	int error;
    430 
    431 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/console", p);
    432 	error = namei(&nd);
    433 	if (error == 0)
    434 		vrele(nd.ni_vp);
    435 	else if (error == ENOENT)
    436 		printf("warning: no /dev/console\n");
    437 	else
    438 		printf("warning: lookup /dev/console: error %d\n", error);
    439 }
    440 
    441 /*
    442  * List of paths to try when searching for "init".
    443  */
    444 static char *initpaths[] = {
    445 	"/sbin/init",
    446 	"/sbin/oinit",
    447 	"/sbin/init.bak",
    448 	NULL,
    449 };
    450 
    451 /*
    452  * Start the initial user process; try exec'ing each pathname in "initpaths".
    453  * The program is invoked with one argument containing the boot flags.
    454  */
    455 static void
    456 start_init(p)
    457 	struct proc *p;
    458 {
    459 	vm_offset_t addr;
    460 	struct sys_execve_args /* {
    461 		syscallarg(const char *) path;
    462 		syscallarg(char * const *) argp;
    463 		syscallarg(char * const *) envp;
    464 	} */ args;
    465 	int options, i, error;
    466 	register_t retval[2];
    467 	char flags[4], *flagsp;
    468 	char **pathp, *path, *ucp, **uap, *arg0, *arg1 = NULL;
    469 
    470 	/*
    471 	 * Now in process 1.
    472 	 */
    473 	initproc = p;
    474 
    475 	/*
    476 	 * This is not the right way to do this.  We really should
    477 	 * hand-craft a descriptor onto /dev/console to hand to init,
    478 	 * but that's a _lot_ more work, and the benefit from this easy
    479 	 * hack makes up for the "good is the enemy of the best" effect.
    480 	 */
    481 	check_console(p);
    482 
    483 	/*
    484 	 * Need just enough stack to hold the faked-up "execve()" arguments.
    485 	 */
    486 	addr = USRSTACK - PAGE_SIZE;
    487 #if defined(UVM)
    488 	if (uvm_map(&p->p_vmspace->vm_map, &addr, PAGE_SIZE,
    489                     NULL, UVM_UNKNOWN_OFFSET,
    490                     UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
    491 		    UVM_ADV_NORMAL,
    492                     UVM_FLAG_FIXED|UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW))
    493 		!= KERN_SUCCESS)
    494 		panic("init: couldn't allocate argument space");
    495 #else
    496 	if (vm_allocate(&p->p_vmspace->vm_map, &addr, (vm_size_t)PAGE_SIZE,
    497 	    FALSE) != 0)
    498 		panic("init: couldn't allocate argument space");
    499 #endif
    500 	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
    501 
    502 	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
    503 		ucp = (char *)(addr + PAGE_SIZE);
    504 
    505 		/*
    506 		 * Construct the boot flag argument.
    507 		 */
    508 		flagsp = flags;
    509 		*flagsp++ = '-';
    510 		options = 0;
    511 
    512 		if (boothowto & RB_SINGLE) {
    513 			*flagsp++ = 's';
    514 			options = 1;
    515 		}
    516 #ifdef notyet
    517 		if (boothowto & RB_FASTBOOT) {
    518 			*flagsp++ = 'f';
    519 			options = 1;
    520 		}
    521 #endif
    522 
    523 		/*
    524 		 * Move out the flags (arg 1), if necessary.
    525 		 */
    526 		if (options != 0) {
    527 			*flagsp++ = '\0';
    528 			i = flagsp - flags;
    529 #ifdef DEBUG
    530 			printf("init: copying out flags `%s' %d\n", flags, i);
    531 #endif
    532 			(void)copyout((caddr_t)flags, (caddr_t)(ucp -= i), i);
    533 			arg1 = ucp;
    534 		}
    535 
    536 		/*
    537 		 * Move out the file name (also arg 0).
    538 		 */
    539 		i = strlen(path) + 1;
    540 #ifdef DEBUG
    541 		printf("init: copying out path `%s' %d\n", path, i);
    542 #endif
    543 		(void)copyout((caddr_t)path, (caddr_t)(ucp -= i), i);
    544 		arg0 = ucp;
    545 
    546 		/*
    547 		 * Move out the arg pointers.
    548 		 */
    549 		uap = (char **)((long)ucp & ~ALIGNBYTES);
    550 		(void)suword((caddr_t)--uap, 0);	/* terminator */
    551 		if (options != 0)
    552 			(void)suword((caddr_t)--uap, (long)arg1);
    553 		(void)suword((caddr_t)--uap, (long)arg0);
    554 
    555 		/*
    556 		 * Point at the arguments.
    557 		 */
    558 		SCARG(&args, path) = arg0;
    559 		SCARG(&args, argp) = uap;
    560 		SCARG(&args, envp) = NULL;
    561 
    562 		/*
    563 		 * Now try to exec the program.  If can't for any reason
    564 		 * other than it doesn't exist, complain.
    565 		 */
    566 		error = sys_execve(p, &args, retval);
    567 		if (error == 0 || error == EJUSTRETURN)
    568 			return;
    569 		if (error != ENOENT)
    570 			printf("exec %s: error %d\n", path, error);
    571 	}
    572 	printf("init: not found\n");
    573 	panic("no init");
    574 }
    575 
    576 static void
    577 start_pagedaemon(p)
    578 	struct proc *p;
    579 {
    580 
    581 	/*
    582 	 * Now in process 2.
    583 	 */
    584 	p->p_flag |= P_INMEM | P_SYSTEM;	/* XXX */
    585 	bcopy("pagedaemon", curproc->p_comm, sizeof("pagedaemon"));
    586 #if defined(UVM)
    587 	uvm_pageout();
    588 #else
    589 	vm_pageout();
    590 #endif
    591 	/* NOTREACHED */
    592 }
    593