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