]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/AT386/model_dep.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / osfmk / i386 / AT386 / model_dep.c
CommitLineData
1c79356b 1/*
6d2010ae 2 * Copyright (c) 2000-2010 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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/*
58 */
59
60/*
61 * File: model_dep.c
62 * Author: Avadis Tevanian, Jr., Michael Wayne Young
63 *
64 * Copyright (C) 1986, Avadis Tevanian, Jr., Michael Wayne Young
65 *
66 * Basic initialization for I386 - ISA bus machines.
67 */
68
1c79356b 69#include <platforms.h>
1c79356b 70#include <mach_kdb.h>
1c79356b
A
71
72#include <mach/i386/vm_param.h>
73
74#include <string.h>
75#include <mach/vm_param.h>
76#include <mach/vm_prot.h>
77#include <mach/machine.h>
78#include <mach/time_value.h>
1c79356b
A
79#include <kern/spl.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>
1c79356b 85#include <kern/cpu_data.h>
91447636 86#include <kern/machine.h>
b0d623f7
A
87#include <i386/postcode.h>
88#include <i386/mp_desc.h>
89#include <i386/misc_protos.h>
90#include <i386/thread.h>
91#include <i386/trap.h>
92#include <i386/machine_routines.h>
93#include <i386/mp.h> /* mp_rendezvous_break_lock */
94#include <i386/cpuid.h>
1c79356b 95#include <i386/fpu.h>
6d2010ae
A
96#include <i386/machine_cpu.h>
97#include <i386/pmap.h>
98#if CONFIG_MTRR
91447636 99#include <i386/mtrr.h>
6d2010ae
A
100#endif
101#include <i386/ucode.h>
0c530ab8 102#include <i386/pmCPU.h>
0c530ab8 103#include <architecture/i386/pio.h> /* inb() */
55e303ae 104#include <pexpert/i386/boot.h>
1c79356b
A
105#if MACH_KDB
106#include <ddb/db_aout.h>
107#endif /* MACH_KDB */
1c79356b 108
0c530ab8
A
109#include <vm/pmap.h>
110#include <vm/vm_map.h>
111#include <vm/vm_kern.h>
112
9bccf70c 113#include <IOKit/IOPlatformExpert.h>
0c530ab8
A
114#include <IOKit/IOHibernatePrivate.h>
115
116#include <pexpert/i386/efi.h>
117
118#include <kern/thread.h>
0c530ab8
A
119#include <mach-o/loader.h>
120#include <mach-o/nlist.h>
9bccf70c 121
b0d623f7 122#include <libkern/kernel_mach_header.h>
6d2010ae
A
123#include <libkern/OSKextLibPrivate.h>
124
125#define DPRINTF(x...)
126//#define DPRINTF(x...) kprintf(x)
91447636 127
55e303ae 128static void machine_conf(void);
1c79356b 129
91447636
A
130extern int default_preemption_rate;
131extern int max_unsafe_quanta;
132extern int max_poll_quanta;
91447636
A
133extern unsigned int panic_is_inited;
134
0c530ab8
A
135int db_run_mode;
136
0c530ab8
A
137volatile int pbtcpu = -1;
138hw_lock_data_t pbtlock; /* backtrace print lock */
139uint32_t pbtcnt = 0;
140
6d2010ae
A
141volatile int panic_double_fault_cpu = -1;
142
b0d623f7
A
143#if defined (__i386__)
144#define PRINT_ARGS_FROM_STACK_FRAME 1
145#elif defined (__x86_64__)
146#define PRINT_ARGS_FROM_STACK_FRAME 0
147#else
148#error unsupported architecture
149#endif
150
151#ifdef __LP64__
152typedef struct nlist_64 kernel_nlist_t;
153#else
154typedef struct nlist kernel_nlist_t;
155#endif
156
0c530ab8
A
157typedef struct _cframe_t {
158 struct _cframe_t *prev;
b0d623f7
A
159 uintptr_t caller;
160#if PRINT_ARGS_FROM_STACK_FRAME
0c530ab8 161 unsigned args[0];
b0d623f7 162#endif
0c530ab8
A
163} cframe_t;
164
2d21ac55
A
165static unsigned panic_io_port;
166static unsigned commit_paniclog_to_nvram;
0c530ab8 167
b7266188 168unsigned int debug_boot_arg;
c910b4d9 169
1c79356b 170void
2d21ac55 171machine_startup(void)
1c79356b 172{
55e303ae 173 int boot_arg;
1c79356b 174
55e303ae
A
175#if 0
176 if( PE_get_hotkey( kPEControlKey ))
177 halt_in_debugger = halt_in_debugger ? 0 : 1;
1c79356b
A
178#endif
179
b7266188 180 if (PE_parse_boot_argn("debug", &debug_boot_arg, sizeof (debug_boot_arg))) {
6d2010ae 181 panicDebugging = TRUE;
b7266188
A
182 if (debug_boot_arg & DB_HALT) halt_in_debugger=1;
183 if (debug_boot_arg & DB_PRT) disable_debug_output=FALSE;
184 if (debug_boot_arg & DB_SLOG) systemLogDiags=TRUE;
b7266188
A
185 if (debug_boot_arg & DB_LOG_PI_SCRN) logPanicDataToScreen=TRUE;
186 } else {
187 debug_boot_arg = 0;
55e303ae 188 }
1c79356b 189
593a1d5f 190 if (!PE_parse_boot_argn("nvram_paniclog", &commit_paniclog_to_nvram, sizeof (commit_paniclog_to_nvram)))
2d21ac55
A
191 commit_paniclog_to_nvram = 1;
192
193 /*
194 * Entering the debugger will put the CPUs into a "safe"
195 * power mode.
196 */
593a1d5f 197 if (PE_parse_boot_argn("pmsafe_debug", &boot_arg, sizeof (boot_arg)))
2d21ac55
A
198 pmsafe_debug = boot_arg;
199
55e303ae
A
200#if NOTYET
201 hw_lock_init(&debugger_lock); /* initialize debugger lock */
6601e61a 202#endif
0c530ab8 203 hw_lock_init(&pbtlock); /* initialize print backtrace lock */
1c79356b
A
204
205#if MACH_KDB
1c79356b 206 /*
55e303ae 207 * Initialize KDB
1c79356b 208 */
55e303ae
A
209#if DB_MACHINE_COMMANDS
210 db_machine_commands_install(ppc_db_commands);
211#endif /* DB_MACHINE_COMMANDS */
1c79356b
A
212 ddb_init();
213
55e303ae
A
214 if (boot_arg & DB_KDB)
215 current_debugger = KDB_CUR_DB;
216
1c79356b
A
217 /*
218 * Cause a breakpoint trap to the debugger before proceeding
219 * any further if the proper option bit was specified in
220 * the boot flags.
1c79356b 221 */
55e303ae
A
222 if (halt_in_debugger && (current_debugger == KDB_CUR_DB)) {
223 Debugger("inline call to debugger(machine_startup)");
224 halt_in_debugger = 0;
225 active_debugger =1;
226 }
227#endif /* MACH_KDB */
228
593a1d5f 229 if (PE_parse_boot_argn("preempt", &boot_arg, sizeof (boot_arg))) {
55e303ae 230 default_preemption_rate = boot_arg;
1c79356b 231 }
593a1d5f 232 if (PE_parse_boot_argn("unsafe", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
233 max_unsafe_quanta = boot_arg;
234 }
593a1d5f 235 if (PE_parse_boot_argn("poll", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
236 max_poll_quanta = boot_arg;
237 }
593a1d5f 238 if (PE_parse_boot_argn("yield", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
239 sched_poll_yield_shift = boot_arg;
240 }
0c530ab8
A
241/* The I/O port to issue a read from, in the event of a panic. Useful for
242 * triggering logic analyzers.
243 */
593a1d5f 244 if (PE_parse_boot_argn("panic_io_port", &boot_arg, sizeof (boot_arg))) {
0c530ab8
A
245 /*I/O ports range from 0 through 0xFFFF */
246 panic_io_port = boot_arg & 0xffff;
247 }
248
55e303ae
A
249 machine_conf();
250
251#if NOTYET
252 ml_thrm_init(); /* Start thermal monitoring on this processor */
1c79356b
A
253#endif
254
255 /*
256 * Start the system.
257 */
91447636
A
258 kernel_bootstrap();
259 /*NOTREACHED*/
1c79356b
A
260}
261
55e303ae
A
262
263static void
264machine_conf(void)
1c79356b 265{
b0d623f7 266 machine_info.memory_size = (typeof(machine_info.memory_size))mem_size;
1c79356b
A
267}
268
0c530ab8
A
269
270extern void *gPEEFIRuntimeServices;
271extern void *gPEEFISystemTable;
272
273/*-
274 * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
275 * code or tables extracted from it, as desired without restriction.
276 *
277 * First, the polynomial itself and its table of feedback terms. The
278 * polynomial is
279 * 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
280 *
281 * Note that we take it "backwards" and put the highest-order term in
282 * the lowest-order bit. The X^32 term is "implied"; the LSB is the
283 * X^31 term, etc. The X^0 term (usually shown as "+1") results in
284 * the MSB being 1
285 *
286 * Note that the usual hardware shift register implementation, which
287 * is what we're using (we're merely optimizing it by doing eight-bit
288 * chunks at a time) shifts bits into the lowest-order term. In our
289 * implementation, that means shifting towards the right. Why do we
290 * do it this way? Because the calculated CRC must be transmitted in
291 * order from highest-order term to lowest-order term. UARTs transmit
292 * characters in order from LSB to MSB. By storing the CRC this way
293 * we hand it to the UART in the order low-byte to high-byte; the UART
294 * sends each low-bit to hight-bit; and the result is transmission bit
295 * by bit from highest- to lowest-order term without requiring any bit
296 * shuffling on our part. Reception works similarly
297 *
298 * The feedback terms table consists of 256, 32-bit entries. Notes
299 *
300 * The table can be generated at runtime if desired; code to do so
301 * is shown later. It might not be obvious, but the feedback
302 * terms simply represent the results of eight shift/xor opera
303 * tions for all combinations of data and CRC register values
304 *
305 * The values must be right-shifted by eight bits by the "updcrc
306 * logic; the shift must be unsigned (bring in zeroes). On some
307 * hardware you could probably optimize the shift in assembler by
308 * using byte-swap instructions
309 * polynomial $edb88320
310 *
311 *
312 * CRC32 code derived from work by Gary S. Brown.
313 */
314
315static uint32_t crc32_tab[] = {
316 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
317 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
318 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
319 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
320 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
321 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
322 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
323 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
324 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
325 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
326 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
327 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
328 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
329 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
330 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
331 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
332 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
333 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
334 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
335 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
336 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
337 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
338 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
339 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
340 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
341 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
342 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
343 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
344 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
345 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
346 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
347 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
348 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
349 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
350 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
351 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
352 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
353 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
354 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
355 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
356 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
357 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
358 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
359};
360
361static uint32_t
362crc32(uint32_t crc, const void *buf, size_t size)
363{
364 const uint8_t *p;
365
366 p = buf;
367 crc = crc ^ ~0U;
368
369 while (size--)
370 crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
371
372 return crc ^ ~0U;
373}
374
375static void
376efi_set_tables_64(EFI_SYSTEM_TABLE_64 * system_table)
377{
378 EFI_RUNTIME_SERVICES_64 *runtime;
379 uint32_t hdr_cksum;
380 uint32_t cksum;
381
6d2010ae 382 DPRINTF("Processing 64-bit EFI tables at %p\n", system_table);
0c530ab8 383 do {
6d2010ae
A
384 DPRINTF("Header:\n");
385 DPRINTF(" Signature: 0x%016llx\n", system_table->Hdr.Signature);
386 DPRINTF(" Revision: 0x%08x\n", system_table->Hdr.Revision);
387 DPRINTF(" HeaderSize: 0x%08x\n", system_table->Hdr.HeaderSize);
388 DPRINTF(" CRC32: 0x%08x\n", system_table->Hdr.CRC32);
389 DPRINTF("RuntimeServices: 0x%016llx\n", system_table->RuntimeServices);
0c530ab8
A
390 if (system_table->Hdr.Signature != EFI_SYSTEM_TABLE_SIGNATURE) {
391 kprintf("Bad EFI system table signature\n");
392 break;
393 }
394 // Verify signature of the system table
395 hdr_cksum = system_table->Hdr.CRC32;
396 system_table->Hdr.CRC32 = 0;
397 cksum = crc32(0L, system_table, system_table->Hdr.HeaderSize);
398
6d2010ae 399 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
400 system_table->Hdr.CRC32 = hdr_cksum;
401 if (cksum != hdr_cksum) {
402 kprintf("Bad EFI system table checksum\n");
403 break;
404 }
405
b0d623f7
A
406 gPEEFISystemTable = system_table;
407
b0d623f7
A
408 if (!cpu_mode_is64bit()) {
409 kprintf("Skipping 64-bit EFI runtime services for 32-bit legacy mode\n");
410 break;
411 }
0c530ab8 412
b0d623f7
A
413 if(system_table->RuntimeServices == 0) {
414 kprintf("No runtime table present\n");
415 break;
416 }
6d2010ae 417 DPRINTF("RuntimeServices table at 0x%qx\n", system_table->RuntimeServices);
b0d623f7
A
418 // 64-bit virtual address is OK for 64-bit EFI and 64/32-bit kernel.
419 runtime = (EFI_RUNTIME_SERVICES_64 *) (uintptr_t)system_table->RuntimeServices;
6d2010ae 420 DPRINTF("Checking runtime services table %p\n", runtime);
b0d623f7
A
421 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
422 kprintf("Bad EFI runtime table signature\n");
423 break;
424 }
0c530ab8
A
425
426 // Verify signature of runtime services table
427 hdr_cksum = runtime->Hdr.CRC32;
428 runtime->Hdr.CRC32 = 0;
429 cksum = crc32(0L, runtime, runtime->Hdr.HeaderSize);
430
6d2010ae 431 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
432 runtime->Hdr.CRC32 = hdr_cksum;
433 if (cksum != hdr_cksum) {
434 kprintf("Bad EFI runtime table checksum\n");
435 break;
436 }
437
438 gPEEFIRuntimeServices = runtime;
439 }
440 while (FALSE);
441}
442
443static void
b0d623f7 444efi_set_tables_32(EFI_SYSTEM_TABLE_32 * system_table)
0c530ab8 445{
b0d623f7 446 EFI_RUNTIME_SERVICES_32 *runtime;
0c530ab8
A
447 uint32_t hdr_cksum;
448 uint32_t cksum;
449
6d2010ae 450 DPRINTF("Processing 32-bit EFI tables at %p\n", system_table);
0c530ab8 451 do {
6d2010ae
A
452 DPRINTF("Header:\n");
453 DPRINTF(" Signature: 0x%016llx\n", system_table->Hdr.Signature);
454 DPRINTF(" Revision: 0x%08x\n", system_table->Hdr.Revision);
455 DPRINTF(" HeaderSize: 0x%08x\n", system_table->Hdr.HeaderSize);
456 DPRINTF(" CRC32: 0x%08x\n", system_table->Hdr.CRC32);
457 DPRINTF("RuntimeServices: 0x%08x\n", system_table->RuntimeServices);
0c530ab8 458 if (system_table->Hdr.Signature != EFI_SYSTEM_TABLE_SIGNATURE) {
b0d623f7 459 kprintf("Bad EFI system table signature\n");
0c530ab8
A
460 break;
461 }
462 // Verify signature of the system table
463 hdr_cksum = system_table->Hdr.CRC32;
464 system_table->Hdr.CRC32 = 0;
6d2010ae 465 DPRINTF("System table at %p HeaderSize 0x%x\n", system_table, system_table->Hdr.HeaderSize);
0c530ab8
A
466 cksum = crc32(0L, system_table, system_table->Hdr.HeaderSize);
467
6d2010ae 468 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
469 system_table->Hdr.CRC32 = hdr_cksum;
470 if (cksum != hdr_cksum) {
471 kprintf("Bad EFI system table checksum\n");
472 break;
473 }
474
b0d623f7 475 gPEEFISystemTable = system_table;
0c530ab8 476
b0d623f7
A
477 if(system_table->RuntimeServices == 0) {
478 kprintf("No runtime table present\n");
479 break;
480 }
6d2010ae 481 DPRINTF("RuntimeServices table at 0x%x\n", system_table->RuntimeServices);
b0d623f7 482 // 32-bit virtual address is OK for 32-bit EFI and 32-bit kernel.
6d2010ae
A
483 // For a 64-bit kernel, booter provides a virtual address mod 4G
484 runtime = (EFI_RUNTIME_SERVICES_32 *)
485#ifdef __x86_64__
486 (system_table->RuntimeServices | VM_MIN_KERNEL_ADDRESS);
487#else
488 system_table->RuntimeServices;
489#endif
490 DPRINTF("Runtime table addressed at %p\n", runtime);
b0d623f7
A
491 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
492 kprintf("Bad EFI runtime table signature\n");
493 break;
494 }
0c530ab8
A
495
496 // Verify signature of runtime services table
497 hdr_cksum = runtime->Hdr.CRC32;
498 runtime->Hdr.CRC32 = 0;
499 cksum = crc32(0L, runtime, runtime->Hdr.HeaderSize);
500
6d2010ae 501 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
502 runtime->Hdr.CRC32 = hdr_cksum;
503 if (cksum != hdr_cksum) {
504 kprintf("Bad EFI runtime table checksum\n");
505 break;
506 }
507
6d2010ae
A
508 DPRINTF("Runtime functions\n");
509 DPRINTF(" GetTime : 0x%x\n", runtime->GetTime);
510 DPRINTF(" SetTime : 0x%x\n", runtime->SetTime);
511 DPRINTF(" GetWakeupTime : 0x%x\n", runtime->GetWakeupTime);
512 DPRINTF(" SetWakeupTime : 0x%x\n", runtime->SetWakeupTime);
513 DPRINTF(" SetVirtualAddressMap : 0x%x\n", runtime->SetVirtualAddressMap);
514 DPRINTF(" ConvertPointer : 0x%x\n", runtime->ConvertPointer);
515 DPRINTF(" GetVariable : 0x%x\n", runtime->GetVariable);
516 DPRINTF(" GetNextVariableName : 0x%x\n", runtime->GetNextVariableName);
517 DPRINTF(" SetVariable : 0x%x\n", runtime->SetVariable);
518 DPRINTF(" GetNextHighMonotonicCount: 0x%x\n", runtime->GetNextHighMonotonicCount);
519 DPRINTF(" ResetSystem : 0x%x\n", runtime->ResetSystem);
520
0c530ab8
A
521 gPEEFIRuntimeServices = runtime;
522 }
523 while (FALSE);
524}
525
526
527/* Map in EFI runtime areas. */
528static void
529efi_init(void)
530{
531 boot_args *args = (boot_args *)PE_state.bootArgs;
532
533 kprintf("Initializing EFI runtime services\n");
534
535 do
536 {
2d21ac55 537 vm_offset_t vm_size, vm_addr;
0c530ab8
A
538 vm_map_offset_t phys_addr;
539 EfiMemoryRange *mptr;
540 unsigned int msize, mcount;
541 unsigned int i;
542
543 msize = args->MemoryMapDescriptorSize;
544 mcount = args->MemoryMapSize / msize;
545
6d2010ae
A
546 DPRINTF("efi_init() kernel base: 0x%x size: 0x%x\n",
547 args->kaddr, args->ksize);
548 DPRINTF(" efiSystemTable physical: 0x%x virtual: %p\n",
549 args->efiSystemTable,
550 (void *) ml_static_ptovirt(args->efiSystemTable));
551 DPRINTF(" efiRuntimeServicesPageStart: 0x%x\n",
552 args->efiRuntimeServicesPageStart);
553 DPRINTF(" efiRuntimeServicesPageCount: 0x%x\n",
554 args->efiRuntimeServicesPageCount);
555 DPRINTF(" efiRuntimeServicesVirtualPageStart: 0x%016llx\n",
556 args->efiRuntimeServicesVirtualPageStart);
b0d623f7 557 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
0c530ab8
A
558 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
559 if (((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) ) {
b0d623f7 560 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
0c530ab8 561 vm_addr = (vm_offset_t) mptr->VirtualStart;
6d2010ae
A
562#ifdef __x86_64__
563 /* For K64 on EFI32, shadow-map into high KVA */
564 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
565 vm_addr |= VM_MIN_KERNEL_ADDRESS;
b0d623f7 566#endif
6d2010ae
A
567 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
568 DPRINTF(" Type: %x phys: %p EFIv: %p kv: %p size: %p\n",
569 mptr->Type,
570 (void *) (uintptr_t) phys_addr,
571 (void *) (uintptr_t) mptr->VirtualStart,
572 (void *) vm_addr,
573 (void *) vm_size);
574 pmap_map(vm_addr, phys_addr, phys_addr + round_page(vm_size),
0c530ab8
A
575 (mptr->Type == kEfiRuntimeServicesCode) ? VM_PROT_READ | VM_PROT_EXECUTE : VM_PROT_READ|VM_PROT_WRITE,
576 (mptr->Type == EfiMemoryMappedIO) ? VM_WIMG_IO : VM_WIMG_USE_DEFAULT);
577 }
578 }
579
6d2010ae 580 if (args->Version != kBootArgsVersion2)
b0d623f7 581 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
0c530ab8
A
582
583 kprintf("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
b0d623f7
A
584 if (args->efiMode == kBootArgsEfiMode64) {
585 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8 586 } else {
b0d623f7 587 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8
A
588 }
589 }
590 while (FALSE);
591
592 return;
593}
594
595/* Remap EFI runtime areas. */
596void
597hibernate_newruntime_map(void * map, vm_size_t map_size, uint32_t system_table_offset)
598{
599 boot_args *args = (boot_args *)PE_state.bootArgs;
600
601 kprintf("Reinitializing EFI runtime services\n");
602
0c530ab8
A
603 do
604 {
2d21ac55 605 vm_offset_t vm_size, vm_addr;
0c530ab8
A
606 vm_map_offset_t phys_addr;
607 EfiMemoryRange *mptr;
608 unsigned int msize, mcount;
609 unsigned int i;
610
611 gPEEFISystemTable = 0;
612 gPEEFIRuntimeServices = 0;
613
614 system_table_offset += ptoa_32(args->efiRuntimeServicesPageStart);
615
2d21ac55
A
616 kprintf("Old system table 0x%x, new 0x%x\n",
617 (uint32_t)args->efiSystemTable, system_table_offset);
0c530ab8 618
2d21ac55 619 args->efiSystemTable = system_table_offset;
0c530ab8
A
620
621 kprintf("Old map:\n");
622 msize = args->MemoryMapDescriptorSize;
623 mcount = args->MemoryMapSize / msize;
b0d623f7 624 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
0c530ab8
A
625 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
626 if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
627
b0d623f7 628 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
0c530ab8 629 vm_addr = (vm_offset_t) mptr->VirtualStart;
6d2010ae
A
630#ifdef __x86_64__
631 /* K64 on EFI32 */
632 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
633 vm_addr |= VM_MIN_KERNEL_ADDRESS;
634#endif
0c530ab8
A
635 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
636
b0d623f7 637 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
0c530ab8
A
638 }
639 }
640
641 pmap_remove(kernel_pmap, i386_ptob(args->efiRuntimeServicesPageStart),
642 i386_ptob(args->efiRuntimeServicesPageStart + args->efiRuntimeServicesPageCount));
643
644 kprintf("New map:\n");
645 msize = args->MemoryMapDescriptorSize;
b0d623f7 646 mcount = (unsigned int )(map_size / msize);
0c530ab8
A
647 mptr = map;
648 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
649 if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
650
b0d623f7 651 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
0c530ab8 652 vm_addr = (vm_offset_t) mptr->VirtualStart;
6d2010ae
A
653#ifdef __x86_64__
654 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
655 vm_addr |= VM_MIN_KERNEL_ADDRESS;
656#endif
0c530ab8
A
657 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
658
b0d623f7 659 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
0c530ab8 660
6d2010ae 661 pmap_map(vm_addr, phys_addr, phys_addr + round_page(vm_size),
0c530ab8
A
662 (mptr->Type == kEfiRuntimeServicesCode) ? VM_PROT_READ | VM_PROT_EXECUTE : VM_PROT_READ|VM_PROT_WRITE,
663 (mptr->Type == EfiMemoryMappedIO) ? VM_WIMG_IO : VM_WIMG_USE_DEFAULT);
664 }
665 }
666
6d2010ae 667 if (args->Version != kBootArgsVersion2)
b0d623f7 668 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
0c530ab8
A
669
670 kprintf("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
b0d623f7
A
671 if (args->efiMode == kBootArgsEfiMode64) {
672 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8 673 } else {
b0d623f7 674 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8
A
675 }
676 }
677 while (FALSE);
678
679 kprintf("Done reinitializing EFI runtime services\n");
680
681 return;
682}
683
1c79356b
A
684/*
685 * Find devices. The system is alive.
686 */
687void
688machine_init(void)
689{
0c530ab8
A
690 /* Ensure panic buffer is initialized. */
691 debug_log_init();
692
1c79356b
A
693 /*
694 * Display CPU identification
695 */
0c530ab8
A
696 cpuid_cpu_display("CPU identification");
697 cpuid_feature_display("CPU features");
698 cpuid_extfeature_display("CPU extended features");
1c79356b 699
0c530ab8
A
700 /*
701 * Initialize EFI runtime services.
702 */
703 efi_init();
55e303ae 704
55e303ae 705 smp_init();
1c79356b
A
706
707 /*
708 * Set up to use floating point.
709 */
710 init_fpu();
711
1c79356b
A
712 /*
713 * Configure clock devices.
714 */
715 clock_config();
91447636 716
6d2010ae 717#if CONFIG_MTRR
91447636
A
718 /*
719 * Initialize MTRR from boot processor.
720 */
721 mtrr_init();
722
723 /*
724 * Set up PAT for boot processor.
725 */
726 pat_init();
6d2010ae 727#endif
91447636
A
728
729 /*
b0d623f7 730 * Free lowmem pages and complete other setup
91447636 731 */
b0d623f7 732 pmap_lowmem_finalize();
1c79356b
A
733}
734
735/*
736 * Halt a cpu.
737 */
738void
739halt_cpu(void)
740{
741 halt_all_cpus(FALSE);
742}
743
744int reset_mem_on_reboot = 1;
745
746/*
747 * Halt the system or reboot.
748 */
749void
9bccf70c 750halt_all_cpus(boolean_t reboot)
1c79356b 751{
55e303ae 752 if (reboot) {
55e303ae
A
753 printf("MACH Reboot\n");
754 PEHaltRestart( kPERestartCPU );
755 } else {
756 printf("CPU halted\n");
757 PEHaltRestart( kPEHaltCPU );
1c79356b 758 }
55e303ae 759 while(1);
1c79356b
A
760}
761
2d21ac55 762
0c530ab8
A
763/* Issue an I/O port read if one has been requested - this is an event logic
764 * analyzers can use as a trigger point.
765 */
766
767void
768panic_io_port_read(void) {
769 if (panic_io_port)
770 (void)inb(panic_io_port);
771}
772
773/* For use with the MP rendezvous mechanism
774 */
775
6d2010ae
A
776uint64_t panic_restart_timeout = ~(0ULL);
777
0c530ab8 778static void
6d2010ae 779machine_halt_cpu(void) {
0c530ab8 780 panic_io_port_read();
6d2010ae
A
781
782 if (panic_restart_timeout != ~(0ULL)) {
783 uint64_t deadline = mach_absolute_time() + panic_restart_timeout;
784 while (mach_absolute_time() < deadline) {
785 cpu_pause();
786 }
787 kprintf("Invoking PE_halt_restart\n");
788 /* Attempt restart via ACPI RESET_REG; at the time of this
789 * writing, this is routine is chained through AppleSMC->
790 * AppleACPIPlatform
791 */
792 if (PE_halt_restart)
793 (*PE_halt_restart)(kPERestartCPU);
794 }
2d21ac55 795 pmCPUHalt(PM_HALT_DEBUG);
1c79356b
A
796}
797
798void
799Debugger(
800 const char *message)
801{
0c530ab8
A
802 unsigned long pi_size = 0;
803 void *stackptr;
6d2010ae 804 int cn = cpu_number();
91447636 805
0c530ab8 806 hw_atomic_add(&debug_mode, 1);
91447636
A
807 if (!panic_is_inited) {
808 postcode(PANIC_HLT);
809 asm("hlt");
810 }
811
1c79356b 812 printf("Debugger called: <%s>\n", message);
91447636 813 kprintf("Debugger called: <%s>\n", message);
1c79356b 814
0c530ab8
A
815 /*
816 * Skip the graphical panic box if no panic string.
817 * This is the case if we're being called from
818 * host_reboot(,HOST_REBOOT_DEBUGGER)
819 * as a quiet way into the debugger.
820 */
821
822 if (panicstr) {
823 disable_preemption();
824
825/* Issue an I/O port read if one has been requested - this is an event logic
826 * analyzers can use as a trigger point.
827 */
828 panic_io_port_read();
829
830 /* Obtain current frame pointer */
b0d623f7 831#if defined (__i386__)
0c530ab8 832 __asm__ volatile("movl %%ebp, %0" : "=m" (stackptr));
b0d623f7
A
833#elif defined (__x86_64__)
834 __asm__ volatile("movq %%rbp, %0" : "=m" (stackptr));
835#endif
0c530ab8
A
836
837 /* Print backtrace - callee is internally synchronized */
6d2010ae 838 panic_i386_backtrace(stackptr, ((panic_double_fault_cpu == cn) ? 80: 48), NULL, FALSE, NULL);
0c530ab8
A
839
840 /* everything should be printed now so copy to NVRAM
841 */
842
843 if( debug_buf_size > 0) {
2d21ac55
A
844 /* Optionally sync the panic log, if any, to NVRAM
845 * This is the default.
846 */
847 if (commit_paniclog_to_nvram) {
0c530ab8 848 unsigned int bufpos;
935ed37a 849 uintptr_t cr0;
b0d623f7
A
850
851 debug_putc(0);
0c530ab8
A
852
853 /* Now call the compressor */
854 /* XXX Consider using the WKdm compressor in the
855 * future, rather than just packing - would need to
856 * be co-ordinated with crashreporter, which decodes
2d21ac55
A
857 * this post-restart. The compressor should be
858 * capable of in-place compression.
0c530ab8 859 */
2d21ac55
A
860 bufpos = packA(debug_buf,
861 (unsigned int) (debug_buf_ptr - debug_buf), debug_buf_size);
0c530ab8
A
862 /* If compression was successful,
863 * use the compressed length
864 */
2d21ac55
A
865 pi_size = bufpos ? bufpos : (unsigned) (debug_buf_ptr - debug_buf);
866
0c530ab8
A
867 /* Save panic log to non-volatile store
868 * Panic info handler must truncate data that is
869 * too long for this platform.
870 * This call must save data synchronously,
871 * since we can subsequently halt the system.
872 */
b0d623f7 873
6d2010ae 874
935ed37a
A
875/* The following sequence is a workaround for:
876 * <rdar://problem/5915669> SnowLeopard10A67: AppleEFINVRAM should not invoke
877 * any routines that use floating point (MMX in this case) when saving panic
878 * logs to nvram/flash.
879 */
880 cr0 = get_cr0();
881 clear_ts();
6d2010ae
A
882
883 kprintf("Attempting to commit panic log to NVRAM\n");
b0d623f7
A
884 pi_size = PESavePanicInfo((unsigned char *)debug_buf,
885 (uint32_t)pi_size );
935ed37a 886 set_cr0(cr0);
6d2010ae 887
2d21ac55
A
888 /* Uncompress in-place, to permit examination of
889 * the panic log by debuggers.
890 */
891
892 if (bufpos) {
893 unpackA(debug_buf, bufpos);
894 }
0c530ab8
A
895 }
896 }
b7266188
A
897
898 /* If the user won't be able to read the dialog,
899 * don't bother trying to show it
900 */
901 if (!PE_reboot_on_panic())
902 draw_panic_dialog();
0c530ab8
A
903
904 if (!panicDebugging) {
6d2010ae 905 unsigned cnum;
0c530ab8
A
906 /* Clear the MP rendezvous function lock, in the event
907 * that a panic occurred while in that codepath.
908 */
909 mp_rendezvous_break_lock();
b7266188 910 if (PE_reboot_on_panic()) {
6d2010ae
A
911 if (PE_halt_restart)
912 (*PE_halt_restart)(kPERestartCPU);
b7266188
A
913 }
914
6d2010ae
A
915 /* Non-maskably interrupt all other processors
916 * If a restart timeout is specified, this processor
917 * will attempt a restart.
0c530ab8 918 */
6d2010ae
A
919 kprintf("Invoking machine_halt_cpu on CPU %d\n", cn);
920 for (cnum = 0; cnum < real_ncpus; cnum++) {
921 if (cnum != (unsigned) cn) {
922 cpu_NMI_interrupt(cnum);
923 }
924 }
925 machine_halt_cpu();
0c530ab8
A
926 /* NOT REACHED */
927 }
928 }
55e303ae 929
1c79356b 930 __asm__("int3");
0c530ab8 931 hw_atomic_sub(&debug_mode, 1);
1c79356b
A
932}
933
1c79356b 934char *
91447636 935machine_boot_info(char *buf, __unused vm_size_t size)
1c79356b
A
936{
937 *buf ='\0';
938 return buf;
939}
940
0c530ab8
A
941/* Routines for address - symbol translation. Not called unless the "keepsyms"
942 * boot-arg is supplied.
943 */
944
945static int
6d2010ae 946panic_print_macho_symbol_name(kernel_mach_header_t *mh, vm_address_t search, const char *module_name)
0c530ab8 947{
b0d623f7 948 kernel_nlist_t *sym = NULL;
0c530ab8 949 struct load_command *cmd;
b0d623f7 950 kernel_segment_command_t *orig_ts = NULL, *orig_le = NULL;
0c530ab8
A
951 struct symtab_command *orig_st = NULL;
952 unsigned int i;
953 char *strings, *bestsym = NULL;
954 vm_address_t bestaddr = 0, diff, curdiff;
b0d623f7
A
955
956 /* Assume that if it's loaded and linked into the kernel, it's a valid Mach-O */
0c530ab8
A
957
958 cmd = (struct load_command *) &mh[1];
959 for (i = 0; i < mh->ncmds; i++) {
b0d623f7
A
960 if (cmd->cmd == LC_SEGMENT_KERNEL) {
961 kernel_segment_command_t *orig_sg = (kernel_segment_command_t *) cmd;
0c530ab8 962
2d21ac55
A
963 if (strncmp(SEG_TEXT, orig_sg->segname,
964 sizeof(orig_sg->segname)) == 0)
0c530ab8 965 orig_ts = orig_sg;
2d21ac55
A
966 else if (strncmp(SEG_LINKEDIT, orig_sg->segname,
967 sizeof(orig_sg->segname)) == 0)
0c530ab8 968 orig_le = orig_sg;
2d21ac55
A
969 else if (strncmp("", orig_sg->segname,
970 sizeof(orig_sg->segname)) == 0)
6d2010ae 971 orig_ts = orig_sg; /* pre-Barolo i386 kexts have a single unnamed segment */
0c530ab8
A
972 }
973 else if (cmd->cmd == LC_SYMTAB)
974 orig_st = (struct symtab_command *) cmd;
975
b0d623f7 976 cmd = (struct load_command *) ((uintptr_t) cmd + cmd->cmdsize);
0c530ab8
A
977 }
978
979 if ((orig_ts == NULL) || (orig_st == NULL) || (orig_le == NULL))
980 return 0;
981
0c530ab8
A
982 if ((search < orig_ts->vmaddr) ||
983 (search >= orig_ts->vmaddr + orig_ts->vmsize)) {
984 /* search out of range for this mach header */
985 return 0;
986 }
987
b0d623f7
A
988 sym = (kernel_nlist_t *)(uintptr_t)(orig_le->vmaddr + orig_st->symoff - orig_le->fileoff);
989 strings = (char *)(uintptr_t)(orig_le->vmaddr + orig_st->stroff - orig_le->fileoff);
0c530ab8
A
990 diff = search;
991
992 for (i = 0; i < orig_st->nsyms; i++) {
b0d623f7
A
993 if (sym[i].n_type & N_STAB) continue;
994
0c530ab8
A
995 if (sym[i].n_value <= search) {
996 curdiff = search - (vm_address_t)sym[i].n_value;
997 if (curdiff < diff) {
998 diff = curdiff;
999 bestaddr = sym[i].n_value;
1000 bestsym = strings + sym[i].n_un.n_strx;
1001 }
1002 }
1003 }
1004
1005 if (bestsym != NULL) {
1006 if (diff != 0) {
6d2010ae 1007 kdb_printf("%s : %s + 0x%lx", module_name, bestsym, (unsigned long)diff);
0c530ab8 1008 } else {
6d2010ae 1009 kdb_printf("%s : %s", module_name, bestsym);
0c530ab8
A
1010 }
1011 return 1;
1012 }
1013 return 0;
1014}
1015
1016extern kmod_info_t * kmod; /* the list of modules */
1017
1018static void
1019panic_print_kmod_symbol_name(vm_address_t search)
1020{
6d2010ae
A
1021 u_int i;
1022
1023 if (gLoadedKextSummaries == NULL)
1024 return;
1025 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
1026 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
1027
1028 if ((search >= summary->address) &&
1029 (search < (summary->address + summary->size)))
1030 {
1031 kernel_mach_header_t *header = (kernel_mach_header_t *)(uintptr_t) summary->address;
1032 if (panic_print_macho_symbol_name(header, search, summary->name) == 0) {
1033 kdb_printf("%s + %llu", summary->name, (unsigned long)search - summary->address);
1034 }
0c530ab8 1035 break;
6d2010ae 1036 }
0c530ab8
A
1037 }
1038}
1039
0c530ab8
A
1040static void
1041panic_print_symbol_name(vm_address_t search)
1042{
1043 /* try searching in the kernel */
6d2010ae 1044 if (panic_print_macho_symbol_name(&_mh_execute_header, search, "mach_kernel") == 0) {
0c530ab8
A
1045 /* that failed, now try to search for the right kext */
1046 panic_print_kmod_symbol_name(search);
1047 }
1048}
1049
1050/* Generate a backtrace, given a frame pointer - this routine
1051 * should walk the stack safely. The trace is appended to the panic log
1052 * and conditionally, to the console. If the trace contains kernel module
1053 * addresses, display the module name, load address and dependencies.
1054 */
1055
1056#define DUMPFRAMES 32
1057#define PBT_TIMEOUT_CYCLES (5 * 1000 * 1000 * 1000ULL)
1058void
935ed37a 1059panic_i386_backtrace(void *_frame, int nframes, const char *msg, boolean_t regdump, x86_saved_state_t *regs)
0c530ab8
A
1060{
1061 cframe_t *frame = (cframe_t *)_frame;
1062 vm_offset_t raddrs[DUMPFRAMES];
935ed37a 1063 vm_offset_t PC = 0;
0c530ab8
A
1064 int frame_index;
1065 volatile uint32_t *ppbtcnt = &pbtcnt;
1066 uint64_t bt_tsc_timeout;
1067 boolean_t keepsyms = FALSE;
6d2010ae 1068 int cn = cpu_number();
0c530ab8 1069
6d2010ae 1070 if(pbtcpu != cn) {
0c530ab8
A
1071 hw_atomic_add(&pbtcnt, 1);
1072 /* Spin on print backtrace lock, which serializes output
1073 * Continue anyway if a timeout occurs.
1074 */
6d2010ae
A
1075 hw_lock_to(&pbtlock, LockTimeOutTSC*2);
1076 pbtcpu = cn;
0c530ab8
A
1077 }
1078
593a1d5f 1079 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms));
0c530ab8 1080
935ed37a 1081 if (msg != NULL) {
b0d623f7 1082 kdb_printf("%s", msg);
935ed37a
A
1083 }
1084
1085 if ((regdump == TRUE) && (regs != NULL)) {
b0d623f7
A
1086#if defined(__x86_64__)
1087 x86_saved_state64_t *ss64p = saved_state64(regs);
1088 kdb_printf(
1089 "RAX: 0x%016llx, RBX: 0x%016llx, RCX: 0x%016llx, RDX: 0x%016llx\n"
1090 "RSP: 0x%016llx, RBP: 0x%016llx, RSI: 0x%016llx, RDI: 0x%016llx\n"
1091 "R8: 0x%016llx, R9: 0x%016llx, R10: 0x%016llx, R11: 0x%016llx\n"
1092 "R12: 0x%016llx, R13: 0x%016llx, R14: 0x%016llx, R15: 0x%016llx\n"
1093 "RFL: 0x%016llx, RIP: 0x%016llx, CS: 0x%016llx, SS: 0x%016llx\n",
1094 ss64p->rax, ss64p->rbx, ss64p->rcx, ss64p->rdx,
1095 ss64p->isf.rsp, ss64p->rbp, ss64p->rsi, ss64p->rdi,
1096 ss64p->r8, ss64p->r9, ss64p->r10, ss64p->r11,
1097 ss64p->r12, ss64p->r13, ss64p->r14, ss64p->r15,
1098 ss64p->isf.rflags, ss64p->isf.rip, ss64p->isf.cs,
1099 ss64p->isf.ss);
1100 PC = ss64p->isf.rip;
1101#else
935ed37a 1102 x86_saved_state32_t *ss32p = saved_state32(regs);
935ed37a
A
1103 kdb_printf(
1104 "EAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x\n"
1105 "CR2: 0x%08x, EBP: 0x%08x, ESI: 0x%08x, EDI: 0x%08x\n"
1106 "EFL: 0x%08x, EIP: 0x%08x, CS: 0x%08x, DS: 0x%08x\n",
1107 ss32p->eax,ss32p->ebx,ss32p->ecx,ss32p->edx,
1108 ss32p->cr2,ss32p->ebp,ss32p->esi,ss32p->edi,
1109 ss32p->efl,ss32p->eip,ss32p->cs, ss32p->ds);
1110 PC = ss32p->eip;
b0d623f7 1111#endif
935ed37a
A
1112 }
1113
1114 kdb_printf("Backtrace (CPU %d), "
b0d623f7 1115#if PRINT_ARGS_FROM_STACK_FRAME
6d2010ae 1116 "Frame : Return Address (4 potential args on stack)\n", cn);
b0d623f7 1117#else
6d2010ae 1118 "Frame : Return Address\n", cn);
b0d623f7 1119#endif
0c530ab8
A
1120
1121 for (frame_index = 0; frame_index < nframes; frame_index++) {
1122 vm_offset_t curframep = (vm_offset_t) frame;
1123
1124 if (!curframep)
1125 break;
1126
1127 if (curframep & 0x3) {
1128 kdb_printf("Unaligned frame\n");
1129 goto invalid;
1130 }
1131
1132 if (!kvtophys(curframep) ||
6d2010ae 1133 !kvtophys(curframep + sizeof(cframe_t) - 1)) {
0c530ab8
A
1134 kdb_printf("No mapping exists for frame pointer\n");
1135 goto invalid;
1136 }
1137
b0d623f7 1138 kdb_printf("%p : 0x%lx ", frame, frame->caller);
0c530ab8
A
1139 if (frame_index < DUMPFRAMES)
1140 raddrs[frame_index] = frame->caller;
1141
b0d623f7 1142#if PRINT_ARGS_FROM_STACK_FRAME
0c530ab8 1143 if (kvtophys((vm_offset_t)&(frame->args[3])))
b0d623f7 1144 kdb_printf("(0x%x 0x%x 0x%x 0x%x) ",
0c530ab8
A
1145 frame->args[0], frame->args[1],
1146 frame->args[2], frame->args[3]);
b0d623f7 1147#endif
0c530ab8
A
1148
1149 /* Display address-symbol translation only if the "keepsyms"
1150 * boot-arg is suppplied, since we unload LINKEDIT otherwise.
1151 * This routine is potentially unsafe; also, function
1152 * boundary identification is unreliable after a strip -x.
1153 */
1154 if (keepsyms)
1155 panic_print_symbol_name((vm_address_t)frame->caller);
1156
b0d623f7
A
1157 kdb_printf("\n");
1158
0c530ab8
A
1159 frame = frame->prev;
1160 }
1161
1162 if (frame_index >= nframes)
1163 kdb_printf("\tBacktrace continues...\n");
1164
1165 goto out;
1166
1167invalid:
2d21ac55 1168 kdb_printf("Backtrace terminated-invalid frame pointer %p\n",frame);
0c530ab8
A
1169out:
1170
1171 /* Identify kernel modules in the backtrace and display their
1172 * load addresses and dependencies. This routine should walk
1173 * the kmod list safely.
1174 */
1175 if (frame_index)
b0d623f7 1176 kmod_panic_dump((vm_offset_t *)&raddrs[0], frame_index);
0c530ab8 1177
935ed37a 1178 if (PC != 0)
b0d623f7 1179 kmod_panic_dump(&PC, 1);
935ed37a 1180
2d21ac55 1181 panic_display_system_configuration();
c910b4d9 1182
0c530ab8
A
1183 /* Release print backtrace lock, to permit other callers in the
1184 * event of panics on multiple processors.
1185 */
1186 hw_lock_unlock(&pbtlock);
1187 hw_atomic_sub(&pbtcnt, 1);
1188 /* Wait for other processors to complete output
1189 * Timeout and continue after PBT_TIMEOUT_CYCLES.
1190 */
1191 bt_tsc_timeout = rdtsc64() + PBT_TIMEOUT_CYCLES;
1192 while(*ppbtcnt && (rdtsc64() < bt_tsc_timeout));
1193}