2 * Copyright (c) 2000-2006 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>
72 #include <mach/i386/vm_param.h>
75 #include <mach/vm_param.h>
76 #include <mach/vm_prot.h>
77 #include <mach/machine.h>
78 #include <mach/time_value.h>
80 #include <kern/assert.h>
81 #include <kern/debug.h>
82 #include <kern/misc_protos.h>
83 #include <kern/startup.h>
84 #include <kern/clock.h>
85 #include <kern/cpu_data.h>
86 #include <kern/machine.h>
89 #include <i386/misc_protos.h>
90 #include <i386/mtrr.h>
91 #include <i386/machine_routines.h>
92 #include <i386/pmCPU.h>
93 #include <i386/postcode.h>
94 #include <i386/trap.h>
95 #include <i386/mp.h> /* mp_rendezvous_break_lock */
96 #include <architecture/i386/pio.h> /* inb() */
97 #include <pexpert/i386/boot.h>
99 #include <ddb/db_aout.h>
100 #endif /* MACH_KDB */
103 #include <vm/vm_map.h>
104 #include <vm/vm_kern.h>
106 #include <i386/mp_desc.h>
108 #include <i386/cpuid.h>
110 #include <IOKit/IOPlatformExpert.h>
111 #include <IOKit/IOHibernatePrivate.h>
113 #include <pexpert/i386/efi.h>
115 #include <kern/thread.h>
116 #include <i386/thread.h>
117 #include <mach-o/loader.h>
118 #include <mach-o/nlist.h>
120 void enable_bluebox(void);
121 void disable_bluebox(void);
123 static void machine_conf(void);
125 extern int default_preemption_rate
;
126 extern int max_unsafe_quanta
;
127 extern int max_poll_quanta
;
128 extern unsigned int panic_is_inited
;
132 volatile int pbtcpu
= -1;
133 hw_lock_data_t pbtlock
; /* backtrace print lock */
136 typedef struct _cframe_t
{
137 struct _cframe_t
*prev
;
142 static unsigned panic_io_port
;
143 static unsigned commit_paniclog_to_nvram
;
146 machine_startup(void)
151 if( PE_get_hotkey( kPEControlKey
))
152 halt_in_debugger
= halt_in_debugger
? 0 : 1;
155 if (PE_parse_boot_arg("debug", &boot_arg
)) {
156 if (boot_arg
& DB_HALT
) halt_in_debugger
=1;
157 if (boot_arg
& DB_PRT
) disable_debug_output
=FALSE
;
158 if (boot_arg
& DB_SLOG
) systemLogDiags
=TRUE
;
159 if (boot_arg
& DB_NMI
) panicDebugging
=TRUE
;
160 if (boot_arg
& DB_LOG_PI_SCRN
) logPanicDataToScreen
=TRUE
;
163 if (!PE_parse_boot_arg("nvram_paniclog", &commit_paniclog_to_nvram
))
164 commit_paniclog_to_nvram
= 1;
167 * Entering the debugger will put the CPUs into a "safe"
170 if (PE_parse_boot_arg("pmsafe_debug", &boot_arg
))
171 pmsafe_debug
= boot_arg
;
174 hw_lock_init(&debugger_lock
); /* initialize debugger lock */
176 hw_lock_init(&pbtlock
); /* initialize print backtrace lock */
182 #if DB_MACHINE_COMMANDS
183 db_machine_commands_install(ppc_db_commands
);
184 #endif /* DB_MACHINE_COMMANDS */
187 if (boot_arg
& DB_KDB
)
188 current_debugger
= KDB_CUR_DB
;
191 * Cause a breakpoint trap to the debugger before proceeding
192 * any further if the proper option bit was specified in
195 if (halt_in_debugger
&& (current_debugger
== KDB_CUR_DB
)) {
196 Debugger("inline call to debugger(machine_startup)");
197 halt_in_debugger
= 0;
200 #endif /* MACH_KDB */
202 if (PE_parse_boot_arg("preempt", &boot_arg
)) {
203 default_preemption_rate
= boot_arg
;
205 if (PE_parse_boot_arg("unsafe", &boot_arg
)) {
206 max_unsafe_quanta
= boot_arg
;
208 if (PE_parse_boot_arg("poll", &boot_arg
)) {
209 max_poll_quanta
= boot_arg
;
211 if (PE_parse_boot_arg("yield", &boot_arg
)) {
212 sched_poll_yield_shift
= boot_arg
;
214 if (PE_parse_boot_arg("idlehalt", &boot_arg
)) {
217 /* The I/O port to issue a read from, in the event of a panic. Useful for
218 * triggering logic analyzers.
220 if (PE_parse_boot_arg("panic_io_port", &boot_arg
)) {
221 /*I/O ports range from 0 through 0xFFFF */
222 panic_io_port
= boot_arg
& 0xffff;
228 ml_thrm_init(); /* Start thermal monitoring on this processor */
242 machine_info
.memory_size
= mem_size
;
246 extern void *gPEEFIRuntimeServices
;
247 extern void *gPEEFISystemTable
;
250 * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
251 * code or tables extracted from it, as desired without restriction.
253 * First, the polynomial itself and its table of feedback terms. The
255 * 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
257 * Note that we take it "backwards" and put the highest-order term in
258 * the lowest-order bit. The X^32 term is "implied"; the LSB is the
259 * X^31 term, etc. The X^0 term (usually shown as "+1") results in
262 * Note that the usual hardware shift register implementation, which
263 * is what we're using (we're merely optimizing it by doing eight-bit
264 * chunks at a time) shifts bits into the lowest-order term. In our
265 * implementation, that means shifting towards the right. Why do we
266 * do it this way? Because the calculated CRC must be transmitted in
267 * order from highest-order term to lowest-order term. UARTs transmit
268 * characters in order from LSB to MSB. By storing the CRC this way
269 * we hand it to the UART in the order low-byte to high-byte; the UART
270 * sends each low-bit to hight-bit; and the result is transmission bit
271 * by bit from highest- to lowest-order term without requiring any bit
272 * shuffling on our part. Reception works similarly
274 * The feedback terms table consists of 256, 32-bit entries. Notes
276 * The table can be generated at runtime if desired; code to do so
277 * is shown later. It might not be obvious, but the feedback
278 * terms simply represent the results of eight shift/xor opera
279 * tions for all combinations of data and CRC register values
281 * The values must be right-shifted by eight bits by the "updcrc
282 * logic; the shift must be unsigned (bring in zeroes). On some
283 * hardware you could probably optimize the shift in assembler by
284 * using byte-swap instructions
285 * polynomial $edb88320
288 * CRC32 code derived from work by Gary S. Brown.
291 static uint32_t crc32_tab
[] = {
292 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
293 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
294 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
295 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
296 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
297 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
298 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
299 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
300 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
301 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
302 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
303 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
304 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
305 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
306 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
307 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
308 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
309 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
310 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
311 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
312 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
313 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
314 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
315 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
316 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
317 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
318 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
319 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
320 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
321 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
322 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
323 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
324 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
325 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
326 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
327 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
328 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
329 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
330 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
331 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
332 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
333 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
334 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
338 crc32(uint32_t crc
, const void *buf
, size_t size
)
346 crc
= crc32_tab
[(crc
^ *p
++) & 0xFF] ^ (crc
>> 8);
352 efi_set_tables_64(EFI_SYSTEM_TABLE_64
* system_table
)
354 EFI_RUNTIME_SERVICES_64
*runtime
;
358 kprintf("Processing 64-bit EFI tables at %p\n", system_table
);
360 if (system_table
->Hdr
.Signature
!= EFI_SYSTEM_TABLE_SIGNATURE
) {
361 kprintf("Bad EFI system table signature\n");
364 // Verify signature of the system table
365 hdr_cksum
= system_table
->Hdr
.CRC32
;
366 system_table
->Hdr
.CRC32
= 0;
367 cksum
= crc32(0L, system_table
, system_table
->Hdr
.HeaderSize
);
369 //kprintf("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
370 system_table
->Hdr
.CRC32
= hdr_cksum
;
371 if (cksum
!= hdr_cksum
) {
372 kprintf("Bad EFI system table checksum\n");
376 gPEEFISystemTable
= system_table
;
378 kprintf("RuntimeServices table at 0x%qx\n", system_table
->RuntimeServices
);
379 runtime
= (EFI_RUNTIME_SERVICES_64
*) (uintptr_t)system_table
->RuntimeServices
; // XXX
380 kprintf("Checking runtime services table %p\n", runtime
);
381 if (runtime
->Hdr
.Signature
!= EFI_RUNTIME_SERVICES_SIGNATURE
) {
382 kprintf("Bad EFI runtime table signature\n");
386 // Verify signature of runtime services table
387 hdr_cksum
= runtime
->Hdr
.CRC32
;
388 runtime
->Hdr
.CRC32
= 0;
389 cksum
= crc32(0L, runtime
, runtime
->Hdr
.HeaderSize
);
391 //kprintf("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
392 runtime
->Hdr
.CRC32
= hdr_cksum
;
393 if (cksum
!= hdr_cksum
) {
394 kprintf("Bad EFI runtime table checksum\n");
398 gPEEFIRuntimeServices
= runtime
;
404 efi_set_tables_32(EFI_SYSTEM_TABLE
* system_table
)
406 EFI_RUNTIME_SERVICES
*runtime
;
410 kprintf("Processing 32-bit EFI tables at %p\n", system_table
);
412 if (system_table
->Hdr
.Signature
!= EFI_SYSTEM_TABLE_SIGNATURE
) {
413 kprintf("Bad EFI system table signature\n");
416 // Verify signature of the system table
417 hdr_cksum
= system_table
->Hdr
.CRC32
;
418 system_table
->Hdr
.CRC32
= 0;
419 cksum
= crc32(0L, system_table
, system_table
->Hdr
.HeaderSize
);
421 //kprintf("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
422 system_table
->Hdr
.CRC32
= hdr_cksum
;
423 if (cksum
!= hdr_cksum
) {
424 kprintf("Bad EFI system table checksum\n");
428 gPEEFISystemTable
= system_table
;
430 kprintf("RuntimeServices table at %p\n", system_table
->RuntimeServices
);
431 runtime
= (EFI_RUNTIME_SERVICES
*) system_table
->RuntimeServices
;
432 if (runtime
->Hdr
.Signature
!= EFI_RUNTIME_SERVICES_SIGNATURE
) {
433 kprintf("Bad EFI runtime table signature\n");
437 // Verify signature of runtime services table
438 hdr_cksum
= runtime
->Hdr
.CRC32
;
439 runtime
->Hdr
.CRC32
= 0;
440 cksum
= crc32(0L, runtime
, runtime
->Hdr
.HeaderSize
);
442 //kprintf("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
443 runtime
->Hdr
.CRC32
= hdr_cksum
;
444 if (cksum
!= hdr_cksum
) {
445 kprintf("Bad EFI runtime table checksum\n");
449 gPEEFIRuntimeServices
= runtime
;
455 /* Map in EFI runtime areas. */
459 boot_args
*args
= (boot_args
*)PE_state
.bootArgs
;
461 kprintf("Initializing EFI runtime services\n");
465 vm_offset_t vm_size
, vm_addr
;
466 vm_map_offset_t phys_addr
;
467 EfiMemoryRange
*mptr
;
468 unsigned int msize
, mcount
;
471 msize
= args
->MemoryMapDescriptorSize
;
472 mcount
= args
->MemoryMapSize
/ msize
;
474 mptr
= (EfiMemoryRange
*)args
->MemoryMap
;
475 for (i
=0; i
< mcount
; i
++, mptr
= (EfiMemoryRange
*)(((vm_offset_t
)mptr
) + msize
)) {
476 if (((mptr
->Attribute
& EFI_MEMORY_RUNTIME
) == EFI_MEMORY_RUNTIME
) ) {
477 vm_size
= i386_ptob((uint32_t)mptr
->NumberOfPages
);
478 vm_addr
= (vm_offset_t
) mptr
->VirtualStart
;
479 phys_addr
= (vm_map_offset_t
) mptr
->PhysicalStart
;
480 pmap_map(vm_addr
, phys_addr
, phys_addr
+ round_page(vm_size
),
481 (mptr
->Type
== kEfiRuntimeServicesCode
) ? VM_PROT_READ
| VM_PROT_EXECUTE
: VM_PROT_READ
|VM_PROT_WRITE
,
482 (mptr
->Type
== EfiMemoryMappedIO
) ? VM_WIMG_IO
: VM_WIMG_USE_DEFAULT
);
486 if (args
->Version
> 1)
487 panic("Incompatible boot args version %d\n", args
->Version
);
489 kprintf("Boot args version %d revision %d mode %d\n", args
->Version
, args
->Revision
, args
->efiMode
);
490 if (args
->Revision
>= 4 && args
->efiMode
== kBootArgsEfiMode64
) {
491 efi_set_tables_64((EFI_SYSTEM_TABLE_64
*) args
->efiSystemTable
);
493 efi_set_tables_32((EFI_SYSTEM_TABLE
*) args
->efiSystemTable
);
501 /* Remap EFI runtime areas. */
503 hibernate_newruntime_map(void * map
, vm_size_t map_size
, uint32_t system_table_offset
)
505 boot_args
*args
= (boot_args
*)PE_state
.bootArgs
;
507 kprintf("Reinitializing EFI runtime services\n");
509 if (args
->Revision
< 3)
513 vm_offset_t vm_size
, vm_addr
;
514 vm_map_offset_t phys_addr
;
515 EfiMemoryRange
*mptr
;
516 unsigned int msize
, mcount
;
519 gPEEFISystemTable
= 0;
520 gPEEFIRuntimeServices
= 0;
522 system_table_offset
+= ptoa_32(args
->efiRuntimeServicesPageStart
);
524 kprintf("Old system table 0x%x, new 0x%x\n",
525 (uint32_t)args
->efiSystemTable
, system_table_offset
);
527 args
->efiSystemTable
= system_table_offset
;
529 kprintf("Old map:\n");
530 msize
= args
->MemoryMapDescriptorSize
;
531 mcount
= args
->MemoryMapSize
/ msize
;
532 mptr
= (EfiMemoryRange
*)args
->MemoryMap
;
533 for (i
=0; i
< mcount
; i
++, mptr
= (EfiMemoryRange
*)(((vm_offset_t
)mptr
) + msize
)) {
534 if ((mptr
->Attribute
& EFI_MEMORY_RUNTIME
) == EFI_MEMORY_RUNTIME
) {
536 vm_size
= i386_ptob((uint32_t)mptr
->NumberOfPages
);
537 vm_addr
= (vm_offset_t
) mptr
->VirtualStart
;
538 phys_addr
= (vm_map_offset_t
) mptr
->PhysicalStart
;
540 kprintf("mapping[%u] %qx @ %x, %llu\n", mptr
->Type
, phys_addr
, vm_addr
, mptr
->NumberOfPages
);
544 pmap_remove(kernel_pmap
, i386_ptob(args
->efiRuntimeServicesPageStart
),
545 i386_ptob(args
->efiRuntimeServicesPageStart
+ args
->efiRuntimeServicesPageCount
));
547 kprintf("New map:\n");
548 msize
= args
->MemoryMapDescriptorSize
;
549 mcount
= map_size
/ msize
;
551 for (i
=0; i
< mcount
; i
++, mptr
= (EfiMemoryRange
*)(((vm_offset_t
)mptr
) + msize
)) {
552 if ((mptr
->Attribute
& EFI_MEMORY_RUNTIME
) == EFI_MEMORY_RUNTIME
) {
554 vm_size
= i386_ptob((uint32_t)mptr
->NumberOfPages
);
555 vm_addr
= (vm_offset_t
) mptr
->VirtualStart
;
556 phys_addr
= (vm_map_offset_t
) mptr
->PhysicalStart
;
558 kprintf("mapping[%u] %qx @ %x, %llu\n", mptr
->Type
, phys_addr
, vm_addr
, mptr
->NumberOfPages
);
560 pmap_map(vm_addr
, phys_addr
, phys_addr
+ round_page(vm_size
),
561 (mptr
->Type
== kEfiRuntimeServicesCode
) ? VM_PROT_READ
| VM_PROT_EXECUTE
: VM_PROT_READ
|VM_PROT_WRITE
,
562 (mptr
->Type
== EfiMemoryMappedIO
) ? VM_WIMG_IO
: VM_WIMG_USE_DEFAULT
);
566 if (args
->Version
> 1)
567 panic("Incompatible boot args version %d\n", args
->Version
);
569 kprintf("Boot args version %d revision %d mode %d\n", args
->Version
, args
->Revision
, args
->efiMode
);
570 if (args
->Revision
>= 4 && args
->efiMode
== kBootArgsEfiMode64
) {
571 efi_set_tables_64((EFI_SYSTEM_TABLE_64
*) args
->efiSystemTable
);
573 efi_set_tables_32((EFI_SYSTEM_TABLE
*) args
->efiSystemTable
);
578 kprintf("Done reinitializing EFI runtime services\n");
584 * Find devices. The system is alive.
589 /* Ensure panic buffer is initialized. */
593 * Display CPU identification
595 cpuid_cpu_display("CPU identification");
596 cpuid_feature_display("CPU features");
597 cpuid_extfeature_display("CPU extended features");
600 * Initialize EFI runtime services.
607 * Set up to use floating point.
612 * Configure clock devices.
617 * Initialize MTRR from boot processor.
622 * Set up PAT for boot processor.
638 halt_all_cpus(FALSE
);
641 int reset_mem_on_reboot
= 1;
644 * Halt the system or reboot.
647 halt_all_cpus(boolean_t reboot
)
650 printf("MACH Reboot\n");
651 PEHaltRestart( kPERestartCPU
);
653 printf("CPU halted\n");
654 PEHaltRestart( kPEHaltCPU
);
660 /* Issue an I/O port read if one has been requested - this is an event logic
661 * analyzers can use as a trigger point.
665 panic_io_port_read(void) {
667 (void)inb(panic_io_port
);
670 /* For use with the MP rendezvous mechanism
675 machine_halt_cpu(__unused
void *arg
) {
676 panic_io_port_read();
677 pmCPUHalt(PM_HALT_DEBUG
);
685 unsigned long pi_size
= 0;
688 hw_atomic_add(&debug_mode
, 1);
689 if (!panic_is_inited
) {
695 printf("Debugger called: <%s>\n", message
);
696 kprintf("Debugger called: <%s>\n", message
);
699 * Skip the graphical panic box if no panic string.
700 * This is the case if we're being called from
701 * host_reboot(,HOST_REBOOT_DEBUGGER)
702 * as a quiet way into the debugger.
706 disable_preemption();
708 /* Issue an I/O port read if one has been requested - this is an event logic
709 * analyzers can use as a trigger point.
711 panic_io_port_read();
713 /* Obtain current frame pointer */
714 __asm__
volatile("movl %%ebp, %0" : "=m" (stackptr
));
716 /* Print backtrace - callee is internally synchronized */
717 panic_i386_backtrace(stackptr
, 16, NULL
, FALSE
, NULL
);
719 /* everything should be printed now so copy to NVRAM
722 if( debug_buf_size
> 0) {
723 /* Optionally sync the panic log, if any, to NVRAM
724 * This is the default.
726 if (commit_paniclog_to_nvram
) {
732 /* Now call the compressor */
733 /* XXX Consider using the WKdm compressor in the
734 * future, rather than just packing - would need to
735 * be co-ordinated with crashreporter, which decodes
736 * this post-restart. The compressor should be
737 * capable of in-place compression.
739 bufpos
= packA(debug_buf
,
740 (unsigned int) (debug_buf_ptr
- debug_buf
), debug_buf_size
);
741 /* If compression was successful,
742 * use the compressed length
744 pi_size
= bufpos
? bufpos
: (unsigned) (debug_buf_ptr
- debug_buf
);
746 /* Save panic log to non-volatile store
747 * Panic info handler must truncate data that is
748 * too long for this platform.
749 * This call must save data synchronously,
750 * since we can subsequently halt the system.
752 kprintf("Attempting to commit panic log to NVRAM\n");
753 /* The following sequence is a workaround for:
754 * <rdar://problem/5915669> SnowLeopard10A67: AppleEFINVRAM should not invoke
755 * any routines that use floating point (MMX in this case) when saving panic
756 * logs to nvram/flash.
761 pi_size
= PESavePanicInfo((unsigned char *)debug_buf
,
765 /* Uncompress in-place, to permit examination of
766 * the panic log by debuggers.
770 unpackA(debug_buf
, bufpos
);
776 if (!panicDebugging
) {
777 /* Clear the MP rendezvous function lock, in the event
778 * that a panic occurred while in that codepath.
780 mp_rendezvous_break_lock();
782 PEHaltRestart(kPEPanicRestartCPU
);
784 /* Force all CPUs to disable interrupts and HLT.
785 * We've panicked, and shouldn't depend on the
786 * PEHaltRestart() mechanism, which relies on several
787 * bits of infrastructure.
789 mp_rendezvous_no_intrs(machine_halt_cpu
, NULL
);
796 hw_atomic_sub(&debug_mode
, 1);
805 disable_bluebox(void)
810 machine_boot_info(char *buf
, __unused vm_size_t size
)
826 } __attribute__((packed
));
828 typedef struct pasc pasc_t
;
830 /* Routines for address - symbol translation. Not called unless the "keepsyms"
831 * boot-arg is supplied.
835 panic_print_macho_symbol_name(struct mach_header
*mh
, vm_address_t search
)
837 struct nlist
*sym
= NULL
;
838 struct load_command
*cmd
;
839 struct segment_command
*orig_ts
= NULL
, *orig_le
= NULL
;
840 struct symtab_command
*orig_st
= NULL
;
842 char *strings
, *bestsym
= NULL
;
843 vm_address_t bestaddr
= 0, diff
, curdiff
;
845 if (mh
->magic
!= MH_MAGIC
) {
846 /* bad magic number */
850 cmd
= (struct load_command
*) &mh
[1];
851 for (i
= 0; i
< mh
->ncmds
; i
++) {
852 if (cmd
->cmd
== LC_SEGMENT
) {
853 struct segment_command
*orig_sg
= (struct segment_command
*) cmd
;
855 if (strncmp(SEG_TEXT
, orig_sg
->segname
,
856 sizeof(orig_sg
->segname
)) == 0)
858 else if (strncmp(SEG_LINKEDIT
, orig_sg
->segname
,
859 sizeof(orig_sg
->segname
)) == 0)
861 else if (strncmp("", orig_sg
->segname
,
862 sizeof(orig_sg
->segname
)) == 0)
863 orig_ts
= orig_sg
; /* kexts have a single unnamed segment */
865 else if (cmd
->cmd
== LC_SYMTAB
)
866 orig_st
= (struct symtab_command
*) cmd
;
868 cmd
= (struct load_command
*) ((caddr_t
) cmd
+ cmd
->cmdsize
);
871 if ((orig_ts
== NULL
) || (orig_st
== NULL
) || (orig_le
== NULL
))
874 /* kexts don't have a LINKEDIT segment for now, so we'll never get this far for kexts */
876 vm_address_t slide
= ((vm_address_t
)mh
) - orig_ts
->vmaddr
;
878 search
-= slide
; /* adjusting search since the binary has slid */
880 if ((search
< orig_ts
->vmaddr
) ||
881 (search
>= orig_ts
->vmaddr
+ orig_ts
->vmsize
)) {
882 /* search out of range for this mach header */
886 sym
= (struct nlist
*)orig_le
->vmaddr
;
887 strings
= ((char *)sym
) + orig_st
->nsyms
* sizeof(struct nlist
);
890 for (i
= 0; i
< orig_st
->nsyms
; i
++) {
891 if (sym
[i
].n_value
<= search
) {
892 curdiff
= search
- (vm_address_t
)sym
[i
].n_value
;
893 if (curdiff
< diff
) {
895 bestaddr
= sym
[i
].n_value
;
896 bestsym
= strings
+ sym
[i
].n_un
.n_strx
;
901 if (bestsym
!= NULL
) {
903 kdb_printf("%s + 0x%08x \n", bestsym
, diff
);
905 kdb_printf("%s \n", bestsym
);
912 extern kmod_info_t
* kmod
; /* the list of modules */
915 panic_print_kmod_symbol_name(vm_address_t search
)
917 kmod_info_t
* current_kmod
= kmod
;
919 while (current_kmod
!= NULL
) {
920 if ((current_kmod
->address
<= search
) &&
921 (current_kmod
->address
+ current_kmod
->size
> search
))
923 current_kmod
= current_kmod
->next
;
925 if (current_kmod
!= NULL
) {
926 /* if kexts had symbol table loaded, we'd call search_symbol_name again; alas, they don't */
927 kdb_printf("%s + %d \n", current_kmod
->name
, search
- current_kmod
->address
);
931 extern struct mach_header _mh_execute_header
; /* the kernel's mach header */
934 panic_print_symbol_name(vm_address_t search
)
936 /* try searching in the kernel */
937 if (panic_print_macho_symbol_name(&_mh_execute_header
, search
) == 0) {
938 /* that failed, now try to search for the right kext */
939 panic_print_kmod_symbol_name(search
);
943 /* Generate a backtrace, given a frame pointer - this routine
944 * should walk the stack safely. The trace is appended to the panic log
945 * and conditionally, to the console. If the trace contains kernel module
946 * addresses, display the module name, load address and dependencies.
949 #define DUMPFRAMES 32
950 #define PBT_TIMEOUT_CYCLES (5 * 1000 * 1000 * 1000ULL)
952 panic_i386_backtrace(void *_frame
, int nframes
, const char *msg
, boolean_t regdump
, x86_saved_state_t
*regs
)
954 cframe_t
*frame
= (cframe_t
*)_frame
;
955 vm_offset_t raddrs
[DUMPFRAMES
];
958 volatile uint32_t *ppbtcnt
= &pbtcnt
;
959 uint64_t bt_tsc_timeout
;
960 boolean_t keepsyms
= FALSE
;
962 if(pbtcpu
!= cpu_number()) {
963 hw_atomic_add(&pbtcnt
, 1);
964 /* Spin on print backtrace lock, which serializes output
965 * Continue anyway if a timeout occurs.
967 hw_lock_to(&pbtlock
, LockTimeOutTSC
);
968 pbtcpu
= cpu_number();
971 PE_parse_boot_arg("keepsyms", &keepsyms
);
977 if ((regdump
== TRUE
) && (regs
!= NULL
)) {
978 x86_saved_state32_t
*ss32p
= saved_state32(regs
);
981 "EAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x\n"
982 "CR2: 0x%08x, EBP: 0x%08x, ESI: 0x%08x, EDI: 0x%08x\n"
983 "EFL: 0x%08x, EIP: 0x%08x, CS: 0x%08x, DS: 0x%08x\n",
984 ss32p
->eax
,ss32p
->ebx
,ss32p
->ecx
,ss32p
->edx
,
985 ss32p
->cr2
,ss32p
->ebp
,ss32p
->esi
,ss32p
->edi
,
986 ss32p
->efl
,ss32p
->eip
,ss32p
->cs
, ss32p
->ds
);
990 kdb_printf("Backtrace (CPU %d), "
991 "Frame : Return Address (4 potential args on stack)\n", cpu_number());
993 for (frame_index
= 0; frame_index
< nframes
; frame_index
++) {
994 vm_offset_t curframep
= (vm_offset_t
) frame
;
999 if (curframep
& 0x3) {
1000 kdb_printf("Unaligned frame\n");
1004 if (!kvtophys(curframep
) ||
1005 !kvtophys(curframep
+ sizeof(cframe_t
))) {
1006 kdb_printf("No mapping exists for frame pointer\n");
1010 kdb_printf("%p : 0x%x ", frame
, frame
->caller
);
1011 if (frame_index
< DUMPFRAMES
)
1012 raddrs
[frame_index
] = frame
->caller
;
1014 if (kvtophys((vm_offset_t
)&(frame
->args
[3])))
1015 kdb_printf("(0x%x 0x%x 0x%x 0x%x) \n",
1016 frame
->args
[0], frame
->args
[1],
1017 frame
->args
[2], frame
->args
[3]);
1019 /* Display address-symbol translation only if the "keepsyms"
1020 * boot-arg is suppplied, since we unload LINKEDIT otherwise.
1021 * This routine is potentially unsafe; also, function
1022 * boundary identification is unreliable after a strip -x.
1025 panic_print_symbol_name((vm_address_t
)frame
->caller
);
1027 /* Stack grows downward */
1028 if (frame
->prev
< frame
) {
1029 frame
= frame
->prev
;
1032 frame
= frame
->prev
;
1035 if (frame_index
>= nframes
)
1036 kdb_printf("\tBacktrace continues...\n");
1041 kdb_printf("Backtrace terminated-invalid frame pointer %p\n",frame
);
1044 /* Identify kernel modules in the backtrace and display their
1045 * load addresses and dependencies. This routine should walk
1046 * the kmod list safely.
1049 kmod_dump((vm_offset_t
*)&raddrs
[0], frame_index
);
1054 panic_display_system_configuration();
1055 /* Release print backtrace lock, to permit other callers in the
1056 * event of panics on multiple processors.
1058 hw_lock_unlock(&pbtlock
);
1059 hw_atomic_sub(&pbtcnt
, 1);
1060 /* Wait for other processors to complete output
1061 * Timeout and continue after PBT_TIMEOUT_CYCLES.
1063 bt_tsc_timeout
= rdtsc64() + PBT_TIMEOUT_CYCLES
;
1064 while(*ppbtcnt
&& (rdtsc64() < bt_tsc_timeout
));