1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <sys/disp.h> 30 #include <sys/promif.h> 31 #include <sys/clock.h> 32 #include <sys/cpuvar.h> 33 #include <sys/stack.h> 34 #include <vm/as.h> 35 #include <vm/hat.h> 36 #include <sys/reboot.h> 37 #include <sys/avintr.h> 38 #include <sys/vtrace.h> 39 #include <sys/proc.h> 40 #include <sys/thread.h> 41 #include <sys/cpupart.h> 42 #include <sys/pset.h> 43 #include <sys/copyops.h> 44 #include <sys/pg.h> 45 #include <sys/disp.h> 46 #include <sys/debug.h> 47 #include <sys/sunddi.h> 48 #include <sys/x86_archext.h> 49 #include <sys/privregs.h> 50 #include <sys/machsystm.h> 51 #include <sys/ontrap.h> 52 #include <sys/bootconf.h> 53 #include <sys/kdi.h> 54 #include <sys/archsystm.h> 55 #include <sys/promif.h> 56 #include <sys/bootconf.h> 57 #include <sys/kobj.h> 58 #include <sys/kobj_lex.h> 59 #include <sys/pci_cfgspace.h> 60 #if defined(__amd64) 61 #include <sys/bootsvcs.h> 62 63 /* 64 * XX64 This stuff deals with switching stacks in case a trapping 65 * thread wants to call back into boot -after- boot has lost track 66 * of the mappings but before the kernel owns the console. 67 * 68 * (A better way to hide this would be to add a 'this' pointer to 69 * every boot syscall so that vmx could get at the resulting save 70 * area.) 71 */ 72 73 struct boot_syscalls *_vmx_sysp; 74 static struct boot_syscalls __kbootsvcs; 75 extern struct boot_syscalls *sysp; 76 extern void _stack_safe_putchar(int c); 77 #endif 78 79 /* 80 * some globals for patching the result of cpuid 81 * to solve problems w/ creative cpu vendors 82 */ 83 84 extern uint32_t cpuid_feature_ecx_include; 85 extern uint32_t cpuid_feature_ecx_exclude; 86 extern uint32_t cpuid_feature_edx_include; 87 extern uint32_t cpuid_feature_edx_exclude; 88 89 /* 90 * Dummy spl priority masks 91 */ 92 static unsigned char dummy_cpu_pri[MAXIPL + 1] = { 93 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 94 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf, 0xf 95 }; 96 97 /* 98 * External Routines: 99 */ 100 101 extern void init_tables(void); 102 103 104 static uint32_t 105 bootprop_getval(char *name) 106 { 107 char prop[32]; 108 u_longlong_t ll; 109 extern struct bootops *bootops; 110 if ((BOP_GETPROPLEN(bootops, name) > sizeof (prop)) || 111 (BOP_GETPROP(bootops, name, prop) < 0) || 112 (kobj_getvalue(prop, &ll) == -1)) 113 return (0); 114 return ((uint32_t)ll); 115 } 116 117 /* 118 * Setup routine called right before main(). Interposing this function 119 * before main() allows us to call it in a machine-independent fashion. 120 */ 121 void 122 mlsetup(struct regs *rp) 123 { 124 extern struct classfuncs sys_classfuncs; 125 extern disp_t cpu0_disp; 126 extern char t0stack[]; 127 int boot_ncpus; 128 129 ASSERT_STACK_ALIGNED(); 130 131 #if defined(__amd64) 132 133 #if (BS_VERSION > 4) 134 /* 135 * When new boot_syscalls are added to the vector, this routine 136 * must be modified to copy them into the kernel's copy of the 137 * vector. 138 */ 139 #error mlsetup() must be updated for amd64 to support new boot_syscalls 140 #endif /* (BS_VERSION > 4) */ 141 142 /* 143 * XX64 This remaps vmx's putchar to use the kernel's version 144 * that switches stacks before diving into vmx 145 * See explanation/complaints in commentary above. 146 */ 147 _vmx_sysp = sysp; 148 sysp = &__kbootsvcs; 149 150 sysp->bsvc_getchar = _vmx_sysp->bsvc_getchar; 151 sysp->bsvc_putchar = _stack_safe_putchar; 152 sysp->bsvc_ischar = _vmx_sysp->bsvc_ischar; 153 #endif 154 /* 155 * initialize cpu_self 156 */ 157 cpu[0]->cpu_self = cpu[0]; 158 159 /* 160 * Set up dummy cpu_pri_data values till psm spl code is 161 * installed. This allows splx() to work on amd64. 162 */ 163 164 cpu[0]->cpu_pri_data = dummy_cpu_pri; 165 166 /* 167 * check if we've got special bits to clear or set 168 * when checking cpu features 169 */ 170 171 cpuid_feature_ecx_include = 172 bootprop_getval("cpuid_feature_ecx_include"); 173 cpuid_feature_ecx_exclude = 174 bootprop_getval("cpuid_feature_ecx_exclude"); 175 cpuid_feature_edx_include = 176 bootprop_getval("cpuid_feature_edx_include"); 177 cpuid_feature_edx_exclude = 178 bootprop_getval("cpuid_feature_edx_exclude"); 179 180 /* 181 * The first lightweight pass (pass0) through the cpuid data 182 * was done in locore before mlsetup was called. Do the next 183 * pass in C code. 184 * 185 * The x86_feature bits are set here on the basis of the capabilities 186 * of the boot CPU. Note that if we choose to support CPUs that have 187 * different feature sets (at which point we would almost certainly 188 * want to set the feature bits to correspond to the feature 189 * minimum) this value may be altered. 190 */ 191 192 x86_feature = cpuid_pass1(cpu[0]); 193 194 /* 195 * Initialize idt0, gdt0, ldt0_default, ktss0 and dftss. 196 */ 197 init_tables(); 198 199 #if defined(__amd64) 200 /*CSTYLED*/ 201 { 202 /* 203 * setup %gs for the kernel 204 */ 205 wrmsr(MSR_AMD_GSBASE, (uint64_t)&cpus[0]); 206 /* 207 * XX64 We should never dereference off "other gsbase" or 208 * "fsbase". So, we should arrange to point FSBASE and 209 * KGSBASE somewhere truly awful e.g. point it at the last 210 * valid address below the hole so that any attempts to index 211 * off them cause an exception. 212 * 213 * For now, point it at 8G -- at least it should be unmapped 214 * until some 64-bit processes run. 215 */ 216 wrmsr(MSR_AMD_FSBASE, 0x200000000UL); 217 wrmsr(MSR_AMD_KGSBASE, 0x200000000UL); 218 } 219 220 #elif defined(__i386) 221 /* 222 * enable large page support right here. 223 */ 224 if (x86_feature & X86_LARGEPAGE) { 225 cr4_value |= CR4_PSE; 226 if (x86_feature & X86_PGE) 227 cr4_value |= CR4_PGE; 228 setup_121_andcall(enable_big_page_support, cr4_value); 229 } 230 231 /* 232 * Some i386 processors do not implement the rdtsc instruction, 233 * or at least they do not implement it correctly. 234 * 235 * For those that do, patch in the rdtsc instructions in 236 * various parts of the kernel right now while the text is 237 * still writable. 238 */ 239 if (x86_feature & X86_TSC) 240 patch_tsc(); 241 #endif 242 243 /* 244 * initialize t0 245 */ 246 t0.t_stk = (caddr_t)rp - MINFRAME; 247 t0.t_stkbase = t0stack; 248 t0.t_pri = maxclsyspri - 3; 249 t0.t_schedflag = TS_LOAD | TS_DONT_SWAP; 250 t0.t_procp = &p0; 251 t0.t_plockp = &p0lock.pl_lock; 252 t0.t_lwp = &lwp0; 253 t0.t_forw = &t0; 254 t0.t_back = &t0; 255 t0.t_next = &t0; 256 t0.t_prev = &t0; 257 t0.t_cpu = cpu[0]; 258 t0.t_disp_queue = &cpu0_disp; 259 t0.t_bind_cpu = PBIND_NONE; 260 t0.t_bind_pset = PS_NONE; 261 t0.t_cpupart = &cp_default; 262 t0.t_clfuncs = &sys_classfuncs.thread; 263 t0.t_copyops = NULL; 264 THREAD_ONPROC(&t0, CPU); 265 266 lwp0.lwp_thread = &t0; 267 lwp0.lwp_regs = (void *) rp; 268 lwp0.lwp_procp = &p0; 269 t0.t_tid = p0.p_lwpcnt = p0.p_lwprcnt = p0.p_lwpid = 1; 270 271 p0.p_exec = NULL; 272 p0.p_stat = SRUN; 273 p0.p_flag = SSYS; 274 p0.p_tlist = &t0; 275 p0.p_stksize = 2*PAGESIZE; 276 p0.p_stkpageszc = 0; 277 p0.p_as = &kas; 278 p0.p_lockp = &p0lock; 279 p0.p_brkpageszc = 0; 280 sigorset(&p0.p_ignore, &ignoredefault); 281 282 CPU->cpu_thread = &t0; 283 bzero(&cpu0_disp, sizeof (disp_t)); 284 CPU->cpu_disp = &cpu0_disp; 285 CPU->cpu_disp->disp_cpu = CPU; 286 CPU->cpu_dispthread = &t0; 287 CPU->cpu_idle_thread = &t0; 288 CPU->cpu_flags = CPU_READY | CPU_RUNNING | CPU_EXISTS | CPU_ENABLE; 289 CPU->cpu_dispatch_pri = t0.t_pri; 290 291 CPU->cpu_id = 0; 292 293 CPU->cpu_tss = &ktss0; 294 295 CPU->cpu_pri = 12; /* initial PIL for the boot CPU */ 296 297 CPU->cpu_gdt = gdt0; 298 299 /* 300 * The kernel doesn't use LDTs unless a process explicitly requests one. 301 */ 302 p0.p_ldt_desc = zero_sdesc; 303 304 /* 305 * Kernel IDT. 306 */ 307 CPU->cpu_idt = idt0; 308 309 /* 310 * Initialize thread/cpu microstate accounting here 311 */ 312 init_mstate(&t0, LMS_SYSTEM); 313 init_cpu_mstate(CPU, CMS_SYSTEM); 314 315 /* 316 * Initialize lists of available and active CPUs. 317 */ 318 cpu_list_init(CPU); 319 320 cpu_vm_data_init(CPU); 321 322 /* lgrp_init() needs PCI config space access */ 323 pci_cfgspace_init(); 324 325 /* 326 * Initialize the lgrp framework 327 */ 328 lgrp_init(); 329 330 rp->r_fp = 0; /* terminate kernel stack traces! */ 331 332 prom_init("kernel", (void *)NULL); 333 334 boot_ncpus = bootprop_getval("boot-ncpus"); 335 336 /* 337 * To avoid wasting kernel memory, we're temporarily limiting the 338 * total number of processors to 32 by default until we get the 339 * capability to scan ACPI tables early on boot to detect how many 340 * processors are actually present. However, 64-bit systems 341 * can be booted with up to 64 processors by setting "boot-ncpus" 342 * boot property to 64. 343 */ 344 if (boot_ncpus <= 0 || boot_ncpus > NCPU) 345 boot_ncpus = 32; 346 347 max_ncpus = boot_max_ncpus = boot_ncpus; 348 349 if (boothowto & RB_HALT) { 350 prom_printf("unix: kernel halted by -h flag\n"); 351 prom_enter_mon(); 352 } 353 354 ASSERT_STACK_ALIGNED(); 355 356 if (workaround_errata(CPU) != 0) 357 panic("critical workaround(s) missing for boot cpu"); 358 } 359