2 * Copyright (c) 2000-2010 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University
34 * All Rights Reserved.
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.
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.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
62 * Author: Avadis Tevanian, Jr., Michael Wayne Young
64 * Copyright (C) 1986, Avadis Tevanian, Jr., Michael Wayne Young
66 * Basic initialization for I386 - ISA bus machines.
69 #include <platforms.h>
71 #include <mach/i386/vm_param.h>
74 #include <mach/vm_param.h>
75 #include <mach/vm_prot.h>
76 #include <mach/machine.h>
77 #include <mach/time_value.h>
79 #include <kern/assert.h>
80 #include <kern/debug.h>
81 #include <kern/misc_protos.h>
82 #include <kern/startup.h>
83 #include <kern/clock.h>
84 #include <kern/cpu_data.h>
85 #include <kern/machine.h>
86 #include <i386/postcode.h>
87 #include <i386/mp_desc.h>
88 #include <i386/misc_protos.h>
89 #include <i386/thread.h>
90 #include <i386/trap.h>
91 #include <i386/machine_routines.h>
92 #include <i386/mp.h> /* mp_rendezvous_break_lock */
93 #include <i386/cpuid.h>
95 #include <i386/machine_cpu.h>
96 #include <i386/pmap.h>
98 #include <i386/mtrr.h>
100 #include <i386/ucode.h>
101 #include <i386/pmCPU.h>
102 #include <architecture/i386/pio.h> /* inb() */
103 #include <pexpert/i386/boot.h>
106 #include <vm/vm_map.h>
107 #include <vm/vm_kern.h>
109 #include <IOKit/IOPlatformExpert.h>
110 #include <IOKit/IOHibernatePrivate.h>
112 #include <pexpert/i386/efi.h>
114 #include <kern/thread.h>
115 #include <kern/sched.h>
116 #include <mach-o/loader.h>
117 #include <mach-o/nlist.h>
119 #include <libkern/kernel_mach_header.h>
120 #include <libkern/OSKextLibPrivate.h>
123 #define DPRINTF(x...) kprintf(x)
125 #define DPRINTF(x...)
128 static void machine_conf(void);
130 extern int max_unsafe_quanta
;
131 extern int max_poll_quanta
;
132 extern unsigned int panic_is_inited
;
136 volatile int pbtcpu
= -1;
137 hw_lock_data_t pbtlock
; /* backtrace print lock */
140 volatile int panic_double_fault_cpu
= -1;
142 #if defined (__i386__)
143 #define PRINT_ARGS_FROM_STACK_FRAME 1
144 #elif defined (__x86_64__)
145 #define PRINT_ARGS_FROM_STACK_FRAME 0
147 #error unsupported architecture
150 typedef struct _cframe_t
{
151 struct _cframe_t
*prev
;
153 #if PRINT_ARGS_FROM_STACK_FRAME
158 static unsigned panic_io_port
;
159 static unsigned commit_paniclog_to_nvram
;
161 unsigned int debug_boot_arg
;
164 machine_startup(void)
169 if( PE_get_hotkey( kPEControlKey
))
170 halt_in_debugger
= halt_in_debugger
? 0 : 1;
173 if (PE_parse_boot_argn("debug", &debug_boot_arg
, sizeof (debug_boot_arg
))) {
174 panicDebugging
= TRUE
;
175 if (debug_boot_arg
& DB_HALT
) halt_in_debugger
=1;
176 if (debug_boot_arg
& DB_PRT
) disable_debug_output
=FALSE
;
177 if (debug_boot_arg
& DB_SLOG
) systemLogDiags
=TRUE
;
178 if (debug_boot_arg
& DB_LOG_PI_SCRN
) logPanicDataToScreen
=TRUE
;
183 if (!PE_parse_boot_argn("nvram_paniclog", &commit_paniclog_to_nvram
, sizeof (commit_paniclog_to_nvram
)))
184 commit_paniclog_to_nvram
= 1;
187 * Entering the debugger will put the CPUs into a "safe"
190 if (PE_parse_boot_argn("pmsafe_debug", &boot_arg
, sizeof (boot_arg
)))
191 pmsafe_debug
= boot_arg
;
194 hw_lock_init(&debugger_lock
); /* initialize debugger lock */
196 hw_lock_init(&pbtlock
); /* initialize print backtrace lock */
198 if (PE_parse_boot_argn("preempt", &boot_arg
, sizeof (boot_arg
))) {
199 default_preemption_rate
= boot_arg
;
201 if (PE_parse_boot_argn("unsafe", &boot_arg
, sizeof (boot_arg
))) {
202 max_unsafe_quanta
= boot_arg
;
204 if (PE_parse_boot_argn("poll", &boot_arg
, sizeof (boot_arg
))) {
205 max_poll_quanta
= boot_arg
;
207 if (PE_parse_boot_argn("yield", &boot_arg
, sizeof (boot_arg
))) {
208 sched_poll_yield_shift
= boot_arg
;
210 /* The I/O port to issue a read from, in the event of a panic. Useful for
211 * triggering logic analyzers.
213 if (PE_parse_boot_argn("panic_io_port", &boot_arg
, sizeof (boot_arg
))) {
214 /*I/O ports range from 0 through 0xFFFF */
215 panic_io_port
= boot_arg
& 0xffff;
221 ml_thrm_init(); /* Start thermal monitoring on this processor */
235 machine_info
.memory_size
= (typeof(machine_info
.memory_size
))mem_size
;
239 extern void *gPEEFIRuntimeServices
;
240 extern void *gPEEFISystemTable
;
243 * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
244 * code or tables extracted from it, as desired without restriction.
246 * First, the polynomial itself and its table of feedback terms. The
248 * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
250 * Note that we take it "backwards" and put the highest-order term in
251 * the lowest-order bit. The X^32 term is "implied"; the LSB is the
252 * X^31 term, etc. The X^0 term (usually shown as "+1") results in
255 * Note that the usual hardware shift register implementation, which
256 * is what we're using (we're merely optimizing it by doing eight-bit
257 * chunks at a time) shifts bits into the lowest-order term. In our
258 * implementation, that means shifting towards the right. Why do we
259 * do it this way? Because the calculated CRC must be transmitted in
260 * order from highest-order term to lowest-order term. UARTs transmit
261 * characters in order from LSB to MSB. By storing the CRC this way
262 * we hand it to the UART in the order low-byte to high-byte; the UART
263 * sends each low-bit to hight-bit; and the result is transmission bit
264 * by bit from highest- to lowest-order term without requiring any bit
265 * shuffling on our part. Reception works similarly
267 * The feedback terms table consists of 256, 32-bit entries. Notes
269 * The table can be generated at runtime if desired; code to do so
270 * is shown later. It might not be obvious, but the feedback
271 * terms simply represent the results of eight shift/xor opera
272 * tions for all combinations of data and CRC register values
274 * The values must be right-shifted by eight bits by the "updcrc
275 * logic; the shift must be unsigned (bring in zeroes). On some
276 * hardware you could probably optimize the shift in assembler by
277 * using byte-swap instructions
278 * polynomial $edb88320
281 * CRC32 code derived from work by Gary S. Brown.
284 static uint32_t crc32_tab
[] = {
285 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
286 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
287 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
288 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
289 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
290 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
291 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
292 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
293 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
294 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
295 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
296 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
297 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
298 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
299 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
300 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
301 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
302 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
303 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
304 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
305 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
306 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
307 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
308 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
309 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
310 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
311 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
312 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
313 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
314 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
315 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
316 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
317 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
318 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
319 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
320 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
321 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
322 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
323 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
324 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
325 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
326 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
327 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
331 crc32(uint32_t crc
, const void *buf
, size_t size
)
339 crc
= crc32_tab
[(crc
^ *p
++) & 0xFF] ^ (crc
>> 8);
345 efi_set_tables_64(EFI_SYSTEM_TABLE_64
* system_table
)
347 EFI_RUNTIME_SERVICES_64
*runtime
;
351 DPRINTF("Processing 64-bit EFI tables at %p\n", system_table
);
353 DPRINTF("Header:\n");
354 DPRINTF(" Signature: 0x%016llx\n", system_table
->Hdr
.Signature
);
355 DPRINTF(" Revision: 0x%08x\n", system_table
->Hdr
.Revision
);
356 DPRINTF(" HeaderSize: 0x%08x\n", system_table
->Hdr
.HeaderSize
);
357 DPRINTF(" CRC32: 0x%08x\n", system_table
->Hdr
.CRC32
);
358 DPRINTF("RuntimeServices: 0x%016llx\n", system_table
->RuntimeServices
);
359 if (system_table
->Hdr
.Signature
!= EFI_SYSTEM_TABLE_SIGNATURE
) {
360 kprintf("Bad EFI system table signature\n");
363 // Verify signature of the system table
364 hdr_cksum
= system_table
->Hdr
.CRC32
;
365 system_table
->Hdr
.CRC32
= 0;
366 cksum
= crc32(0L, system_table
, system_table
->Hdr
.HeaderSize
);
368 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum
, hdr_cksum
);
369 system_table
->Hdr
.CRC32
= hdr_cksum
;
370 if (cksum
!= hdr_cksum
) {
371 kprintf("Bad EFI system table checksum\n");
375 gPEEFISystemTable
= system_table
;
377 if (!cpu_mode_is64bit()) {
378 kprintf("Skipping 64-bit EFI runtime services for 32-bit legacy mode\n");
382 if(system_table
->RuntimeServices
== 0) {
383 kprintf("No runtime table present\n");
386 DPRINTF("RuntimeServices table at 0x%qx\n", system_table
->RuntimeServices
);
387 // 64-bit virtual address is OK for 64-bit EFI and 64/32-bit kernel.
388 runtime
= (EFI_RUNTIME_SERVICES_64
*) (uintptr_t)system_table
->RuntimeServices
;
389 DPRINTF("Checking runtime services table %p\n", runtime
);
390 if (runtime
->Hdr
.Signature
!= EFI_RUNTIME_SERVICES_SIGNATURE
) {
391 kprintf("Bad EFI runtime table signature\n");
395 // Verify signature of runtime services table
396 hdr_cksum
= runtime
->Hdr
.CRC32
;
397 runtime
->Hdr
.CRC32
= 0;
398 cksum
= crc32(0L, runtime
, runtime
->Hdr
.HeaderSize
);
400 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum
, hdr_cksum
);
401 runtime
->Hdr
.CRC32
= hdr_cksum
;
402 if (cksum
!= hdr_cksum
) {
403 kprintf("Bad EFI runtime table checksum\n");
407 gPEEFIRuntimeServices
= runtime
;
413 efi_set_tables_32(EFI_SYSTEM_TABLE_32
* system_table
)
415 EFI_RUNTIME_SERVICES_32
*runtime
;
419 DPRINTF("Processing 32-bit EFI tables at %p\n", system_table
);
421 DPRINTF("Header:\n");
422 DPRINTF(" Signature: 0x%016llx\n", system_table
->Hdr
.Signature
);
423 DPRINTF(" Revision: 0x%08x\n", system_table
->Hdr
.Revision
);
424 DPRINTF(" HeaderSize: 0x%08x\n", system_table
->Hdr
.HeaderSize
);
425 DPRINTF(" CRC32: 0x%08x\n", system_table
->Hdr
.CRC32
);
426 DPRINTF("RuntimeServices: 0x%08x\n", system_table
->RuntimeServices
);
427 if (system_table
->Hdr
.Signature
!= EFI_SYSTEM_TABLE_SIGNATURE
) {
428 kprintf("Bad EFI system table signature\n");
431 // Verify signature of the system table
432 hdr_cksum
= system_table
->Hdr
.CRC32
;
433 system_table
->Hdr
.CRC32
= 0;
434 DPRINTF("System table at %p HeaderSize 0x%x\n", system_table
, system_table
->Hdr
.HeaderSize
);
435 cksum
= crc32(0L, system_table
, system_table
->Hdr
.HeaderSize
);
437 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum
, hdr_cksum
);
438 system_table
->Hdr
.CRC32
= hdr_cksum
;
439 if (cksum
!= hdr_cksum
) {
440 kprintf("Bad EFI system table checksum\n");
444 gPEEFISystemTable
= system_table
;
446 if(system_table
->RuntimeServices
== 0) {
447 kprintf("No runtime table present\n");
450 DPRINTF("RuntimeServices table at 0x%x\n", system_table
->RuntimeServices
);
451 // 32-bit virtual address is OK for 32-bit EFI and 32-bit kernel.
452 // For a 64-bit kernel, booter provides a virtual address mod 4G
453 runtime
= (EFI_RUNTIME_SERVICES_32
*)
455 (system_table
->RuntimeServices
| VM_MIN_KERNEL_ADDRESS
);
457 system_table
->RuntimeServices
;
459 DPRINTF("Runtime table addressed at %p\n", runtime
);
460 if (runtime
->Hdr
.Signature
!= EFI_RUNTIME_SERVICES_SIGNATURE
) {
461 kprintf("Bad EFI runtime table signature\n");
465 // Verify signature of runtime services table
466 hdr_cksum
= runtime
->Hdr
.CRC32
;
467 runtime
->Hdr
.CRC32
= 0;
468 cksum
= crc32(0L, runtime
, runtime
->Hdr
.HeaderSize
);
470 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum
, hdr_cksum
);
471 runtime
->Hdr
.CRC32
= hdr_cksum
;
472 if (cksum
!= hdr_cksum
) {
473 kprintf("Bad EFI runtime table checksum\n");
477 DPRINTF("Runtime functions\n");
478 DPRINTF(" GetTime : 0x%x\n", runtime
->GetTime
);
479 DPRINTF(" SetTime : 0x%x\n", runtime
->SetTime
);
480 DPRINTF(" GetWakeupTime : 0x%x\n", runtime
->GetWakeupTime
);
481 DPRINTF(" SetWakeupTime : 0x%x\n", runtime
->SetWakeupTime
);
482 DPRINTF(" SetVirtualAddressMap : 0x%x\n", runtime
->SetVirtualAddressMap
);
483 DPRINTF(" ConvertPointer : 0x%x\n", runtime
->ConvertPointer
);
484 DPRINTF(" GetVariable : 0x%x\n", runtime
->GetVariable
);
485 DPRINTF(" GetNextVariableName : 0x%x\n", runtime
->GetNextVariableName
);
486 DPRINTF(" SetVariable : 0x%x\n", runtime
->SetVariable
);
487 DPRINTF(" GetNextHighMonotonicCount: 0x%x\n", runtime
->GetNextHighMonotonicCount
);
488 DPRINTF(" ResetSystem : 0x%x\n", runtime
->ResetSystem
);
490 gPEEFIRuntimeServices
= runtime
;
496 /* Map in EFI runtime areas. */
500 boot_args
*args
= (boot_args
*)PE_state
.bootArgs
;
502 kprintf("Initializing EFI runtime services\n");
506 vm_offset_t vm_size
, vm_addr
;
507 vm_map_offset_t phys_addr
;
508 EfiMemoryRange
*mptr
;
509 unsigned int msize
, mcount
;
512 msize
= args
->MemoryMapDescriptorSize
;
513 mcount
= args
->MemoryMapSize
/ msize
;
515 DPRINTF("efi_init() kernel base: 0x%x size: 0x%x\n",
516 args
->kaddr
, args
->ksize
);
517 DPRINTF(" efiSystemTable physical: 0x%x virtual: %p\n",
518 args
->efiSystemTable
,
519 (void *) ml_static_ptovirt(args
->efiSystemTable
));
520 DPRINTF(" efiRuntimeServicesPageStart: 0x%x\n",
521 args
->efiRuntimeServicesPageStart
);
522 DPRINTF(" efiRuntimeServicesPageCount: 0x%x\n",
523 args
->efiRuntimeServicesPageCount
);
524 DPRINTF(" efiRuntimeServicesVirtualPageStart: 0x%016llx\n",
525 args
->efiRuntimeServicesVirtualPageStart
);
526 mptr
= (EfiMemoryRange
*)ml_static_ptovirt(args
->MemoryMap
);
527 for (i
=0; i
< mcount
; i
++, mptr
= (EfiMemoryRange
*)(((vm_offset_t
)mptr
) + msize
)) {
528 if (((mptr
->Attribute
& EFI_MEMORY_RUNTIME
) == EFI_MEMORY_RUNTIME
) ) {
529 vm_size
= (vm_offset_t
)i386_ptob((uint32_t)mptr
->NumberOfPages
);
530 vm_addr
= (vm_offset_t
) mptr
->VirtualStart
;
532 /* For K64 on EFI32, shadow-map into high KVA */
533 if (vm_addr
< VM_MIN_KERNEL_ADDRESS
)
534 vm_addr
|= VM_MIN_KERNEL_ADDRESS
;
536 phys_addr
= (vm_map_offset_t
) mptr
->PhysicalStart
;
537 DPRINTF(" Type: %x phys: %p EFIv: %p kv: %p size: %p\n",
539 (void *) (uintptr_t) phys_addr
,
540 (void *) (uintptr_t) mptr
->VirtualStart
,
543 pmap_map_bd(vm_addr
, phys_addr
, phys_addr
+ round_page(vm_size
),
544 (mptr
->Type
== kEfiRuntimeServicesCode
) ? VM_PROT_READ
| VM_PROT_EXECUTE
: VM_PROT_READ
|VM_PROT_WRITE
,
545 (mptr
->Type
== EfiMemoryMappedIO
) ? VM_WIMG_IO
: VM_WIMG_USE_DEFAULT
);
549 if (args
->Version
!= kBootArgsVersion2
)
550 panic("Incompatible boot args version %d revision %d\n", args
->Version
, args
->Revision
);
552 DPRINTF("Boot args version %d revision %d mode %d\n", args
->Version
, args
->Revision
, args
->efiMode
);
553 if (args
->efiMode
== kBootArgsEfiMode64
) {
554 efi_set_tables_64((EFI_SYSTEM_TABLE_64
*) ml_static_ptovirt(args
->efiSystemTable
));
556 efi_set_tables_32((EFI_SYSTEM_TABLE_32
*) ml_static_ptovirt(args
->efiSystemTable
));
564 /* Remap EFI runtime areas. */
566 hibernate_newruntime_map(void * map
, vm_size_t map_size
, uint32_t system_table_offset
)
568 boot_args
*args
= (boot_args
*)PE_state
.bootArgs
;
570 kprintf("Reinitializing EFI runtime services\n");
574 vm_offset_t vm_size
, vm_addr
;
575 vm_map_offset_t phys_addr
;
576 EfiMemoryRange
*mptr
;
577 unsigned int msize
, mcount
;
580 gPEEFISystemTable
= 0;
581 gPEEFIRuntimeServices
= 0;
583 system_table_offset
+= ptoa_32(args
->efiRuntimeServicesPageStart
);
585 kprintf("Old system table 0x%x, new 0x%x\n",
586 (uint32_t)args
->efiSystemTable
, system_table_offset
);
588 args
->efiSystemTable
= system_table_offset
;
590 kprintf("Old map:\n");
591 msize
= args
->MemoryMapDescriptorSize
;
592 mcount
= args
->MemoryMapSize
/ msize
;
593 mptr
= (EfiMemoryRange
*)ml_static_ptovirt(args
->MemoryMap
);
594 for (i
=0; i
< mcount
; i
++, mptr
= (EfiMemoryRange
*)(((vm_offset_t
)mptr
) + msize
)) {
595 if ((mptr
->Attribute
& EFI_MEMORY_RUNTIME
) == EFI_MEMORY_RUNTIME
) {
597 vm_size
= (vm_offset_t
)i386_ptob((uint32_t)mptr
->NumberOfPages
);
598 vm_addr
= (vm_offset_t
) mptr
->VirtualStart
;
601 if (vm_addr
< VM_MIN_KERNEL_ADDRESS
)
602 vm_addr
|= VM_MIN_KERNEL_ADDRESS
;
604 phys_addr
= (vm_map_offset_t
) mptr
->PhysicalStart
;
606 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr
->Type
, phys_addr
, (unsigned long)vm_addr
, mptr
->NumberOfPages
);
610 pmap_remove(kernel_pmap
, i386_ptob(args
->efiRuntimeServicesPageStart
),
611 i386_ptob(args
->efiRuntimeServicesPageStart
+ args
->efiRuntimeServicesPageCount
));
613 kprintf("New map:\n");
614 msize
= args
->MemoryMapDescriptorSize
;
615 mcount
= (unsigned int )(map_size
/ msize
);
617 for (i
=0; i
< mcount
; i
++, mptr
= (EfiMemoryRange
*)(((vm_offset_t
)mptr
) + msize
)) {
618 if ((mptr
->Attribute
& EFI_MEMORY_RUNTIME
) == EFI_MEMORY_RUNTIME
) {
620 vm_size
= (vm_offset_t
)i386_ptob((uint32_t)mptr
->NumberOfPages
);
621 vm_addr
= (vm_offset_t
) mptr
->VirtualStart
;
623 if (vm_addr
< VM_MIN_KERNEL_ADDRESS
)
624 vm_addr
|= VM_MIN_KERNEL_ADDRESS
;
626 phys_addr
= (vm_map_offset_t
) mptr
->PhysicalStart
;
628 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr
->Type
, phys_addr
, (unsigned long)vm_addr
, mptr
->NumberOfPages
);
630 pmap_map(vm_addr
, phys_addr
, phys_addr
+ round_page(vm_size
),
631 (mptr
->Type
== kEfiRuntimeServicesCode
) ? VM_PROT_READ
| VM_PROT_EXECUTE
: VM_PROT_READ
|VM_PROT_WRITE
,
632 (mptr
->Type
== EfiMemoryMappedIO
) ? VM_WIMG_IO
: VM_WIMG_USE_DEFAULT
);
636 if (args
->Version
!= kBootArgsVersion2
)
637 panic("Incompatible boot args version %d revision %d\n", args
->Version
, args
->Revision
);
639 kprintf("Boot args version %d revision %d mode %d\n", args
->Version
, args
->Revision
, args
->efiMode
);
640 if (args
->efiMode
== kBootArgsEfiMode64
) {
641 efi_set_tables_64((EFI_SYSTEM_TABLE_64
*) ml_static_ptovirt(args
->efiSystemTable
));
643 efi_set_tables_32((EFI_SYSTEM_TABLE_32
*) ml_static_ptovirt(args
->efiSystemTable
));
648 kprintf("Done reinitializing EFI runtime services\n");
654 * Find devices. The system is alive.
660 /* Now with VM up, switch to dynamically allocated cpu data */
664 /* Ensure panic buffer is initialized. */
668 * Display CPU identification
670 cpuid_cpu_display("CPU identification");
671 cpuid_feature_display("CPU features");
672 cpuid_extfeature_display("CPU extended features");
675 * Initialize EFI runtime services.
682 * Set up to use floating point.
687 * Configure clock devices.
693 * Initialize MTRR from boot processor.
698 * Set up PAT for boot processor.
704 * Free lowmem pages and complete other setup
706 pmap_lowmem_finalize();
715 halt_all_cpus(FALSE
);
718 int reset_mem_on_reboot
= 1;
721 * Halt the system or reboot.
724 halt_all_cpus(boolean_t reboot
)
727 printf("MACH Reboot\n");
728 PEHaltRestart( kPERestartCPU
);
730 printf("CPU halted\n");
731 PEHaltRestart( kPEHaltCPU
);
737 /* Issue an I/O port read if one has been requested - this is an event logic
738 * analyzers can use as a trigger point.
742 panic_io_port_read(void) {
744 (void)inb(panic_io_port
);
747 /* For use with the MP rendezvous mechanism
750 uint64_t panic_restart_timeout
= ~(0ULL);
752 #define PANIC_RESTART_TIMEOUT (3ULL * NSEC_PER_SEC)
755 machine_halt_cpu(void) {
758 panic_io_port_read();
760 /* Halt here forever if we're not rebooting */
761 if (!PE_reboot_on_panic() && panic_restart_timeout
== ~(0ULL)) {
762 pmCPUHalt(PM_HALT_DEBUG
);
766 if (PE_reboot_on_panic())
767 deadline
= mach_absolute_time() + PANIC_RESTART_TIMEOUT
;
769 deadline
= mach_absolute_time() + panic_restart_timeout
;
771 while (mach_absolute_time() < deadline
)
774 kprintf("Invoking PE_halt_restart\n");
775 /* Attempt restart via ACPI RESET_REG; at the time of this
776 * writing, this is routine is chained through AppleSMC->
780 (*PE_halt_restart
)(kPERestartCPU
);
781 pmCPUHalt(PM_HALT_DEBUG
);
786 __unused
unsigned int reason
,
797 unsigned long pi_size
= 0;
799 int cn
= cpu_number();
801 hw_atomic_add(&debug_mode
, 1);
802 if (!panic_is_inited
) {
807 printf("Debugger called: <%s>\n", message
);
808 kprintf("Debugger called: <%s>\n", message
);
811 * Skip the graphical panic box if no panic string.
812 * This is the case if we're being called from
813 * host_reboot(,HOST_REBOOT_DEBUGGER)
814 * as a quiet way into the debugger.
818 disable_preemption();
820 /* Issue an I/O port read if one has been requested - this is an event logic
821 * analyzers can use as a trigger point.
823 panic_io_port_read();
825 /* Obtain current frame pointer */
826 #if defined (__i386__)
827 __asm__
volatile("movl %%ebp, %0" : "=m" (stackptr
));
828 #elif defined (__x86_64__)
829 __asm__
volatile("movq %%rbp, %0" : "=m" (stackptr
));
832 /* Print backtrace - callee is internally synchronized */
833 panic_i386_backtrace(stackptr
, ((panic_double_fault_cpu
== cn
) ? 80: 48), NULL
, FALSE
, NULL
);
835 /* everything should be printed now so copy to NVRAM
838 if( debug_buf_size
> 0) {
839 /* Optionally sync the panic log, if any, to NVRAM
840 * This is the default.
842 if (commit_paniclog_to_nvram
) {
848 /* Now call the compressor */
849 /* XXX Consider using the WKdm compressor in the
850 * future, rather than just packing - would need to
851 * be co-ordinated with crashreporter, which decodes
852 * this post-restart. The compressor should be
853 * capable of in-place compression.
855 bufpos
= packA(debug_buf
,
856 (unsigned int) (debug_buf_ptr
- debug_buf
), debug_buf_size
);
857 /* If compression was successful,
858 * use the compressed length
860 pi_size
= bufpos
? bufpos
: (unsigned) (debug_buf_ptr
- debug_buf
);
862 /* Save panic log to non-volatile store
863 * Panic info handler must truncate data that is
864 * too long for this platform.
865 * This call must save data synchronously,
866 * since we can subsequently halt the system.
870 /* The following sequence is a workaround for:
871 * <rdar://problem/5915669> SnowLeopard10A67: AppleEFINVRAM should not invoke
872 * any routines that use floating point (MMX in this case) when saving panic
873 * logs to nvram/flash.
878 kprintf("Attempting to commit panic log to NVRAM\n");
879 pi_size
= PESavePanicInfo((unsigned char *)debug_buf
,
883 /* Uncompress in-place, to permit examination of
884 * the panic log by debuggers.
888 unpackA(debug_buf
, bufpos
);
893 /* If the user won't be able to read the dialog,
894 * don't bother trying to show it
896 if (!PE_reboot_on_panic())
899 if (!panicDebugging
) {
901 /* Clear the MP rendezvous function lock, in the event
902 * that a panic occurred while in that codepath.
904 mp_rendezvous_break_lock();
906 /* Non-maskably interrupt all other processors
907 * If a restart timeout is specified, this processor
908 * will attempt a restart.
910 kprintf("Invoking machine_halt_cpu on CPU %d\n", cn
);
911 for (cnum
= 0; cnum
< real_ncpus
; cnum
++) {
912 if (cnum
!= (unsigned) cn
) {
913 cpu_NMI_interrupt(cnum
);
922 hw_atomic_sub(&debug_mode
, 1);
926 machine_boot_info(char *buf
, __unused vm_size_t size
)
932 /* Routines for address - symbol translation. Not called unless the "keepsyms"
933 * boot-arg is supplied.
937 panic_print_macho_symbol_name(kernel_mach_header_t
*mh
, vm_address_t search
, const char *module_name
)
939 kernel_nlist_t
*sym
= NULL
;
940 struct load_command
*cmd
;
941 kernel_segment_command_t
*orig_ts
= NULL
, *orig_le
= NULL
;
942 struct symtab_command
*orig_st
= NULL
;
944 char *strings
, *bestsym
= NULL
;
945 vm_address_t bestaddr
= 0, diff
, curdiff
;
947 /* Assume that if it's loaded and linked into the kernel, it's a valid Mach-O */
949 cmd
= (struct load_command
*) &mh
[1];
950 for (i
= 0; i
< mh
->ncmds
; i
++) {
951 if (cmd
->cmd
== LC_SEGMENT_KERNEL
) {
952 kernel_segment_command_t
*orig_sg
= (kernel_segment_command_t
*) cmd
;
954 if (strncmp(SEG_TEXT
, orig_sg
->segname
,
955 sizeof(orig_sg
->segname
)) == 0)
957 else if (strncmp(SEG_LINKEDIT
, orig_sg
->segname
,
958 sizeof(orig_sg
->segname
)) == 0)
960 else if (strncmp("", orig_sg
->segname
,
961 sizeof(orig_sg
->segname
)) == 0)
962 orig_ts
= orig_sg
; /* pre-Lion i386 kexts have a single unnamed segment */
964 else if (cmd
->cmd
== LC_SYMTAB
)
965 orig_st
= (struct symtab_command
*) cmd
;
967 cmd
= (struct load_command
*) ((uintptr_t) cmd
+ cmd
->cmdsize
);
970 if ((orig_ts
== NULL
) || (orig_st
== NULL
) || (orig_le
== NULL
))
973 if ((search
< orig_ts
->vmaddr
) ||
974 (search
>= orig_ts
->vmaddr
+ orig_ts
->vmsize
)) {
975 /* search out of range for this mach header */
979 sym
= (kernel_nlist_t
*)(uintptr_t)(orig_le
->vmaddr
+ orig_st
->symoff
- orig_le
->fileoff
);
980 strings
= (char *)(uintptr_t)(orig_le
->vmaddr
+ orig_st
->stroff
- orig_le
->fileoff
);
983 for (i
= 0; i
< orig_st
->nsyms
; i
++) {
984 if (sym
[i
].n_type
& N_STAB
) continue;
986 if (sym
[i
].n_value
<= search
) {
987 curdiff
= search
- (vm_address_t
)sym
[i
].n_value
;
988 if (curdiff
< diff
) {
990 bestaddr
= sym
[i
].n_value
;
991 bestsym
= strings
+ sym
[i
].n_un
.n_strx
;
996 if (bestsym
!= NULL
) {
998 kdb_printf("%s : %s + 0x%lx", module_name
, bestsym
, (unsigned long)diff
);
1000 kdb_printf("%s : %s", module_name
, bestsym
);
1007 extern kmod_info_t
* kmod
; /* the list of modules */
1010 panic_print_kmod_symbol_name(vm_address_t search
)
1014 if (gLoadedKextSummaries
== NULL
)
1016 for (i
= 0; i
< gLoadedKextSummaries
->numSummaries
; ++i
) {
1017 OSKextLoadedKextSummary
*summary
= gLoadedKextSummaries
->summaries
+ i
;
1019 if ((search
>= summary
->address
) &&
1020 (search
< (summary
->address
+ summary
->size
)))
1022 kernel_mach_header_t
*header
= (kernel_mach_header_t
*)(uintptr_t) summary
->address
;
1023 if (panic_print_macho_symbol_name(header
, search
, summary
->name
) == 0) {
1024 kdb_printf("%s + %llu", summary
->name
, (unsigned long)search
- summary
->address
);
1032 panic_print_symbol_name(vm_address_t search
)
1034 /* try searching in the kernel */
1035 if (panic_print_macho_symbol_name(&_mh_execute_header
, search
, "mach_kernel") == 0) {
1036 /* that failed, now try to search for the right kext */
1037 panic_print_kmod_symbol_name(search
);
1041 /* Generate a backtrace, given a frame pointer - this routine
1042 * should walk the stack safely. The trace is appended to the panic log
1043 * and conditionally, to the console. If the trace contains kernel module
1044 * addresses, display the module name, load address and dependencies.
1047 #define DUMPFRAMES 32
1048 #define PBT_TIMEOUT_CYCLES (5 * 1000 * 1000 * 1000ULL)
1050 panic_i386_backtrace(void *_frame
, int nframes
, const char *msg
, boolean_t regdump
, x86_saved_state_t
*regs
)
1052 cframe_t
*frame
= (cframe_t
*)_frame
;
1053 vm_offset_t raddrs
[DUMPFRAMES
];
1056 volatile uint32_t *ppbtcnt
= &pbtcnt
;
1057 uint64_t bt_tsc_timeout
;
1058 boolean_t keepsyms
= FALSE
;
1059 int cn
= cpu_number();
1062 hw_atomic_add(&pbtcnt
, 1);
1063 /* Spin on print backtrace lock, which serializes output
1064 * Continue anyway if a timeout occurs.
1066 hw_lock_to(&pbtlock
, LockTimeOutTSC
*2);
1070 PE_parse_boot_argn("keepsyms", &keepsyms
, sizeof (keepsyms
));
1073 kdb_printf("%s", msg
);
1076 if ((regdump
== TRUE
) && (regs
!= NULL
)) {
1077 #if defined(__x86_64__)
1078 x86_saved_state64_t
*ss64p
= saved_state64(regs
);
1080 "RAX: 0x%016llx, RBX: 0x%016llx, RCX: 0x%016llx, RDX: 0x%016llx\n"
1081 "RSP: 0x%016llx, RBP: 0x%016llx, RSI: 0x%016llx, RDI: 0x%016llx\n"
1082 "R8: 0x%016llx, R9: 0x%016llx, R10: 0x%016llx, R11: 0x%016llx\n"
1083 "R12: 0x%016llx, R13: 0x%016llx, R14: 0x%016llx, R15: 0x%016llx\n"
1084 "RFL: 0x%016llx, RIP: 0x%016llx, CS: 0x%016llx, SS: 0x%016llx\n",
1085 ss64p
->rax
, ss64p
->rbx
, ss64p
->rcx
, ss64p
->rdx
,
1086 ss64p
->isf
.rsp
, ss64p
->rbp
, ss64p
->rsi
, ss64p
->rdi
,
1087 ss64p
->r8
, ss64p
->r9
, ss64p
->r10
, ss64p
->r11
,
1088 ss64p
->r12
, ss64p
->r13
, ss64p
->r14
, ss64p
->r15
,
1089 ss64p
->isf
.rflags
, ss64p
->isf
.rip
, ss64p
->isf
.cs
,
1091 PC
= ss64p
->isf
.rip
;
1093 x86_saved_state32_t
*ss32p
= saved_state32(regs
);
1095 "EAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x\n"
1096 "CR2: 0x%08x, EBP: 0x%08x, ESI: 0x%08x, EDI: 0x%08x\n"
1097 "EFL: 0x%08x, EIP: 0x%08x, CS: 0x%08x, DS: 0x%08x\n",
1098 ss32p
->eax
,ss32p
->ebx
,ss32p
->ecx
,ss32p
->edx
,
1099 ss32p
->cr2
,ss32p
->ebp
,ss32p
->esi
,ss32p
->edi
,
1100 ss32p
->efl
,ss32p
->eip
,ss32p
->cs
, ss32p
->ds
);
1105 kdb_printf("Backtrace (CPU %d), "
1106 #if PRINT_ARGS_FROM_STACK_FRAME
1107 "Frame : Return Address (4 potential args on stack)\n", cn
);
1109 "Frame : Return Address\n", cn
);
1112 for (frame_index
= 0; frame_index
< nframes
; frame_index
++) {
1113 vm_offset_t curframep
= (vm_offset_t
) frame
;
1118 if (curframep
& 0x3) {
1119 kdb_printf("Unaligned frame\n");
1123 if (!kvtophys(curframep
) ||
1124 !kvtophys(curframep
+ sizeof(cframe_t
) - 1)) {
1125 kdb_printf("No mapping exists for frame pointer\n");
1129 kdb_printf("%p : 0x%lx ", frame
, frame
->caller
);
1130 if (frame_index
< DUMPFRAMES
)
1131 raddrs
[frame_index
] = frame
->caller
;
1133 #if PRINT_ARGS_FROM_STACK_FRAME
1134 if (kvtophys((vm_offset_t
)&(frame
->args
[3])))
1135 kdb_printf("(0x%x 0x%x 0x%x 0x%x) ",
1136 frame
->args
[0], frame
->args
[1],
1137 frame
->args
[2], frame
->args
[3]);
1140 /* Display address-symbol translation only if the "keepsyms"
1141 * boot-arg is suppplied, since we unload LINKEDIT otherwise.
1142 * This routine is potentially unsafe; also, function
1143 * boundary identification is unreliable after a strip -x.
1146 panic_print_symbol_name((vm_address_t
)frame
->caller
);
1150 frame
= frame
->prev
;
1153 if (frame_index
>= nframes
)
1154 kdb_printf("\tBacktrace continues...\n");
1159 kdb_printf("Backtrace terminated-invalid frame pointer %p\n",frame
);
1162 /* Identify kernel modules in the backtrace and display their
1163 * load addresses and dependencies. This routine should walk
1164 * the kmod list safely.
1167 kmod_panic_dump((vm_offset_t
*)&raddrs
[0], frame_index
);
1170 kmod_panic_dump(&PC
, 1);
1172 panic_display_system_configuration();
1174 /* Release print backtrace lock, to permit other callers in the
1175 * event of panics on multiple processors.
1177 hw_lock_unlock(&pbtlock
);
1178 hw_atomic_sub(&pbtcnt
, 1);
1179 /* Wait for other processors to complete output
1180 * Timeout and continue after PBT_TIMEOUT_CYCLES.
1182 bt_tsc_timeout
= rdtsc64() + PBT_TIMEOUT_CYCLES
;
1183 while(*ppbtcnt
&& (rdtsc64() < bt_tsc_timeout
));