xref: /freebsd/sys/kern/init_main.c (revision 2cf6bdac50a18ebb4e0f1b6999751aa4a89f7d6e)
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
42df8bae1dSRodney W. Grimes  */
43df8bae1dSRodney W. Grimes 
44677b542eSDavid E. O'Brien #include <sys/cdefs.h>
45677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
46677b542eSDavid E. O'Brien 
4767481196SJohn Birrell #include "opt_init_path.h"
4840244964SRobert Watson #include "opt_mac.h"
494bd49128SPeter Wemm 
50df8bae1dSRodney W. Grimes #include <sys/param.h>
519e209b12SAlfred Perlstein #include <sys/kernel.h>
52f36ba452SJake Burkholder #include <sys/exec.h>
53b3c5c18dSBruce Evans #include <sys/file.h>
54df8bae1dSRodney W. Grimes #include <sys/filedesc.h>
550384fff8SJason Evans #include <sys/ktr.h>
561005a129SJohn Baldwin #include <sys/lock.h>
5740244964SRobert Watson #include <sys/mac.h>
58ac0ad63fSBruce Evans #include <sys/mount.h>
5935e0e5b3SJohn Baldwin #include <sys/mutex.h>
608f19eb88SIan Dowse #include <sys/syscallsubr.h>
61946bb7a2SPoul-Henning Kamp #include <sys/sysctl.h>
62df8bae1dSRodney W. Grimes #include <sys/proc.h>
63df8bae1dSRodney W. Grimes #include <sys/resourcevar.h>
64df8bae1dSRodney W. Grimes #include <sys/systm.h>
6536240ea5SDoug Rabson #include <sys/signalvar.h>
66df8bae1dSRodney W. Grimes #include <sys/vnode.h>
67f3f0ca60SSøren Schmidt #include <sys/sysent.h>
68df8bae1dSRodney W. Grimes #include <sys/reboot.h>
69de028f5aSJeff Roberson #include <sys/sched.h>
701005a129SJohn Baldwin #include <sys/sx.h>
71ad7507e2SSteven Wallace #include <sys/sysproto.h>
72efeaf95aSDavid Greenman #include <sys/vmmeter.h>
7374b2192aSJohn Dyson #include <sys/unistd.h>
7494e9d7c1SPeter Wemm #include <sys/malloc.h>
75db901281SPoul-Henning Kamp #include <sys/conf.h>
76df8bae1dSRodney W. Grimes 
77df8bae1dSRodney W. Grimes #include <machine/cpu.h>
78df8bae1dSRodney W. Grimes 
79df8bae1dSRodney W. Grimes #include <vm/vm.h>
80efeaf95aSDavid Greenman #include <vm/vm_param.h>
81efeaf95aSDavid Greenman #include <vm/pmap.h>
82efeaf95aSDavid Greenman #include <vm/vm_map.h>
83efeaf95aSDavid Greenman #include <sys/user.h>
846faaa756SWolfram Schneider #include <sys/copyright.h>
85df8bae1dSRodney W. Grimes 
8637b087a6SPeter Wemm void mi_startup(void);				/* Should be elsewhere */
87df8bae1dSRodney W. Grimes 
88df8bae1dSRodney W. Grimes /* Components of the first process -- never freed. */
89154c04e5SPoul-Henning Kamp static struct session session0;
90154c04e5SPoul-Henning Kamp static struct pgrp pgrp0;
91df8bae1dSRodney W. Grimes struct	proc proc0;
92079b7badSJulian Elischer struct	thread thread0;
934f0db5e0SJulian Elischer struct	kse kse0;
944f0db5e0SJulian Elischer struct	ksegrp ksegrp0;
95154c04e5SPoul-Henning Kamp static struct filedesc0 filedesc0;
9623734995SJake Burkholder struct	vmspace vmspace0;
972b14f991SJulian Elischer struct	proc *initproc;
98df8bae1dSRodney W. Grimes 
992976b7f1SDavid Greenman struct	vnode *rootvp;
100c463cf1cSBruce Evans int	boothowto = 0;		/* initialized so that it can be patched */
1018d0bf3d6SJordan K. Hubbard SYSCTL_INT(_debug, OID_AUTO, boothowto, CTLFLAG_RD, &boothowto, 0, "");
1027a08bae6SJohn Baldwin int	bootverbose;
1037a08bae6SJohn Baldwin SYSCTL_INT(_debug, OID_AUTO, bootverbose, CTLFLAG_RW, &bootverbose, 0, "");
104946bb7a2SPoul-Henning Kamp 
1052b14f991SJulian Elischer /*
1062b14f991SJulian Elischer  * This ensures that there is at least one entry so that the sysinit_set
1072b14f991SJulian Elischer  * symbol is not undefined.  A sybsystem ID of SI_SUB_DUMMY is never
1082b14f991SJulian Elischer  * executed.
10926f9a767SRodney W. Grimes  */
1102b14f991SJulian Elischer SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL)
1118a129caeSDavid Greenman 
11294e9d7c1SPeter Wemm /*
11394e9d7c1SPeter Wemm  * The sysinit table itself.  Items are checked off as the are run.
11494e9d7c1SPeter Wemm  * If we want to register new sysinit types, add them to newsysinit.
11594e9d7c1SPeter Wemm  */
116f41325dbSPeter Wemm SET_DECLARE(sysinit_set, struct sysinit);
117f41325dbSPeter Wemm struct sysinit **sysinit, **sysinit_end;
118f41325dbSPeter Wemm struct sysinit **newsysinit, **newsysinit_end;
11994e9d7c1SPeter Wemm 
12094e9d7c1SPeter Wemm /*
12194e9d7c1SPeter Wemm  * Merge a new sysinit set into the current set, reallocating it if
12294e9d7c1SPeter Wemm  * necessary.  This can only be called after malloc is running.
12394e9d7c1SPeter Wemm  */
12494e9d7c1SPeter Wemm void
125f41325dbSPeter Wemm sysinit_add(struct sysinit **set, struct sysinit **set_end)
12694e9d7c1SPeter Wemm {
12794e9d7c1SPeter Wemm 	struct sysinit **newset;
12894e9d7c1SPeter Wemm 	struct sysinit **sipp;
12994e9d7c1SPeter Wemm 	struct sysinit **xipp;
130f41325dbSPeter Wemm 	int count;
13194e9d7c1SPeter Wemm 
132f41325dbSPeter Wemm 	count = set_end - set;
133ddd62546SPeter Wemm 	if (newsysinit)
134f41325dbSPeter Wemm 		count += newsysinit_end - newsysinit;
135ddd62546SPeter Wemm 	else
136f41325dbSPeter Wemm 		count += sysinit_end - sysinit;
13794e9d7c1SPeter Wemm 	newset = malloc(count * sizeof(*sipp), M_TEMP, M_NOWAIT);
13894e9d7c1SPeter Wemm 	if (newset == NULL)
13994e9d7c1SPeter Wemm 		panic("cannot malloc for sysinit");
14094e9d7c1SPeter Wemm 	xipp = newset;
141ddd62546SPeter Wemm 	if (newsysinit)
142f41325dbSPeter Wemm 		for (sipp = newsysinit; sipp < newsysinit_end; sipp++)
143ddd62546SPeter Wemm 			*xipp++ = *sipp;
144ddd62546SPeter Wemm 	else
145f41325dbSPeter Wemm 		for (sipp = sysinit; sipp < sysinit_end; sipp++)
14694e9d7c1SPeter Wemm 			*xipp++ = *sipp;
147f41325dbSPeter Wemm 	for (sipp = set; sipp < set_end; sipp++)
14894e9d7c1SPeter Wemm 		*xipp++ = *sipp;
149ddd62546SPeter Wemm 	if (newsysinit)
150ddd62546SPeter Wemm 		free(newsysinit, M_TEMP);
15194e9d7c1SPeter Wemm 	newsysinit = newset;
152f41325dbSPeter Wemm 	newsysinit_end = newset + count;
15394e9d7c1SPeter Wemm }
15426f9a767SRodney W. Grimes 
155df8bae1dSRodney W. Grimes /*
156df8bae1dSRodney W. Grimes  * System startup; initialize the world, create process 0, mount root
157df8bae1dSRodney W. Grimes  * filesystem, and fork to create init and pagedaemon.  Most of the
158df8bae1dSRodney W. Grimes  * hard work is done in the lower-level initialization routines including
159df8bae1dSRodney W. Grimes  * startup(), which does memory initialization and autoconfiguration.
1602b14f991SJulian Elischer  *
1612b14f991SJulian Elischer  * This allows simple addition of new kernel subsystems that require
1622b14f991SJulian Elischer  * boot time initialization.  It also allows substitution of subsystem
1632b14f991SJulian Elischer  * (for instance, a scheduler, kernel profiler, or VM system) by object
164c5b193bfSPoul-Henning Kamp  * module.  Finally, it allows for optional "kernel threads".
165df8bae1dSRodney W. Grimes  */
16626f9a767SRodney W. Grimes void
16737b087a6SPeter Wemm mi_startup(void)
168df8bae1dSRodney W. Grimes {
1692b14f991SJulian Elischer 
1702b14f991SJulian Elischer 	register struct sysinit **sipp;		/* system initialization*/
1712b14f991SJulian Elischer 	register struct sysinit **xipp;		/* interior loop of sort*/
1722b14f991SJulian Elischer 	register struct sysinit *save;		/* bubble*/
1732b14f991SJulian Elischer 
174f41325dbSPeter Wemm 	if (sysinit == NULL) {
175f41325dbSPeter Wemm 		sysinit = SET_BEGIN(sysinit_set);
176f41325dbSPeter Wemm 		sysinit_end = SET_LIMIT(sysinit_set);
177f41325dbSPeter Wemm 	}
178f41325dbSPeter Wemm 
17994e9d7c1SPeter Wemm restart:
1802b14f991SJulian Elischer 	/*
1812b14f991SJulian Elischer 	 * Perform a bubble sort of the system initialization objects by
1822b14f991SJulian Elischer 	 * their subsystem (primary key) and order (secondary key).
1832b14f991SJulian Elischer 	 */
184f41325dbSPeter Wemm 	for (sipp = sysinit; sipp < sysinit_end; sipp++) {
185f41325dbSPeter Wemm 		for (xipp = sipp + 1; xipp < sysinit_end; xipp++) {
1862b14f991SJulian Elischer 			if ((*sipp)->subsystem < (*xipp)->subsystem ||
1872b14f991SJulian Elischer 			     ((*sipp)->subsystem == (*xipp)->subsystem &&
188af4b2d2dSPeter Wemm 			      (*sipp)->order <= (*xipp)->order))
1892b14f991SJulian Elischer 				continue;	/* skip*/
1902b14f991SJulian Elischer 			save = *sipp;
1912b14f991SJulian Elischer 			*sipp = *xipp;
1922b14f991SJulian Elischer 			*xipp = save;
1932b14f991SJulian Elischer 		}
1942b14f991SJulian Elischer 	}
1952b14f991SJulian Elischer 
1962b14f991SJulian Elischer 	/*
1972b14f991SJulian Elischer 	 * Traverse the (now) ordered list of system initialization tasks.
1982b14f991SJulian Elischer 	 * Perform each task, and continue on to the next task.
1992b14f991SJulian Elischer 	 *
2002b14f991SJulian Elischer 	 * The last item on the list is expected to be the scheduler,
2012b14f991SJulian Elischer 	 * which will not return.
2022b14f991SJulian Elischer 	 */
203f41325dbSPeter Wemm 	for (sipp = sysinit; sipp < sysinit_end; sipp++) {
20474b2192aSJohn Dyson 
2052b14f991SJulian Elischer 		if ((*sipp)->subsystem == SI_SUB_DUMMY)
2062b14f991SJulian Elischer 			continue;	/* skip dummy task(s)*/
2072b14f991SJulian Elischer 
20894e9d7c1SPeter Wemm 		if ((*sipp)->subsystem == SI_SUB_DONE)
20994e9d7c1SPeter Wemm 			continue;
21094e9d7c1SPeter Wemm 
2119c8b8baaSPeter Wemm 		/* Call function */
2122b14f991SJulian Elischer 		(*((*sipp)->func))((*sipp)->udata);
21394e9d7c1SPeter Wemm 
21494e9d7c1SPeter Wemm 		/* Check off the one we're just done */
21594e9d7c1SPeter Wemm 		(*sipp)->subsystem = SI_SUB_DONE;
21694e9d7c1SPeter Wemm 
21794e9d7c1SPeter Wemm 		/* Check if we've installed more sysinit items via KLD */
21894e9d7c1SPeter Wemm 		if (newsysinit != NULL) {
219f41325dbSPeter Wemm 			if (sysinit != SET_BEGIN(sysinit_set))
22094e9d7c1SPeter Wemm 				free(sysinit, M_TEMP);
22194e9d7c1SPeter Wemm 			sysinit = newsysinit;
222f41325dbSPeter Wemm 			sysinit_end = newsysinit_end;
22394e9d7c1SPeter Wemm 			newsysinit = NULL;
224f41325dbSPeter Wemm 			newsysinit_end = NULL;
22594e9d7c1SPeter Wemm 			goto restart;
22694e9d7c1SPeter Wemm 		}
2272b14f991SJulian Elischer 	}
2282b14f991SJulian Elischer 
229477a642cSPeter Wemm 	panic("Shouldn't get here!");
2302b14f991SJulian Elischer 	/* NOTREACHED*/
2312b14f991SJulian Elischer }
2322b14f991SJulian Elischer 
2332b14f991SJulian Elischer 
2342b14f991SJulian Elischer /*
2352b14f991SJulian Elischer  ***************************************************************************
2362b14f991SJulian Elischer  ****
2372b14f991SJulian Elischer  **** The following SYSINIT's belong elsewhere, but have not yet
2382b14f991SJulian Elischer  **** been moved.
2392b14f991SJulian Elischer  ****
2402b14f991SJulian Elischer  ***************************************************************************
2412b14f991SJulian Elischer  */
2429ef6c28aSBruce Evans static void
24337b087a6SPeter Wemm print_caddr_t(void *data __unused)
2449ef6c28aSBruce Evans {
2459ef6c28aSBruce Evans 	printf("%s", (char *)data);
2469ef6c28aSBruce Evans }
247d841aaa7SBruce Evans SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)
2487a08bae6SJohn Baldwin SYSINIT(version, SI_SUB_COPYRIGHT, SI_ORDER_SECOND, print_caddr_t, version)
2497a08bae6SJohn Baldwin 
2502cf6bdacSPoul-Henning Kamp #ifdef WITNESS
2512cf6bdacSPoul-Henning Kamp static char wit_warn[] =
2522cf6bdacSPoul-Henning Kamp      "WARNING: WITNESS option enabled, expect reduced performance.\n";
2532cf6bdacSPoul-Henning Kamp SYSINIT(witwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 1,
2542cf6bdacSPoul-Henning Kamp    print_caddr_t, wit_warn)
2552cf6bdacSPoul-Henning Kamp #endif
2562cf6bdacSPoul-Henning Kamp 
2572cf6bdacSPoul-Henning Kamp #ifdef DIAGNOSTIC
2582cf6bdacSPoul-Henning Kamp static char diag_warn[] =
2592cf6bdacSPoul-Henning Kamp      "WARNING: DIAGNOSTIC option enabled, expect reduced performance.\n";
2602cf6bdacSPoul-Henning Kamp SYSINIT(diagwarn, SI_SUB_COPYRIGHT, SI_ORDER_SECOND + 2,
2612cf6bdacSPoul-Henning Kamp     print_caddr_t, diag_warn)
2622cf6bdacSPoul-Henning Kamp #endif
2632cf6bdacSPoul-Henning Kamp 
2647a08bae6SJohn Baldwin static void
2657a08bae6SJohn Baldwin set_boot_verbose(void *data __unused)
2667a08bae6SJohn Baldwin {
2677a08bae6SJohn Baldwin 
2687a08bae6SJohn Baldwin 	if (boothowto & RB_VERBOSE)
2697a08bae6SJohn Baldwin 		bootverbose++;
2707a08bae6SJohn Baldwin }
2717a08bae6SJohn Baldwin SYSINIT(boot_verbose, SI_SUB_TUNABLES, SI_ORDER_ANY, set_boot_verbose, NULL)
2722b14f991SJulian Elischer 
273f36ba452SJake Burkholder struct sysentvec null_sysvec = {
274f36ba452SJake Burkholder 	0,
275f36ba452SJake Burkholder 	NULL,
276f36ba452SJake Burkholder 	0,
277f36ba452SJake Burkholder 	0,
278f36ba452SJake Burkholder 	NULL,
279f36ba452SJake Burkholder 	0,
280f36ba452SJake Burkholder 	NULL,
281f36ba452SJake Burkholder 	NULL,
282f36ba452SJake Burkholder 	NULL,
283f36ba452SJake Burkholder 	NULL,
284f36ba452SJake Burkholder 	NULL,
285f36ba452SJake Burkholder 	NULL,
286f36ba452SJake Burkholder 	NULL,
287f36ba452SJake Burkholder 	"null",
288f36ba452SJake Burkholder 	NULL,
289f36ba452SJake Burkholder 	NULL,
290f36ba452SJake Burkholder 	0,
291f36ba452SJake Burkholder 	PAGE_SIZE,
292f36ba452SJake Burkholder 	VM_MIN_ADDRESS,
293f36ba452SJake Burkholder 	VM_MAXUSER_ADDRESS,
294f36ba452SJake Burkholder 	USRSTACK,
295f36ba452SJake Burkholder 	PS_STRINGS,
296f36ba452SJake Burkholder 	VM_PROT_ALL,
297f36ba452SJake Burkholder 	NULL,
298c460ac3aSPeter Wemm 	NULL,
299f36ba452SJake Burkholder 	NULL
300f36ba452SJake Burkholder };
3013ebc1248SPeter Wemm 
3022b14f991SJulian Elischer /*
3032b14f991SJulian Elischer  ***************************************************************************
3042b14f991SJulian Elischer  ****
3050c920c0dSGiorgos Keramidas  **** The two following SYSINIT's are proc0 specific glue code.  I am not
3062b14f991SJulian Elischer  **** convinced that they can not be safely combined, but their order of
3072b14f991SJulian Elischer  **** operation has been maintained as the same as the original init_main.c
3082b14f991SJulian Elischer  **** for right now.
3092b14f991SJulian Elischer  ****
3102b14f991SJulian Elischer  **** These probably belong in init_proc.c or kern_proc.c, since they
3112b14f991SJulian Elischer  **** deal with proc0 (the fork template process).
3122b14f991SJulian Elischer  ****
3132b14f991SJulian Elischer  ***************************************************************************
3142b14f991SJulian Elischer  */
3152b14f991SJulian Elischer /* ARGSUSED*/
316154c04e5SPoul-Henning Kamp static void
31737b087a6SPeter Wemm proc0_init(void *dummy __unused)
3182b14f991SJulian Elischer {
319df8bae1dSRodney W. Grimes 	register struct proc		*p;
320df8bae1dSRodney W. Grimes 	register struct filedesc0	*fdp;
32192579404SAlexander Langer 	register unsigned i;
322b40ce416SJulian Elischer 	struct thread *td;
323079b7badSJulian Elischer 	struct ksegrp *kg;
324079b7badSJulian Elischer 	struct kse *ke;
325df8bae1dSRodney W. Grimes 
3260cddd8f0SMatthew Dillon 	GIANT_REQUIRED;
327df8bae1dSRodney W. Grimes 	p = &proc0;
328079b7badSJulian Elischer 	td = &thread0;
3294f0db5e0SJulian Elischer 	ke = &kse0;
3304f0db5e0SJulian Elischer 	kg = &ksegrp0;
331df8bae1dSRodney W. Grimes 
332de028f5aSJeff Roberson 	ke->ke_sched = kse0_sched;
333de028f5aSJeff Roberson 	kg->kg_sched = ksegrp0_sched;
334de028f5aSJeff Roberson 	p->p_sched = proc0_sched;
335de028f5aSJeff Roberson 	td->td_sched = thread0_sched;
336de028f5aSJeff Roberson 
337df8bae1dSRodney W. Grimes 	/*
3380384fff8SJason Evans 	 * Initialize magic number.
3390384fff8SJason Evans 	 */
3400384fff8SJason Evans 	p->p_magic = P_MAGIC;
3410384fff8SJason Evans 
3420384fff8SJason Evans 	/*
343079b7badSJulian Elischer 	 * Initialize thread, process and pgrp structures.
344a3bfb996SJeffrey Hsu 	 */
345a3bfb996SJeffrey Hsu 	procinit();
346e602ba25SJulian Elischer 	threadinit();
347a3bfb996SJeffrey Hsu 
348a3bfb996SJeffrey Hsu 	/*
349b1508c72SDavid Greenman 	 * Initialize sleep queue hash table
350b1508c72SDavid Greenman 	 */
351b1508c72SDavid Greenman 	sleepinit();
352b1508c72SDavid Greenman 
353b1508c72SDavid Greenman 	/*
3543075778bSJohn Dyson 	 * additional VM structures
3553075778bSJohn Dyson 	 */
3563075778bSJohn Dyson 	vm_init2();
3573075778bSJohn Dyson 
3583075778bSJohn Dyson 	/*
359df8bae1dSRodney W. Grimes 	 * Create process 0 (the swapper).
360df8bae1dSRodney W. Grimes 	 */
361a3bfb996SJeffrey Hsu 	LIST_INSERT_HEAD(&allproc, p, p_list);
3627b531e60SJohn Baldwin 	LIST_INSERT_HEAD(PIDHASH(0), p, p_hash);
3636008862bSJohn Baldwin 	mtx_init(&pgrp0.pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK);
364df8bae1dSRodney W. Grimes 	p->p_pgrp = &pgrp0;
365a3bfb996SJeffrey Hsu 	LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
366a3bfb996SJeffrey Hsu 	LIST_INIT(&pgrp0.pg_members);
367a3bfb996SJeffrey Hsu 	LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
368a3bfb996SJeffrey Hsu 
369df8bae1dSRodney W. Grimes 	pgrp0.pg_session = &session0;
3706008862bSJohn Baldwin 	mtx_init(&session0.s_mtx, "session", NULL, MTX_DEF);
371df8bae1dSRodney W. Grimes 	session0.s_count = 1;
372df8bae1dSRodney W. Grimes 	session0.s_leader = p;
373df8bae1dSRodney W. Grimes 
3743ebc1248SPeter Wemm 	p->p_sysent = &null_sysvec;
375f3f0ca60SSøren Schmidt 
376e602ba25SJulian Elischer 	/*
377e602ba25SJulian Elischer 	 * proc_linkup was already done in init_i386() or alphainit() etc.
378e602ba25SJulian Elischer 	 * because the earlier code needed to follow td->td_proc. Otherwise
379e602ba25SJulian Elischer 	 * I would have done it here.. maybe this means this should be
380e602ba25SJulian Elischer 	 * done earlier too.
381e602ba25SJulian Elischer 	 */
382f202965eSJohn Baldwin 	p->p_flag = P_SYSTEM;
383f202965eSJohn Baldwin 	p->p_sflag = PS_INMEM;
384e602ba25SJulian Elischer 	p->p_state = PRS_NORMAL;
385e602ba25SJulian Elischer 	td->td_state = TDS_RUNNING;
386e602ba25SJulian Elischer 	kg->kg_nice = NZERO;
3872c100766SJulian Elischer 	kg->kg_pri_class = PRI_TIMESHARE;
3882c100766SJulian Elischer 	kg->kg_user_pri = PUSER;
3892c100766SJulian Elischer 	td->td_priority = PVM;
3902c100766SJulian Elischer 	td->td_base_pri = PUSER;
391e602ba25SJulian Elischer 	td->td_kse = ke; /* XXXKSE */
392060563ecSJulian Elischer 	td->td_oncpu = 0;
393c3b98db0SJulian Elischer 	ke->ke_state = KES_THREAD;
394e602ba25SJulian Elischer 	ke->ke_thread = td;
3952c1011f7SJohn Dyson 	p->p_peers = 0;
3962c1011f7SJohn Dyson 	p->p_leader = p;
397e602ba25SJulian Elischer 
3982c1011f7SJohn Dyson 
399df8bae1dSRodney W. Grimes 	bcopy("swapper", p->p_comm, sizeof ("swapper"));
400df8bae1dSRodney W. Grimes 
401c06eb4e2SSam Leffler 	callout_init(&p->p_itcallout, CALLOUT_MPSAFE);
402c06eb4e2SSam Leffler 	callout_init(&td->td_slpcallout, CALLOUT_MPSAFE);
4034f559836SJake Burkholder 
404df8bae1dSRodney W. Grimes 	/* Create credentials. */
405df8bae1dSRodney W. Grimes 	p->p_ucred = crget();
406df8bae1dSRodney W. Grimes 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
407f535380cSDon Lewis 	p->p_ucred->cr_uidinfo = uifind(0);
408b1fc0ec1SRobert Watson 	p->p_ucred->cr_ruidinfo = uifind(0);
40991421ba2SRobert Watson 	p->p_ucred->cr_prison = NULL;	/* Don't jail it. */
41040244964SRobert Watson #ifdef MAC
41140244964SRobert Watson 	mac_create_proc0(p->p_ucred);
41240244964SRobert Watson #endif
4138e2e767bSJohn Baldwin 	td->td_ucred = crhold(p->p_ucred);
41475c13541SPoul-Henning Kamp 
41590af4afaSJohn Baldwin 	/* Create sigacts. */
41690af4afaSJohn Baldwin 	p->p_sigacts = sigacts_alloc();
4176626c604SJulian Elischer 
41837b087a6SPeter Wemm 	/* Initialize signal state for process 0. */
41937b087a6SPeter Wemm 	siginit(&proc0);
42037b087a6SPeter Wemm 
421df8bae1dSRodney W. Grimes 	/* Create the file descriptor table. */
422a2fe44e8SDag-Erling Smørgrav 	/* XXX this duplicates part of fdinit() */
423df8bae1dSRodney W. Grimes 	fdp = &filedesc0;
424df8bae1dSRodney W. Grimes 	p->p_fd = &fdp->fd_fd;
425ad05d580STor Egge 	p->p_fdtol = NULL;
4266008862bSJohn Baldwin 	mtx_init(&fdp->fd_fd.fd_mtx, FILEDESC_LOCK_DESC, NULL, MTX_DEF);
427df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_refcnt = 1;
428c142b0fcSRobert Watson 	fdp->fd_fd.fd_cmask = CMASK;
429df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
430df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
431df8bae1dSRodney W. Grimes 	fdp->fd_fd.fd_nfiles = NDFILE;
432a2fe44e8SDag-Erling Smørgrav 	fdp->fd_fd.fd_map = fdp->fd_dmap;
433df8bae1dSRodney W. Grimes 
434df8bae1dSRodney W. Grimes 	/* Create the limits structures. */
43591d5354aSJohn Baldwin 	p->p_limit = lim_alloc();
43691d5354aSJohn Baldwin 	for (i = 0; i < RLIM_NLIMITS; i++)
43791d5354aSJohn Baldwin 		p->p_limit->pl_rlimit[i].rlim_cur =
43891d5354aSJohn Baldwin 		    p->p_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY;
43991d5354aSJohn Baldwin 	p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_cur =
44091d5354aSJohn Baldwin 	    p->p_limit->pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles;
44191d5354aSJohn Baldwin 	p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_cur =
44291d5354aSJohn Baldwin 	    p->p_limit->pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc;
443df8bae1dSRodney W. Grimes 	i = ptoa(cnt.v_free_count);
44491d5354aSJohn Baldwin 	p->p_limit->pl_rlimit[RLIMIT_RSS].rlim_max = i;
44591d5354aSJohn Baldwin 	p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
44691d5354aSJohn Baldwin 	p->p_limit->pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
4475715307fSJohn Baldwin 	p->p_cpulimit = RLIM_INFINITY;
448df8bae1dSRodney W. Grimes 
449df8bae1dSRodney W. Grimes 	/* Allocate a prototype map so we have something to fork. */
450b1028ad1SLuoqi Chen 	pmap_pinit0(vmspace_pmap(&vmspace0));
451df8bae1dSRodney W. Grimes 	p->p_vmspace = &vmspace0;
452df8bae1dSRodney W. Grimes 	vmspace0.vm_refcnt = 1;
45305ba50f5SJake Burkholder 	vm_map_init(&vmspace0.vm_map, p->p_sysent->sv_minuser,
45405ba50f5SJake Burkholder 	    p->p_sysent->sv_maxuser);
455b1028ad1SLuoqi Chen 	vmspace0.vm_map.pmap = vmspace_pmap(&vmspace0);
456df8bae1dSRodney W. Grimes 
45739fb8e6bSJulian Elischer 	/*
45890af4afaSJohn Baldwin 	 * We continue to place resource usage info
45990af4afaSJohn Baldwin 	 * in the user struct so that it's pageable.
460df8bae1dSRodney W. Grimes 	 */
461b40ce416SJulian Elischer 	p->p_stats = &p->p_uarea->u_stats;
462df8bae1dSRodney W. Grimes 
463df8bae1dSRodney W. Grimes 	/*
464a3bfb996SJeffrey Hsu 	 * Charge root for one process.
465df8bae1dSRodney W. Grimes 	 */
466b1fc0ec1SRobert Watson 	(void)chgproccnt(p->p_ucred->cr_ruidinfo, 1, 0);
46726f9a767SRodney W. Grimes }
4682b14f991SJulian Elischer SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
4692b14f991SJulian Elischer 
4702b14f991SJulian Elischer /* ARGSUSED*/
471154c04e5SPoul-Henning Kamp static void
47237b087a6SPeter Wemm proc0_post(void *dummy __unused)
4732b14f991SJulian Elischer {
47400af9731SPoul-Henning Kamp 	struct timespec ts;
47537b087a6SPeter Wemm 	struct proc *p;
476a6fc8288SPeter Wemm 
4772b14f991SJulian Elischer 	/*
4781b0b259eSBruce Evans 	 * Now we can look at the time, having had a chance to verify the
4791b0b259eSBruce Evans 	 * time from the filesystem.  Pretend that proc0 started now.
4802b14f991SJulian Elischer 	 */
4811005a129SJohn Baldwin 	sx_slock(&allproc_lock);
48237b087a6SPeter Wemm 	LIST_FOREACH(p, &allproc, p_list) {
48387ccef7bSDag-Erling Smørgrav 		microuptime(&p->p_stats->p_start);
4841cbb9c3bSPoul-Henning Kamp 		p->p_runtime.sec = 0;
4851cbb9c3bSPoul-Henning Kamp 		p->p_runtime.frac = 0;
48637b087a6SPeter Wemm 	}
4871005a129SJohn Baldwin 	sx_sunlock(&allproc_lock);
488e2256f43SPeter Wemm 	binuptime(PCPU_PTR(switchtime));
4890384fff8SJason Evans 	PCPU_SET(switchticks, ticks);
4902b14f991SJulian Elischer 
491a6fc8288SPeter Wemm 	/*
492a6fc8288SPeter Wemm 	 * Give the ``random'' number generator a thump.
493a6fc8288SPeter Wemm 	 */
49400af9731SPoul-Henning Kamp 	nanotime(&ts);
49500af9731SPoul-Henning Kamp 	srandom(ts.tv_sec ^ ts.tv_nsec);
4962b14f991SJulian Elischer }
4972b14f991SJulian Elischer SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL)
4982b14f991SJulian Elischer 
499df8bae1dSRodney W. Grimes /*
5002b14f991SJulian Elischer  ***************************************************************************
5012b14f991SJulian Elischer  ****
5022b14f991SJulian Elischer  **** The following SYSINIT's and glue code should be moved to the
5032b14f991SJulian Elischer  **** respective files on a per subsystem basis.
5042b14f991SJulian Elischer  ****
5052b14f991SJulian Elischer  ***************************************************************************
506df8bae1dSRodney W. Grimes  */
507df8bae1dSRodney W. Grimes 
508df8bae1dSRodney W. Grimes 
509df8bae1dSRodney W. Grimes /*
5102b14f991SJulian Elischer  ***************************************************************************
5112b14f991SJulian Elischer  ****
5122b14f991SJulian Elischer  **** The following code probably belongs in another file, like
51337b087a6SPeter Wemm  **** kern/init_init.c.
5142b14f991SJulian Elischer  ****
5152b14f991SJulian Elischer  ***************************************************************************
516df8bae1dSRodney W. Grimes  */
517df8bae1dSRodney W. Grimes 
518df8bae1dSRodney W. Grimes /*
519df8bae1dSRodney W. Grimes  * List of paths to try when searching for "init".
520df8bae1dSRodney W. Grimes  */
5215f967b24SDag-Erling Smørgrav static char init_path[MAXPATHLEN] =
52267481196SJohn Birrell #ifdef	INIT_PATH
52367481196SJohn Birrell     __XSTRING(INIT_PATH);
52467481196SJohn Birrell #else
525e4082284SJohn Birrell     "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall";
52667481196SJohn Birrell #endif
527af1408e3SLuigi Rizzo SYSCTL_STRING(_kern, OID_AUTO, init_path, CTLFLAG_RD, init_path, 0,
528af1408e3SLuigi Rizzo 	"Path used to search the init process");
529df8bae1dSRodney W. Grimes 
530df8bae1dSRodney W. Grimes /*
5315f967b24SDag-Erling Smørgrav  * Start the initial user process; try exec'ing each pathname in init_path.
532df8bae1dSRodney W. Grimes  * The program is invoked with one argument containing the boot flags.
533df8bae1dSRodney W. Grimes  */
534df8bae1dSRodney W. Grimes static void
53537b087a6SPeter Wemm start_init(void *dummy)
536df8bae1dSRodney W. Grimes {
537df8bae1dSRodney W. Grimes 	vm_offset_t addr;
538df8bae1dSRodney W. Grimes 	struct execve_args args;
5395f967b24SDag-Erling Smørgrav 	int options, error;
5405f967b24SDag-Erling Smørgrav 	char *var, *path, *next, *s;
5415f967b24SDag-Erling Smørgrav 	char *ucp, **uap, *arg0, *arg1;
542b40ce416SJulian Elischer 	struct thread *td;
5439c8b8baaSPeter Wemm 	struct proc *p;
544b7116168SPeter Wemm 	int init_does_devfs = 0;
545df8bae1dSRodney W. Grimes 
5469ed346baSBosko Milekic 	mtx_lock(&Giant);
5470384fff8SJason Evans 
5480cddd8f0SMatthew Dillon 	GIANT_REQUIRED;
5490cddd8f0SMatthew Dillon 
550b40ce416SJulian Elischer 	td = curthread;
551b40ce416SJulian Elischer 	p = td->td_proc;
552df8bae1dSRodney W. Grimes 
553563af2ecSMaxime Henrion 	vfs_mountroot();
554fb92273bSPoul-Henning Kamp 
55537b087a6SPeter Wemm 	/* Get the vnode for '/'.  Set p->p_fd->fd_cdir to reference it. */
55637b087a6SPeter Wemm 	if (VFS_ROOT(TAILQ_FIRST(&mountlist), &rootvnode))
55737b087a6SPeter Wemm 		panic("cannot find root vnode");
558426da3bcSAlfred Perlstein 	FILEDESC_LOCK(p->p_fd);
55937b087a6SPeter Wemm 	p->p_fd->fd_cdir = rootvnode;
56037b087a6SPeter Wemm 	VREF(p->p_fd->fd_cdir);
56137b087a6SPeter Wemm 	p->p_fd->fd_rdir = rootvnode;
562a90ef2aeSIan Dowse 	VREF(p->p_fd->fd_rdir);
563426da3bcSAlfred Perlstein 	FILEDESC_UNLOCK(p->p_fd);
564b40ce416SJulian Elischer 	VOP_UNLOCK(rootvnode, 0, td);
565a87cdf83SRobert Watson #ifdef MAC
566a87cdf83SRobert Watson 	mac_create_root_mount(td->td_ucred, TAILQ_FIRST(&mountlist));
567a87cdf83SRobert Watson #endif
56837b087a6SPeter Wemm 
569b7116168SPeter Wemm 	/*
570b7116168SPeter Wemm 	 * For disk based systems, we probably cannot do this yet
571b7116168SPeter Wemm 	 * since the fs will be read-only.  But a NFS root
572b7116168SPeter Wemm 	 * might be ok.  It is worth a shot.
573b7116168SPeter Wemm 	 */
5748f19eb88SIan Dowse 	error = kern_mkdir(td, "/dev", UIO_SYSSPACE, 0700);
575b7116168SPeter Wemm 	if (error == EEXIST)
576b7116168SPeter Wemm 		error = 0;
577b7116168SPeter Wemm 	if (error == 0)
5786dbde1feSMaxime Henrion 		error = kernel_vmount(0, "fstype", "devfs",
5796dbde1feSMaxime Henrion 		    "fspath", "/dev", NULL);
580b7116168SPeter Wemm 	if (error != 0)
581b7116168SPeter Wemm 		init_does_devfs = 1;
582b7116168SPeter Wemm 
583df8bae1dSRodney W. Grimes 	/*
584df8bae1dSRodney W. Grimes 	 * Need just enough stack to hold the faked-up "execve()" arguments.
585df8bae1dSRodney W. Grimes 	 */
58605ba50f5SJake Burkholder 	addr = p->p_sysent->sv_usrstack - PAGE_SIZE;
5875f967b24SDag-Erling Smørgrav 	if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE,
5885f967b24SDag-Erling Smørgrav 			FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0)
589df8bae1dSRodney W. Grimes 		panic("init: couldn't allocate argument space");
590df8bae1dSRodney W. Grimes 	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
59126f9a767SRodney W. Grimes 	p->p_vmspace->vm_ssize = 1;
592df8bae1dSRodney W. Grimes 
5935f967b24SDag-Erling Smørgrav 	if ((var = getenv("init_path")) != NULL) {
594e80fb434SRobert Drehmel 		strlcpy(init_path, var, sizeof(init_path));
595d786139cSMaxime Henrion 		freeenv(var);
5965f967b24SDag-Erling Smørgrav 	}
5975f967b24SDag-Erling Smørgrav 
59867481196SJohn Birrell 	for (path = init_path; *path != '\0'; path = next) {
599e4082284SJohn Birrell 		while (*path == ':')
6005f967b24SDag-Erling Smørgrav 			path++;
60167481196SJohn Birrell 		if (*path == '\0')
6025f967b24SDag-Erling Smørgrav 			break;
603e4082284SJohn Birrell 		for (next = path; *next != '\0' && *next != ':'; next++)
6045f967b24SDag-Erling Smørgrav 			/* nothing */ ;
6055f967b24SDag-Erling Smørgrav 		if (bootverbose)
606ba41a07dSDmitrij Tejblum 			printf("start_init: trying %.*s\n", (int)(next - path),
607ba41a07dSDmitrij Tejblum 			    path);
6085f967b24SDag-Erling Smørgrav 
609df8bae1dSRodney W. Grimes 		/*
610df8bae1dSRodney W. Grimes 		 * Move out the boot flag argument.
611df8bae1dSRodney W. Grimes 		 */
612df8bae1dSRodney W. Grimes 		options = 0;
61305ba50f5SJake Burkholder 		ucp = (char *)p->p_sysent->sv_usrstack;
614df8bae1dSRodney W. Grimes 		(void)subyte(--ucp, 0);		/* trailing zero */
615df8bae1dSRodney W. Grimes 		if (boothowto & RB_SINGLE) {
616df8bae1dSRodney W. Grimes 			(void)subyte(--ucp, 's');
617df8bae1dSRodney W. Grimes 			options = 1;
618df8bae1dSRodney W. Grimes 		}
619df8bae1dSRodney W. Grimes #ifdef notyet
620df8bae1dSRodney W. Grimes                 if (boothowto & RB_FASTBOOT) {
621df8bae1dSRodney W. Grimes 			(void)subyte(--ucp, 'f');
622df8bae1dSRodney W. Grimes 			options = 1;
623df8bae1dSRodney W. Grimes 		}
624df8bae1dSRodney W. Grimes #endif
62517755ac8SPoul-Henning Kamp 
62617755ac8SPoul-Henning Kamp #ifdef BOOTCDROM
62717755ac8SPoul-Henning Kamp 		(void)subyte(--ucp, 'C');
62817755ac8SPoul-Henning Kamp 		options = 1;
62917755ac8SPoul-Henning Kamp #endif
630b7116168SPeter Wemm 		if (init_does_devfs) {
6313f54a085SPoul-Henning Kamp 			(void)subyte(--ucp, 'd');
6323f54a085SPoul-Henning Kamp 			options = 1;
633db901281SPoul-Henning Kamp 		}
634db901281SPoul-Henning Kamp 
635df8bae1dSRodney W. Grimes 		if (options == 0)
636df8bae1dSRodney W. Grimes 			(void)subyte(--ucp, '-');
637df8bae1dSRodney W. Grimes 		(void)subyte(--ucp, '-');		/* leading hyphen */
638df8bae1dSRodney W. Grimes 		arg1 = ucp;
639df8bae1dSRodney W. Grimes 
640df8bae1dSRodney W. Grimes 		/*
641df8bae1dSRodney W. Grimes 		 * Move out the file name (also arg 0).
642df8bae1dSRodney W. Grimes 		 */
6435f967b24SDag-Erling Smørgrav 		(void)subyte(--ucp, 0);
6445f967b24SDag-Erling Smørgrav 		for (s = next - 1; s >= path; s--)
6455f967b24SDag-Erling Smørgrav 			(void)subyte(--ucp, *s);
646df8bae1dSRodney W. Grimes 		arg0 = ucp;
647df8bae1dSRodney W. Grimes 
648df8bae1dSRodney W. Grimes 		/*
649df8bae1dSRodney W. Grimes 		 * Move out the arg pointers.
650df8bae1dSRodney W. Grimes 		 */
651a20d7755SDoug Rabson 		uap = (char **)((intptr_t)ucp & ~(sizeof(intptr_t)-1));
652c2da0fd9SBruce Evans 		(void)suword((caddr_t)--uap, (long)0);	/* terminator */
653c2da0fd9SBruce Evans 		(void)suword((caddr_t)--uap, (long)(intptr_t)arg1);
654c2da0fd9SBruce Evans 		(void)suword((caddr_t)--uap, (long)(intptr_t)arg0);
655df8bae1dSRodney W. Grimes 
656df8bae1dSRodney W. Grimes 		/*
657df8bae1dSRodney W. Grimes 		 * Point at the arguments.
658df8bae1dSRodney W. Grimes 		 */
659df8bae1dSRodney W. Grimes 		args.fname = arg0;
66026f9a767SRodney W. Grimes 		args.argv = uap;
66126f9a767SRodney W. Grimes 		args.envv = NULL;
662df8bae1dSRodney W. Grimes 
663df8bae1dSRodney W. Grimes 		/*
664df8bae1dSRodney W. Grimes 		 * Now try to exec the program.  If can't for any reason
665df8bae1dSRodney W. Grimes 		 * other than it doesn't exist, complain.
6662b14f991SJulian Elischer 		 *
66737b087a6SPeter Wemm 		 * Otherwise, return via fork_trampoline() all the way
6689c8b8baaSPeter Wemm 		 * to user mode as init!
669df8bae1dSRodney W. Grimes 		 */
670b40ce416SJulian Elischer 		if ((error = execve(td, &args)) == 0) {
6719ed346baSBosko Milekic 			mtx_unlock(&Giant);
672df8bae1dSRodney W. Grimes 			return;
673db72809dSJohn Baldwin 		}
674df8bae1dSRodney W. Grimes 		if (error != ENOENT)
675ba41a07dSDmitrij Tejblum 			printf("exec %.*s: error %d\n", (int)(next - path),
676ba41a07dSDmitrij Tejblum 			    path, error);
677df8bae1dSRodney W. Grimes 	}
678580e7e5aSGreg Lehey 	printf("init: not found in path %s\n", init_path);
679df8bae1dSRodney W. Grimes 	panic("no init");
680df8bae1dSRodney W. Grimes }
68137b087a6SPeter Wemm 
68237b087a6SPeter Wemm /*
68337b087a6SPeter Wemm  * Like kthread_create(), but runs in it's own address space.
68437b087a6SPeter Wemm  * We do this early to reserve pid 1.
68537b087a6SPeter Wemm  *
68637b087a6SPeter Wemm  * Note special case - do not make it runnable yet.  Other work
68737b087a6SPeter Wemm  * in progress will change this more.
68837b087a6SPeter Wemm  */
68937b087a6SPeter Wemm static void
69037b087a6SPeter Wemm create_init(const void *udata __unused)
69137b087a6SPeter Wemm {
6925a06cb0cSRobert Watson 	struct ucred *newcred, *oldcred;
69337b087a6SPeter Wemm 	int error;
69437b087a6SPeter Wemm 
695316ec49aSScott Long 	error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, 0, &initproc);
69637b087a6SPeter Wemm 	if (error)
69737b087a6SPeter Wemm 		panic("cannot fork init: %d\n", error);
698bafc8f25SRobert Watson 	KASSERT(initproc->p_pid == 1, ("create_init: initproc->p_pid != 1"));
6995a06cb0cSRobert Watson 	/* divorce init's credentials from the kernel's */
7005a06cb0cSRobert Watson 	newcred = crget();
701f202965eSJohn Baldwin 	PROC_LOCK(initproc);
702f202965eSJohn Baldwin 	initproc->p_flag |= P_SYSTEM;
7035a06cb0cSRobert Watson 	oldcred = initproc->p_ucred;
7045a06cb0cSRobert Watson 	crcopy(newcred, oldcred);
70540244964SRobert Watson #ifdef MAC
70640244964SRobert Watson 	mac_create_proc1(newcred);
70740244964SRobert Watson #endif
7085a06cb0cSRobert Watson 	initproc->p_ucred = newcred;
709f202965eSJohn Baldwin 	PROC_UNLOCK(initproc);
7105a06cb0cSRobert Watson 	crfree(oldcred);
7114d1a4bb7SRobert Watson 	cred_update_thread(FIRST_THREAD_IN_PROC(initproc));
7129ed346baSBosko Milekic 	mtx_lock_spin(&sched_lock);
713f202965eSJohn Baldwin 	initproc->p_sflag |= PS_INMEM;
7149ed346baSBosko Milekic 	mtx_unlock_spin(&sched_lock);
715079b7badSJulian Elischer 	cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL);
71637b087a6SPeter Wemm }
71737b087a6SPeter Wemm SYSINIT(init, SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL)
71837b087a6SPeter Wemm 
71937b087a6SPeter Wemm /*
72037b087a6SPeter Wemm  * Make it runnable now.
72137b087a6SPeter Wemm  */
72237b087a6SPeter Wemm static void
72337b087a6SPeter Wemm kick_init(const void *udata __unused)
72437b087a6SPeter Wemm {
725079b7badSJulian Elischer 	struct thread *td;
726f202965eSJohn Baldwin 
727079b7badSJulian Elischer 	td = FIRST_THREAD_IN_PROC(initproc);
7289ed346baSBosko Milekic 	mtx_lock_spin(&sched_lock);
72971fad9fdSJulian Elischer 	TD_SET_CAN_RUN(td);
730e602ba25SJulian Elischer 	setrunqueue(td);	/* XXXKSE */
7319ed346baSBosko Milekic 	mtx_unlock_spin(&sched_lock);
73237b087a6SPeter Wemm }
73337b087a6SPeter Wemm SYSINIT(kickinit, SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kick_init, NULL)
734