]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/AT386/model_dep.c
xnu-2050.18.24.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
A
70
71#include <mach/i386/vm_param.h>
72
73#include <string.h>
74#include <mach/vm_param.h>
75#include <mach/vm_prot.h>
76#include <mach/machine.h>
77#include <mach/time_value.h>
1c79356b
A
78#include <kern/spl.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>
1c79356b 84#include <kern/cpu_data.h>
91447636 85#include <kern/machine.h>
b0d623f7
A
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>
1c79356b 94#include <i386/fpu.h>
6d2010ae
A
95#include <i386/machine_cpu.h>
96#include <i386/pmap.h>
97#if CONFIG_MTRR
91447636 98#include <i386/mtrr.h>
6d2010ae
A
99#endif
100#include <i386/ucode.h>
0c530ab8 101#include <i386/pmCPU.h>
0c530ab8 102#include <architecture/i386/pio.h> /* inb() */
55e303ae 103#include <pexpert/i386/boot.h>
1c79356b 104
0c530ab8
A
105#include <vm/pmap.h>
106#include <vm/vm_map.h>
107#include <vm/vm_kern.h>
108
9bccf70c 109#include <IOKit/IOPlatformExpert.h>
0c530ab8
A
110#include <IOKit/IOHibernatePrivate.h>
111
112#include <pexpert/i386/efi.h>
113
114#include <kern/thread.h>
316670eb 115#include <kern/sched.h>
0c530ab8
A
116#include <mach-o/loader.h>
117#include <mach-o/nlist.h>
9bccf70c 118
b0d623f7 119#include <libkern/kernel_mach_header.h>
6d2010ae
A
120#include <libkern/OSKextLibPrivate.h>
121
7ddcb079
A
122#if DEBUG
123#define DPRINTF(x...) kprintf(x)
124#else
6d2010ae 125#define DPRINTF(x...)
7ddcb079 126#endif
91447636 127
55e303ae 128static void machine_conf(void);
1c79356b 129
91447636
A
130extern int max_unsafe_quanta;
131extern int max_poll_quanta;
91447636
A
132extern unsigned int panic_is_inited;
133
0c530ab8
A
134int db_run_mode;
135
0c530ab8
A
136volatile int pbtcpu = -1;
137hw_lock_data_t pbtlock; /* backtrace print lock */
138uint32_t pbtcnt = 0;
139
6d2010ae
A
140volatile int panic_double_fault_cpu = -1;
141
b0d623f7
A
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
146#else
147#error unsupported architecture
148#endif
149
0c530ab8
A
150typedef struct _cframe_t {
151 struct _cframe_t *prev;
b0d623f7
A
152 uintptr_t caller;
153#if PRINT_ARGS_FROM_STACK_FRAME
0c530ab8 154 unsigned args[0];
b0d623f7 155#endif
0c530ab8
A
156} cframe_t;
157
2d21ac55
A
158static unsigned panic_io_port;
159static unsigned commit_paniclog_to_nvram;
0c530ab8 160
b7266188 161unsigned int debug_boot_arg;
c910b4d9 162
1c79356b 163void
2d21ac55 164machine_startup(void)
1c79356b 165{
55e303ae 166 int boot_arg;
1c79356b 167
55e303ae
A
168#if 0
169 if( PE_get_hotkey( kPEControlKey ))
170 halt_in_debugger = halt_in_debugger ? 0 : 1;
1c79356b
A
171#endif
172
b7266188 173 if (PE_parse_boot_argn("debug", &debug_boot_arg, sizeof (debug_boot_arg))) {
6d2010ae 174 panicDebugging = TRUE;
b7266188
A
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;
b7266188
A
178 if (debug_boot_arg & DB_LOG_PI_SCRN) logPanicDataToScreen=TRUE;
179 } else {
180 debug_boot_arg = 0;
55e303ae 181 }
1c79356b 182
593a1d5f 183 if (!PE_parse_boot_argn("nvram_paniclog", &commit_paniclog_to_nvram, sizeof (commit_paniclog_to_nvram)))
2d21ac55
A
184 commit_paniclog_to_nvram = 1;
185
186 /*
187 * Entering the debugger will put the CPUs into a "safe"
188 * power mode.
189 */
593a1d5f 190 if (PE_parse_boot_argn("pmsafe_debug", &boot_arg, sizeof (boot_arg)))
2d21ac55
A
191 pmsafe_debug = boot_arg;
192
55e303ae
A
193#if NOTYET
194 hw_lock_init(&debugger_lock); /* initialize debugger lock */
6601e61a 195#endif
0c530ab8 196 hw_lock_init(&pbtlock); /* initialize print backtrace lock */
1c79356b 197
593a1d5f 198 if (PE_parse_boot_argn("preempt", &boot_arg, sizeof (boot_arg))) {
55e303ae 199 default_preemption_rate = boot_arg;
1c79356b 200 }
593a1d5f 201 if (PE_parse_boot_argn("unsafe", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
202 max_unsafe_quanta = boot_arg;
203 }
593a1d5f 204 if (PE_parse_boot_argn("poll", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
205 max_poll_quanta = boot_arg;
206 }
593a1d5f 207 if (PE_parse_boot_argn("yield", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
208 sched_poll_yield_shift = boot_arg;
209 }
0c530ab8
A
210/* The I/O port to issue a read from, in the event of a panic. Useful for
211 * triggering logic analyzers.
212 */
593a1d5f 213 if (PE_parse_boot_argn("panic_io_port", &boot_arg, sizeof (boot_arg))) {
0c530ab8
A
214 /*I/O ports range from 0 through 0xFFFF */
215 panic_io_port = boot_arg & 0xffff;
216 }
217
55e303ae
A
218 machine_conf();
219
220#if NOTYET
221 ml_thrm_init(); /* Start thermal monitoring on this processor */
1c79356b
A
222#endif
223
224 /*
225 * Start the system.
226 */
91447636
A
227 kernel_bootstrap();
228 /*NOTREACHED*/
1c79356b
A
229}
230
55e303ae
A
231
232static void
233machine_conf(void)
1c79356b 234{
b0d623f7 235 machine_info.memory_size = (typeof(machine_info.memory_size))mem_size;
1c79356b
A
236}
237
0c530ab8
A
238
239extern void *gPEEFIRuntimeServices;
240extern void *gPEEFISystemTable;
241
242/*-
243 * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
244 * code or tables extracted from it, as desired without restriction.
245 *
246 * First, the polynomial itself and its table of feedback terms. The
247 * polynomial is
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
249 *
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
253 * the MSB being 1
254 *
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
266 *
267 * The feedback terms table consists of 256, 32-bit entries. Notes
268 *
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
273 *
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
279 *
280 *
281 * CRC32 code derived from work by Gary S. Brown.
282 */
283
284static 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
328};
329
330static uint32_t
331crc32(uint32_t crc, const void *buf, size_t size)
332{
333 const uint8_t *p;
334
335 p = buf;
336 crc = crc ^ ~0U;
337
338 while (size--)
339 crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
340
341 return crc ^ ~0U;
342}
343
344static void
345efi_set_tables_64(EFI_SYSTEM_TABLE_64 * system_table)
346{
347 EFI_RUNTIME_SERVICES_64 *runtime;
348 uint32_t hdr_cksum;
349 uint32_t cksum;
350
6d2010ae 351 DPRINTF("Processing 64-bit EFI tables at %p\n", system_table);
0c530ab8 352 do {
6d2010ae
A
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);
0c530ab8
A
359 if (system_table->Hdr.Signature != EFI_SYSTEM_TABLE_SIGNATURE) {
360 kprintf("Bad EFI system table signature\n");
361 break;
362 }
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);
367
6d2010ae 368 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
369 system_table->Hdr.CRC32 = hdr_cksum;
370 if (cksum != hdr_cksum) {
371 kprintf("Bad EFI system table checksum\n");
372 break;
373 }
374
b0d623f7
A
375 gPEEFISystemTable = system_table;
376
b0d623f7
A
377 if (!cpu_mode_is64bit()) {
378 kprintf("Skipping 64-bit EFI runtime services for 32-bit legacy mode\n");
379 break;
380 }
0c530ab8 381
b0d623f7
A
382 if(system_table->RuntimeServices == 0) {
383 kprintf("No runtime table present\n");
384 break;
385 }
6d2010ae 386 DPRINTF("RuntimeServices table at 0x%qx\n", system_table->RuntimeServices);
b0d623f7
A
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;
6d2010ae 389 DPRINTF("Checking runtime services table %p\n", runtime);
b0d623f7
A
390 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
391 kprintf("Bad EFI runtime table signature\n");
392 break;
393 }
0c530ab8
A
394
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);
399
6d2010ae 400 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
401 runtime->Hdr.CRC32 = hdr_cksum;
402 if (cksum != hdr_cksum) {
403 kprintf("Bad EFI runtime table checksum\n");
404 break;
405 }
406
407 gPEEFIRuntimeServices = runtime;
408 }
409 while (FALSE);
410}
411
412static void
b0d623f7 413efi_set_tables_32(EFI_SYSTEM_TABLE_32 * system_table)
0c530ab8 414{
b0d623f7 415 EFI_RUNTIME_SERVICES_32 *runtime;
0c530ab8
A
416 uint32_t hdr_cksum;
417 uint32_t cksum;
418
6d2010ae 419 DPRINTF("Processing 32-bit EFI tables at %p\n", system_table);
0c530ab8 420 do {
6d2010ae
A
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);
0c530ab8 427 if (system_table->Hdr.Signature != EFI_SYSTEM_TABLE_SIGNATURE) {
b0d623f7 428 kprintf("Bad EFI system table signature\n");
0c530ab8
A
429 break;
430 }
431 // Verify signature of the system table
432 hdr_cksum = system_table->Hdr.CRC32;
433 system_table->Hdr.CRC32 = 0;
6d2010ae 434 DPRINTF("System table at %p HeaderSize 0x%x\n", system_table, system_table->Hdr.HeaderSize);
0c530ab8
A
435 cksum = crc32(0L, system_table, system_table->Hdr.HeaderSize);
436
6d2010ae 437 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
438 system_table->Hdr.CRC32 = hdr_cksum;
439 if (cksum != hdr_cksum) {
440 kprintf("Bad EFI system table checksum\n");
441 break;
442 }
443
b0d623f7 444 gPEEFISystemTable = system_table;
0c530ab8 445
b0d623f7
A
446 if(system_table->RuntimeServices == 0) {
447 kprintf("No runtime table present\n");
448 break;
449 }
6d2010ae 450 DPRINTF("RuntimeServices table at 0x%x\n", system_table->RuntimeServices);
b0d623f7 451 // 32-bit virtual address is OK for 32-bit EFI and 32-bit kernel.
6d2010ae
A
452 // For a 64-bit kernel, booter provides a virtual address mod 4G
453 runtime = (EFI_RUNTIME_SERVICES_32 *)
454#ifdef __x86_64__
455 (system_table->RuntimeServices | VM_MIN_KERNEL_ADDRESS);
456#else
457 system_table->RuntimeServices;
458#endif
459 DPRINTF("Runtime table addressed at %p\n", runtime);
b0d623f7
A
460 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
461 kprintf("Bad EFI runtime table signature\n");
462 break;
463 }
0c530ab8
A
464
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);
469
6d2010ae 470 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
0c530ab8
A
471 runtime->Hdr.CRC32 = hdr_cksum;
472 if (cksum != hdr_cksum) {
473 kprintf("Bad EFI runtime table checksum\n");
474 break;
475 }
476
6d2010ae
A
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);
489
0c530ab8
A
490 gPEEFIRuntimeServices = runtime;
491 }
492 while (FALSE);
493}
494
495
496/* Map in EFI runtime areas. */
497static void
498efi_init(void)
499{
500 boot_args *args = (boot_args *)PE_state.bootArgs;
501
502 kprintf("Initializing EFI runtime services\n");
503
504 do
505 {
2d21ac55 506 vm_offset_t vm_size, vm_addr;
0c530ab8
A
507 vm_map_offset_t phys_addr;
508 EfiMemoryRange *mptr;
509 unsigned int msize, mcount;
510 unsigned int i;
511
512 msize = args->MemoryMapDescriptorSize;
513 mcount = args->MemoryMapSize / msize;
514
6d2010ae
A
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);
b0d623f7 526 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
0c530ab8
A
527 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
528 if (((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) ) {
b0d623f7 529 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
0c530ab8 530 vm_addr = (vm_offset_t) mptr->VirtualStart;
6d2010ae
A
531#ifdef __x86_64__
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;
b0d623f7 535#endif
6d2010ae
A
536 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
537 DPRINTF(" Type: %x phys: %p EFIv: %p kv: %p size: %p\n",
538 mptr->Type,
539 (void *) (uintptr_t) phys_addr,
540 (void *) (uintptr_t) mptr->VirtualStart,
541 (void *) vm_addr,
542 (void *) vm_size);
7ddcb079 543 pmap_map_bd(vm_addr, phys_addr, phys_addr + round_page(vm_size),
0c530ab8
A
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);
546 }
547 }
548
6d2010ae 549 if (args->Version != kBootArgsVersion2)
b0d623f7 550 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
0c530ab8 551
7ddcb079 552 DPRINTF("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
b0d623f7
A
553 if (args->efiMode == kBootArgsEfiMode64) {
554 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8 555 } else {
b0d623f7 556 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8
A
557 }
558 }
559 while (FALSE);
560
561 return;
562}
563
564/* Remap EFI runtime areas. */
565void
566hibernate_newruntime_map(void * map, vm_size_t map_size, uint32_t system_table_offset)
567{
568 boot_args *args = (boot_args *)PE_state.bootArgs;
569
570 kprintf("Reinitializing EFI runtime services\n");
571
0c530ab8
A
572 do
573 {
2d21ac55 574 vm_offset_t vm_size, vm_addr;
0c530ab8
A
575 vm_map_offset_t phys_addr;
576 EfiMemoryRange *mptr;
577 unsigned int msize, mcount;
578 unsigned int i;
579
580 gPEEFISystemTable = 0;
581 gPEEFIRuntimeServices = 0;
582
583 system_table_offset += ptoa_32(args->efiRuntimeServicesPageStart);
584
2d21ac55
A
585 kprintf("Old system table 0x%x, new 0x%x\n",
586 (uint32_t)args->efiSystemTable, system_table_offset);
0c530ab8 587
2d21ac55 588 args->efiSystemTable = system_table_offset;
0c530ab8
A
589
590 kprintf("Old map:\n");
591 msize = args->MemoryMapDescriptorSize;
592 mcount = args->MemoryMapSize / msize;
b0d623f7 593 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
0c530ab8
A
594 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
595 if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
596
b0d623f7 597 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
0c530ab8 598 vm_addr = (vm_offset_t) mptr->VirtualStart;
6d2010ae
A
599#ifdef __x86_64__
600 /* K64 on EFI32 */
601 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
602 vm_addr |= VM_MIN_KERNEL_ADDRESS;
603#endif
0c530ab8
A
604 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
605
b0d623f7 606 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
0c530ab8
A
607 }
608 }
609
610 pmap_remove(kernel_pmap, i386_ptob(args->efiRuntimeServicesPageStart),
611 i386_ptob(args->efiRuntimeServicesPageStart + args->efiRuntimeServicesPageCount));
612
613 kprintf("New map:\n");
614 msize = args->MemoryMapDescriptorSize;
b0d623f7 615 mcount = (unsigned int )(map_size / msize);
0c530ab8
A
616 mptr = map;
617 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
618 if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
619
b0d623f7 620 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
0c530ab8 621 vm_addr = (vm_offset_t) mptr->VirtualStart;
6d2010ae
A
622#ifdef __x86_64__
623 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
624 vm_addr |= VM_MIN_KERNEL_ADDRESS;
625#endif
0c530ab8
A
626 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
627
b0d623f7 628 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
0c530ab8 629
6d2010ae 630 pmap_map(vm_addr, phys_addr, phys_addr + round_page(vm_size),
0c530ab8
A
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);
633 }
634 }
635
6d2010ae 636 if (args->Version != kBootArgsVersion2)
b0d623f7 637 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
0c530ab8
A
638
639 kprintf("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
b0d623f7
A
640 if (args->efiMode == kBootArgsEfiMode64) {
641 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8 642 } else {
b0d623f7 643 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
0c530ab8
A
644 }
645 }
646 while (FALSE);
647
648 kprintf("Done reinitializing EFI runtime services\n");
649
650 return;
651}
652
1c79356b
A
653/*
654 * Find devices. The system is alive.
655 */
656void
657machine_init(void)
658{
316670eb
A
659#if __x86_64__
660 /* Now with VM up, switch to dynamically allocated cpu data */
661 cpu_data_realloc();
662#endif
663
0c530ab8
A
664 /* Ensure panic buffer is initialized. */
665 debug_log_init();
666
1c79356b
A
667 /*
668 * Display CPU identification
669 */
0c530ab8
A
670 cpuid_cpu_display("CPU identification");
671 cpuid_feature_display("CPU features");
672 cpuid_extfeature_display("CPU extended features");
1c79356b 673
0c530ab8
A
674 /*
675 * Initialize EFI runtime services.
676 */
677 efi_init();
55e303ae 678
55e303ae 679 smp_init();
1c79356b
A
680
681 /*
682 * Set up to use floating point.
683 */
684 init_fpu();
685
1c79356b
A
686 /*
687 * Configure clock devices.
688 */
689 clock_config();
91447636 690
6d2010ae 691#if CONFIG_MTRR
91447636
A
692 /*
693 * Initialize MTRR from boot processor.
694 */
695 mtrr_init();
696
697 /*
698 * Set up PAT for boot processor.
699 */
700 pat_init();
6d2010ae 701#endif
91447636
A
702
703 /*
b0d623f7 704 * Free lowmem pages and complete other setup
91447636 705 */
b0d623f7 706 pmap_lowmem_finalize();
1c79356b
A
707}
708
709/*
710 * Halt a cpu.
711 */
712void
713halt_cpu(void)
714{
715 halt_all_cpus(FALSE);
716}
717
718int reset_mem_on_reboot = 1;
719
720/*
721 * Halt the system or reboot.
722 */
723void
9bccf70c 724halt_all_cpus(boolean_t reboot)
1c79356b 725{
55e303ae 726 if (reboot) {
55e303ae
A
727 printf("MACH Reboot\n");
728 PEHaltRestart( kPERestartCPU );
729 } else {
730 printf("CPU halted\n");
731 PEHaltRestart( kPEHaltCPU );
1c79356b 732 }
55e303ae 733 while(1);
1c79356b
A
734}
735
2d21ac55 736
0c530ab8
A
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.
739 */
740
741void
742panic_io_port_read(void) {
743 if (panic_io_port)
744 (void)inb(panic_io_port);
745}
746
747/* For use with the MP rendezvous mechanism
748 */
749
6d2010ae
A
750uint64_t panic_restart_timeout = ~(0ULL);
751
13f56ec4
A
752#define PANIC_RESTART_TIMEOUT (3ULL * NSEC_PER_SEC)
753
0c530ab8 754static void
6d2010ae 755machine_halt_cpu(void) {
13f56ec4
A
756 uint64_t deadline;
757
0c530ab8 758 panic_io_port_read();
6d2010ae 759
13f56ec4
A
760 /* Halt here forever if we're not rebooting */
761 if (!PE_reboot_on_panic() && panic_restart_timeout == ~(0ULL)) {
762 pmCPUHalt(PM_HALT_DEBUG);
763 return;
6d2010ae 764 }
13f56ec4
A
765
766 if (PE_reboot_on_panic())
767 deadline = mach_absolute_time() + PANIC_RESTART_TIMEOUT;
768 else
769 deadline = mach_absolute_time() + panic_restart_timeout;
770
771 while (mach_absolute_time() < deadline)
772 cpu_pause();
773
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->
777 * AppleACPIPlatform
778 */
13f56ec4
A
779 if (PE_halt_restart)
780 (*PE_halt_restart)(kPERestartCPU);
2d21ac55 781 pmCPUHalt(PM_HALT_DEBUG);
1c79356b
A
782}
783
316670eb
A
784void
785DebuggerWithContext(
786 __unused unsigned int reason,
787 __unused void *ctx,
788 const char *message)
789{
790 Debugger(message);
791}
792
1c79356b
A
793void
794Debugger(
795 const char *message)
796{
0c530ab8
A
797 unsigned long pi_size = 0;
798 void *stackptr;
6d2010ae 799 int cn = cpu_number();
91447636 800
0c530ab8 801 hw_atomic_add(&debug_mode, 1);
91447636
A
802 if (!panic_is_inited) {
803 postcode(PANIC_HLT);
804 asm("hlt");
805 }
806
1c79356b 807 printf("Debugger called: <%s>\n", message);
91447636 808 kprintf("Debugger called: <%s>\n", message);
1c79356b 809
0c530ab8
A
810 /*
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.
815 */
816
817 if (panicstr) {
818 disable_preemption();
819
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.
822 */
823 panic_io_port_read();
824
825 /* Obtain current frame pointer */
b0d623f7 826#if defined (__i386__)
0c530ab8 827 __asm__ volatile("movl %%ebp, %0" : "=m" (stackptr));
b0d623f7
A
828#elif defined (__x86_64__)
829 __asm__ volatile("movq %%rbp, %0" : "=m" (stackptr));
830#endif
0c530ab8
A
831
832 /* Print backtrace - callee is internally synchronized */
6d2010ae 833 panic_i386_backtrace(stackptr, ((panic_double_fault_cpu == cn) ? 80: 48), NULL, FALSE, NULL);
0c530ab8
A
834
835 /* everything should be printed now so copy to NVRAM
836 */
837
838 if( debug_buf_size > 0) {
2d21ac55
A
839 /* Optionally sync the panic log, if any, to NVRAM
840 * This is the default.
841 */
842 if (commit_paniclog_to_nvram) {
0c530ab8 843 unsigned int bufpos;
935ed37a 844 uintptr_t cr0;
b0d623f7
A
845
846 debug_putc(0);
0c530ab8
A
847
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
2d21ac55
A
852 * this post-restart. The compressor should be
853 * capable of in-place compression.
0c530ab8 854 */
2d21ac55
A
855 bufpos = packA(debug_buf,
856 (unsigned int) (debug_buf_ptr - debug_buf), debug_buf_size);
0c530ab8
A
857 /* If compression was successful,
858 * use the compressed length
859 */
2d21ac55
A
860 pi_size = bufpos ? bufpos : (unsigned) (debug_buf_ptr - debug_buf);
861
0c530ab8
A
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.
867 */
b0d623f7 868
6d2010ae 869
935ed37a
A
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.
874 */
875 cr0 = get_cr0();
876 clear_ts();
6d2010ae
A
877
878 kprintf("Attempting to commit panic log to NVRAM\n");
b0d623f7
A
879 pi_size = PESavePanicInfo((unsigned char *)debug_buf,
880 (uint32_t)pi_size );
935ed37a 881 set_cr0(cr0);
6d2010ae 882
2d21ac55
A
883 /* Uncompress in-place, to permit examination of
884 * the panic log by debuggers.
885 */
886
887 if (bufpos) {
888 unpackA(debug_buf, bufpos);
889 }
0c530ab8
A
890 }
891 }
b7266188
A
892
893 /* If the user won't be able to read the dialog,
894 * don't bother trying to show it
895 */
896 if (!PE_reboot_on_panic())
897 draw_panic_dialog();
0c530ab8
A
898
899 if (!panicDebugging) {
6d2010ae 900 unsigned cnum;
0c530ab8
A
901 /* Clear the MP rendezvous function lock, in the event
902 * that a panic occurred while in that codepath.
903 */
904 mp_rendezvous_break_lock();
b7266188 905
6d2010ae
A
906 /* Non-maskably interrupt all other processors
907 * If a restart timeout is specified, this processor
908 * will attempt a restart.
0c530ab8 909 */
6d2010ae
A
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);
914 }
915 }
916 machine_halt_cpu();
0c530ab8
A
917 /* NOT REACHED */
918 }
919 }
55e303ae 920
1c79356b 921 __asm__("int3");
0c530ab8 922 hw_atomic_sub(&debug_mode, 1);
1c79356b
A
923}
924
1c79356b 925char *
91447636 926machine_boot_info(char *buf, __unused vm_size_t size)
1c79356b
A
927{
928 *buf ='\0';
929 return buf;
930}
931
0c530ab8
A
932/* Routines for address - symbol translation. Not called unless the "keepsyms"
933 * boot-arg is supplied.
934 */
935
936static int
6d2010ae 937panic_print_macho_symbol_name(kernel_mach_header_t *mh, vm_address_t search, const char *module_name)
0c530ab8 938{
b0d623f7 939 kernel_nlist_t *sym = NULL;
0c530ab8 940 struct load_command *cmd;
b0d623f7 941 kernel_segment_command_t *orig_ts = NULL, *orig_le = NULL;
0c530ab8
A
942 struct symtab_command *orig_st = NULL;
943 unsigned int i;
944 char *strings, *bestsym = NULL;
945 vm_address_t bestaddr = 0, diff, curdiff;
b0d623f7
A
946
947 /* Assume that if it's loaded and linked into the kernel, it's a valid Mach-O */
0c530ab8
A
948
949 cmd = (struct load_command *) &mh[1];
950 for (i = 0; i < mh->ncmds; i++) {
b0d623f7
A
951 if (cmd->cmd == LC_SEGMENT_KERNEL) {
952 kernel_segment_command_t *orig_sg = (kernel_segment_command_t *) cmd;
0c530ab8 953
2d21ac55
A
954 if (strncmp(SEG_TEXT, orig_sg->segname,
955 sizeof(orig_sg->segname)) == 0)
0c530ab8 956 orig_ts = orig_sg;
2d21ac55
A
957 else if (strncmp(SEG_LINKEDIT, orig_sg->segname,
958 sizeof(orig_sg->segname)) == 0)
0c530ab8 959 orig_le = orig_sg;
2d21ac55
A
960 else if (strncmp("", orig_sg->segname,
961 sizeof(orig_sg->segname)) == 0)
7ee9d059 962 orig_ts = orig_sg; /* pre-Lion i386 kexts have a single unnamed segment */
0c530ab8
A
963 }
964 else if (cmd->cmd == LC_SYMTAB)
965 orig_st = (struct symtab_command *) cmd;
966
b0d623f7 967 cmd = (struct load_command *) ((uintptr_t) cmd + cmd->cmdsize);
0c530ab8
A
968 }
969
970 if ((orig_ts == NULL) || (orig_st == NULL) || (orig_le == NULL))
971 return 0;
972
0c530ab8
A
973 if ((search < orig_ts->vmaddr) ||
974 (search >= orig_ts->vmaddr + orig_ts->vmsize)) {
975 /* search out of range for this mach header */
976 return 0;
977 }
978
b0d623f7
A
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);
0c530ab8
A
981 diff = search;
982
983 for (i = 0; i < orig_st->nsyms; i++) {
b0d623f7
A
984 if (sym[i].n_type & N_STAB) continue;
985
0c530ab8
A
986 if (sym[i].n_value <= search) {
987 curdiff = search - (vm_address_t)sym[i].n_value;
988 if (curdiff < diff) {
989 diff = curdiff;
990 bestaddr = sym[i].n_value;
991 bestsym = strings + sym[i].n_un.n_strx;
992 }
993 }
994 }
995
996 if (bestsym != NULL) {
997 if (diff != 0) {
6d2010ae 998 kdb_printf("%s : %s + 0x%lx", module_name, bestsym, (unsigned long)diff);
0c530ab8 999 } else {
6d2010ae 1000 kdb_printf("%s : %s", module_name, bestsym);
0c530ab8
A
1001 }
1002 return 1;
1003 }
1004 return 0;
1005}
1006
1007extern kmod_info_t * kmod; /* the list of modules */
1008
1009static void
1010panic_print_kmod_symbol_name(vm_address_t search)
1011{
6d2010ae
A
1012 u_int i;
1013
1014 if (gLoadedKextSummaries == NULL)
1015 return;
1016 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
1017 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
1018
1019 if ((search >= summary->address) &&
1020 (search < (summary->address + summary->size)))
1021 {
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);
1025 }
0c530ab8 1026 break;
6d2010ae 1027 }
0c530ab8
A
1028 }
1029}
1030
0c530ab8
A
1031static void
1032panic_print_symbol_name(vm_address_t search)
1033{
1034 /* try searching in the kernel */
6d2010ae 1035 if (panic_print_macho_symbol_name(&_mh_execute_header, search, "mach_kernel") == 0) {
0c530ab8
A
1036 /* that failed, now try to search for the right kext */
1037 panic_print_kmod_symbol_name(search);
1038 }
1039}
1040
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.
1045 */
1046
1047#define DUMPFRAMES 32
1048#define PBT_TIMEOUT_CYCLES (5 * 1000 * 1000 * 1000ULL)
1049void
935ed37a 1050panic_i386_backtrace(void *_frame, int nframes, const char *msg, boolean_t regdump, x86_saved_state_t *regs)
0c530ab8
A
1051{
1052 cframe_t *frame = (cframe_t *)_frame;
1053 vm_offset_t raddrs[DUMPFRAMES];
935ed37a 1054 vm_offset_t PC = 0;
0c530ab8
A
1055 int frame_index;
1056 volatile uint32_t *ppbtcnt = &pbtcnt;
1057 uint64_t bt_tsc_timeout;
1058 boolean_t keepsyms = FALSE;
6d2010ae 1059 int cn = cpu_number();
0c530ab8 1060
6d2010ae 1061 if(pbtcpu != cn) {
0c530ab8
A
1062 hw_atomic_add(&pbtcnt, 1);
1063 /* Spin on print backtrace lock, which serializes output
1064 * Continue anyway if a timeout occurs.
1065 */
6d2010ae
A
1066 hw_lock_to(&pbtlock, LockTimeOutTSC*2);
1067 pbtcpu = cn;
0c530ab8
A
1068 }
1069
593a1d5f 1070 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms));
0c530ab8 1071
935ed37a 1072 if (msg != NULL) {
b0d623f7 1073 kdb_printf("%s", msg);
935ed37a
A
1074 }
1075
1076 if ((regdump == TRUE) && (regs != NULL)) {
b0d623f7
A
1077#if defined(__x86_64__)
1078 x86_saved_state64_t *ss64p = saved_state64(regs);
1079 kdb_printf(
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,
1090 ss64p->isf.ss);
1091 PC = ss64p->isf.rip;
1092#else
935ed37a 1093 x86_saved_state32_t *ss32p = saved_state32(regs);
935ed37a
A
1094 kdb_printf(
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);
1101 PC = ss32p->eip;
b0d623f7 1102#endif
935ed37a
A
1103 }
1104
1105 kdb_printf("Backtrace (CPU %d), "
b0d623f7 1106#if PRINT_ARGS_FROM_STACK_FRAME
6d2010ae 1107 "Frame : Return Address (4 potential args on stack)\n", cn);
b0d623f7 1108#else
6d2010ae 1109 "Frame : Return Address\n", cn);
b0d623f7 1110#endif
0c530ab8
A
1111
1112 for (frame_index = 0; frame_index < nframes; frame_index++) {
1113 vm_offset_t curframep = (vm_offset_t) frame;
1114
1115 if (!curframep)
1116 break;
1117
1118 if (curframep & 0x3) {
1119 kdb_printf("Unaligned frame\n");
1120 goto invalid;
1121 }
1122
1123 if (!kvtophys(curframep) ||
6d2010ae 1124 !kvtophys(curframep + sizeof(cframe_t) - 1)) {
0c530ab8
A
1125 kdb_printf("No mapping exists for frame pointer\n");
1126 goto invalid;
1127 }
1128
b0d623f7 1129 kdb_printf("%p : 0x%lx ", frame, frame->caller);
0c530ab8
A
1130 if (frame_index < DUMPFRAMES)
1131 raddrs[frame_index] = frame->caller;
1132
b0d623f7 1133#if PRINT_ARGS_FROM_STACK_FRAME
0c530ab8 1134 if (kvtophys((vm_offset_t)&(frame->args[3])))
b0d623f7 1135 kdb_printf("(0x%x 0x%x 0x%x 0x%x) ",
0c530ab8
A
1136 frame->args[0], frame->args[1],
1137 frame->args[2], frame->args[3]);
b0d623f7 1138#endif
0c530ab8
A
1139
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.
1144 */
1145 if (keepsyms)
1146 panic_print_symbol_name((vm_address_t)frame->caller);
1147
b0d623f7
A
1148 kdb_printf("\n");
1149
0c530ab8
A
1150 frame = frame->prev;
1151 }
1152
1153 if (frame_index >= nframes)
1154 kdb_printf("\tBacktrace continues...\n");
1155
1156 goto out;
1157
1158invalid:
2d21ac55 1159 kdb_printf("Backtrace terminated-invalid frame pointer %p\n",frame);
0c530ab8
A
1160out:
1161
1162 /* Identify kernel modules in the backtrace and display their
1163 * load addresses and dependencies. This routine should walk
1164 * the kmod list safely.
1165 */
1166 if (frame_index)
b0d623f7 1167 kmod_panic_dump((vm_offset_t *)&raddrs[0], frame_index);
0c530ab8 1168
935ed37a 1169 if (PC != 0)
b0d623f7 1170 kmod_panic_dump(&PC, 1);
935ed37a 1171
2d21ac55 1172 panic_display_system_configuration();
c910b4d9 1173
0c530ab8
A
1174 /* Release print backtrace lock, to permit other callers in the
1175 * event of panics on multiple processors.
1176 */
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.
1181 */
1182 bt_tsc_timeout = rdtsc64() + PBT_TIMEOUT_CYCLES;
1183 while(*ppbtcnt && (rdtsc64() < bt_tsc_timeout));
1184}