init_main.c revision 31396
1139749Simp/*
2123474Swpaul * Copyright (c) 1995 Terrence R. Lambert
3123474Swpaul * All rights reserved.
4123474Swpaul *
5123474Swpaul * Copyright (c) 1982, 1986, 1989, 1991, 1992, 1993
6123474Swpaul *	The Regents of the University of California.  All rights reserved.
7123474Swpaul * (c) UNIX System Laboratories, Inc.
8123474Swpaul * All or some portions of this file are derived from material licensed
9123474Swpaul * to the University of California by American Telephone and Telegraph
10123474Swpaul * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11123474Swpaul * the permission of UNIX System Laboratories, Inc.
12123474Swpaul *
13123474Swpaul * Redistribution and use in source and binary forms, with or without
14123474Swpaul * modification, are permitted provided that the following conditions
15123474Swpaul * are met:
16123474Swpaul * 1. Redistributions of source code must retain the above copyright
17123474Swpaul *    notice, this list of conditions and the following disclaimer.
18123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright
19123474Swpaul *    notice, this list of conditions and the following disclaimer in the
20123474Swpaul *    documentation and/or other materials provided with the distribution.
21123474Swpaul * 3. All advertising materials mentioning features or use of this software
22123474Swpaul *    must display the following acknowledgement:
23123474Swpaul *	This product includes software developed by the University of
24123474Swpaul *	California, Berkeley and its contributors.
25123474Swpaul * 4. Neither the name of the University nor the names of its contributors
26123474Swpaul *    may be used to endorse or promote products derived from this software
27123474Swpaul *    without specific prior written permission.
28123474Swpaul *
29123474Swpaul * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30123474Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31123474Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32123474Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33123474Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34123474Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35128229Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36128229Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37128229Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38151207Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39151207Swpaul * SUCH DAMAGE.
40151207Swpaul *
41151207Swpaul *	@(#)init_main.c	8.9 (Berkeley) 1/21/94
42151207Swpaul * $Id: init_main.c,v 1.74 1997/11/07 08:52:53 phk Exp $
43151207Swpaul */
44151207Swpaul
45151207Swpaul#include "opt_devfs.h"
46151207Swpaul
47151207Swpaul#include <sys/param.h>
48126706Swpaul#include <sys/file.h>
49123474Swpaul#include <sys/filedesc.h>
50123474Swpaul#include <sys/kernel.h>
51123620Swpaul#include <sys/mount.h>
52123474Swpaul#include <sys/sysctl.h>
53123474Swpaul#include <sys/proc.h>
54123474Swpaul#include <sys/resourcevar.h>
55126706Swpaul#include <sys/signalvar.h>
56126706Swpaul#include <sys/systm.h>
57126706Swpaul#include <sys/vnode.h>
58126706Swpaul#include <sys/sysent.h>
59126706Swpaul#include <sys/reboot.h>
60126706Swpaul#include <sys/sysproto.h>
61186507Sweongyo#include <sys/vmmeter.h>
62186507Sweongyo
63186507Sweongyo#include <machine/cpu.h>
64186507Sweongyo
65186507Sweongyo#include <vm/vm.h>
66186507Sweongyo#include <vm/vm_param.h>
67123474Swpaul#include <vm/vm_prot.h>
68151207Swpaul#include <sys/lock.h>
69123474Swpaul#include <vm/pmap.h>
70123474Swpaul#include <vm/vm_map.h>
71123474Swpaul#include <sys/user.h>
72145895Swpaul#include <sys/copyright.h>
73123474Swpaul
74123474Swpaulextern struct linker_set	sysinit_set;	/* XXX */
75123474Swpaul
76123474Swpaulextern void __main __P((void));
77151207Swpaulextern void main __P((void *framep));
78123474Swpaul
79123474Swpaul/* Components of the first process -- never freed. */
80123474Swpaulstatic struct session session0;
81151207Swpaulstatic struct pgrp pgrp0;
82151207Swpaulstruct	proc proc0;
83151207Swpaulstatic struct pcred cred0;
84151207Swpaulstatic struct filedesc0 filedesc0;
85151207Swpaulstatic struct plimit limit0;
86151207Swpaulstatic struct vmspace vmspace0;
87151207Swpaul#ifndef SMP	/* per-cpu on smp */
88151207Swpaulstruct	proc *curproc = &proc0;
89151207Swpaul#endif
90123474Swpaulstruct	proc *initproc;
91123474Swpaul
92151207Swpaulint cmask = CMASK;
93131750Swpaulextern	struct user *proc0paddr;
94151451Swpaul
95123474Swpaulstruct	vnode *rootvp;
96183587Sweongyoint	boothowto = 0;		/* initialized so that it can be patched */
97123474Swpaul
98151207Swpaulstruct	timeval boottime;
99151207SwpaulSYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime,
100151207Swpaul	CTLFLAG_RD, &boottime, timeval, "");
101151207Swpaul
102151207Swpaulstatic int shutdowntimeout = 120;
103151207SwpaulSYSCTL_INT(_kern, OID_AUTO, shutdown_timeout,
104151207Swpaul	CTLFLAG_RW, &shutdowntimeout, 0, "");
105151207Swpaul
106151207Swpaul#ifndef SMP	/* per-cpu on smp */
107151207Swpaulstruct	timeval runtime;
108178354Ssam#endif
109178354Ssam
110178354Ssam/*
111178354Ssam * Promiscuous argument pass for start_init()
112178354Ssam *
113178354Ssam * This is a kludge because we use a return from main() rather than a call
114178354Ssam * to a new routine in locore.s to kick the kernel alive from locore.s.
115178354Ssam */
116189488Sweongyostatic void	*init_framep;
117186507Sweongyo
118189488Sweongyo
119189488Sweongyo#if __GNUC__ >= 2
120186507Sweongyovoid __main() {}
121186507Sweongyo#endif
122189488Sweongyo
123189488Sweongyo
124192984Sthompsa/*
125189488Sweongyo * This ensures that there is at least one entry so that the sysinit_set
126189488Sweongyo * symbol is not undefined.  A sybsystem ID of SI_SUB_DUMMY is never
127189488Sweongyo * executed.
128189488Sweongyo */
129189488SweongyoSYSINIT(placeholder, SI_SUB_DUMMY,SI_ORDER_ANY, NULL, NULL)
130186507Sweongyo
131189488Sweongyo
132189488Sweongyo/*
133189488Sweongyo * System startup; initialize the world, create process 0, mount root
134189488Sweongyo * filesystem, and fork to create init and pagedaemon.  Most of the
135189488Sweongyo * hard work is done in the lower-level initialization routines including
136189488Sweongyo * startup(), which does memory initialization and autoconfiguration.
137189488Sweongyo *
138186507Sweongyo * This allows simple addition of new kernel subsystems that require
139189488Sweongyo * boot time initialization.  It also allows substitution of subsystem
140189488Sweongyo * (for instance, a scheduler, kernel profiler, or VM system) by object
141193045Sthompsa * module.  Finally, it allows for optional "kernel threads", like an LFS
142189488Sweongyo * cleaner.
143189488Sweongyo */
144186507Sweongyovoid
145189719Sweongyomain(framep)
146189719Sweongyo	void *framep;
147189719Sweongyo{
148189719Sweongyo
149189950Sweongyo	register struct sysinit **sipp;		/* system initialization*/
150189719Sweongyo	register struct sysinit **xipp;		/* interior loop of sort*/
151189719Sweongyo	register struct sysinit *save;		/* bubble*/
152189719Sweongyo
153189719Sweongyo	/*
154123474Swpaul	 * Copy the locore.s frame pointer for proc0, this is forked into
155147256Sbrooks	 * all other processes.
156123474Swpaul	 */
157124821Swpaul	init_framep = framep;
158124821Swpaul
159124821Swpaul#ifdef SMP
160123474Swpaul	/*
161123474Swpaul	 * XXX curproc is per-cpu in SMP, and exists in freshly mapped pages,
162123474Swpaul	 * so its value must be initialized now before it is used by various
163123474Swpaul	 * initialization routines.  proc0_init() isn't soon enough:
164123474Swpaul	 * among other things, configure() is called first, and may call
165123474Swpaul	 * setdumpdev(), which panics without a valid curproc.
166123474Swpaul	 */
167123474Swpaul	curproc = &proc0;
168123474Swpaul#endif /* SMP */
169123474Swpaul
170123474Swpaul	/*
171123474Swpaul	 * Perform a bubble sort of the system initialization objects by
172131953Swpaul	 * their subsystem (primary key) and order (secondary key).
173123474Swpaul	 *
174131953Swpaul	 * Since some things care about execution order, this is the
175123474Swpaul	 * operation which ensures continued function.
176179723Scokane	 */
177151207Swpaul	for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
178123474Swpaul		for( xipp = sipp + 1; *xipp; xipp++) {
179123474Swpaul			if( (*sipp)->subsystem < (*xipp)->subsystem ||
180141524Swpaul			    ( (*sipp)->subsystem == (*xipp)->subsystem &&
181141524Swpaul			      (*sipp)->order < (*xipp)->order))
182123474Swpaul				continue;	/* skip*/
183191746Sthompsa			save = *sipp;
184178286Scokane			*sipp = *xipp;
185123474Swpaul			*xipp = save;
186123474Swpaul		}
187123474Swpaul	}
188123474Swpaul
189123474Swpaul	/*
190123474Swpaul	 * Traverse the (now) ordered list of system initialization tasks.
191141963Swpaul	 * Perform each task, and continue on to the next task.
192123474Swpaul	 *
193123474Swpaul	 * The last item on the list is expected to be the scheduler,
194123474Swpaul	 * which will not return.
195123695Swpaul	 */
196123695Swpaul	for( sipp = (struct sysinit **)sysinit_set.ls_items; *sipp; sipp++) {
197151207Swpaul		if( (*sipp)->subsystem == SI_SUB_DUMMY)
198123695Swpaul			continue;	/* skip dummy task(s)*/
199123695Swpaul
200125076Swpaul		switch( (*sipp)->type) {
201123474Swpaul		case SI_TYPE_DEFAULT:
202123620Swpaul			/* no special processing*/
203123474Swpaul			(*((*sipp)->func))( (*sipp)->udata);
204145485Swpaul			break;
205151207Swpaul
206151207Swpaul		case SI_TYPE_KTHREAD:
207151207Swpaul			/* kernel thread*/
208151451Swpaul			if (fork(&proc0, NULL))
209146230Swpaul				panic("fork kernel process");
210123474Swpaul			cpu_set_fork_handler(pfind(proc0.p_retval[0]),
211151207Swpaul			    (*sipp)->func, (*sipp)->udata);
212123474Swpaul			break;
213123474Swpaul
214123474Swpaul		default:
215123474Swpaul			panic( "init_main: unrecognized init type");
216123474Swpaul		}
217151207Swpaul	}
218151207Swpaul
219151207Swpaul	panic("Shouldn't get here!");
220151451Swpaul	/* NOTREACHED*/
221151451Swpaul}
222171390Sthompsa
223171390Sthompsa
224171390Sthompsa/*
225179498Scokane * Start a kernel process.  This is called after a fork() call in
226179498Scokane * main() in the file kern/init_main.c.
227186507Sweongyo *
228192984Sthompsa * This function is used to start "internal" daemons.
229189719Sweongyo */
230189950Sweongyo/* ARGSUSED*/
231189950Sweongyovoid
232189488Sweongyokproc_start(udata)
233189488Sweongyo	void *udata;
234189488Sweongyo{
235189488Sweongyo	struct kproc_desc	*kp = udata;
236189488Sweongyo	struct proc		*p = curproc;
237189488Sweongyo
238189488Sweongyo#ifdef DIAGNOSTIC
239189719Sweongyo	printf("Start pid=%d <%s>\n",p->p_pid, kp->arg0);
240189719Sweongyo#endif
241189719Sweongyo
242186507Sweongyo	/* save a global descriptor, if desired*/
243186507Sweongyo	if( kp->global_procpp != NULL)
244189950Sweongyo		*kp->global_procpp	= p;
245123474Swpaul
246123474Swpaul	/* this is a non-swapped system process*/
247189488Sweongyo	p->p_flag |= P_INMEM | P_SYSTEM;
248189488Sweongyo
249189488Sweongyo	/* set up arg0 for 'ps', et al*/
250189719Sweongyo	strcpy( p->p_comm, kp->arg0);
251189719Sweongyo
252189719Sweongyo	/* call the processes' main()...*/
253189719Sweongyo	(*kp->func)();
254
255	/* NOTREACHED */
256	panic("kproc_start: %s", kp->arg0);
257}
258
259
260/*
261 ***************************************************************************
262 ****
263 **** The following SYSINIT's belong elsewhere, but have not yet
264 **** been moved.
265 ****
266 ***************************************************************************
267 */
268#ifdef OMIT
269/*
270 * Handled by vfs_mountroot (bad idea) at this time... should be
271 * done the same as 4.4Lite2.
272 */
273SYSINIT(swapinit, SI_SUB_SWAP, SI_ORDER_FIRST, swapinit, NULL)
274#endif	/* OMIT*/
275
276static void print_caddr_t __P((void *data));
277static void
278print_caddr_t(data)
279	void *data;
280{
281	printf("%s", (char *)data);
282}
283SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)
284
285
286/*
287 ***************************************************************************
288 ****
289 **** The two following SYSINT's are proc0 specific glue code.  I am not
290 **** convinced that they can not be safely combined, but their order of
291 **** operation has been maintained as the same as the original init_main.c
292 **** for right now.
293 ****
294 **** These probably belong in init_proc.c or kern_proc.c, since they
295 **** deal with proc0 (the fork template process).
296 ****
297 ***************************************************************************
298 */
299/* ARGSUSED*/
300static void proc0_init __P((void *dummy));
301static void
302proc0_init(dummy)
303	void *dummy;
304{
305	register struct proc		*p;
306	register struct filedesc0	*fdp;
307	register unsigned i;
308
309	/*
310	 * Initialize the current process pointer (curproc) before
311	 * any possible traps/probes to simplify trap processing.
312	 */
313	p = &proc0;
314	curproc = p;			/* XXX redundant*/
315
316	/*
317	 * Initialize process and pgrp structures.
318	 */
319	procinit();
320
321	/*
322	 * Initialize sleep queue hash table
323	 */
324	sleepinit();
325
326	/*
327	 * additional VM structures
328	 */
329	vm_init2();
330
331	/*
332	 * Create process 0 (the swapper).
333	 */
334	LIST_INSERT_HEAD(&allproc, p, p_list);
335	p->p_pgrp = &pgrp0;
336	LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
337	LIST_INIT(&pgrp0.pg_members);
338	LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
339
340	pgrp0.pg_session = &session0;
341	session0.s_count = 1;
342	session0.s_leader = p;
343
344	p->p_sysent = &aout_sysvec;
345
346	p->p_flag = P_INMEM | P_SYSTEM;
347	p->p_stat = SRUN;
348	p->p_nice = NZERO;
349	p->p_rtprio.type = RTP_PRIO_NORMAL;
350	p->p_rtprio.prio = 0;
351
352/*
353 * Link for kernel based threads
354 */
355	p->p_peers = 0;
356	p->p_leader = p;
357
358	bcopy("swapper", p->p_comm, sizeof ("swapper"));
359
360	/* Create credentials. */
361	cred0.p_refcnt = 1;
362	p->p_cred = &cred0;
363	p->p_ucred = crget();
364	p->p_ucred->cr_ngroups = 1;	/* group 0 */
365
366	/* Create the file descriptor table. */
367	fdp = &filedesc0;
368	p->p_fd = &fdp->fd_fd;
369	fdp->fd_fd.fd_refcnt = 1;
370	fdp->fd_fd.fd_cmask = cmask;
371	fdp->fd_fd.fd_ofiles = fdp->fd_dfiles;
372	fdp->fd_fd.fd_ofileflags = fdp->fd_dfileflags;
373	fdp->fd_fd.fd_nfiles = NDFILE;
374
375	/* Create the limits structures. */
376	p->p_limit = &limit0;
377	for (i = 0; i < sizeof(p->p_rlimit)/sizeof(p->p_rlimit[0]); i++)
378		limit0.pl_rlimit[i].rlim_cur =
379		    limit0.pl_rlimit[i].rlim_max = RLIM_INFINITY;
380	limit0.pl_rlimit[RLIMIT_NOFILE].rlim_cur =
381	    limit0.pl_rlimit[RLIMIT_NOFILE].rlim_max = maxfiles;
382	limit0.pl_rlimit[RLIMIT_NPROC].rlim_cur =
383	    limit0.pl_rlimit[RLIMIT_NPROC].rlim_max = maxproc;
384	i = ptoa(cnt.v_free_count);
385	limit0.pl_rlimit[RLIMIT_RSS].rlim_max = i;
386	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_max = i;
387	limit0.pl_rlimit[RLIMIT_MEMLOCK].rlim_cur = i / 3;
388	limit0.p_refcnt = 1;
389
390	/* Allocate a prototype map so we have something to fork. */
391	p->p_vmspace = &vmspace0;
392	vmspace0.vm_refcnt = 1;
393	pmap_pinit(&vmspace0.vm_pmap);
394	vm_map_init(&vmspace0.vm_map, round_page(VM_MIN_ADDRESS),
395	    trunc_page(VM_MAXUSER_ADDRESS), TRUE);
396	vmspace0.vm_map.pmap = &vmspace0.vm_pmap;
397	p->p_addr = proc0paddr;				/* XXX */
398
399#define INCOMPAT_LITES2
400#ifdef INCOMPAT_LITES2
401	/*
402	 * proc0 needs to have a coherent frame base in it's stack.
403	 */
404	cpu_set_init_frame(p, init_framep);			/* XXX! */
405#endif	/* INCOMPAT_LITES2*/
406
407	/*
408	 * We continue to place resource usage info and signal
409	 * actions in the user struct so they're pageable.
410	 */
411	p->p_stats = &p->p_addr->u_stats;
412	p->p_sigacts = &p->p_addr->u_sigacts;
413
414	/*
415	 * Charge root for one process.
416	 */
417	(void)chgproccnt(0, 1);
418}
419SYSINIT(p0init, SI_SUB_INTRINSIC, SI_ORDER_FIRST, proc0_init, NULL)
420
421/* ARGSUSED*/
422static void proc0_post __P((void *dummy));
423static void
424proc0_post(dummy)
425	void *dummy;
426{
427	struct timeval tv;
428
429	/*
430	 * Now can look at time, having had a chance to verify the time
431	 * from the file system.  Reset p->p_rtime as it may have been
432	 * munched in mi_switch() after the time got set.
433	 */
434	gettime(&boottime);
435	proc0.p_stats->p_start = runtime = mono_time = boottime;
436	proc0.p_rtime.tv_sec = proc0.p_rtime.tv_usec = 0;
437
438	/*
439	 * Give the ``random'' number generator a thump.
440	 */
441	microtime(&tv);
442	srandom(tv.tv_sec ^ tv.tv_usec);
443
444	/* Initialize signal state for process 0. */
445	siginit(&proc0);
446}
447SYSINIT(p0post, SI_SUB_INTRINSIC_POST, SI_ORDER_FIRST, proc0_post, NULL)
448
449
450
451
452/*
453 ***************************************************************************
454 ****
455 **** The following SYSINIT's and glue code should be moved to the
456 **** respective files on a per subsystem basis.
457 ****
458 ***************************************************************************
459 */
460/* ARGSUSED */
461static void sched_setup __P((void *dummy));
462static void
463sched_setup(dummy)
464	void *dummy;
465{
466	/* Kick off timeout driven events by calling first time. */
467	roundrobin(NULL);
468	schedcpu(NULL);
469}
470SYSINIT(sched_setup, SI_SUB_KICK_SCHEDULER, SI_ORDER_FIRST, sched_setup, NULL)
471
472/* ARGSUSED */
473static void root_conf __P((void *dummy));
474static void
475root_conf(dummy)
476	void *dummy;
477{
478	cpu_rootconf();
479}
480SYSINIT(root_conf, SI_SUB_ROOT_CONF, SI_ORDER_FIRST, root_conf, NULL)
481
482/* ARGSUSED */
483static void dump_conf __P((void *dummy));
484static void
485dump_conf(dummy)
486	void *dummy;
487{
488	cpu_dumpconf();
489}
490SYSINIT(dump_conf, SI_SUB_DUMP_CONF, SI_ORDER_FIRST, dump_conf, NULL)
491
492/* ARGSUSED*/
493static void xxx_vfs_mountroot __P((void *fsnamep));
494#ifdef BOOTP
495extern void bootpc_init __P((void));
496#endif
497static void
498xxx_vfs_mountroot(fsnamep)
499	void *fsnamep;
500{
501  /* XXX Add a separate SYSINIT entry */
502#ifdef BOOTP
503	bootpc_init();
504#endif
505	/* Mount the root file system. */
506	if (vfs_mountrootfs(*((char **) fsnamep)))
507		panic("cannot mount root");
508}
509SYSINIT(mountroot, SI_SUB_MOUNT_ROOT, SI_ORDER_FIRST, xxx_vfs_mountroot,
510	&mountrootfsname)
511
512/* ARGSUSED*/
513static void xxx_vfs_root_fdtab __P((void *dummy));
514static void
515xxx_vfs_root_fdtab(dummy)
516	void *dummy;
517{
518	register struct filedesc0	*fdp = &filedesc0;
519
520	/* Get the vnode for '/'.  Set fdp->fd_fd.fd_cdir to reference it. */
521	if (VFS_ROOT(mountlist.cqh_first, &rootvnode))
522		panic("cannot find root vnode");
523	fdp->fd_fd.fd_cdir = rootvnode;
524	VREF(fdp->fd_fd.fd_cdir);
525	VOP_UNLOCK(rootvnode, 0, &proc0);
526	fdp->fd_fd.fd_rdir = NULL;
527}
528SYSINIT(retrofit, SI_SUB_ROOT_FDTAB, SI_ORDER_FIRST, xxx_vfs_root_fdtab, NULL)
529
530
531/*
532 ***************************************************************************
533 ****
534 **** The following code probably belongs in another file, like
535 **** kern/init_init.c.  It is here for two reasons only:
536 ****
537 ****	1)	This code returns to startup the system; this is
538 ****		abnormal for a kernel thread.
539 ****	2)	This code promiscuously uses init_frame
540 ****
541 ***************************************************************************
542 */
543
544static void kthread_init __P((void *dummy));
545SYSINIT_KT(init,SI_SUB_KTHREAD_INIT, SI_ORDER_FIRST, kthread_init, NULL)
546
547
548extern void prepare_usermode __P((void));
549static void start_init __P((struct proc *p));
550
551/* ARGSUSED*/
552static void
553kthread_init(dummy)
554	void *dummy;
555{
556	/* Create process 1 (init(8)). */
557	start_init(curproc);
558
559	prepare_usermode();
560
561	/*
562	 * This returns to the fork trampoline, then to user mode.
563	 */
564	return;
565}
566
567
568/*
569 * List of paths to try when searching for "init".
570 */
571static char *initpaths[] = {
572	"/sbin/init",
573	"/sbin/oinit",
574	"/sbin/init.bak",
575	"/stand/sysinstall",
576	NULL,
577};
578
579/*
580 * Start the initial user process; try exec'ing each pathname in "initpaths".
581 * The program is invoked with one argument containing the boot flags.
582 */
583static void
584start_init(p)
585	struct proc *p;
586{
587	vm_offset_t addr;
588	struct execve_args args;
589	int options, i, error;
590	char **pathp, *path, *ucp, **uap, *arg0, *arg1;
591
592	initproc = p;
593
594	/*
595	 * Need just enough stack to hold the faked-up "execve()" arguments.
596	 */
597	addr = trunc_page(VM_MAXUSER_ADDRESS - PAGE_SIZE);
598	if (vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr, PAGE_SIZE, FALSE, VM_PROT_ALL, VM_PROT_ALL, 0) != 0)
599		panic("init: couldn't allocate argument space");
600	p->p_vmspace->vm_maxsaddr = (caddr_t)addr;
601	p->p_vmspace->vm_ssize = 1;
602
603	for (pathp = &initpaths[0]; (path = *pathp) != NULL; pathp++) {
604		/*
605		 * Move out the boot flag argument.
606		 */
607		options = 0;
608		ucp = (char *)USRSTACK;
609		(void)subyte(--ucp, 0);		/* trailing zero */
610		if (boothowto & RB_SINGLE) {
611			(void)subyte(--ucp, 's');
612			options = 1;
613		}
614#ifdef notyet
615                if (boothowto & RB_FASTBOOT) {
616			(void)subyte(--ucp, 'f');
617			options = 1;
618		}
619#endif
620
621#ifdef BOOTCDROM
622		(void)subyte(--ucp, 'C');
623		options = 1;
624#endif
625
626#if defined(DEVFS) && defined(DEVFS_ROOT)
627		(void)subyte(--ucp, 'd');
628		options = 1;
629#endif
630		if (options == 0)
631			(void)subyte(--ucp, '-');
632		(void)subyte(--ucp, '-');		/* leading hyphen */
633		arg1 = ucp;
634
635		/*
636		 * Move out the file name (also arg 0).
637		 */
638		for (i = strlen(path) + 1; i >= 0; i--)
639			(void)subyte(--ucp, path[i]);
640		arg0 = ucp;
641
642		/*
643		 * Move out the arg pointers.
644		 */
645		uap = (char **)((int)ucp & ~(NBPW-1));
646		(void)suword((caddr_t)--uap, 0);	/* terminator */
647		(void)suword((caddr_t)--uap, (int)arg1);
648		(void)suword((caddr_t)--uap, (int)arg0);
649
650		/*
651		 * Point at the arguments.
652		 */
653		args.fname = arg0;
654		args.argv = uap;
655		args.envv = NULL;
656
657		/*
658		 * Now try to exec the program.  If can't for any reason
659		 * other than it doesn't exist, complain.
660		 *
661		 * Otherwise return to main() which returns to btext
662		 * which completes the system startup.
663		 */
664		if ((error = execve(p, &args)) == 0)
665			return;
666		if (error != ENOENT)
667			printf("exec %s: error %d\n", path, error);
668	}
669	printf("init: not found\n");
670	panic("no init");
671}
672