]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/i386_init.c
560a88ffc65d907e25b0715d435caa1075c1021a
[apple/xnu.git] / osfmk / i386 / i386_init.c
1 /*
2 * Copyright (c) 2003-2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University
34 * All Rights Reserved.
35 *
36 * Permission to use, copy, modify and distribute this software and its
37 * documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
41 *
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45 *
46 * Carnegie Mellon requests users of this software to return to
47 *
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
52 *
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
55 */
56
57 #include <platforms.h>
58 #include <mach_kdb.h>
59
60 #include <mach/i386/vm_param.h>
61
62 #include <string.h>
63 #include <mach/vm_param.h>
64 #include <mach/vm_prot.h>
65 #include <mach/machine.h>
66 #include <mach/time_value.h>
67 #include <kern/spl.h>
68 #include <kern/assert.h>
69 #include <kern/debug.h>
70 #include <kern/misc_protos.h>
71 #include <kern/startup.h>
72 #include <kern/clock.h>
73 #include <kern/pms.h>
74 #include <kern/xpr.h>
75 #include <kern/cpu_data.h>
76 #include <kern/processor.h>
77 #include <console/serial_protos.h>
78 #include <vm/vm_page.h>
79 #include <vm/pmap.h>
80 #include <vm/vm_kern.h>
81 #include <machine/pal_routines.h>
82 #include <i386/fpu.h>
83 #include <i386/pmap.h>
84 #include <i386/misc_protos.h>
85 #include <i386/cpu_threads.h>
86 #include <i386/cpuid.h>
87 #include <i386/lapic.h>
88 #include <i386/mp.h>
89 #include <i386/mp_desc.h>
90 #if CONFIG_MTRR
91 #include <i386/mtrr.h>
92 #endif
93 #include <i386/machine_routines.h>
94 #if CONFIG_MCA
95 #include <i386/machine_check.h>
96 #endif
97 #include <i386/ucode.h>
98 #include <i386/postcode.h>
99 #include <i386/Diagnostics.h>
100 #include <i386/pmCPU.h>
101 #include <i386/tsc.h>
102 #include <i386/locks.h> /* LcksOpts */
103 #ifdef __i386__
104 #include <i386/cpu_capabilities.h>
105 #if MACH_KDB
106 #include <machine/db_machdep.h>
107 #endif
108 #endif
109 #if DEBUG
110 #include <machine/pal_routines.h>
111 #endif
112
113 #if DEBUG
114 #define DBG(x...) kprintf(x)
115 #else
116 #define DBG(x...)
117 #endif
118 #if MACH_KDB
119 #include <ddb/db_aout.h>
120 #endif /* MACH_KDB */
121
122 int debug_task;
123
124 static boot_args *kernelBootArgs;
125
126 extern int disableConsoleOutput;
127 extern const char version[];
128 extern const char version_variant[];
129 extern int nx_enabled;
130
131 #ifdef __x86_64__
132 extern void *low_eintstack;
133 #endif
134
135 void *KPTphys;
136 pd_entry_t *IdlePTD;
137 #ifdef __i386__
138 pd_entry_t *IdlePDPT64;
139 #endif
140
141 char *physfree;
142
143 /*
144 * Note: ALLOCPAGES() can only be used safely within Idle_PTs_init()
145 * due to the mutation of physfree.
146 */
147 static void *
148 ALLOCPAGES(int npages)
149 {
150 uintptr_t tmp = (uintptr_t)physfree;
151 bzero(physfree, npages * PAGE_SIZE);
152 physfree += npages * PAGE_SIZE;
153 #ifdef __x86_64__
154 tmp += VM_MIN_KERNEL_ADDRESS & ~LOW_4GB_MASK;
155 #endif
156 return (void *)tmp;
157 }
158
159 static void
160 fillkpt(pt_entry_t *base, int prot, uintptr_t src, int index, int count)
161 {
162 int i;
163 for (i=0; i<count; i++) {
164 base[index] = src | prot | INTEL_PTE_VALID;
165 src += PAGE_SIZE;
166 index++;
167 }
168 }
169
170 extern pmap_paddr_t first_avail;
171
172 #ifdef __x86_64__
173 int break_kprintf = 0;
174
175 uint64_t
176 x86_64_pre_sleep(void)
177 {
178 IdlePML4[0] = IdlePML4[KERNEL_PML4_INDEX];
179 uint64_t oldcr3 = get_cr3_raw();
180 set_cr3_raw((uint32_t) (uintptr_t)ID_MAP_VTOP(IdlePML4));
181 return oldcr3;
182 }
183
184 void
185 x86_64_post_sleep(uint64_t new_cr3)
186 {
187 IdlePML4[0] = 0;
188 set_cr3_raw((uint32_t) new_cr3);
189 }
190
191 #endif
192
193 #ifdef __i386__
194 #define ID_MAP_VTOP(x) x
195 #endif
196
197
198 #ifdef __x86_64__
199 // Set up the physical mapping - NPHYSMAP GB of memory mapped at a high address
200 // NPHYSMAP is determined by the maximum supported RAM size plus 4GB to account
201 // the PCI hole (which is less 4GB but not more).
202
203 // Compile-time guard:
204 extern int maxphymapsupported[NPHYSMAP <= PTE_PER_PAGE ? 1 : -1];
205 static void
206 physmap_init(void)
207 {
208 pt_entry_t *physmapL3 = ALLOCPAGES(1);
209 struct {
210 pt_entry_t entries[PTE_PER_PAGE];
211 } * physmapL2 = ALLOCPAGES(NPHYSMAP);
212
213 uintptr_t i;
214 for(i=0;i<NPHYSMAP;i++) {
215 physmapL3[i] = ((uintptr_t)ID_MAP_VTOP(&physmapL2[i]))
216 | INTEL_PTE_VALID
217 | INTEL_PTE_WRITE;
218 uintptr_t j;
219 for(j=0;j<PTE_PER_PAGE;j++) {
220 physmapL2[i].entries[j] = (((i*PTE_PER_PAGE+j)<<PDSHIFT)
221 | INTEL_PTE_PS
222 | INTEL_PTE_VALID
223 | INTEL_PTE_WRITE);
224 }
225 }
226
227 IdlePML4[KERNEL_PHYSMAP_INDEX] = ((uintptr_t)ID_MAP_VTOP(physmapL3))
228 | INTEL_PTE_VALID
229 | INTEL_PTE_WRITE;
230 if (cpuid_extfeatures() & CPUID_EXTFEATURE_XD) {
231 IdlePML4[KERNEL_PHYSMAP_INDEX] |= INTEL_PTE_NX;
232 }
233
234 DBG("physical map idlepml4[%d]: 0x%llx\n",
235 KERNEL_PHYSMAP_INDEX, IdlePML4[KERNEL_PHYSMAP_INDEX]);
236 }
237 #endif
238
239 static void
240 Idle_PTs_init(void)
241 {
242 /* Allocate the "idle" kernel page tables: */
243 KPTphys = ALLOCPAGES(NKPT); /* level 1 */
244 IdlePTD = ALLOCPAGES(NPGPTD); /* level 2 */
245
246 #ifdef __x86_64__
247 physmap_init();
248 #else
249 IdlePDPT64 = ALLOCPAGES(1);
250
251 // Recursive mapping of PTEs
252 fillkpt(IdlePTD, INTEL_PTE_WRITE, (uintptr_t)IdlePTD, PTDPTDI, NPGPTD);
253 // commpage
254 fillkpt(IdlePTD, INTEL_PTE_WRITE|INTEL_PTE_USER, (uintptr_t)ALLOCPAGES(1), _COMM_PAGE32_BASE_ADDRESS >> PDESHIFT,1);
255 #endif
256 // Fill the lowest level with everything up to physfree
257 fillkpt(KPTphys,
258 INTEL_PTE_WRITE, 0, 0, (int)(((uintptr_t)physfree) >> PAGE_SHIFT));
259
260 // Rewrite the 2nd-lowest level to point to pages of KPTphys.
261 // This was previously filled statically by idle_pt.c, and thus
262 // must be done after the KPTphys fill since IdlePTD is in use
263 fillkpt(IdlePTD,
264 INTEL_PTE_WRITE, (uintptr_t)ID_MAP_VTOP(KPTphys), 0, NKPT);
265
266 // IdlePDPT entries
267 #ifdef __i386__
268 fillkpt(IdlePDPT, 0, (uintptr_t)IdlePTD, 0, NPGPTD);
269 #else
270 fillkpt(IdlePDPT, INTEL_PTE_WRITE, (uintptr_t)ID_MAP_VTOP(IdlePTD), 0, NPGPTD);
271 #endif
272
273 // Flush the TLB now we're done rewriting the page tables..
274 set_cr3_raw(get_cr3_raw());
275 }
276
277 /*
278 * vstart() is called in the natural mode (64bit for K64, 32 for K32)
279 * on a set of bootstrap pagetables which use large, 2MB pages to map
280 * all of physical memory in both. See idle_pt.c for details.
281 *
282 * In K64 this identity mapping is mirrored the top and bottom 512GB
283 * slots of PML4.
284 *
285 * The bootstrap processor called with argument boot_args_start pointing to
286 * the boot-args block. The kernel's (4K page) page tables are allocated and
287 * initialized before switching to these.
288 *
289 * Non-bootstrap processors are called with argument boot_args_start NULL.
290 * These processors switch immediately to the existing kernel page tables.
291 */
292 void
293 vstart(vm_offset_t boot_args_start)
294 {
295 boolean_t is_boot_cpu = !(boot_args_start == 0);
296 int cpu;
297 uint32_t lphysfree;
298
299 postcode(VSTART_ENTRY);
300
301 if (is_boot_cpu) {
302 /*
303 * Get startup parameters.
304 */
305 kernelBootArgs = (boot_args *)boot_args_start;
306 lphysfree = kernelBootArgs->kaddr + kernelBootArgs->ksize;
307 physfree = (void *)(uintptr_t)((lphysfree + PAGE_SIZE - 1) &~ (PAGE_SIZE - 1));
308 #if DEBUG
309 pal_serial_init();
310 #endif
311 DBG("revision 0x%x\n", kernelBootArgs->Revision);
312 DBG("version 0x%x\n", kernelBootArgs->Version);
313 DBG("command line %s\n", kernelBootArgs->CommandLine);
314 DBG("memory map 0x%x\n", kernelBootArgs->MemoryMap);
315 DBG("memory map sz 0x%x\n", kernelBootArgs->MemoryMapSize);
316 DBG("kaddr 0x%x\n", kernelBootArgs->kaddr);
317 DBG("ksize 0x%x\n", kernelBootArgs->ksize);
318 DBG("physfree %p\n", physfree);
319 DBG("bootargs: %p, &ksize: %p &kaddr: %p\n",
320 kernelBootArgs,
321 &kernelBootArgs->ksize,
322 &kernelBootArgs->kaddr);
323 #ifdef __x86_64__
324 /* enable NX/XD, boot processor */
325 if (cpuid_extfeatures() & CPUID_EXTFEATURE_XD) {
326 wrmsr64(MSR_IA32_EFER, rdmsr64(MSR_IA32_EFER) | MSR_IA32_EFER_NXE);
327 DBG("vstart() NX/XD enabled\n");
328 }
329 #endif
330 postcode(PSTART_PAGE_TABLES);
331
332 Idle_PTs_init();
333
334 first_avail = (vm_offset_t)ID_MAP_VTOP(physfree);
335
336 cpu = 0;
337 cpu_data_alloc(TRUE);
338
339
340 /*
341 * Setup boot args given the physical start address.
342 */
343 kernelBootArgs = (boot_args *)
344 ml_static_ptovirt(boot_args_start);
345 DBG("i386_init(0x%lx) kernelBootArgs=%p\n",
346 (unsigned long)boot_args_start, kernelBootArgs);
347
348 PE_init_platform(FALSE, kernelBootArgs);
349 postcode(PE_INIT_PLATFORM_D);
350 } else {
351 /* Find our logical cpu number */
352 cpu = lapic_to_cpu[(LAPIC_READ(ID)>>LAPIC_ID_SHIFT) & LAPIC_ID_MASK];
353 DBG("CPU: %d, GSBASE initial value: 0x%llx\n", cpu, rdmsr64(MSR_IA32_GS_BASE));
354 #ifdef __x86_64__
355 if (cpuid_extfeatures() & CPUID_EXTFEATURE_XD) {
356 wrmsr64(MSR_IA32_EFER, rdmsr64(MSR_IA32_EFER) | MSR_IA32_EFER_NXE);
357 DBG("vstart() NX/XD enabled, non-boot\n");
358 }
359 #endif
360 }
361
362 #ifdef __x86_64__
363 if(is_boot_cpu)
364 cpu_desc_init64(cpu_datap(cpu));
365 cpu_desc_load64(cpu_datap(cpu));
366 #else
367 if(is_boot_cpu)
368 cpu_desc_init(cpu_datap(cpu));
369 cpu_desc_load(cpu_datap(cpu));
370 #endif
371 if (is_boot_cpu)
372 cpu_mode_init(current_cpu_datap()); /* cpu_mode_init() will be
373 * invoked on the APs
374 * via i386_init_slave()
375 */
376 #ifdef __x86_64__
377 /* Done with identity mapping */
378 IdlePML4[0] = 0;
379 #endif
380
381 postcode(VSTART_EXIT);
382 #ifdef __i386__
383 if (cpuid_extfeatures() & CPUID_EXTFEATURE_XD) {
384 wrmsr64(MSR_IA32_EFER, rdmsr64(MSR_IA32_EFER) | MSR_IA32_EFER_NXE);
385 DBG("vstart() NX/XD enabled, i386\n");
386 }
387
388 if (is_boot_cpu)
389 i386_init();
390 else
391 i386_init_slave();
392 /*NOTREACHED*/
393 #else
394 /* We need to switch to a new per-cpu stack, but we must do this atomically with
395 * the call to ensure the compiler doesn't assume anything about the stack before
396 * e.g. tail-call optimisations
397 */
398 if (is_boot_cpu)
399 {
400 asm volatile(
401 "mov %1, %%rdi;"
402 "mov %0, %%rsp;"
403 "call _i386_init;" : : "r"
404 (cpu_datap(cpu)->cpu_int_stack_top), "r" (boot_args_start));
405 }
406 else
407 {
408 asm volatile(
409 "mov %0, %%rsp;"
410 "call _i386_init_slave;" : : "r"
411 (cpu_datap(cpu)->cpu_int_stack_top));
412 }
413 /*NOTREACHED*/
414 #endif
415 }
416
417 /*
418 * Cpu initialization. Running virtual, but without MACH VM
419 * set up.
420 */
421 void
422 i386_init(void)
423 {
424 unsigned int maxmem;
425 uint64_t maxmemtouse;
426 unsigned int cpus = 0;
427 boolean_t fidn;
428 boolean_t IA32e = TRUE;
429
430 postcode(I386_INIT_ENTRY);
431
432 pal_i386_init();
433
434 #if CONFIG_MCA
435 /* Initialize machine-check handling */
436 mca_cpu_init();
437 #endif
438
439
440 kernel_early_bootstrap();
441
442 master_cpu = 0;
443 cpu_init();
444
445 postcode(CPU_INIT_D);
446
447 printf_init(); /* Init this in case we need debugger */
448 panic_init(); /* Init this in case we need debugger */
449
450 /* setup debugging output if one has been chosen */
451 PE_init_kprintf(FALSE);
452
453 if (!PE_parse_boot_argn("diag", &dgWork.dgFlags, sizeof (dgWork.dgFlags)))
454 dgWork.dgFlags = 0;
455
456 serialmode = 0;
457 if(PE_parse_boot_argn("serial", &serialmode, sizeof (serialmode))) {
458 /* We want a serial keyboard and/or console */
459 kprintf("Serial mode specified: %08X\n", serialmode);
460 }
461 if(serialmode & 1) {
462 (void)switch_to_serial_console();
463 disableConsoleOutput = FALSE; /* Allow printfs to happen */
464 }
465
466 /* setup console output */
467 PE_init_printf(FALSE);
468
469 kprintf("version_variant = %s\n", version_variant);
470 kprintf("version = %s\n", version);
471
472 if (!PE_parse_boot_argn("maxmem", &maxmem, sizeof (maxmem)))
473 maxmemtouse = 0;
474 else
475 maxmemtouse = ((uint64_t)maxmem) * MB;
476
477 if (PE_parse_boot_argn("cpus", &cpus, sizeof (cpus))) {
478 if ((0 < cpus) && (cpus < max_ncpus))
479 max_ncpus = cpus;
480 }
481
482 /*
483 * debug support for > 4G systems
484 */
485 if (!PE_parse_boot_argn("himemory_mode", &vm_himemory_mode, sizeof (vm_himemory_mode)))
486 vm_himemory_mode = 0;
487
488 if (!PE_parse_boot_argn("immediate_NMI", &fidn, sizeof (fidn)))
489 force_immediate_debugger_NMI = FALSE;
490 else
491 force_immediate_debugger_NMI = fidn;
492
493 #if DEBUG
494 nanoseconds_to_absolutetime(URGENCY_NOTIFICATION_ASSERT_NS, &urgency_notification_assert_abstime_threshold);
495 #endif
496 PE_parse_boot_argn("urgency_notification_abstime",
497 &urgency_notification_assert_abstime_threshold,
498 sizeof(urgency_notification_assert_abstime_threshold));
499
500 #if CONFIG_YONAH
501 /*
502 * At this point we check whether we are a 64-bit processor
503 * and that we're not restricted to legacy mode, 32-bit operation.
504 */
505 if (cpuid_extfeatures() & CPUID_EXTFEATURE_EM64T) {
506 boolean_t legacy_mode;
507 kprintf("EM64T supported");
508 if (PE_parse_boot_argn("-legacy", &legacy_mode, sizeof (legacy_mode))) {
509 kprintf(" but legacy mode forced\n");
510 IA32e = FALSE;
511 } else {
512 kprintf(" and will be enabled\n");
513 }
514 } else
515 IA32e = FALSE;
516 #endif
517
518 if (!(cpuid_extfeatures() & CPUID_EXTFEATURE_XD))
519 nx_enabled = 0;
520
521 /*
522 * VM initialization, after this we're using page tables...
523 * The maximum number of cpus must be set beforehand.
524 */
525 i386_vm_init(maxmemtouse, IA32e, kernelBootArgs);
526
527 /* create the console for verbose or pretty mode */
528 /* Note: doing this prior to tsc_init() allows for graceful panic! */
529 PE_init_platform(TRUE, kernelBootArgs);
530 PE_create_console();
531
532 tsc_init();
533 power_management_init();
534
535 processor_bootstrap();
536 thread_bootstrap();
537
538 machine_startup();
539 }
540
541 static void
542 do_init_slave(boolean_t fast_restart)
543 {
544 void *init_param = FULL_SLAVE_INIT;
545
546 postcode(I386_INIT_SLAVE);
547
548 if (!fast_restart) {
549 /* Ensure that caching and write-through are enabled */
550 set_cr0(get_cr0() & ~(CR0_NW|CR0_CD));
551
552 DBG("i386_init_slave() CPU%d: phys (%d) active.\n",
553 get_cpu_number(), get_cpu_phys_number());
554
555 assert(!ml_get_interrupts_enabled());
556
557 cpu_mode_init(current_cpu_datap());
558
559 #if CONFIG_MCA
560 mca_cpu_init();
561 #endif
562
563 lapic_configure();
564 LAPIC_DUMP();
565 LAPIC_CPU_MAP_DUMP();
566
567 init_fpu();
568
569 #if CONFIG_MTRR
570 mtrr_update_cpu();
571 #endif
572 } else
573 init_param = FAST_SLAVE_INIT;
574
575 /* update CPU microcode */
576 ucode_update_wake();
577
578 #if CONFIG_VMX
579 /* resume VT operation */
580 vmx_resume();
581 #endif
582
583 #if CONFIG_MTRR
584 if (!fast_restart)
585 pat_init();
586 #endif
587
588 cpu_thread_init(); /* not strictly necessary */
589
590 #ifdef __x86_64__
591 /* Re-zero the identity-map for the idle PT's. This MUST be done before
592 * cpu_running is set so that other slaves can set up their own
593 * identity-map */
594 if (!fast_restart)
595 IdlePML4[0] = 0;
596 #endif
597
598 cpu_init(); /* Sets cpu_running which starter cpu waits for */
599
600 slave_main(init_param);
601
602 panic("do_init_slave() returned from slave_main()");
603 }
604
605 /*
606 * i386_init_slave() is called from pstart.
607 * We're in the cpu's interrupt stack with interrupts disabled.
608 * At this point we are in legacy mode. We need to switch on IA32e
609 * if the mode is set to 64-bits.
610 */
611 void
612 i386_init_slave(void)
613 {
614 do_init_slave(FALSE);
615 }
616
617 /*
618 * i386_init_slave_fast() is called from pmCPUHalt.
619 * We're running on the idle thread and need to fix up
620 * some accounting and get it so that the scheduler sees this
621 * CPU again.
622 */
623 void
624 i386_init_slave_fast(void)
625 {
626 do_init_slave(TRUE);
627 }
628
629