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