xref: /onnv-gate/usr/src/uts/common/os/main.c (revision 2267:c5d9a656170f)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51676Sjpk  * Common Development and Distribution License (the "License").
61676Sjpk  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
221676Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*	Copyright (c) 1988 AT&T	*/
270Sstevel@tonic-gate /*	  All Rights Reserved  	*/
280Sstevel@tonic-gate 
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"	/* from SVr4.0 1.31 */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/param.h>
340Sstevel@tonic-gate #include <sys/sysmacros.h>
350Sstevel@tonic-gate #include <sys/pcb.h>
360Sstevel@tonic-gate #include <sys/systm.h>
370Sstevel@tonic-gate #include <sys/signal.h>
380Sstevel@tonic-gate #include <sys/cred.h>
390Sstevel@tonic-gate #include <sys/user.h>
400Sstevel@tonic-gate #include <sys/vfs.h>
410Sstevel@tonic-gate #include <sys/vnode.h>
420Sstevel@tonic-gate #include <sys/proc.h>
430Sstevel@tonic-gate #include <sys/time.h>
440Sstevel@tonic-gate #include <sys/file.h>
450Sstevel@tonic-gate #include <sys/priocntl.h>
460Sstevel@tonic-gate #include <sys/procset.h>
470Sstevel@tonic-gate #include <sys/disp.h>
480Sstevel@tonic-gate #include <sys/callo.h>
490Sstevel@tonic-gate #include <sys/callb.h>
500Sstevel@tonic-gate #include <sys/debug.h>
510Sstevel@tonic-gate #include <sys/conf.h>
520Sstevel@tonic-gate #include <sys/bootconf.h>
530Sstevel@tonic-gate #include <sys/utsname.h>
540Sstevel@tonic-gate #include <sys/cmn_err.h>
550Sstevel@tonic-gate #include <sys/vmparam.h>
560Sstevel@tonic-gate #include <sys/modctl.h>
570Sstevel@tonic-gate #include <sys/vm.h>
580Sstevel@tonic-gate #include <sys/callb.h>
590Sstevel@tonic-gate #include <sys/kmem.h>
600Sstevel@tonic-gate #include <sys/vmem.h>
610Sstevel@tonic-gate #include <sys/cpuvar.h>
620Sstevel@tonic-gate #include <sys/cladm.h>
630Sstevel@tonic-gate #include <sys/corectl.h>
640Sstevel@tonic-gate #include <sys/exec.h>
650Sstevel@tonic-gate #include <sys/syscall.h>
660Sstevel@tonic-gate #include <sys/reboot.h>
670Sstevel@tonic-gate #include <sys/task.h>
680Sstevel@tonic-gate #include <sys/exacct.h>
690Sstevel@tonic-gate #include <sys/autoconf.h>
700Sstevel@tonic-gate #include <sys/errorq.h>
710Sstevel@tonic-gate #include <sys/class.h>
720Sstevel@tonic-gate #include <sys/stack.h>
730Sstevel@tonic-gate 
740Sstevel@tonic-gate #include <vm/as.h>
750Sstevel@tonic-gate #include <vm/seg_kmem.h>
760Sstevel@tonic-gate #include <sys/dc_ki.h>
770Sstevel@tonic-gate 
780Sstevel@tonic-gate #include <c2/audit.h>
790Sstevel@tonic-gate 
800Sstevel@tonic-gate /* well known processes */
810Sstevel@tonic-gate proc_t *proc_sched;		/* memory scheduler */
820Sstevel@tonic-gate proc_t *proc_init;		/* init */
830Sstevel@tonic-gate proc_t *proc_pageout;		/* pageout daemon */
840Sstevel@tonic-gate proc_t *proc_fsflush;		/* fsflush daemon */
850Sstevel@tonic-gate 
860Sstevel@tonic-gate pgcnt_t	maxmem;		/* Maximum available memory in pages.	*/
870Sstevel@tonic-gate pgcnt_t	freemem;	/* Current available memory in pages.	*/
880Sstevel@tonic-gate int	audit_active;
890Sstevel@tonic-gate int	interrupts_unleashed;	/* set when we do the first spl0() */
900Sstevel@tonic-gate 
910Sstevel@tonic-gate kmem_cache_t *process_cache;	/* kmem cache for proc structures */
920Sstevel@tonic-gate 
930Sstevel@tonic-gate /*
940Sstevel@tonic-gate  * Process 0's lwp directory and lwpid hash table.
950Sstevel@tonic-gate  */
960Sstevel@tonic-gate lwpdir_t p0_lwpdir[2];
970Sstevel@tonic-gate lwpdir_t *p0_tidhash[2];
980Sstevel@tonic-gate lwpent_t p0_lep;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate  * Machine-independent initialization code
1020Sstevel@tonic-gate  * Called from cold start routine as
1030Sstevel@tonic-gate  * soon as a stack and segmentation
1040Sstevel@tonic-gate  * have been established.
1050Sstevel@tonic-gate  * Functions:
1060Sstevel@tonic-gate  *	clear and free user core
1070Sstevel@tonic-gate  *	turn on clock
1080Sstevel@tonic-gate  *	hand craft 0th process
1090Sstevel@tonic-gate  *	call all initialization routines
1100Sstevel@tonic-gate  *	fork	- process 0 to schedule
1110Sstevel@tonic-gate  *		- process 1 execute bootstrap
1120Sstevel@tonic-gate  *		- process 2 to page out
1130Sstevel@tonic-gate  *	create system threads
1140Sstevel@tonic-gate  */
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate int cluster_bootflags = 0;
1170Sstevel@tonic-gate 
1180Sstevel@tonic-gate void
1190Sstevel@tonic-gate cluster_wrapper(void)
1200Sstevel@tonic-gate {
1210Sstevel@tonic-gate 	cluster();
1220Sstevel@tonic-gate 	panic("cluster()  returned");
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate 
125*2267Sdp char initname[INITNAME_SZ] = "/sbin/init";	/* also referenced by zone0 */
126*2267Sdp char initargs[BOOTARGS_MAX] = "";		/* also referenced by zone0 */
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate /*
129*2267Sdp  * Construct a stack for init containing the arguments to it, then
130*2267Sdp  * pass control to exec_common.
1310Sstevel@tonic-gate  */
132*2267Sdp int
133*2267Sdp exec_init(const char *initpath, const char *args)
1340Sstevel@tonic-gate {
135*2267Sdp 	caddr32_t ucp;
1360Sstevel@tonic-gate 	caddr32_t *uap;
137*2267Sdp 	caddr32_t *argv;
138*2267Sdp 	caddr32_t exec_fnamep;
139*2267Sdp 	char *scratchargs;
140*2267Sdp 	int i, sarg;
141*2267Sdp 	size_t argvlen, alen;
142*2267Sdp 	boolean_t in_arg;
1430Sstevel@tonic-gate 	int argc = 0;
144*2267Sdp 	int error = 0, count = 0;
1450Sstevel@tonic-gate 	proc_t *p = ttoproc(curthread);
1460Sstevel@tonic-gate 	klwp_t *lwp = ttolwp(curthread);
1470Sstevel@tonic-gate 
148*2267Sdp 	if (args == NULL)
149*2267Sdp 		args = "";
1500Sstevel@tonic-gate 
151*2267Sdp 	alen = strlen(initpath) + 1 + strlen(args) + 1;
152*2267Sdp 	scratchargs = kmem_alloc(alen, KM_SLEEP);
153*2267Sdp 	(void) snprintf(scratchargs, alen, "%s %s", initpath, args);
1540Sstevel@tonic-gate 
155*2267Sdp 	/*
156*2267Sdp 	 * We do a quick two state parse of the string to sort out how big
157*2267Sdp 	 * argc should be.
158*2267Sdp 	 */
159*2267Sdp 	in_arg = B_FALSE;
160*2267Sdp 	for (i = 0; i < strlen(scratchargs); i++) {
161*2267Sdp 		if (scratchargs[i] == ' ' || scratchargs[i] == '\0') {
162*2267Sdp 			if (in_arg) {
163*2267Sdp 				in_arg = B_FALSE;
164*2267Sdp 				argc++;
165*2267Sdp 			}
166*2267Sdp 		} else {
167*2267Sdp 			in_arg = B_TRUE;
168*2267Sdp 		}
1690Sstevel@tonic-gate 	}
170*2267Sdp 	argvlen = sizeof (caddr32_t) * (argc + 1);
171*2267Sdp 	argv = kmem_zalloc(argvlen, KM_SLEEP);
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	/*
174*2267Sdp 	 * We pull off a bit of a hack here.  We work our way through the
175*2267Sdp 	 * args string, putting nulls at the ends of space delimited tokens
176*2267Sdp 	 * (boot args don't support quoting at this time).  Then we just
177*2267Sdp 	 * copy the whole mess to userland in one go.  In other words, we
178*2267Sdp 	 * transform this: "init -s -r\0" into this on the stack:
179*2267Sdp 	 *
180*2267Sdp 	 *	-0x00 \0
181*2267Sdp 	 *	-0x01 r
182*2267Sdp 	 *	-0x02 -  <--------.
183*2267Sdp 	 *	-0x03 \0	  |
184*2267Sdp 	 *	-0x04 s		  |
185*2267Sdp 	 *	-0x05 -  <------. |
186*2267Sdp 	 *	-0x06 \0	| |
187*2267Sdp 	 *	-0x07 t		| |
188*2267Sdp 	 *	-0x08 i 	| |
189*2267Sdp 	 *	-0x09 n		| |
190*2267Sdp 	 *	-0x0a i  <---.  | |
191*2267Sdp 	 *	-0x10 NULL   |  | |	(argv[3])
192*2267Sdp 	 *	-0x14   -----|--|-'	(argv[2])
193*2267Sdp 	 *	-0x18  ------|--'	(argv[1])
194*2267Sdp 	 *	-0x1c -------'		(argv[0])
195*2267Sdp 	 *
196*2267Sdp 	 * Since we know the value of ucp at the beginning of this process,
197*2267Sdp 	 * we can trivially compute the argv[] array which we also need to
198*2267Sdp 	 * place in userland: argv[i] = ucp - sarg(i), where ucp is the
199*2267Sdp 	 * stack ptr, and sarg is the string index of the start of the
200*2267Sdp 	 * argument.
2010Sstevel@tonic-gate 	 */
202*2267Sdp 	ucp = (caddr32_t)(uintptr_t)p->p_usrstack;
203*2267Sdp 
204*2267Sdp 	argc = 0;
205*2267Sdp 	in_arg = B_FALSE;
206*2267Sdp 	sarg = 0;
207*2267Sdp 
208*2267Sdp 	for (i = 0; i < alen; i++) {
209*2267Sdp 		if (scratchargs[i] == ' ' || scratchargs[i] == '\0') {
210*2267Sdp 			if (in_arg == B_TRUE) {
211*2267Sdp 				in_arg = B_FALSE;
212*2267Sdp 				scratchargs[i] = '\0';
213*2267Sdp 				argv[argc++] = ucp - (alen - sarg);
214*2267Sdp 			}
215*2267Sdp 		} else if (in_arg == B_FALSE) {
216*2267Sdp 			in_arg = B_TRUE;
217*2267Sdp 			sarg = i;
218*2267Sdp 		}
219*2267Sdp 	}
220*2267Sdp 	ucp -= alen;
221*2267Sdp 	error |= copyout(scratchargs, (caddr_t)(uintptr_t)ucp, alen);
222*2267Sdp 
2230Sstevel@tonic-gate 	uap = (caddr32_t *)P2ALIGN((uintptr_t)ucp, sizeof (caddr32_t));
224*2267Sdp 	uap--;	/* advance to be below the word we're in */
225*2267Sdp 	uap -= (argc + 1);	/* advance argc words down, plus one for NULL */
226*2267Sdp 	error |= copyout(argv, uap, argvlen);
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	if (error != 0) {
2290Sstevel@tonic-gate 		zcmn_err(p->p_zone->zone_id, CE_WARN,
2300Sstevel@tonic-gate 		    "Could not construct stack for init.\n");
231*2267Sdp 		kmem_free(argv, argvlen);
232*2267Sdp 		kmem_free(scratchargs, alen);
2330Sstevel@tonic-gate 		return (EFAULT);
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate 
236*2267Sdp 	exec_fnamep = argv[0];
237*2267Sdp 	kmem_free(argv, argvlen);
238*2267Sdp 	kmem_free(scratchargs, alen);
239*2267Sdp 
2400Sstevel@tonic-gate 	/*
2410Sstevel@tonic-gate 	 * Point at the arguments.
2420Sstevel@tonic-gate 	 */
2430Sstevel@tonic-gate 	lwp->lwp_ap = lwp->lwp_arg;
244*2267Sdp 	lwp->lwp_arg[0] = (uintptr_t)exec_fnamep;
2450Sstevel@tonic-gate 	lwp->lwp_arg[1] = (uintptr_t)uap;
2460Sstevel@tonic-gate 	lwp->lwp_arg[2] = NULL;
2470Sstevel@tonic-gate 	curthread->t_post_sys = 1;
2480Sstevel@tonic-gate 	curthread->t_sysnum = SYS_execve;
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate again:
251*2267Sdp 	error = exec_common((const char *)(uintptr_t)exec_fnamep,
252*2267Sdp 	    (const char **)(uintptr_t)uap, NULL);
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	/*
2550Sstevel@tonic-gate 	 * Normally we would just set lwp_argsaved and t_post_sys and
2560Sstevel@tonic-gate 	 * let post_syscall reset lwp_ap for us.  Unfortunately,
2570Sstevel@tonic-gate 	 * exec_init isn't always called from a system call.  Instead
2580Sstevel@tonic-gate 	 * of making a mess of trap_cleanup, we just reset the args
2590Sstevel@tonic-gate 	 * pointer here.
2600Sstevel@tonic-gate 	 */
2610Sstevel@tonic-gate 	reset_syscall_args();
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	switch (error) {
2640Sstevel@tonic-gate 	case 0:
2650Sstevel@tonic-gate 		return (0);
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate 	case ENOENT:
2680Sstevel@tonic-gate 		zcmn_err(p->p_zone->zone_id, CE_WARN,
2690Sstevel@tonic-gate 		    "exec(%s) failed (file not found).\n", initpath);
2700Sstevel@tonic-gate 		return (ENOENT);
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	case EAGAIN:
2730Sstevel@tonic-gate 	case EINTR:
2740Sstevel@tonic-gate 		++count;
2750Sstevel@tonic-gate 		if (count < 5) {
2760Sstevel@tonic-gate 			zcmn_err(p->p_zone->zone_id, CE_WARN,
2770Sstevel@tonic-gate 			    "exec(%s) failed with errno %d.  Retrying...\n",
2780Sstevel@tonic-gate 			    initpath, error);
2790Sstevel@tonic-gate 			goto again;
2800Sstevel@tonic-gate 		}
2810Sstevel@tonic-gate 	}
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	zcmn_err(p->p_zone->zone_id, CE_WARN,
2840Sstevel@tonic-gate 	    "exec(%s) failed with errno %d.", initpath, error);
2850Sstevel@tonic-gate 	return (error);
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate 
288*2267Sdp /*
289*2267Sdp  * This routine does all of the common setup for invoking init; global
290*2267Sdp  * and non-global zones employ this routine for the functionality which is
291*2267Sdp  * in common.
292*2267Sdp  *
293*2267Sdp  * This program (init, presumably) must be a 32-bit process.
294*2267Sdp  */
295*2267Sdp int
296*2267Sdp start_init_common()
297*2267Sdp {
298*2267Sdp 	proc_t *p = curproc;
299*2267Sdp 	ASSERT_STACK_ALIGNED();
300*2267Sdp 	p->p_zone->zone_proc_initpid = p->p_pid;
301*2267Sdp 
302*2267Sdp 	p->p_cstime = p->p_stime = p->p_cutime = p->p_utime = 0;
303*2267Sdp 	p->p_usrstack = (caddr_t)USRSTACK32;
304*2267Sdp 	p->p_model = DATAMODEL_ILP32;
305*2267Sdp 	p->p_stkprot = PROT_ZFOD & ~PROT_EXEC;
306*2267Sdp 	p->p_datprot = PROT_ZFOD & ~PROT_EXEC;
307*2267Sdp 	p->p_stk_ctl = INT32_MAX;
308*2267Sdp 
309*2267Sdp 	p->p_as = as_alloc();
310*2267Sdp 	p->p_as->a_userlimit = (caddr_t)USERLIMIT32;
311*2267Sdp 	(void) hat_setup(p->p_as->a_hat, HAT_INIT);
312*2267Sdp 
313*2267Sdp 	init_core();
314*2267Sdp 
315*2267Sdp 	init_mstate(curthread, LMS_SYSTEM);
316*2267Sdp 	return (exec_init(p->p_zone->zone_initname, p->p_zone->zone_bootargs));
317*2267Sdp }
318*2267Sdp 
319*2267Sdp /*
320*2267Sdp  * Start the initial user process for the global zone; once running, if
321*2267Sdp  * init should subsequently fail, it will be automatically be caught in the
322*2267Sdp  * exit(2) path, and restarted by restart_init().
323*2267Sdp  */
324*2267Sdp static void
325*2267Sdp start_init(void)
326*2267Sdp {
327*2267Sdp 	proc_init = curproc;
328*2267Sdp 
329*2267Sdp 	ASSERT(curproc->p_zone->zone_initname != NULL);
330*2267Sdp 
331*2267Sdp 	if (start_init_common() != 0)
332*2267Sdp 		halt("unix: Could not start init");
333*2267Sdp 	lwp_rtt();
334*2267Sdp }
335*2267Sdp 
3360Sstevel@tonic-gate void
3370Sstevel@tonic-gate main(void)
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate 	proc_t		*p = ttoproc(curthread);	/* &p0 */
3400Sstevel@tonic-gate 	int		(**initptr)();
3410Sstevel@tonic-gate 	extern void	sched();
3420Sstevel@tonic-gate 	extern void	fsflush();
3430Sstevel@tonic-gate 	extern void	thread_reaper();
3440Sstevel@tonic-gate 	extern int	(*init_tbl[])();
3450Sstevel@tonic-gate 	extern int	(*mp_init_tbl[])();
3460Sstevel@tonic-gate 	extern id_t	syscid, defaultcid;
3470Sstevel@tonic-gate 	extern int	swaploaded;
3480Sstevel@tonic-gate 	extern int	netboot;
3490Sstevel@tonic-gate 	extern void	vm_init(void);
3500Sstevel@tonic-gate 	extern void	cbe_init(void);
3510Sstevel@tonic-gate 	extern void	clock_init(void);
3520Sstevel@tonic-gate 	extern void	physio_bufs_init(void);
3530Sstevel@tonic-gate 	extern void	pm_cfb_setup_intr(void);
3540Sstevel@tonic-gate 	extern int	pm_adjust_timestamps(dev_info_t *, void *);
3550Sstevel@tonic-gate 	extern void	start_other_cpus(int);
3560Sstevel@tonic-gate 	extern void	sysevent_evc_thrinit();
3570Sstevel@tonic-gate 	extern void	lgrp_main_init(void);
3580Sstevel@tonic-gate 	extern void	lgrp_main_mp_init(void);
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	/*
3610Sstevel@tonic-gate 	 * In the horrible world of x86 in-lines, you can't get symbolic
3620Sstevel@tonic-gate 	 * structure offsets a la genassym.  This assertion is here so
3630Sstevel@tonic-gate 	 * that the next poor slob who innocently changes the offset of
3640Sstevel@tonic-gate 	 * cpu_thread doesn't waste as much time as I just did finding
3650Sstevel@tonic-gate 	 * out that it's hard-coded in i86/ml/i86.il.  Similarly for
3660Sstevel@tonic-gate 	 * curcpup.  You're welcome.
3670Sstevel@tonic-gate 	 */
3680Sstevel@tonic-gate 	ASSERT(CPU == CPU->cpu_self);
3690Sstevel@tonic-gate 	ASSERT(curthread == CPU->cpu_thread);
3700Sstevel@tonic-gate 	ASSERT_STACK_ALIGNED();
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate 	/*
3730Sstevel@tonic-gate 	 * Setup the first lgroup, and home t0
3740Sstevel@tonic-gate 	 */
3750Sstevel@tonic-gate 	lgrp_setup();
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	startup();
3780Sstevel@tonic-gate 	segkmem_gc();
3790Sstevel@tonic-gate 	callb_init();
3800Sstevel@tonic-gate 	callout_init();	/* callout table MUST be init'd before clock starts */
3810Sstevel@tonic-gate 	cbe_init();
3820Sstevel@tonic-gate 	clock_init();
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	/*
3850Sstevel@tonic-gate 	 * May need to probe to determine latencies from CPU 0 after
3860Sstevel@tonic-gate 	 * gethrtime() comes alive in cbe_init() and before enabling interrupts
3870Sstevel@tonic-gate 	 */
3880Sstevel@tonic-gate 	lgrp_plat_probe();
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	/*
3910Sstevel@tonic-gate 	 * Call all system initialization functions.
3920Sstevel@tonic-gate 	 */
3930Sstevel@tonic-gate 	for (initptr = &init_tbl[0]; *initptr; initptr++)
3940Sstevel@tonic-gate 		(**initptr)();
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	/*
3970Sstevel@tonic-gate 	 * initialize vm related stuff.
3980Sstevel@tonic-gate 	 */
3990Sstevel@tonic-gate 	vm_init();
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	/*
4020Sstevel@tonic-gate 	 * initialize buffer pool for raw I/O requests
4030Sstevel@tonic-gate 	 */
4040Sstevel@tonic-gate 	physio_bufs_init();
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	ttolwp(curthread)->lwp_error = 0; /* XXX kludge for SCSI driver */
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	/*
4090Sstevel@tonic-gate 	 * Drop the interrupt level and allow interrupts.  At this point
4100Sstevel@tonic-gate 	 * the DDI guarantees that interrupts are enabled.
4110Sstevel@tonic-gate 	 */
4120Sstevel@tonic-gate 	(void) spl0();
4130Sstevel@tonic-gate 	interrupts_unleashed = 1;
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	vfs_mountroot();	/* Mount the root file system */
4160Sstevel@tonic-gate 	errorq_init();		/* after vfs_mountroot() so DDI root is ready */
4170Sstevel@tonic-gate 	cpu_kstat_init(CPU);	/* after vfs_mountroot() so TOD is valid */
4180Sstevel@tonic-gate 	ddi_walk_devs(ddi_root_node(), pm_adjust_timestamps, NULL);
4190Sstevel@tonic-gate 				/* after vfs_mountroot() so hrestime is valid */
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	post_startup();
4220Sstevel@tonic-gate 	swaploaded = 1;
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 	/*
4250Sstevel@tonic-gate 	 * Initial C2 audit system
4260Sstevel@tonic-gate 	 */
4270Sstevel@tonic-gate #ifdef C2_AUDIT
4280Sstevel@tonic-gate 	audit_init();	/* C2 hook */
4290Sstevel@tonic-gate #endif
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	/*
4320Sstevel@tonic-gate 	 * Plumb the protocol modules and drivers only if we are not
4330Sstevel@tonic-gate 	 * networked booted, in this case we already did it in rootconf().
4340Sstevel@tonic-gate 	 */
4350Sstevel@tonic-gate 	if (netboot == 0)
4360Sstevel@tonic-gate 		(void) strplumb();
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	gethrestime(&u.u_start);
4390Sstevel@tonic-gate 	curthread->t_start = u.u_start.tv_sec;
4400Sstevel@tonic-gate 	p->p_mstart = gethrtime();
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	/*
4430Sstevel@tonic-gate 	 * Perform setup functions that can only be done after root
4440Sstevel@tonic-gate 	 * and swap have been set up.
4450Sstevel@tonic-gate 	 */
4460Sstevel@tonic-gate 	consconfig();
4470Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
4480Sstevel@tonic-gate 	release_bootstrap();
4490Sstevel@tonic-gate #endif
4500Sstevel@tonic-gate 	/*
4510Sstevel@tonic-gate 	 * attach drivers with ddi-forceattach prop
4520Sstevel@tonic-gate 	 * This must be done after consconfig() to prevent usb key/mouse
4530Sstevel@tonic-gate 	 * from attaching before the upper console stream is plumbed.
4540Sstevel@tonic-gate 	 * It must be done early enough to load hotplug drivers (e.g.
4550Sstevel@tonic-gate 	 * pcmcia nexus) so that devices enumerated via hotplug is
4560Sstevel@tonic-gate 	 * available before I/O subsystem is fully initialized.
4570Sstevel@tonic-gate 	 */
4580Sstevel@tonic-gate 	i_ddi_forceattach_drivers();
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	/*
4610Sstevel@tonic-gate 	 * Set the scan rate and other parameters of the paging subsystem.
4620Sstevel@tonic-gate 	 */
4630Sstevel@tonic-gate 	setupclock(0);
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	/*
4660Sstevel@tonic-gate 	 * Create kmem cache for proc structures
4670Sstevel@tonic-gate 	 */
4680Sstevel@tonic-gate 	process_cache = kmem_cache_create("process_cache", sizeof (proc_t),
4690Sstevel@tonic-gate 	    0, NULL, NULL, NULL, NULL, NULL, 0);
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	/*
4720Sstevel@tonic-gate 	 * Initialize process 0's lwp directory and lwpid hash table.
4730Sstevel@tonic-gate 	 */
4740Sstevel@tonic-gate 	p->p_lwpdir = p->p_lwpfree = p0_lwpdir;
4750Sstevel@tonic-gate 	p->p_lwpdir->ld_next = p->p_lwpdir + 1;
4760Sstevel@tonic-gate 	p->p_lwpdir_sz = 2;
4770Sstevel@tonic-gate 	p->p_tidhash = p0_tidhash;
4780Sstevel@tonic-gate 	p->p_tidhash_sz = 2;
4790Sstevel@tonic-gate 	p0_lep.le_thread = curthread;
4800Sstevel@tonic-gate 	p0_lep.le_lwpid = curthread->t_tid;
4810Sstevel@tonic-gate 	p0_lep.le_start = curthread->t_start;
4820Sstevel@tonic-gate 	lwp_hash_in(p, &p0_lep);
4830Sstevel@tonic-gate 
4840Sstevel@tonic-gate 	/*
4850Sstevel@tonic-gate 	 * Initialize extended accounting.
4860Sstevel@tonic-gate 	 */
4870Sstevel@tonic-gate 	exacct_init();
4880Sstevel@tonic-gate 
4890Sstevel@tonic-gate 	/*
4900Sstevel@tonic-gate 	 * Initialize threads of sysevent event channels
4910Sstevel@tonic-gate 	 */
4920Sstevel@tonic-gate 	sysevent_evc_thrinit();
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	/*
4950Sstevel@tonic-gate 	 * main lgroup initialization
4960Sstevel@tonic-gate 	 * This must be done after post_startup(), but before
4970Sstevel@tonic-gate 	 * start_other_cpus()
4980Sstevel@tonic-gate 	 */
4990Sstevel@tonic-gate 	lgrp_main_init();
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	/*
5020Sstevel@tonic-gate 	 * Perform MP initialization, if any.
5030Sstevel@tonic-gate 	 */
5040Sstevel@tonic-gate 	start_other_cpus(0);
5050Sstevel@tonic-gate 
5060Sstevel@tonic-gate 	/*
5070Sstevel@tonic-gate 	 * Finish lgrp initialization after all CPUS are brought online.
5080Sstevel@tonic-gate 	 */
5090Sstevel@tonic-gate 	lgrp_main_mp_init();
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	/*
5120Sstevel@tonic-gate 	 * After mp_init(), number of cpus are known (this is
5130Sstevel@tonic-gate 	 * true for the time being, when there are actually
5140Sstevel@tonic-gate 	 * hot pluggable cpus then this scheme  would not do).
5150Sstevel@tonic-gate 	 * Any per cpu initialization is done here.
5160Sstevel@tonic-gate 	 */
5170Sstevel@tonic-gate 	kmem_mp_init();
5180Sstevel@tonic-gate 	vmem_update(NULL);
5190Sstevel@tonic-gate 
5200Sstevel@tonic-gate 	for (initptr = &mp_init_tbl[0]; *initptr; initptr++)
5210Sstevel@tonic-gate 		(**initptr)();
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	/*
5240Sstevel@tonic-gate 	 * This must be called after start_other_cpus
5250Sstevel@tonic-gate 	 */
5260Sstevel@tonic-gate 	pm_cfb_setup_intr();
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 	/*
5290Sstevel@tonic-gate 	 * Make init process; enter scheduling loop with system process.
5300Sstevel@tonic-gate 	 */
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 	/* create init process */
533*2267Sdp 	if (newproc(start_init, NULL, defaultcid, 59, NULL))
5340Sstevel@tonic-gate 		panic("main: unable to fork init.");
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 	/* create pageout daemon */
5370Sstevel@tonic-gate 	if (newproc(pageout, NULL, syscid, maxclsyspri - 1, NULL))
5380Sstevel@tonic-gate 		panic("main: unable to fork pageout()");
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	/* create fsflush daemon */
5410Sstevel@tonic-gate 	if (newproc(fsflush, NULL, syscid, minclsyspri, NULL))
5420Sstevel@tonic-gate 		panic("main: unable to fork fsflush()");
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	/* create cluster process if we're a member of one */
5450Sstevel@tonic-gate 	if (cluster_bootflags & CLUSTER_BOOTED) {
5460Sstevel@tonic-gate 		if (newproc(cluster_wrapper, NULL, syscid, minclsyspri, NULL))
5470Sstevel@tonic-gate 			panic("main: unable to fork cluster()");
5480Sstevel@tonic-gate 	}
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 	/*
5510Sstevel@tonic-gate 	 * Create system threads (threads are associated with p0)
5520Sstevel@tonic-gate 	 */
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	/* create thread_reaper daemon */
5550Sstevel@tonic-gate 	(void) thread_create(NULL, 0, (void (*)())thread_reaper,
5560Sstevel@tonic-gate 	    NULL, 0, &p0, TS_RUN, minclsyspri);
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	/* create module uninstall daemon */
5590Sstevel@tonic-gate 	/* BugID 1132273. If swapping over NFS need a bigger stack */
5600Sstevel@tonic-gate 	(void) thread_create(NULL, 0, (void (*)())mod_uninstall_daemon,
5610Sstevel@tonic-gate 	    NULL, 0, &p0, TS_RUN, minclsyspri);
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 	(void) thread_create(NULL, 0, seg_pasync_thread,
5640Sstevel@tonic-gate 	    NULL, 0, &p0, TS_RUN, minclsyspri);
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	pid_setmin();
5670Sstevel@tonic-gate 
5680Sstevel@tonic-gate 	bcopy("sched", u.u_psargs, 6);
5690Sstevel@tonic-gate 	bcopy("sched", u.u_comm, 5);
5700Sstevel@tonic-gate 	sched();
5710Sstevel@tonic-gate 	/* NOTREACHED */
5720Sstevel@tonic-gate }
573