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 5*1676Sjpk * Common Development and Distribution License (the "License"). 6*1676Sjpk * 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 /* 22*1676Sjpk * 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 1250Sstevel@tonic-gate char initname[INITNAME_SZ] = "/sbin/init"; 1260Sstevel@tonic-gate char initargs[INITARGS_SZ] = ""; 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate /* 1290Sstevel@tonic-gate * Start the initial user process. 1300Sstevel@tonic-gate * The program [initname] may be invoked with one argument 1310Sstevel@tonic-gate * containing the boot flags. 1320Sstevel@tonic-gate * 1330Sstevel@tonic-gate * It must be a 32-bit program. 1340Sstevel@tonic-gate */ 1350Sstevel@tonic-gate void 1360Sstevel@tonic-gate icode(void) 1370Sstevel@tonic-gate { 1380Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate ASSERT_STACK_ALIGNED(); 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate /* 1430Sstevel@tonic-gate * Allocate user address space and stack segment 1440Sstevel@tonic-gate */ 1450Sstevel@tonic-gate proc_init = p; 1460Sstevel@tonic-gate zone0.zone_proc_initpid = proc_init->p_pid; 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate p->p_cstime = p->p_stime = p->p_cutime = p->p_utime = 0; 1490Sstevel@tonic-gate p->p_usrstack = (caddr_t)USRSTACK32; 1500Sstevel@tonic-gate p->p_model = DATAMODEL_ILP32; 1510Sstevel@tonic-gate p->p_stkprot = PROT_ZFOD & ~PROT_EXEC; 1520Sstevel@tonic-gate p->p_datprot = PROT_ZFOD & ~PROT_EXEC; 1530Sstevel@tonic-gate p->p_stk_ctl = INT32_MAX; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate p->p_as = as_alloc(); 1560Sstevel@tonic-gate p->p_as->a_userlimit = (caddr_t)USERLIMIT32; 1570Sstevel@tonic-gate (void) hat_setup(p->p_as->a_hat, HAT_INIT); 1580Sstevel@tonic-gate init_core(); 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate init_mstate(curthread, LMS_SYSTEM); 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate if (exec_init(initname, 1, initargs[0] == '\0' ? NULL : initargs) != 0) 1630Sstevel@tonic-gate halt("Could not start init"); 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate lwp_rtt(); 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate int 1690Sstevel@tonic-gate exec_init(const char *initpath, int useboothowto, const char *args) 1700Sstevel@tonic-gate { 1710Sstevel@tonic-gate char *ucp; 1720Sstevel@tonic-gate caddr32_t *uap; 1730Sstevel@tonic-gate char *argv[4]; /* backwards */ 1740Sstevel@tonic-gate int argc = 0; 1750Sstevel@tonic-gate int error = 0, len, count = 0, i; 1760Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 1770Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate /* 1800Sstevel@tonic-gate * Construct the exec arguments in userland. That is, make an array 1810Sstevel@tonic-gate * of pointers to the argument strings, just like for execv(). This 1820Sstevel@tonic-gate * is done backwards. 1830Sstevel@tonic-gate */ 1840Sstevel@tonic-gate ucp = p->p_usrstack; 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate argv[0] = NULL; /* argv terminator */ 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate if (args != NULL) { 1890Sstevel@tonic-gate len = strlen(args) + 1; 1900Sstevel@tonic-gate ucp -= len; 1910Sstevel@tonic-gate error |= copyoutstr(args, ucp, len, NULL); 1920Sstevel@tonic-gate argv[++argc] = ucp; 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate 1950Sstevel@tonic-gate if (useboothowto && 1960Sstevel@tonic-gate boothowto & (RB_SINGLE|RB_RECONFIG|RB_VERBOSE)) { 1970Sstevel@tonic-gate error |= subyte(--ucp, '\0'); /* trailing null byte */ 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate if (boothowto & RB_SINGLE) 2000Sstevel@tonic-gate error |= subyte(--ucp, 's'); 2010Sstevel@tonic-gate if (boothowto & RB_RECONFIG) 2020Sstevel@tonic-gate error |= subyte(--ucp, 'r'); 2030Sstevel@tonic-gate if (boothowto & RB_VERBOSE) 2040Sstevel@tonic-gate error |= subyte(--ucp, 'v'); 2050Sstevel@tonic-gate error |= subyte(--ucp, '-'); /* leading hyphen */ 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate argv[++argc] = ucp; 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate len = strlen(initpath) + 1; 2110Sstevel@tonic-gate ucp -= len; 2120Sstevel@tonic-gate error |= copyoutstr(initpath, ucp, len, NULL); 2130Sstevel@tonic-gate argv[++argc] = ucp; 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* 2160Sstevel@tonic-gate * Move out the arg pointers. 2170Sstevel@tonic-gate */ 2180Sstevel@tonic-gate uap = (caddr32_t *)P2ALIGN((uintptr_t)ucp, sizeof (caddr32_t)); 2190Sstevel@tonic-gate for (i = 0; i < argc + 1; ++i) 2200Sstevel@tonic-gate error |= suword32(--uap, (uint32_t)(uintptr_t)argv[i]); 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate if (error != 0) { 2230Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 2240Sstevel@tonic-gate "Could not construct stack for init.\n"); 2250Sstevel@tonic-gate return (EFAULT); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate /* 2290Sstevel@tonic-gate * Point at the arguments. 2300Sstevel@tonic-gate */ 2310Sstevel@tonic-gate lwp->lwp_ap = lwp->lwp_arg; 2320Sstevel@tonic-gate lwp->lwp_arg[0] = (uintptr_t)argv[argc]; 2330Sstevel@tonic-gate lwp->lwp_arg[1] = (uintptr_t)uap; 2340Sstevel@tonic-gate lwp->lwp_arg[2] = NULL; 2350Sstevel@tonic-gate curthread->t_post_sys = 1; 2360Sstevel@tonic-gate curthread->t_sysnum = SYS_execve; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate again: 2390Sstevel@tonic-gate error = exec_common((const char *)argv[argc], (const char **)uap, NULL); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate /* 2420Sstevel@tonic-gate * Normally we would just set lwp_argsaved and t_post_sys and 2430Sstevel@tonic-gate * let post_syscall reset lwp_ap for us. Unfortunately, 2440Sstevel@tonic-gate * exec_init isn't always called from a system call. Instead 2450Sstevel@tonic-gate * of making a mess of trap_cleanup, we just reset the args 2460Sstevel@tonic-gate * pointer here. 2470Sstevel@tonic-gate */ 2480Sstevel@tonic-gate reset_syscall_args(); 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate switch (error) { 2510Sstevel@tonic-gate case 0: 2520Sstevel@tonic-gate return (0); 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate case ENOENT: 2550Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 2560Sstevel@tonic-gate "exec(%s) failed (file not found).\n", initpath); 2570Sstevel@tonic-gate return (ENOENT); 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate case EAGAIN: 2600Sstevel@tonic-gate case EINTR: 2610Sstevel@tonic-gate ++count; 2620Sstevel@tonic-gate if (count < 5) { 2630Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 2640Sstevel@tonic-gate "exec(%s) failed with errno %d. Retrying...\n", 2650Sstevel@tonic-gate initpath, error); 2660Sstevel@tonic-gate goto again; 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate } 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 2710Sstevel@tonic-gate "exec(%s) failed with errno %d.", initpath, error); 2720Sstevel@tonic-gate return (error); 2730Sstevel@tonic-gate } 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate void 2760Sstevel@tonic-gate main(void) 2770Sstevel@tonic-gate { 2780Sstevel@tonic-gate proc_t *p = ttoproc(curthread); /* &p0 */ 2790Sstevel@tonic-gate int (**initptr)(); 2800Sstevel@tonic-gate extern void sched(); 2810Sstevel@tonic-gate extern void fsflush(); 2820Sstevel@tonic-gate extern void thread_reaper(); 2830Sstevel@tonic-gate extern int (*init_tbl[])(); 2840Sstevel@tonic-gate extern int (*mp_init_tbl[])(); 2850Sstevel@tonic-gate extern id_t syscid, defaultcid; 2860Sstevel@tonic-gate extern int swaploaded; 2870Sstevel@tonic-gate extern int netboot; 2880Sstevel@tonic-gate extern void vm_init(void); 2890Sstevel@tonic-gate extern void cbe_init(void); 2900Sstevel@tonic-gate extern void clock_init(void); 2910Sstevel@tonic-gate extern void physio_bufs_init(void); 2920Sstevel@tonic-gate extern void pm_cfb_setup_intr(void); 2930Sstevel@tonic-gate extern int pm_adjust_timestamps(dev_info_t *, void *); 2940Sstevel@tonic-gate extern void start_other_cpus(int); 2950Sstevel@tonic-gate extern void sysevent_evc_thrinit(); 2960Sstevel@tonic-gate extern void lgrp_main_init(void); 2970Sstevel@tonic-gate extern void lgrp_main_mp_init(void); 2980Sstevel@tonic-gate 2990Sstevel@tonic-gate /* 3000Sstevel@tonic-gate * In the horrible world of x86 in-lines, you can't get symbolic 3010Sstevel@tonic-gate * structure offsets a la genassym. This assertion is here so 3020Sstevel@tonic-gate * that the next poor slob who innocently changes the offset of 3030Sstevel@tonic-gate * cpu_thread doesn't waste as much time as I just did finding 3040Sstevel@tonic-gate * out that it's hard-coded in i86/ml/i86.il. Similarly for 3050Sstevel@tonic-gate * curcpup. You're welcome. 3060Sstevel@tonic-gate */ 3070Sstevel@tonic-gate ASSERT(CPU == CPU->cpu_self); 3080Sstevel@tonic-gate ASSERT(curthread == CPU->cpu_thread); 3090Sstevel@tonic-gate ASSERT_STACK_ALIGNED(); 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate /* 3120Sstevel@tonic-gate * Setup the first lgroup, and home t0 3130Sstevel@tonic-gate */ 3140Sstevel@tonic-gate lgrp_setup(); 3150Sstevel@tonic-gate 3160Sstevel@tonic-gate startup(); 3170Sstevel@tonic-gate segkmem_gc(); 3180Sstevel@tonic-gate callb_init(); 3190Sstevel@tonic-gate callout_init(); /* callout table MUST be init'd before clock starts */ 3200Sstevel@tonic-gate cbe_init(); 3210Sstevel@tonic-gate clock_init(); 3220Sstevel@tonic-gate 3230Sstevel@tonic-gate /* 3240Sstevel@tonic-gate * May need to probe to determine latencies from CPU 0 after 3250Sstevel@tonic-gate * gethrtime() comes alive in cbe_init() and before enabling interrupts 3260Sstevel@tonic-gate */ 3270Sstevel@tonic-gate lgrp_plat_probe(); 3280Sstevel@tonic-gate 3290Sstevel@tonic-gate /* 3300Sstevel@tonic-gate * Call all system initialization functions. 3310Sstevel@tonic-gate */ 3320Sstevel@tonic-gate for (initptr = &init_tbl[0]; *initptr; initptr++) 3330Sstevel@tonic-gate (**initptr)(); 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate /* 3360Sstevel@tonic-gate * initialize vm related stuff. 3370Sstevel@tonic-gate */ 3380Sstevel@tonic-gate vm_init(); 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate /* 3410Sstevel@tonic-gate * initialize buffer pool for raw I/O requests 3420Sstevel@tonic-gate */ 3430Sstevel@tonic-gate physio_bufs_init(); 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate ttolwp(curthread)->lwp_error = 0; /* XXX kludge for SCSI driver */ 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Drop the interrupt level and allow interrupts. At this point 3490Sstevel@tonic-gate * the DDI guarantees that interrupts are enabled. 3500Sstevel@tonic-gate */ 3510Sstevel@tonic-gate (void) spl0(); 3520Sstevel@tonic-gate interrupts_unleashed = 1; 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate vfs_mountroot(); /* Mount the root file system */ 3550Sstevel@tonic-gate errorq_init(); /* after vfs_mountroot() so DDI root is ready */ 3560Sstevel@tonic-gate cpu_kstat_init(CPU); /* after vfs_mountroot() so TOD is valid */ 3570Sstevel@tonic-gate ddi_walk_devs(ddi_root_node(), pm_adjust_timestamps, NULL); 3580Sstevel@tonic-gate /* after vfs_mountroot() so hrestime is valid */ 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate post_startup(); 3610Sstevel@tonic-gate swaploaded = 1; 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate /* 3640Sstevel@tonic-gate * Initial C2 audit system 3650Sstevel@tonic-gate */ 3660Sstevel@tonic-gate #ifdef C2_AUDIT 3670Sstevel@tonic-gate audit_init(); /* C2 hook */ 3680Sstevel@tonic-gate #endif 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate /* 3710Sstevel@tonic-gate * Plumb the protocol modules and drivers only if we are not 3720Sstevel@tonic-gate * networked booted, in this case we already did it in rootconf(). 3730Sstevel@tonic-gate */ 3740Sstevel@tonic-gate if (netboot == 0) 3750Sstevel@tonic-gate (void) strplumb(); 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate gethrestime(&u.u_start); 3780Sstevel@tonic-gate curthread->t_start = u.u_start.tv_sec; 3790Sstevel@tonic-gate p->p_mstart = gethrtime(); 3800Sstevel@tonic-gate 3810Sstevel@tonic-gate /* 3820Sstevel@tonic-gate * Perform setup functions that can only be done after root 3830Sstevel@tonic-gate * and swap have been set up. 3840Sstevel@tonic-gate */ 3850Sstevel@tonic-gate consconfig(); 3860Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 3870Sstevel@tonic-gate release_bootstrap(); 3880Sstevel@tonic-gate #endif 3890Sstevel@tonic-gate /* 3900Sstevel@tonic-gate * attach drivers with ddi-forceattach prop 3910Sstevel@tonic-gate * This must be done after consconfig() to prevent usb key/mouse 3920Sstevel@tonic-gate * from attaching before the upper console stream is plumbed. 3930Sstevel@tonic-gate * It must be done early enough to load hotplug drivers (e.g. 3940Sstevel@tonic-gate * pcmcia nexus) so that devices enumerated via hotplug is 3950Sstevel@tonic-gate * available before I/O subsystem is fully initialized. 3960Sstevel@tonic-gate */ 3970Sstevel@tonic-gate i_ddi_forceattach_drivers(); 3980Sstevel@tonic-gate 3990Sstevel@tonic-gate /* 4000Sstevel@tonic-gate * Set the scan rate and other parameters of the paging subsystem. 4010Sstevel@tonic-gate */ 4020Sstevel@tonic-gate setupclock(0); 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate /* 4050Sstevel@tonic-gate * Create kmem cache for proc structures 4060Sstevel@tonic-gate */ 4070Sstevel@tonic-gate process_cache = kmem_cache_create("process_cache", sizeof (proc_t), 4080Sstevel@tonic-gate 0, NULL, NULL, NULL, NULL, NULL, 0); 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate /* 4110Sstevel@tonic-gate * Initialize process 0's lwp directory and lwpid hash table. 4120Sstevel@tonic-gate */ 4130Sstevel@tonic-gate p->p_lwpdir = p->p_lwpfree = p0_lwpdir; 4140Sstevel@tonic-gate p->p_lwpdir->ld_next = p->p_lwpdir + 1; 4150Sstevel@tonic-gate p->p_lwpdir_sz = 2; 4160Sstevel@tonic-gate p->p_tidhash = p0_tidhash; 4170Sstevel@tonic-gate p->p_tidhash_sz = 2; 4180Sstevel@tonic-gate p0_lep.le_thread = curthread; 4190Sstevel@tonic-gate p0_lep.le_lwpid = curthread->t_tid; 4200Sstevel@tonic-gate p0_lep.le_start = curthread->t_start; 4210Sstevel@tonic-gate lwp_hash_in(p, &p0_lep); 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate /* 4240Sstevel@tonic-gate * Initialize extended accounting. 4250Sstevel@tonic-gate */ 4260Sstevel@tonic-gate exacct_init(); 4270Sstevel@tonic-gate 4280Sstevel@tonic-gate /* 4290Sstevel@tonic-gate * Initialize threads of sysevent event channels 4300Sstevel@tonic-gate */ 4310Sstevel@tonic-gate sysevent_evc_thrinit(); 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate /* 4340Sstevel@tonic-gate * main lgroup initialization 4350Sstevel@tonic-gate * This must be done after post_startup(), but before 4360Sstevel@tonic-gate * start_other_cpus() 4370Sstevel@tonic-gate */ 4380Sstevel@tonic-gate lgrp_main_init(); 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate /* 4410Sstevel@tonic-gate * Perform MP initialization, if any. 4420Sstevel@tonic-gate */ 4430Sstevel@tonic-gate start_other_cpus(0); 4440Sstevel@tonic-gate 4450Sstevel@tonic-gate /* 4460Sstevel@tonic-gate * Finish lgrp initialization after all CPUS are brought online. 4470Sstevel@tonic-gate */ 4480Sstevel@tonic-gate lgrp_main_mp_init(); 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate /* 4510Sstevel@tonic-gate * After mp_init(), number of cpus are known (this is 4520Sstevel@tonic-gate * true for the time being, when there are actually 4530Sstevel@tonic-gate * hot pluggable cpus then this scheme would not do). 4540Sstevel@tonic-gate * Any per cpu initialization is done here. 4550Sstevel@tonic-gate */ 4560Sstevel@tonic-gate kmem_mp_init(); 4570Sstevel@tonic-gate vmem_update(NULL); 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate for (initptr = &mp_init_tbl[0]; *initptr; initptr++) 4600Sstevel@tonic-gate (**initptr)(); 4610Sstevel@tonic-gate 4620Sstevel@tonic-gate /* 4630Sstevel@tonic-gate * This must be called after start_other_cpus 4640Sstevel@tonic-gate */ 4650Sstevel@tonic-gate pm_cfb_setup_intr(); 4660Sstevel@tonic-gate 4670Sstevel@tonic-gate /* 4680Sstevel@tonic-gate * Make init process; enter scheduling loop with system process. 4690Sstevel@tonic-gate */ 4700Sstevel@tonic-gate 4710Sstevel@tonic-gate /* create init process */ 4720Sstevel@tonic-gate if (newproc(icode, NULL, defaultcid, 59, NULL)) 4730Sstevel@tonic-gate panic("main: unable to fork init."); 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate /* create pageout daemon */ 4760Sstevel@tonic-gate if (newproc(pageout, NULL, syscid, maxclsyspri - 1, NULL)) 4770Sstevel@tonic-gate panic("main: unable to fork pageout()"); 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate /* create fsflush daemon */ 4800Sstevel@tonic-gate if (newproc(fsflush, NULL, syscid, minclsyspri, NULL)) 4810Sstevel@tonic-gate panic("main: unable to fork fsflush()"); 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate /* create cluster process if we're a member of one */ 4840Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED) { 4850Sstevel@tonic-gate if (newproc(cluster_wrapper, NULL, syscid, minclsyspri, NULL)) 4860Sstevel@tonic-gate panic("main: unable to fork cluster()"); 4870Sstevel@tonic-gate } 4880Sstevel@tonic-gate 4890Sstevel@tonic-gate /* 4900Sstevel@tonic-gate * Create system threads (threads are associated with p0) 4910Sstevel@tonic-gate */ 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate /* create thread_reaper daemon */ 4940Sstevel@tonic-gate (void) thread_create(NULL, 0, (void (*)())thread_reaper, 4950Sstevel@tonic-gate NULL, 0, &p0, TS_RUN, minclsyspri); 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate /* create module uninstall daemon */ 4980Sstevel@tonic-gate /* BugID 1132273. If swapping over NFS need a bigger stack */ 4990Sstevel@tonic-gate (void) thread_create(NULL, 0, (void (*)())mod_uninstall_daemon, 5000Sstevel@tonic-gate NULL, 0, &p0, TS_RUN, minclsyspri); 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate (void) thread_create(NULL, 0, seg_pasync_thread, 5030Sstevel@tonic-gate NULL, 0, &p0, TS_RUN, minclsyspri); 5040Sstevel@tonic-gate 5050Sstevel@tonic-gate pid_setmin(); 5060Sstevel@tonic-gate 5070Sstevel@tonic-gate bcopy("sched", u.u_psargs, 6); 5080Sstevel@tonic-gate bcopy("sched", u.u_comm, 5); 5090Sstevel@tonic-gate sched(); 5100Sstevel@tonic-gate /* NOTREACHED */ 5110Sstevel@tonic-gate } 512