1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1988 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" /* from SVr4.0 1.31 */ 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/pcb.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/priocntl.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/procset.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/var.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/disp.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/callo.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/callb.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/vmparam.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/vm.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/callb.h> 61*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 62*7c478bd9Sstevel@tonic-gate #include <sys/vmem.h> 63*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h> 64*7c478bd9Sstevel@tonic-gate #include <sys/cladm.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/exec.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/syscall.h> 68*7c478bd9Sstevel@tonic-gate #include <sys/reboot.h> 69*7c478bd9Sstevel@tonic-gate #include <sys/task.h> 70*7c478bd9Sstevel@tonic-gate #include <sys/exacct.h> 71*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 72*7c478bd9Sstevel@tonic-gate #include <sys/errorq.h> 73*7c478bd9Sstevel@tonic-gate #include <sys/class.h> 74*7c478bd9Sstevel@tonic-gate #include <sys/stack.h> 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 77*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 78*7c478bd9Sstevel@tonic-gate #include <sys/dc_ki.h> 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate #include <c2/audit.h> 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate /* well known processes */ 83*7c478bd9Sstevel@tonic-gate proc_t *proc_sched; /* memory scheduler */ 84*7c478bd9Sstevel@tonic-gate proc_t *proc_init; /* init */ 85*7c478bd9Sstevel@tonic-gate proc_t *proc_pageout; /* pageout daemon */ 86*7c478bd9Sstevel@tonic-gate proc_t *proc_fsflush; /* fsflush daemon */ 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate pgcnt_t maxmem; /* Maximum available memory in pages. */ 89*7c478bd9Sstevel@tonic-gate pgcnt_t freemem; /* Current available memory in pages. */ 90*7c478bd9Sstevel@tonic-gate int audit_active; 91*7c478bd9Sstevel@tonic-gate int interrupts_unleashed; /* set when we do the first spl0() */ 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate kmem_cache_t *process_cache; /* kmem cache for proc structures */ 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* 96*7c478bd9Sstevel@tonic-gate * Process 0's lwp directory and lwpid hash table. 97*7c478bd9Sstevel@tonic-gate */ 98*7c478bd9Sstevel@tonic-gate lwpdir_t p0_lwpdir[2]; 99*7c478bd9Sstevel@tonic-gate lwpdir_t *p0_tidhash[2]; 100*7c478bd9Sstevel@tonic-gate lwpent_t p0_lep; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /* 103*7c478bd9Sstevel@tonic-gate * Machine-independent initialization code 104*7c478bd9Sstevel@tonic-gate * Called from cold start routine as 105*7c478bd9Sstevel@tonic-gate * soon as a stack and segmentation 106*7c478bd9Sstevel@tonic-gate * have been established. 107*7c478bd9Sstevel@tonic-gate * Functions: 108*7c478bd9Sstevel@tonic-gate * clear and free user core 109*7c478bd9Sstevel@tonic-gate * turn on clock 110*7c478bd9Sstevel@tonic-gate * hand craft 0th process 111*7c478bd9Sstevel@tonic-gate * call all initialization routines 112*7c478bd9Sstevel@tonic-gate * fork - process 0 to schedule 113*7c478bd9Sstevel@tonic-gate * - process 1 execute bootstrap 114*7c478bd9Sstevel@tonic-gate * - process 2 to page out 115*7c478bd9Sstevel@tonic-gate * create system threads 116*7c478bd9Sstevel@tonic-gate */ 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate int cluster_bootflags = 0; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate void 121*7c478bd9Sstevel@tonic-gate cluster_wrapper(void) 122*7c478bd9Sstevel@tonic-gate { 123*7c478bd9Sstevel@tonic-gate cluster(); 124*7c478bd9Sstevel@tonic-gate panic("cluster() returned"); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate char initname[INITNAME_SZ] = "/sbin/init"; 128*7c478bd9Sstevel@tonic-gate char initargs[INITARGS_SZ] = ""; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * Start the initial user process. 132*7c478bd9Sstevel@tonic-gate * The program [initname] may be invoked with one argument 133*7c478bd9Sstevel@tonic-gate * containing the boot flags. 134*7c478bd9Sstevel@tonic-gate * 135*7c478bd9Sstevel@tonic-gate * It must be a 32-bit program. 136*7c478bd9Sstevel@tonic-gate */ 137*7c478bd9Sstevel@tonic-gate void 138*7c478bd9Sstevel@tonic-gate icode(void) 139*7c478bd9Sstevel@tonic-gate { 140*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate ASSERT_STACK_ALIGNED(); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate /* 145*7c478bd9Sstevel@tonic-gate * Allocate user address space and stack segment 146*7c478bd9Sstevel@tonic-gate */ 147*7c478bd9Sstevel@tonic-gate proc_init = p; 148*7c478bd9Sstevel@tonic-gate zone0.zone_proc_initpid = proc_init->p_pid; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate p->p_cstime = p->p_stime = p->p_cutime = p->p_utime = 0; 151*7c478bd9Sstevel@tonic-gate p->p_usrstack = (caddr_t)USRSTACK32; 152*7c478bd9Sstevel@tonic-gate p->p_model = DATAMODEL_ILP32; 153*7c478bd9Sstevel@tonic-gate p->p_stkprot = PROT_ZFOD & ~PROT_EXEC; 154*7c478bd9Sstevel@tonic-gate p->p_datprot = PROT_ZFOD & ~PROT_EXEC; 155*7c478bd9Sstevel@tonic-gate p->p_stk_ctl = INT32_MAX; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate p->p_as = as_alloc(); 158*7c478bd9Sstevel@tonic-gate p->p_as->a_userlimit = (caddr_t)USERLIMIT32; 159*7c478bd9Sstevel@tonic-gate (void) hat_setup(p->p_as->a_hat, HAT_INIT); 160*7c478bd9Sstevel@tonic-gate init_core(); 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate init_mstate(curthread, LMS_SYSTEM); 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate if (exec_init(initname, 1, initargs[0] == '\0' ? NULL : initargs) != 0) 165*7c478bd9Sstevel@tonic-gate halt("Could not start init"); 166*7c478bd9Sstevel@tonic-gate 167*7c478bd9Sstevel@tonic-gate lwp_rtt(); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate int 171*7c478bd9Sstevel@tonic-gate exec_init(const char *initpath, int useboothowto, const char *args) 172*7c478bd9Sstevel@tonic-gate { 173*7c478bd9Sstevel@tonic-gate char *ucp; 174*7c478bd9Sstevel@tonic-gate caddr32_t *uap; 175*7c478bd9Sstevel@tonic-gate char *argv[4]; /* backwards */ 176*7c478bd9Sstevel@tonic-gate int argc = 0; 177*7c478bd9Sstevel@tonic-gate int error = 0, len, count = 0, i; 178*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); 179*7c478bd9Sstevel@tonic-gate klwp_t *lwp = ttolwp(curthread); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* 182*7c478bd9Sstevel@tonic-gate * Construct the exec arguments in userland. That is, make an array 183*7c478bd9Sstevel@tonic-gate * of pointers to the argument strings, just like for execv(). This 184*7c478bd9Sstevel@tonic-gate * is done backwards. 185*7c478bd9Sstevel@tonic-gate */ 186*7c478bd9Sstevel@tonic-gate ucp = p->p_usrstack; 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate argv[0] = NULL; /* argv terminator */ 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate if (args != NULL) { 191*7c478bd9Sstevel@tonic-gate len = strlen(args) + 1; 192*7c478bd9Sstevel@tonic-gate ucp -= len; 193*7c478bd9Sstevel@tonic-gate error |= copyoutstr(args, ucp, len, NULL); 194*7c478bd9Sstevel@tonic-gate argv[++argc] = ucp; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate if (useboothowto && 198*7c478bd9Sstevel@tonic-gate boothowto & (RB_SINGLE|RB_RECONFIG|RB_VERBOSE)) { 199*7c478bd9Sstevel@tonic-gate error |= subyte(--ucp, '\0'); /* trailing null byte */ 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (boothowto & RB_SINGLE) 202*7c478bd9Sstevel@tonic-gate error |= subyte(--ucp, 's'); 203*7c478bd9Sstevel@tonic-gate if (boothowto & RB_RECONFIG) 204*7c478bd9Sstevel@tonic-gate error |= subyte(--ucp, 'r'); 205*7c478bd9Sstevel@tonic-gate if (boothowto & RB_VERBOSE) 206*7c478bd9Sstevel@tonic-gate error |= subyte(--ucp, 'v'); 207*7c478bd9Sstevel@tonic-gate error |= subyte(--ucp, '-'); /* leading hyphen */ 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate argv[++argc] = ucp; 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate len = strlen(initpath) + 1; 213*7c478bd9Sstevel@tonic-gate ucp -= len; 214*7c478bd9Sstevel@tonic-gate error |= copyoutstr(initpath, ucp, len, NULL); 215*7c478bd9Sstevel@tonic-gate argv[++argc] = ucp; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate /* 218*7c478bd9Sstevel@tonic-gate * Move out the arg pointers. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate uap = (caddr32_t *)P2ALIGN((uintptr_t)ucp, sizeof (caddr32_t)); 221*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc + 1; ++i) 222*7c478bd9Sstevel@tonic-gate error |= suword32(--uap, (uint32_t)(uintptr_t)argv[i]); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate if (error != 0) { 225*7c478bd9Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 226*7c478bd9Sstevel@tonic-gate "Could not construct stack for init.\n"); 227*7c478bd9Sstevel@tonic-gate return (EFAULT); 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* 231*7c478bd9Sstevel@tonic-gate * Point at the arguments. 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate lwp->lwp_ap = lwp->lwp_arg; 234*7c478bd9Sstevel@tonic-gate lwp->lwp_arg[0] = (uintptr_t)argv[argc]; 235*7c478bd9Sstevel@tonic-gate lwp->lwp_arg[1] = (uintptr_t)uap; 236*7c478bd9Sstevel@tonic-gate lwp->lwp_arg[2] = NULL; 237*7c478bd9Sstevel@tonic-gate curthread->t_post_sys = 1; 238*7c478bd9Sstevel@tonic-gate curthread->t_sysnum = SYS_execve; 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate again: 241*7c478bd9Sstevel@tonic-gate error = exec_common((const char *)argv[argc], (const char **)uap, NULL); 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * Normally we would just set lwp_argsaved and t_post_sys and 245*7c478bd9Sstevel@tonic-gate * let post_syscall reset lwp_ap for us. Unfortunately, 246*7c478bd9Sstevel@tonic-gate * exec_init isn't always called from a system call. Instead 247*7c478bd9Sstevel@tonic-gate * of making a mess of trap_cleanup, we just reset the args 248*7c478bd9Sstevel@tonic-gate * pointer here. 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate reset_syscall_args(); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate switch (error) { 253*7c478bd9Sstevel@tonic-gate case 0: 254*7c478bd9Sstevel@tonic-gate return (0); 255*7c478bd9Sstevel@tonic-gate 256*7c478bd9Sstevel@tonic-gate case ENOENT: 257*7c478bd9Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 258*7c478bd9Sstevel@tonic-gate "exec(%s) failed (file not found).\n", initpath); 259*7c478bd9Sstevel@tonic-gate return (ENOENT); 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate case EAGAIN: 262*7c478bd9Sstevel@tonic-gate case EINTR: 263*7c478bd9Sstevel@tonic-gate ++count; 264*7c478bd9Sstevel@tonic-gate if (count < 5) { 265*7c478bd9Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 266*7c478bd9Sstevel@tonic-gate "exec(%s) failed with errno %d. Retrying...\n", 267*7c478bd9Sstevel@tonic-gate initpath, error); 268*7c478bd9Sstevel@tonic-gate goto again; 269*7c478bd9Sstevel@tonic-gate } 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate zcmn_err(p->p_zone->zone_id, CE_WARN, 273*7c478bd9Sstevel@tonic-gate "exec(%s) failed with errno %d.", initpath, error); 274*7c478bd9Sstevel@tonic-gate return (error); 275*7c478bd9Sstevel@tonic-gate } 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate void 278*7c478bd9Sstevel@tonic-gate main(void) 279*7c478bd9Sstevel@tonic-gate { 280*7c478bd9Sstevel@tonic-gate proc_t *p = ttoproc(curthread); /* &p0 */ 281*7c478bd9Sstevel@tonic-gate int (**initptr)(); 282*7c478bd9Sstevel@tonic-gate extern void sched(); 283*7c478bd9Sstevel@tonic-gate extern void fsflush(); 284*7c478bd9Sstevel@tonic-gate extern void thread_reaper(); 285*7c478bd9Sstevel@tonic-gate extern int (*init_tbl[])(); 286*7c478bd9Sstevel@tonic-gate extern int (*mp_init_tbl[])(); 287*7c478bd9Sstevel@tonic-gate extern id_t syscid, defaultcid; 288*7c478bd9Sstevel@tonic-gate extern int swaploaded; 289*7c478bd9Sstevel@tonic-gate extern int netboot; 290*7c478bd9Sstevel@tonic-gate extern void vm_init(void); 291*7c478bd9Sstevel@tonic-gate extern void cbe_init(void); 292*7c478bd9Sstevel@tonic-gate extern void clock_init(void); 293*7c478bd9Sstevel@tonic-gate extern void physio_bufs_init(void); 294*7c478bd9Sstevel@tonic-gate extern void pm_cfb_setup_intr(void); 295*7c478bd9Sstevel@tonic-gate extern int pm_adjust_timestamps(dev_info_t *, void *); 296*7c478bd9Sstevel@tonic-gate extern void start_other_cpus(int); 297*7c478bd9Sstevel@tonic-gate extern void sysevent_evc_thrinit(); 298*7c478bd9Sstevel@tonic-gate extern void lgrp_main_init(void); 299*7c478bd9Sstevel@tonic-gate extern void lgrp_main_mp_init(void); 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate /* 302*7c478bd9Sstevel@tonic-gate * In the horrible world of x86 in-lines, you can't get symbolic 303*7c478bd9Sstevel@tonic-gate * structure offsets a la genassym. This assertion is here so 304*7c478bd9Sstevel@tonic-gate * that the next poor slob who innocently changes the offset of 305*7c478bd9Sstevel@tonic-gate * cpu_thread doesn't waste as much time as I just did finding 306*7c478bd9Sstevel@tonic-gate * out that it's hard-coded in i86/ml/i86.il. Similarly for 307*7c478bd9Sstevel@tonic-gate * curcpup. You're welcome. 308*7c478bd9Sstevel@tonic-gate */ 309*7c478bd9Sstevel@tonic-gate ASSERT(CPU == CPU->cpu_self); 310*7c478bd9Sstevel@tonic-gate ASSERT(curthread == CPU->cpu_thread); 311*7c478bd9Sstevel@tonic-gate ASSERT_STACK_ALIGNED(); 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate /* 314*7c478bd9Sstevel@tonic-gate * Setup the first lgroup, and home t0 315*7c478bd9Sstevel@tonic-gate */ 316*7c478bd9Sstevel@tonic-gate lgrp_setup(); 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate startup(); 319*7c478bd9Sstevel@tonic-gate segkmem_gc(); 320*7c478bd9Sstevel@tonic-gate callb_init(); 321*7c478bd9Sstevel@tonic-gate callout_init(); /* callout table MUST be init'd before clock starts */ 322*7c478bd9Sstevel@tonic-gate cbe_init(); 323*7c478bd9Sstevel@tonic-gate clock_init(); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* 326*7c478bd9Sstevel@tonic-gate * May need to probe to determine latencies from CPU 0 after 327*7c478bd9Sstevel@tonic-gate * gethrtime() comes alive in cbe_init() and before enabling interrupts 328*7c478bd9Sstevel@tonic-gate */ 329*7c478bd9Sstevel@tonic-gate lgrp_plat_probe(); 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate /* 332*7c478bd9Sstevel@tonic-gate * Call all system initialization functions. 333*7c478bd9Sstevel@tonic-gate */ 334*7c478bd9Sstevel@tonic-gate for (initptr = &init_tbl[0]; *initptr; initptr++) 335*7c478bd9Sstevel@tonic-gate (**initptr)(); 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate /* 338*7c478bd9Sstevel@tonic-gate * initialize vm related stuff. 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate vm_init(); 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate /* 343*7c478bd9Sstevel@tonic-gate * initialize buffer pool for raw I/O requests 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate physio_bufs_init(); 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate ttolwp(curthread)->lwp_error = 0; /* XXX kludge for SCSI driver */ 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate /* 350*7c478bd9Sstevel@tonic-gate * Drop the interrupt level and allow interrupts. At this point 351*7c478bd9Sstevel@tonic-gate * the DDI guarantees that interrupts are enabled. 352*7c478bd9Sstevel@tonic-gate */ 353*7c478bd9Sstevel@tonic-gate (void) spl0(); 354*7c478bd9Sstevel@tonic-gate interrupts_unleashed = 1; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate vfs_mountroot(); /* Mount the root file system */ 357*7c478bd9Sstevel@tonic-gate errorq_init(); /* after vfs_mountroot() so DDI root is ready */ 358*7c478bd9Sstevel@tonic-gate cpu_kstat_init(CPU); /* after vfs_mountroot() so TOD is valid */ 359*7c478bd9Sstevel@tonic-gate ddi_walk_devs(ddi_root_node(), pm_adjust_timestamps, NULL); 360*7c478bd9Sstevel@tonic-gate /* after vfs_mountroot() so hrestime is valid */ 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate post_startup(); 363*7c478bd9Sstevel@tonic-gate swaploaded = 1; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate /* 366*7c478bd9Sstevel@tonic-gate * Initial C2 audit system 367*7c478bd9Sstevel@tonic-gate */ 368*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT 369*7c478bd9Sstevel@tonic-gate audit_init(); /* C2 hook */ 370*7c478bd9Sstevel@tonic-gate #endif 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * Plumb the protocol modules and drivers only if we are not 374*7c478bd9Sstevel@tonic-gate * networked booted, in this case we already did it in rootconf(). 375*7c478bd9Sstevel@tonic-gate */ 376*7c478bd9Sstevel@tonic-gate if (netboot == 0) 377*7c478bd9Sstevel@tonic-gate (void) strplumb(); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate gethrestime(&u.u_start); 380*7c478bd9Sstevel@tonic-gate curthread->t_start = u.u_start.tv_sec; 381*7c478bd9Sstevel@tonic-gate p->p_mstart = gethrtime(); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate /* 384*7c478bd9Sstevel@tonic-gate * Perform setup functions that can only be done after root 385*7c478bd9Sstevel@tonic-gate * and swap have been set up. 386*7c478bd9Sstevel@tonic-gate */ 387*7c478bd9Sstevel@tonic-gate consconfig(); 388*7c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 389*7c478bd9Sstevel@tonic-gate release_bootstrap(); 390*7c478bd9Sstevel@tonic-gate #endif 391*7c478bd9Sstevel@tonic-gate /* 392*7c478bd9Sstevel@tonic-gate * attach drivers with ddi-forceattach prop 393*7c478bd9Sstevel@tonic-gate * This must be done after consconfig() to prevent usb key/mouse 394*7c478bd9Sstevel@tonic-gate * from attaching before the upper console stream is plumbed. 395*7c478bd9Sstevel@tonic-gate * It must be done early enough to load hotplug drivers (e.g. 396*7c478bd9Sstevel@tonic-gate * pcmcia nexus) so that devices enumerated via hotplug is 397*7c478bd9Sstevel@tonic-gate * available before I/O subsystem is fully initialized. 398*7c478bd9Sstevel@tonic-gate */ 399*7c478bd9Sstevel@tonic-gate i_ddi_forceattach_drivers(); 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate /* 402*7c478bd9Sstevel@tonic-gate * Set the scan rate and other parameters of the paging subsystem. 403*7c478bd9Sstevel@tonic-gate */ 404*7c478bd9Sstevel@tonic-gate setupclock(0); 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate /* 407*7c478bd9Sstevel@tonic-gate * Create kmem cache for proc structures 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate process_cache = kmem_cache_create("process_cache", sizeof (proc_t), 410*7c478bd9Sstevel@tonic-gate 0, NULL, NULL, NULL, NULL, NULL, 0); 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate /* 413*7c478bd9Sstevel@tonic-gate * Initialize process 0's lwp directory and lwpid hash table. 414*7c478bd9Sstevel@tonic-gate */ 415*7c478bd9Sstevel@tonic-gate p->p_lwpdir = p->p_lwpfree = p0_lwpdir; 416*7c478bd9Sstevel@tonic-gate p->p_lwpdir->ld_next = p->p_lwpdir + 1; 417*7c478bd9Sstevel@tonic-gate p->p_lwpdir_sz = 2; 418*7c478bd9Sstevel@tonic-gate p->p_tidhash = p0_tidhash; 419*7c478bd9Sstevel@tonic-gate p->p_tidhash_sz = 2; 420*7c478bd9Sstevel@tonic-gate p0_lep.le_thread = curthread; 421*7c478bd9Sstevel@tonic-gate p0_lep.le_lwpid = curthread->t_tid; 422*7c478bd9Sstevel@tonic-gate p0_lep.le_start = curthread->t_start; 423*7c478bd9Sstevel@tonic-gate lwp_hash_in(p, &p0_lep); 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate /* 426*7c478bd9Sstevel@tonic-gate * Initialize extended accounting. 427*7c478bd9Sstevel@tonic-gate */ 428*7c478bd9Sstevel@tonic-gate exacct_init(); 429*7c478bd9Sstevel@tonic-gate 430*7c478bd9Sstevel@tonic-gate /* 431*7c478bd9Sstevel@tonic-gate * Initialize threads of sysevent event channels 432*7c478bd9Sstevel@tonic-gate */ 433*7c478bd9Sstevel@tonic-gate sysevent_evc_thrinit(); 434*7c478bd9Sstevel@tonic-gate 435*7c478bd9Sstevel@tonic-gate /* 436*7c478bd9Sstevel@tonic-gate * main lgroup initialization 437*7c478bd9Sstevel@tonic-gate * This must be done after post_startup(), but before 438*7c478bd9Sstevel@tonic-gate * start_other_cpus() 439*7c478bd9Sstevel@tonic-gate */ 440*7c478bd9Sstevel@tonic-gate lgrp_main_init(); 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate /* 443*7c478bd9Sstevel@tonic-gate * Perform MP initialization, if any. 444*7c478bd9Sstevel@tonic-gate */ 445*7c478bd9Sstevel@tonic-gate start_other_cpus(0); 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate /* 448*7c478bd9Sstevel@tonic-gate * Finish lgrp initialization after all CPUS are brought online. 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate lgrp_main_mp_init(); 451*7c478bd9Sstevel@tonic-gate 452*7c478bd9Sstevel@tonic-gate /* 453*7c478bd9Sstevel@tonic-gate * After mp_init(), number of cpus are known (this is 454*7c478bd9Sstevel@tonic-gate * true for the time being, when there are actually 455*7c478bd9Sstevel@tonic-gate * hot pluggable cpus then this scheme would not do). 456*7c478bd9Sstevel@tonic-gate * Any per cpu initialization is done here. 457*7c478bd9Sstevel@tonic-gate */ 458*7c478bd9Sstevel@tonic-gate kmem_mp_init(); 459*7c478bd9Sstevel@tonic-gate vmem_update(NULL); 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate for (initptr = &mp_init_tbl[0]; *initptr; initptr++) 462*7c478bd9Sstevel@tonic-gate (**initptr)(); 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate /* 465*7c478bd9Sstevel@tonic-gate * This must be called after start_other_cpus 466*7c478bd9Sstevel@tonic-gate */ 467*7c478bd9Sstevel@tonic-gate pm_cfb_setup_intr(); 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate /* 470*7c478bd9Sstevel@tonic-gate * Make init process; enter scheduling loop with system process. 471*7c478bd9Sstevel@tonic-gate */ 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* create init process */ 474*7c478bd9Sstevel@tonic-gate if (newproc(icode, NULL, defaultcid, 59, NULL)) 475*7c478bd9Sstevel@tonic-gate panic("main: unable to fork init."); 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* create pageout daemon */ 478*7c478bd9Sstevel@tonic-gate if (newproc(pageout, NULL, syscid, maxclsyspri - 1, NULL)) 479*7c478bd9Sstevel@tonic-gate panic("main: unable to fork pageout()"); 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate /* create fsflush daemon */ 482*7c478bd9Sstevel@tonic-gate if (newproc(fsflush, NULL, syscid, minclsyspri, NULL)) 483*7c478bd9Sstevel@tonic-gate panic("main: unable to fork fsflush()"); 484*7c478bd9Sstevel@tonic-gate 485*7c478bd9Sstevel@tonic-gate /* create cluster process if we're a member of one */ 486*7c478bd9Sstevel@tonic-gate if (cluster_bootflags & CLUSTER_BOOTED) { 487*7c478bd9Sstevel@tonic-gate if (newproc(cluster_wrapper, NULL, syscid, minclsyspri, NULL)) 488*7c478bd9Sstevel@tonic-gate panic("main: unable to fork cluster()"); 489*7c478bd9Sstevel@tonic-gate } 490*7c478bd9Sstevel@tonic-gate 491*7c478bd9Sstevel@tonic-gate /* 492*7c478bd9Sstevel@tonic-gate * Create system threads (threads are associated with p0) 493*7c478bd9Sstevel@tonic-gate */ 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate /* create thread_reaper daemon */ 496*7c478bd9Sstevel@tonic-gate (void) thread_create(NULL, 0, (void (*)())thread_reaper, 497*7c478bd9Sstevel@tonic-gate NULL, 0, &p0, TS_RUN, minclsyspri); 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate /* create module uninstall daemon */ 500*7c478bd9Sstevel@tonic-gate /* BugID 1132273. If swapping over NFS need a bigger stack */ 501*7c478bd9Sstevel@tonic-gate (void) thread_create(NULL, 0, (void (*)())mod_uninstall_daemon, 502*7c478bd9Sstevel@tonic-gate NULL, 0, &p0, TS_RUN, minclsyspri); 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate (void) thread_create(NULL, 0, seg_pasync_thread, 505*7c478bd9Sstevel@tonic-gate NULL, 0, &p0, TS_RUN, minclsyspri); 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate pid_setmin(); 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate bcopy("sched", u.u_psargs, 6); 510*7c478bd9Sstevel@tonic-gate bcopy("sched", u.u_comm, 5); 511*7c478bd9Sstevel@tonic-gate sched(); 512*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 513*7c478bd9Sstevel@tonic-gate } 514