xref: /freebsd/sys/kern/init_main.c (revision ac0ad63f37c54b240c2b34ed812bc2ef699b8af6)
1df8bae1dSRodney W. Grimes /*
22b14f991SJulian Elischer  * Copyright (c) 1995 Terrence R. Lambert
32b14f991SJulian Elischer  * All rights reserved.
42b14f991SJulian Elischer  *
5df8bae1dSRodney W. Grimes  * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
6df8bae1dSRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
7df8bae1dSRodney W. Grimes  * (c) UNIX System Laboratories, Inc.
8df8bae1dSRodney W. Grimes  * All or some portions of this file are derived from material licensed
9df8bae1dSRodney W. Grimes  * to the University of California by American Telephone and Telegraph
10df8bae1dSRodney W. Grimes  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11df8bae1dSRodney W. Grimes  * the permission of UNIX System Laboratories, Inc.
12df8bae1dSRodney W. Grimes  *
13df8bae1dSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
14df8bae1dSRodney W. Grimes  * modification, are permitted provided that the following conditions
15df8bae1dSRodney W. Grimes  * are met:
16df8bae1dSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
17df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
18df8bae1dSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
19df8bae1dSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
20df8bae1dSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
21df8bae1dSRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
22df8bae1dSRodney W. Grimes  *    must display the following acknowledgement:
23df8bae1dSRodney W. Grimes  *	This product includes software developed by the University of
24df8bae1dSRodney W. Grimes  *	California, Berkeley and its contributors.
25df8bae1dSRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
26df8bae1dSRodney W. Grimes  *    may be used to endorse or promote products derived from this software
27df8bae1dSRodney W. Grimes  *    without specific prior written permission.
28df8bae1dSRodney W. Grimes  *
29df8bae1dSRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30df8bae1dSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31df8bae1dSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32df8bae1dSRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33df8bae1dSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34df8bae1dSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35df8bae1dSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36df8bae1dSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37df8bae1dSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38df8bae1dSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39df8bae1dSRodney W. Grimes  * SUCH DAMAGE.
40df8bae1dSRodney W. Grimes  *
41df8bae1dSRodney W. Grimes  *	@(#)init_main.c	8.9 (Berkeley) 1/21/94
421130b656SJordan K. Hubbard  * $FreeBSD$
43df8bae1dSRodney W. Grimes  */
44df8bae1dSRodney W. Grimes 
454bd49128SPeter Wemm #include "opt_rlimit.h"
4619060a3aSPoul-Henning Kamp #include "opt_devfs.h"
474bd49128SPeter Wemm 
48df8bae1dSRodney W. Grimes #include <sys/param.h>
49df8bae1dSRodney W. Grimes #include <sys/filedesc.h>
50df8bae1dSRodney W. Grimes #include <sys/kernel.h>
51ac0ad63fSBruce Evans #include <sys/mount.h>
52946bb7a2SPoul-Henning Kamp #include <sys/sysctl.h>
53df8bae1dSRodney W. Grimes #include <sys/proc.h>
54df8bae1dSRodney W. Grimes #include <sys/resourcevar.h>
55df8bae1dSRodney W. Grimes #include <sys/signalvar.h>
56df8bae1dSRodney W. Grimes #include <sys/systm.h>
57df8bae1dSRodney W. Grimes #include <sys/vnode.h>
58f3f0ca60SSøren Schmidt #include <sys/sysent.h>
59df8bae1dSRodney W. Grimes #include <sys/reboot.h>
60ad7507e2SSteven Wallace #include <sys/sysproto.h>
61efeaf95aSDavid Greenman #include <sys/vmmeter.h>
62df8bae1dSRodney W. Grimes 
63df8bae1dSRodney W. Grimes #include <machine/cpu.h>
64df8bae1dSRodney W. Grimes 
65df8bae1dSRodney W. Grimes #include <vm/vm.h>
66efeaf95aSDavid Greenman #include <vm/vm_param.h>
67efeaf95aSDavid Greenman #include <vm/vm_prot.h>
68efeaf95aSDavid Greenman #include <vm/lock.h>
69efeaf95aSDavid Greenman #include <vm/pmap.h>
70efeaf95aSDavid Greenman #include <vm/vm_map.h>
71efeaf95aSDavid Greenman #include <sys/user.h>
72df8bae1dSRodney W. Grimes 
739ef6c28aSBruce Evans extern struct linker_set	sysinit_set;	/* XXX */
749ef6c28aSBruce Evans 
759ef6c28aSBruce Evans extern void __main __P((void));
769ef6c28aSBruce Evans extern void main __P((void *framep));
77df8bae1dSRodney W. Grimes 
78df8bae1dSRodney W. Grimes /* Components of the first process -- never freed. */
79154c04e5SPoul-Henning Kamp static struct session session0;
80154c04e5SPoul-Henning Kamp static struct pgrp pgrp0;
81df8bae1dSRodney W. Grimes struct	proc proc0;
82154c04e5SPoul-Henning Kamp static struct pcred cred0;
83154c04e5SPoul-Henning Kamp static struct filedesc0 filedesc0;
84154c04e5SPoul-Henning Kamp static struct plimit limit0;
85154c04e5SPoul-Henning Kamp static struct vmspace vmspace0;
86df8bae1dSRodney W. Grimes struct	proc *curproc = &proc0;
872b14f991SJulian Elischer struct	proc *initproc;
88df8bae1dSRodney W. Grimes 
89dedb7b62SPeter Wemm int cmask = CMASK;
90df8bae1dSRodney W. Grimes extern	struct user *proc0paddr;
91df8bae1dSRodney W. Grimes 
922976b7f1SDavid Greenman struct	vnode *rootvp;
93df8bae1dSRodney W. Grimes int	boothowto;
94946bb7a2SPoul-Henning Kamp 
95df8bae1dSRodney W. Grimes struct	timeval boottime;
96946bb7a2SPoul-Henning Kamp SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime,
97946bb7a2SPoul-Henning Kamp 	CTLFLAG_RW, &boottime, timeval, "");
98946bb7a2SPoul-Henning Kamp 
99df8bae1dSRodney W. Grimes struct	timeval runtime;
100df8bae1dSRodney W. Grimes 
1012b14f991SJulian Elischer /*
1022b14f991SJulian Elischer  * Promiscuous argument pass for start_init()
1032b14f991SJulian Elischer  *
1042b14f991SJulian Elischer  * This is a kludge because we use a return from main() rather than a call
10537b688c4SAlexander Langer  * to a new routine in locore.s to kick the kernel alive from locore.s.
1062b14f991SJulian Elischer  */
1072b14f991SJulian Elischer static void	*init_framep;
1082b14f991SJulian Elischer 
109df8bae1dSRodney W. Grimes 
11026f9a767SRodney W. Grimes #if __GNUC__ >= 2
11126f9a767SRodney W. Grimes void __main() {}
11226f9a767SRodney W. Grimes #endif
11326f9a767SRodney W. Grimes 
1142b14f991SJulian Elischer 
11526f9a767SRodney W. Grimes /*
1162b14f991SJulian Elischer  * This ensures that there is at least one entry so that the sysinit_set
1172b14f991SJulian Elischer  * symbol is not undefined.  A sybsystem ID of SI_SUB_DUMMY is never
1182b14f991SJulian Elischer  * executed.
11926f9a767SRodney W. Grimes  */
1202b14f991SJulian Elischer SYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL)
1218a129caeSDavid Greenman 
12226f9a767SRodney W. Grimes 
123df8bae1dSRodney W. Grimes /*
124df8bae1dSRodney W. Grimes  * System startup; initialize the world, create process 0, mount root
125df8bae1dSRodney W. Grimes  * filesystem, and fork to create init and pagedaemon.  Most of the
126df8bae1dSRodney W. Grimes  * hard work is done in the lower-level initialization routines including
127df8bae1dSRodney W. Grimes  * startup(), which does memory initialization and autoconfiguration.
1282b14f991SJulian Elischer  *
1292b14f991SJulian Elischer  * This allows simple addition of new kernel subsystems that require
1302b14f991SJulian Elischer  * boot time initialization.  It also allows substitution of subsystem
1312b14f991SJulian Elischer  * (for instance, a scheduler, kernel profiler, or VM system) by object
1322b14f991SJulian Elischer  * module.  Finally, it allows for optional "kernel threads", like an LFS
1332b14f991SJulian Elischer  * cleaner.
134df8bae1dSRodney W. Grimes  */
13526f9a767SRodney W. Grimes void
136df8bae1dSRodney W. Grimes main(framep)
137df8bae1dSRodney W. Grimes 	void *framep;
138df8bae1dSRodney W. Grimes {
1392b14f991SJulian Elischer 
1402b14f991SJulian Elischer 	register struct sysinit **sipp;		/* system initialization*/
1412b14f991SJulian Elischer 	register struct sysinit **xipp;		/* interior loop of sort*/
1422b14f991SJulian Elischer 	register struct sysinit *save;		/* bubble*/
1432b14f991SJulian Elischer 	int			rval[2];	/* SI_TYPE_KTHREAD support*/
1442b14f991SJulian Elischer 
1452b14f991SJulian Elischer 	/*
1462b14f991SJulian Elischer 	 * Save the locore.s frame pointer for start_init().
1472b14f991SJulian Elischer 	 */
1482b14f991SJulian Elischer 	init_framep = framep;
1492b14f991SJulian Elischer 
1502b14f991SJulian Elischer 	/*
1512b14f991SJulian Elischer 	 * Perform a bubble sort of the system initialization objects by
1522b14f991SJulian Elischer 	 * their subsystem (primary key) and order (secondary key).
1532b14f991SJulian Elischer 	 *
1542b14f991SJulian Elischer 	 * Since some things care about execution order, this is the
1552b14f991SJulian Elischer 	 * operation which ensures continued function.
1562b14f991SJulian Elischer 	 */
1572b14f991SJulian Elischer 	for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
1582b14f991SJulian Elischer 		for( xipp = sipp + 1; *xipp; xipp++) {
1592b14f991SJulian Elischer 			if( (*sipp)->subsystem < (*xipp)->subsystem ||
1602b14f991SJulian Elischer 			    ( (*sipp)->subsystem == (*xipp)->subsystem &&
1612b14f991SJulian Elischer 			      (*sipp)->order < (*xipp)->order))
1622b14f991SJulian Elischer 				continue;	/* skip*/
1632b14f991SJulian Elischer 			save = *sipp;
1642b14f991SJulian Elischer 			*sipp = *xipp;
1652b14f991SJulian Elischer 			*xipp = save;
1662b14f991SJulian Elischer 		}
1672b14f991SJulian Elischer 	}
1682b14f991SJulian Elischer 
1692b14f991SJulian Elischer 	/*
1702b14f991SJulian Elischer 	 * Traverse the (now) ordered list of system initialization tasks.
1712b14f991SJulian Elischer 	 * Perform each task, and continue on to the next task.
1722b14f991SJulian Elischer 	 *
1732b14f991SJulian Elischer 	 * The last item on the list is expected to be the scheduler,
1742b14f991SJulian Elischer 	 * which will not return.
1752b14f991SJulian Elischer 	 */
1762b14f991SJulian Elischer 	for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
1772b14f991SJulian Elischer 		if( (*sipp)->subsystem == SI_SUB_DUMMY)
1782b14f991SJulian Elischer 			continue;	/* skip dummy task(s)*/
1792b14f991SJulian Elischer 
1802b14f991SJulian Elischer 		switch( (*sipp)->type) {
1812b14f991SJulian Elischer 		case SI_TYPE_DEFAULT:
1822b14f991SJulian Elischer 			/* no special processing*/
1832b14f991SJulian Elischer 			(*((*sipp)->func))( (*sipp)->udata);
1842b14f991SJulian Elischer 			break;
1852b14f991SJulian Elischer 
1862b14f991SJulian Elischer 		case SI_TYPE_KTHREAD:
1872b14f991SJulian Elischer 			/* kernel thread*/
1882b14f991SJulian Elischer 			if (fork(&proc0, NULL, rval))
1892b14f991SJulian Elischer 				panic("fork kernel process");
1902b14f991SJulian Elischer 			if (rval[1]) {
1912b14f991SJulian Elischer 				(*((*sipp)->func))( (*sipp)->udata);
1922b14f991SJulian Elischer 				/*
1932b14f991SJulian Elischer 				 * The call to start "init" returns
1942b14f991SJulian Elischer 				 * here after the scheduler has been
1952b14f991SJulian Elischer 				 * started, and returns to the caller
1962b14f991SJulian Elischer 				 * in i386/i386/locore.s.  This is a
1972b14f991SJulian Elischer 				 * necessary part of initialization
1982b14f991SJulian Elischer 				 * and is rather non-obvious.
1992b14f991SJulian Elischer 				 *
2002b14f991SJulian Elischer 				 * No other "kernel threads" should
2012b14f991SJulian Elischer 				 * return here.  Call panic() instead.
2022b14f991SJulian Elischer 				 */
2032b14f991SJulian Elischer 				return;
2042b14f991SJulian Elischer 			}
2052b14f991SJulian Elischer 			break;
2062b14f991SJulian Elischer 
2072b14f991SJulian Elischer 		default:
2082b14f991SJulian Elischer 			panic( "init_main: unrecognized init type");
2092b14f991SJulian Elischer 		}
2102b14f991SJulian Elischer 	}
2112b14f991SJulian Elischer 
2122b14f991SJulian Elischer 	/* NOTREACHED*/
2132b14f991SJulian Elischer }
2142b14f991SJulian Elischer 
2152b14f991SJulian Elischer 
2162b14f991SJulian Elischer /*
2172b14f991SJulian Elischer  * Start a kernel process.  This is called after a fork() call in
2182b14f991SJulian Elischer  * main() in the file kern/init_main.c.
2192b14f991SJulian Elischer  *
2202b14f991SJulian Elischer  * This function is used to start "internal" daemons.
2212b14f991SJulian Elischer  */
2222b14f991SJulian Elischer /* ARGSUSED*/
2232b14f991SJulian Elischer void
2242b14f991SJulian Elischer kproc_start(udata)
225d841aaa7SBruce Evans 	void *udata;
2262b14f991SJulian Elischer {
227d841aaa7SBruce Evans 	struct kproc_desc	*kp = udata;
2282b14f991SJulian Elischer 	struct proc		*p = curproc;
2292b14f991SJulian Elischer 
2302b14f991SJulian Elischer 	/* save a global descriptor, if desired*/
2312b14f991SJulian Elischer 	if( kp->global_procpp != NULL)
2322b14f991SJulian Elischer 		*kp->global_procpp	= p;
2332b14f991SJulian Elischer 
2342b14f991SJulian Elischer 	/* this is a non-swapped system process*/
2352b14f991SJulian Elischer 	p->p_flag |= P_INMEM | P_SYSTEM;
2362b14f991SJulian Elischer 
2372b14f991SJulian Elischer 	/* set up arg0 for 'ps', et al*/
2382b14f991SJulian Elischer 	strcpy( p->p_comm, kp->arg0);
2392b14f991SJulian Elischer 
2402b14f991SJulian Elischer 	/* call the processes' main()...*/
2412b14f991SJulian Elischer 	(*kp->func)();
2422b14f991SJulian Elischer 
2432b14f991SJulian Elischer 	/* NOTREACHED */
2442b14f991SJulian Elischer 	panic("kproc_start: %s", kp->arg0);
2452b14f991SJulian Elischer }
2462b14f991SJulian Elischer 
2472b14f991SJulian Elischer 
2482b14f991SJulian Elischer /*
2492b14f991SJulian Elischer  ***************************************************************************
2502b14f991SJulian Elischer  ****
2512b14f991SJulian Elischer  **** The following SYSINIT's belong elsewhere, but have not yet
2522b14f991SJulian Elischer  **** been moved.
2532b14f991SJulian Elischer  ****
2542b14f991SJulian Elischer  ***************************************************************************
2552b14f991SJulian Elischer  */
2562b14f991SJulian Elischer #ifdef OMIT
2572b14f991SJulian Elischer /*
2582b14f991SJulian Elischer  * Handled by vfs_mountroot (bad idea) at this time... should be
2592b14f991SJulian Elischer  * done the same as 4.4Lite2.
2602b14f991SJulian Elischer  */
2612b14f991SJulian Elischer SYSINIT(swapinit, SI_SUB_SWAP, SI_ORDER_FIRST, swapinit, NULL)
2622b14f991SJulian Elischer #endif	/* OMIT*/
2632b14f991SJulian Elischer 
2642b14f991SJulian Elischer /*
2652b14f991SJulian Elischer  * Should get its own file...
2662b14f991SJulian Elischer  */
2672b14f991SJulian Elischer #ifdef HPFPLIB
2682b14f991SJulian Elischer char	copyright[] =
2692b14f991SJulian Elischer "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\nCopyright (c) 1992 Hewlett-Packard Company\nCopyright (c) 1992 Motorola Inc.\nAll rights reserved.\n\n";
2702b14f991SJulian Elischer #else
2712b14f991SJulian Elischer char	copyright[] =
272b316c8b2SSatoshi Asami "Copyright (c) 1992-1996 FreeBSD Inc.\n"
273ad63a118SSatoshi Asami #ifdef PC98
274ad63a118SSatoshi Asami "Copyright (c) 1994-1996  FreeBSD(98) porting team.\n"
275ad63a118SSatoshi Asami "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.\n"
276ad63a118SSatoshi Asami "Copyright (c) 1992  A.Kojima F.Ukai M.Ishii (KMC).\n"
277ad63a118SSatoshi Asami "\tAll rights reserved.\n\n";
278ad63a118SSatoshi Asami #else
2792b14f991SJulian Elischer "Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California.  All rights reserved.\n\n";
2802b14f991SJulian Elischer #endif
281ad63a118SSatoshi Asami #endif
2824590fd3aSDavid Greenman static void print_caddr_t __P((void *data));
2839ef6c28aSBruce Evans static void
2849ef6c28aSBruce Evans print_caddr_t(data)
2854590fd3aSDavid Greenman 	void *data;
2869ef6c28aSBruce Evans {
2879ef6c28aSBruce Evans 	printf("%s", (char *)data);
2889ef6c28aSBruce Evans }
289d841aaa7SBruce Evans SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)
2902b14f991SJulian Elischer 
2912b14f991SJulian Elischer 
2922b14f991SJulian Elischer /*
2932b14f991SJulian Elischer  ***************************************************************************
2942b14f991SJulian Elischer  ****
2952b14f991SJulian Elischer  **** The two following SYSINT's are proc0 specific glue code.  I am not
2962b14f991SJulian Elischer  **** convinced that they can not be safely combined, but their order of
2972b14f991SJulian Elischer  **** operation has been maintained as the same as the original init_main.c
2982b14f991SJulian Elischer  **** for right now.
2992b14f991SJulian Elischer  ****
3002b14f991SJulian Elischer  **** These probably belong in init_proc.c or kern_proc.c, since they
3012b14f991SJulian Elischer  **** deal with proc0 (the fork template process).
3022b14f991SJulian Elischer  ****
3032b14f991SJulian Elischer  ***************************************************************************
3042b14f991SJulian Elischer  */
3052b14f991SJulian Elischer /* ARGSUSED*/
306154c04e5SPoul-Henning Kamp static void proc0_init __P((void *dummy));
307154c04e5SPoul-Henning Kamp static void
308d841aaa7SBruce Evans proc0_init(dummy)
309d841aaa7SBruce Evans 	void *dummy;
3102b14f991SJulian Elischer {
311df8bae1dSRodney W. Grimes 	register struct proc		*p;
312df8bae1dSRodney W. Grimes 	register struct filedesc0	*fdp;
31392579404SAlexander Langer 	register unsigned i;
314df8bae1dSRodney W. Grimes 
315df8bae1dSRodney W. Grimes 	/*
316df8bae1dSRodney W. Grimes 	 * Initialize the current process pointer (curproc) before
317df8bae1dSRodney W. Grimes 	 * any possible traps/probes to simplify trap processing.
318df8bae1dSRodney W. Grimes 	 */
319df8bae1dSRodney W. Grimes 	p = &proc0;
3202b14f991SJulian Elischer 	curproc = p;			/* XXX redundant*/
321df8bae1dSRodney W. Grimes 
322df8bae1dSRodney W. Grimes 	/*
323a3bfb996SJeffrey Hsu 	 * Initialize process and pgrp structures.
324a3bfb996SJeffrey Hsu 	 */
325a3bfb996SJeffrey Hsu 	procinit();
326a3bfb996SJeffrey Hsu 
327a3bfb996SJeffrey Hsu 	/*
328b1508c72SDavid Greenman 	 * Initialize sleep queue hash table
329b1508c72SDavid Greenman 	 */
330b1508c72SDavid Greenman 	sleepinit();
331b1508c72SDavid Greenman 
332b1508c72SDavid Greenman 	/*
333df8bae1dSRodney W. Grimes 	 * Create process 0 (the swapper).
334df8bae1dSRodney W. Grimes 	 */
335a3bfb996SJeffrey Hsu 	LIST_INSERT_HEAD(&allproc, p, p_list);
336df8bae1dSRodney W. Grimes 	p->p_pgrp = &pgrp0;
337a3bfb996SJeffrey Hsu 	LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
338a3bfb996SJeffrey Hsu 	LIST_INIT(&pgrp0.pg_members);
339a3bfb996SJeffrey Hsu 	LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
340a3bfb996SJeffrey Hsu 
341df8bae1dSRodney W. Grimes 	pgrp0.pg_session = &session0;
342df8bae1dSRodney W. Grimes 	session0.s_count = 1;
343df8bae1dSRodney W. Grimes 	session0.s_leader = p;
344df8bae1dSRodney W. Grimes 
345f3f0ca60SSøren Schmidt 	p->p_sysent = &aout_sysvec;
346f3f0ca60SSøren Schmidt 
347df8bae1dSRodney W. Grimes 	p->p_flag = P_INMEM | P_SYSTEM;
348df8bae1dSRodney W. Grimes 	p->p_stat = SRUN;
349df8bae1dSRodney W. Grimes 	p->p_nice = NZERO;
3507216391eSDavid Greenman 	p->p_rtprio.type = RTP_PRIO_NORMAL;
3517216391eSDavid Greenman 	p->p_rtprio.prio = 0;
352f992f480SDavid Greenman 
353df8bae1dSRodney W. Grimes 	bcopy("swapper", p->p_comm, sizeof ("swapper"));
354df8bae1dSRodney W. Grimes 
355df8bae1dSRodney W. Grimes 	/* Create credentials. */
356df8bae1dSRodney W. Grimes 	cred0.p_refcnt = 1;
357df8bae1dSRodney W. Grimes 	p->p_cred = &cred0;
358df8bae1dSRodney W. Grimes 	p->p_ucred = crget();
359df8bae1dSRodney W. Grimes 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
360df8bae1dSRodney W. Grimes 
361df8bae1dSRodney W. Grimes 	/* Create the file descriptor table. */
362df8bae1dSRodney W. Grimes 	fdp = &filedesc0;
363df8bae1dSRodney W. Grimes 	p->p_fd = &fdp->fd_fd;
364df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_refcnt = 1;
365df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_cmask = cmask;
366df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
367df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
368df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_nfiles = NDFILE;
369df8bae1dSRodney W. Grimes 
370df8bae1dSRodney W. Grimes 	/* Create the limits structures. */
371df8bae1dSRodney W. Grimes 	p->p_limit = &limit0;
372df8bae1dSRodney W. Grimes 	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
373df8bae1dSRodney W. Grimes 		limit0.pl_rlimit[i].rlim_cur =
374df8bae1dSRodney W. Grimes 		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
375df8bae1dSRodney W. Grimes 	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur = NOFILE;
376df8bae1dSRodney W. Grimes 	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur = MAXUPRC;
377df8bae1dSRodney W. Grimes 	i = ptoa(cnt.v_free_count);
378df8bae1dSRodney W. Grimes 	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
379df8bae1dSRodney W. Grimes 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
380df8bae1dSRodney W. Grimes 	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
381df8bae1dSRodney W. Grimes 	limit0.p_refcnt = 1;
382df8bae1dSRodney W. Grimes 
383df8bae1dSRodney W. Grimes 	/* Allocate a prototype map so we have something to fork. */
384df8bae1dSRodney W. Grimes 	p->p_vmspace = &vmspace0;
385df8bae1dSRodney W. Grimes 	vmspace0.vm_refcnt = 1;
386df8bae1dSRodney W. Grimes 	pmap_pinit(&vmspace0.vm_pmap);
38726f9a767SRodney W. Grimes 	vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS),
38847dcd2e5SJohn Dyson 	    trunc_page(VM_MAXUSER_ADDRESS), TRUE);
389df8bae1dSRodney W. Grimes 	vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
390df8bae1dSRodney W. Grimes 	p->p_addr = proc0paddr;				/* XXX */
391df8bae1dSRodney W. Grimes 
3922b14f991SJulian Elischer #define INCOMPAT_LITES2
3932b14f991SJulian Elischer #ifdef INCOMPAT_LITES2
394df8bae1dSRodney W. Grimes 	/*
3952384fde5SDavid Greenman 	 * proc0 needs to have a coherent frame base, too.
3962384fde5SDavid Greenman 	 * This probably makes the identical call for the init proc
3972384fde5SDavid Greenman 	 * that happens later unnecessary since it should inherit
3982384fde5SDavid Greenman 	 * it during the fork.
3992384fde5SDavid Greenman 	 */
4002b14f991SJulian Elischer 	cpu_set_init_frame(p, init_framep);			/* XXX! */
4012b14f991SJulian Elischer #endif	/* INCOMPAT_LITES2*/
4022384fde5SDavid Greenman 
4032384fde5SDavid Greenman 	/*
404df8bae1dSRodney W. Grimes 	 * We continue to place resource usage info and signal
405df8bae1dSRodney W. Grimes 	 * actions in the user struct so they're pageable.
406df8bae1dSRodney W. Grimes 	 */
407df8bae1dSRodney W. Grimes 	p->p_stats = &p->p_addr->u_stats;
408df8bae1dSRodney W. Grimes 	p->p_sigacts = &p->p_addr->u_sigacts;
409df8bae1dSRodney W. Grimes 
410df8bae1dSRodney W. Grimes 	/*
411a3bfb996SJeffrey Hsu 	 * Charge root for one process.
412df8bae1dSRodney W. Grimes 	 */
413df8bae1dSRodney W. Grimes 	(void)chgproccnt(0, 1);
41426f9a767SRodney W. Grimes }
4152b14f991SJulian Elischer SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
4162b14f991SJulian Elischer 
4172b14f991SJulian Elischer /* ARGSUSED*/
418154c04e5SPoul-Henning Kamp static void proc0_post __P((void *dummy));
419154c04e5SPoul-Henning Kamp static void
420d841aaa7SBruce Evans proc0_post(dummy)
421d841aaa7SBruce Evans 	void *dummy;
4222b14f991SJulian Elischer {
423a6fc8288SPeter Wemm 	struct timeval tv;
424a6fc8288SPeter Wemm 
4252b14f991SJulian Elischer 	/*
4262b14f991SJulian Elischer 	 * Now can look at time, having had a chance to verify the time
4272b14f991SJulian Elischer 	 * from the file system.  Reset p->p_rtime as it may have been
4282b14f991SJulian Elischer 	 * munched in mi_switch() after the time got set.
4292b14f991SJulian Elischer 	 */
4302b14f991SJulian Elischer 	proc0.p_stats->p_start = runtime = mono_time = boottime = time;
4312b14f991SJulian Elischer 	proc0.p_rtime.tv_sec = proc0.p_rtime.tv_usec = 0;
4322b14f991SJulian Elischer 
433a6fc8288SPeter Wemm 	/*
434a6fc8288SPeter Wemm 	 * Give the ``random'' number generator a thump.
435a6fc8288SPeter Wemm 	 */
436a6fc8288SPeter Wemm 	microtime(&tv);
437a6fc8288SPeter Wemm 	srandom(tv.tv_sec ^ tv.tv_usec);
438a6fc8288SPeter Wemm 
4392b14f991SJulian Elischer 	/* Initialize signal state for process 0. */
4402b14f991SJulian Elischer 	siginit(&proc0);
4412b14f991SJulian Elischer }
4422b14f991SJulian Elischer SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL)
4432b14f991SJulian Elischer 
4442b14f991SJulian Elischer 
4452b14f991SJulian Elischer 
446df8bae1dSRodney W. Grimes 
447df8bae1dSRodney W. Grimes /*
4482b14f991SJulian Elischer  ***************************************************************************
4492b14f991SJulian Elischer  ****
4502b14f991SJulian Elischer  **** The following SYSINIT's and glue code should be moved to the
4512b14f991SJulian Elischer  **** respective files on a per subsystem basis.
4522b14f991SJulian Elischer  ****
4532b14f991SJulian Elischer  ***************************************************************************
454df8bae1dSRodney W. Grimes  */
4552b14f991SJulian Elischer /* ARGSUSED*/
456154c04e5SPoul-Henning Kamp static void sched_setup __P((void *dummy));
457154c04e5SPoul-Henning Kamp static void
458d841aaa7SBruce Evans sched_setup(dummy)
459d841aaa7SBruce Evans 	void *dummy;
4602b14f991SJulian Elischer {
461df8bae1dSRodney W. Grimes 	/* Kick off timeout driven events by calling first time. */
462df8bae1dSRodney W. Grimes 	roundrobin(NULL);
463df8bae1dSRodney W. Grimes 	schedcpu(NULL);
4642b14f991SJulian Elischer }
4652b14f991SJulian Elischer SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL)
466df8bae1dSRodney W. Grimes 
4672b14f991SJulian Elischer /* ARGSUSED*/
468154c04e5SPoul-Henning Kamp static void xxx_vfs_mountroot __P((void *dummy));
469154c04e5SPoul-Henning Kamp static void
470d841aaa7SBruce Evans xxx_vfs_mountroot(dummy)
471d841aaa7SBruce Evans 	void *dummy;
4722b14f991SJulian Elischer {
473df8bae1dSRodney W. Grimes 	/* Mount the root file system. */
4744590fd3aSDavid Greenman 	if ((*mountroot)(mountrootvfsops))
475df8bae1dSRodney W. Grimes 		panic("cannot mount root");
4762b14f991SJulian Elischer }
4772b14f991SJulian Elischer SYSINIT(mountroot, SI_SUB_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot, NULL)
4782b14f991SJulian Elischer 
4792b14f991SJulian Elischer /* ARGSUSED*/
480154c04e5SPoul-Henning Kamp static void xxx_vfs_root_fdtab __P((void *dummy));
481154c04e5SPoul-Henning Kamp static void
482d841aaa7SBruce Evans xxx_vfs_root_fdtab(dummy)
483d841aaa7SBruce Evans 	void *dummy;
4842b14f991SJulian Elischer {
4852b14f991SJulian Elischer 	register struct filedesc0	*fdp = &filedesc0;
486df8bae1dSRodney W. Grimes 
487df8bae1dSRodney W. Grimes 	/* Get the vnode for '/'.  Set fdp->fd_fd.fd_cdir to reference it. */
488628641f8SDavid Greenman 	if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
489df8bae1dSRodney W. Grimes 		panic("cannot find root vnode");
490df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_cdir = rootvnode;
491df8bae1dSRodney W. Grimes 	VREF(fdp->fd_fd.fd_cdir);
492df8bae1dSRodney W. Grimes 	VOP_UNLOCK(rootvnode);
493df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_rdir = NULL;
4942b14f991SJulian Elischer }
4952b14f991SJulian Elischer SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL)
4962b14f991SJulian Elischer 
497df8bae1dSRodney W. Grimes 
498df8bae1dSRodney W. Grimes /*
4992b14f991SJulian Elischer  ***************************************************************************
5002b14f991SJulian Elischer  ****
5012b14f991SJulian Elischer  **** The following code probably belongs in another file, like
5022b14f991SJulian Elischer  **** kern/init_init.c.  It is here for two reasons only:
5032b14f991SJulian Elischer  ****
5042b14f991SJulian Elischer  ****	1)	This code returns to startup the system; this is
5052b14f991SJulian Elischer  ****		abnormal for a kernel thread.
5062b14f991SJulian Elischer  ****	2)	This code promiscuously uses init_frame
5072b14f991SJulian Elischer  ****
5082b14f991SJulian Elischer  ***************************************************************************
509df8bae1dSRodney W. Grimes  */
510df8bae1dSRodney W. Grimes 
511d841aaa7SBruce Evans static void kthread_init __P((void *dummy));
5122b14f991SJulian Elischer SYSINIT_KT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kthread_init, NULL)
5132b14f991SJulian Elischer 
5142b14f991SJulian Elischer 
5152b14f991SJulian Elischer static void start_init __P((struct proc *p, void *framep));
5162b14f991SJulian Elischer 
5172b14f991SJulian Elischer /* ARGSUSED*/
5182b14f991SJulian Elischer static void
519d841aaa7SBruce Evans kthread_init(dummy)
520d841aaa7SBruce Evans 	void *dummy;
5212b14f991SJulian Elischer {
522df8bae1dSRodney W. Grimes 
523df8bae1dSRodney W. Grimes 	/* Create process 1 (init(8)). */
5242b14f991SJulian Elischer 	start_init(curproc, init_framep);
5252b14f991SJulian Elischer 
5262b14f991SJulian Elischer 	/*
5272b14f991SJulian Elischer 	 * This is the only kernel thread allowed to return yo the
5282b14f991SJulian Elischer 	 * caller!!!
5292b14f991SJulian Elischer 	 */
530df8bae1dSRodney W. Grimes 	return;
531df8bae1dSRodney W. Grimes }
532df8bae1dSRodney W. Grimes 
533df8bae1dSRodney W. Grimes 
534df8bae1dSRodney W. Grimes /*
535df8bae1dSRodney W. Grimes  * List of paths to try when searching for "init".
536df8bae1dSRodney W. Grimes  */
537df8bae1dSRodney W. Grimes static char *initpaths[] = {
538df8bae1dSRodney W. Grimes 	"/sbin/init",
539df8bae1dSRodney W. Grimes 	"/sbin/oinit",
540df8bae1dSRodney W. Grimes 	"/sbin/init.bak",
5412257b745SPoul-Henning Kamp 	"/stand/sysinstall",
542df8bae1dSRodney W. Grimes 	NULL,
543df8bae1dSRodney W. Grimes };
544df8bae1dSRodney W. Grimes 
545df8bae1dSRodney W. Grimes /*
546df8bae1dSRodney W. Grimes  * Start the initial user process; try exec'ing each pathname in "initpaths".
547df8bae1dSRodney W. Grimes  * The program is invoked with one argument containing the boot flags.
548df8bae1dSRodney W. Grimes  */
549df8bae1dSRodney W. Grimes static void
550df8bae1dSRodney W. Grimes start_init(p, framep)
551df8bae1dSRodney W. Grimes 	struct proc *p;
552df8bae1dSRodney W. Grimes 	void *framep;
553df8bae1dSRodney W. Grimes {
554df8bae1dSRodney W. Grimes 	vm_offset_t addr;
555df8bae1dSRodney W. Grimes 	struct execve_args args;
556df8bae1dSRodney W. Grimes 	int options, i, retval[2], error;
557df8bae1dSRodney W. Grimes 	char **pathp, *path, *ucp, **uap, *arg0, *arg1;
558df8bae1dSRodney W. Grimes 
559df8bae1dSRodney W. Grimes 	initproc = p;
560df8bae1dSRodney W. Grimes 
561df8bae1dSRodney W. Grimes 	/*
562df8bae1dSRodney W. Grimes 	 * We need to set the system call frame as if we were entered through
563df8bae1dSRodney W. Grimes 	 * a syscall() so that when we call execve() below, it will be able
564df8bae1dSRodney W. Grimes 	 * to set the entry point (see setregs) when it tries to exec.  The
565df8bae1dSRodney W. Grimes 	 * startup code in "locore.s" has allocated space for the frame and
566df8bae1dSRodney W. Grimes 	 * passed a pointer to that space as main's argument.
567df8bae1dSRodney W. Grimes 	 */
568df8bae1dSRodney W. Grimes 	cpu_set_init_frame(p, framep);
569df8bae1dSRodney W. Grimes 
570df8bae1dSRodney W. Grimes 	/*
571df8bae1dSRodney W. Grimes 	 * Need just enough stack to hold the faked-up "execve()" arguments.
572df8bae1dSRodney W. Grimes 	 */
57326f9a767SRodney W. Grimes 	addr = trunc_page(VM_MAXUSER_ADDRESS - PAGE_SIZE);
574bd7e5f99SJohn Dyson 	if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0)
575df8bae1dSRodney W. Grimes 		panic("init: couldn't allocate argument space");
576df8bae1dSRodney W. Grimes 	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
57726f9a767SRodney W. Grimes 	p->p_vmspace->vm_ssize = 1;
578df8bae1dSRodney W. Grimes 
579df8bae1dSRodney W. Grimes 	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
580df8bae1dSRodney W. Grimes 		/*
581df8bae1dSRodney W. Grimes 		 * Move out the boot flag argument.
582df8bae1dSRodney W. Grimes 		 */
583df8bae1dSRodney W. Grimes 		options = 0;
584df8bae1dSRodney W. Grimes 		ucp = (char *)USRSTACK;
585df8bae1dSRodney W. Grimes 		(void)subyte(--ucp, 0);		/* trailing zero */
586df8bae1dSRodney W. Grimes 		if (boothowto & RB_SINGLE) {
587df8bae1dSRodney W. Grimes 			(void)subyte(--ucp, 's');
588df8bae1dSRodney W. Grimes 			options = 1;
589df8bae1dSRodney W. Grimes 		}
590df8bae1dSRodney W. Grimes #ifdef notyet
591df8bae1dSRodney W. Grimes                 if (boothowto & RB_FASTBOOT) {
592df8bae1dSRodney W. Grimes 			(void)subyte(--ucp, 'f');
593df8bae1dSRodney W. Grimes 			options = 1;
594df8bae1dSRodney W. Grimes 		}
595df8bae1dSRodney W. Grimes #endif
59617755ac8SPoul-Henning Kamp 
59717755ac8SPoul-Henning Kamp #ifdef BOOTCDROM
59817755ac8SPoul-Henning Kamp 		(void)subyte(--ucp, 'C');
59917755ac8SPoul-Henning Kamp 		options = 1;
60017755ac8SPoul-Henning Kamp #endif
60119060a3aSPoul-Henning Kamp 
60219060a3aSPoul-Henning Kamp #if defined(DEVFS) && defined(DEVFS_ROOT)
60319060a3aSPoul-Henning Kamp 		(void)subyte(--ucp, 'd');
60419060a3aSPoul-Henning Kamp 		options = 1;
60519060a3aSPoul-Henning Kamp #endif
606df8bae1dSRodney W. Grimes 		if (options == 0)
607df8bae1dSRodney W. Grimes 			(void)subyte(--ucp, '-');
608df8bae1dSRodney W. Grimes 		(void)subyte(--ucp, '-');		/* leading hyphen */
609df8bae1dSRodney W. Grimes 		arg1 = ucp;
610df8bae1dSRodney W. Grimes 
611df8bae1dSRodney W. Grimes 		/*
612df8bae1dSRodney W. Grimes 		 * Move out the file name (also arg 0).
613df8bae1dSRodney W. Grimes 		 */
614df8bae1dSRodney W. Grimes 		for (i = strlen(path) + 1; i >= 0; i--)
615df8bae1dSRodney W. Grimes 			(void)subyte(--ucp, path[i]);
616df8bae1dSRodney W. Grimes 		arg0 = ucp;
617df8bae1dSRodney W. Grimes 
618df8bae1dSRodney W. Grimes 		/*
619df8bae1dSRodney W. Grimes 		 * Move out the arg pointers.
620df8bae1dSRodney W. Grimes 		 */
621df8bae1dSRodney W. Grimes 		uap = (char **)((int)ucp & ~(NBPW-1));
622df8bae1dSRodney W. Grimes 		(void)suword((caddr_t)--uap, 0);	/* terminator */
623df8bae1dSRodney W. Grimes 		(void)suword((caddr_t)--uap, (int)arg1);
624df8bae1dSRodney W. Grimes 		(void)suword((caddr_t)--uap, (int)arg0);
625df8bae1dSRodney W. Grimes 
626df8bae1dSRodney W. Grimes 		/*
627df8bae1dSRodney W. Grimes 		 * Point at the arguments.
628df8bae1dSRodney W. Grimes 		 */
629df8bae1dSRodney W. Grimes 		args.fname = arg0;
63026f9a767SRodney W. Grimes 		args.argv = uap;
63126f9a767SRodney W. Grimes 		args.envv = NULL;
632df8bae1dSRodney W. Grimes 
633df8bae1dSRodney W. Grimes 		/*
634df8bae1dSRodney W. Grimes 		 * Now try to exec the program.  If can't for any reason
635df8bae1dSRodney W. Grimes 		 * other than it doesn't exist, complain.
6362b14f991SJulian Elischer 		 *
6372b14f991SJulian Elischer 		 * Otherwise return to main() which returns to btext
6382b14f991SJulian Elischer 		 * which completes the system startup.
639df8bae1dSRodney W. Grimes 		 */
640b5e8ce9fSBruce Evans 		if ((error = execve(p, &args, &retval[0])) == 0)
641df8bae1dSRodney W. Grimes 			return;
642df8bae1dSRodney W. Grimes 		if (error != ENOENT)
643df8bae1dSRodney W. Grimes 			printf("exec %s: error %d\n", path, error);
644df8bae1dSRodney W. Grimes 	}
645df8bae1dSRodney W. Grimes 	printf("init: not found\n");
646df8bae1dSRodney W. Grimes 	panic("no init");
647df8bae1dSRodney W. Grimes }
648