]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/AT386/model_dep.c
xnu-2050.24.15.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 892
0c530ab8 893 if (!panicDebugging) {
6d2010ae 894 unsigned cnum;
0c530ab8
A
895 /* Clear the MP rendezvous function lock, in the event
896 * that a panic occurred while in that codepath.
897 */
898 mp_rendezvous_break_lock();
b7266188 899
6d2010ae
A
900 /* Non-maskably interrupt all other processors
901 * If a restart timeout is specified, this processor
902 * will attempt a restart.
0c530ab8 903 */
6d2010ae
A
904 kprintf("Invoking machine_halt_cpu on CPU %d\n", cn);
905 for (cnum = 0; cnum < real_ncpus; cnum++) {
906 if (cnum != (unsigned) cn) {
907 cpu_NMI_interrupt(cnum);
908 }
909 }
910 machine_halt_cpu();
0c530ab8
A
911 /* NOT REACHED */
912 }
913 }
55e303ae 914
1c79356b 915 __asm__("int3");
0c530ab8 916 hw_atomic_sub(&debug_mode, 1);
1c79356b
A
917}
918
1c79356b 919char *
91447636 920machine_boot_info(char *buf, __unused vm_size_t size)
1c79356b
A
921{
922 *buf ='\0';
923 return buf;
924}
925
0c530ab8
A
926/* Routines for address - symbol translation. Not called unless the "keepsyms"
927 * boot-arg is supplied.
928 */
929
930static int
6d2010ae 931panic_print_macho_symbol_name(kernel_mach_header_t *mh, vm_address_t search, const char *module_name)
0c530ab8 932{
b0d623f7 933 kernel_nlist_t *sym = NULL;
0c530ab8 934 struct load_command *cmd;
b0d623f7 935 kernel_segment_command_t *orig_ts = NULL, *orig_le = NULL;
0c530ab8
A
936 struct symtab_command *orig_st = NULL;
937 unsigned int i;
938 char *strings, *bestsym = NULL;
939 vm_address_t bestaddr = 0, diff, curdiff;
b0d623f7
A
940
941 /* Assume that if it's loaded and linked into the kernel, it's a valid Mach-O */
0c530ab8
A
942
943 cmd = (struct load_command *) &mh[1];
944 for (i = 0; i < mh->ncmds; i++) {
b0d623f7
A
945 if (cmd->cmd == LC_SEGMENT_KERNEL) {
946 kernel_segment_command_t *orig_sg = (kernel_segment_command_t *) cmd;
0c530ab8 947
2d21ac55
A
948 if (strncmp(SEG_TEXT, orig_sg->segname,
949 sizeof(orig_sg->segname)) == 0)
0c530ab8 950 orig_ts = orig_sg;
2d21ac55
A
951 else if (strncmp(SEG_LINKEDIT, orig_sg->segname,
952 sizeof(orig_sg->segname)) == 0)
0c530ab8 953 orig_le = orig_sg;
2d21ac55
A
954 else if (strncmp("", orig_sg->segname,
955 sizeof(orig_sg->segname)) == 0)
7ee9d059 956 orig_ts = orig_sg; /* pre-Lion i386 kexts have a single unnamed segment */
0c530ab8
A
957 }
958 else if (cmd->cmd == LC_SYMTAB)
959 orig_st = (struct symtab_command *) cmd;
960
b0d623f7 961 cmd = (struct load_command *) ((uintptr_t) cmd + cmd->cmdsize);
0c530ab8
A
962 }
963
964 if ((orig_ts == NULL) || (orig_st == NULL) || (orig_le == NULL))
965 return 0;
966
0c530ab8
A
967 if ((search < orig_ts->vmaddr) ||
968 (search >= orig_ts->vmaddr + orig_ts->vmsize)) {
969 /* search out of range for this mach header */
970 return 0;
971 }
972
b0d623f7
A
973 sym = (kernel_nlist_t *)(uintptr_t)(orig_le->vmaddr + orig_st->symoff - orig_le->fileoff);
974 strings = (char *)(uintptr_t)(orig_le->vmaddr + orig_st->stroff - orig_le->fileoff);
0c530ab8
A
975 diff = search;
976
977 for (i = 0; i < orig_st->nsyms; i++) {
b0d623f7
A
978 if (sym[i].n_type & N_STAB) continue;
979
0c530ab8
A
980 if (sym[i].n_value <= search) {
981 curdiff = search - (vm_address_t)sym[i].n_value;
982 if (curdiff < diff) {
983 diff = curdiff;
984 bestaddr = sym[i].n_value;
985 bestsym = strings + sym[i].n_un.n_strx;
986 }
987 }
988 }
989
990 if (bestsym != NULL) {
991 if (diff != 0) {
6d2010ae 992 kdb_printf("%s : %s + 0x%lx", module_name, bestsym, (unsigned long)diff);
0c530ab8 993 } else {
6d2010ae 994 kdb_printf("%s : %s", module_name, bestsym);
0c530ab8
A
995 }
996 return 1;
997 }
998 return 0;
999}
1000
1001extern kmod_info_t * kmod; /* the list of modules */
1002
1003static void
1004panic_print_kmod_symbol_name(vm_address_t search)
1005{
6d2010ae
A
1006 u_int i;
1007
1008 if (gLoadedKextSummaries == NULL)
1009 return;
1010 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
1011 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
1012
1013 if ((search >= summary->address) &&
1014 (search < (summary->address + summary->size)))
1015 {
1016 kernel_mach_header_t *header = (kernel_mach_header_t *)(uintptr_t) summary->address;
1017 if (panic_print_macho_symbol_name(header, search, summary->name) == 0) {
1018 kdb_printf("%s + %llu", summary->name, (unsigned long)search - summary->address);
1019 }
0c530ab8 1020 break;
6d2010ae 1021 }
0c530ab8
A
1022 }
1023}
1024
0c530ab8
A
1025static void
1026panic_print_symbol_name(vm_address_t search)
1027{
1028 /* try searching in the kernel */
6d2010ae 1029 if (panic_print_macho_symbol_name(&_mh_execute_header, search, "mach_kernel") == 0) {
0c530ab8
A
1030 /* that failed, now try to search for the right kext */
1031 panic_print_kmod_symbol_name(search);
1032 }
1033}
1034
1035/* Generate a backtrace, given a frame pointer - this routine
1036 * should walk the stack safely. The trace is appended to the panic log
1037 * and conditionally, to the console. If the trace contains kernel module
1038 * addresses, display the module name, load address and dependencies.
1039 */
1040
1041#define DUMPFRAMES 32
1042#define PBT_TIMEOUT_CYCLES (5 * 1000 * 1000 * 1000ULL)
1043void
935ed37a 1044panic_i386_backtrace(void *_frame, int nframes, const char *msg, boolean_t regdump, x86_saved_state_t *regs)
0c530ab8
A
1045{
1046 cframe_t *frame = (cframe_t *)_frame;
1047 vm_offset_t raddrs[DUMPFRAMES];
935ed37a 1048 vm_offset_t PC = 0;
0c530ab8
A
1049 int frame_index;
1050 volatile uint32_t *ppbtcnt = &pbtcnt;
1051 uint64_t bt_tsc_timeout;
1052 boolean_t keepsyms = FALSE;
6d2010ae 1053 int cn = cpu_number();
0c530ab8 1054
6d2010ae 1055 if(pbtcpu != cn) {
0c530ab8
A
1056 hw_atomic_add(&pbtcnt, 1);
1057 /* Spin on print backtrace lock, which serializes output
1058 * Continue anyway if a timeout occurs.
1059 */
6d2010ae
A
1060 hw_lock_to(&pbtlock, LockTimeOutTSC*2);
1061 pbtcpu = cn;
0c530ab8
A
1062 }
1063
593a1d5f 1064 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms));
0c530ab8 1065
935ed37a 1066 if (msg != NULL) {
b0d623f7 1067 kdb_printf("%s", msg);
935ed37a
A
1068 }
1069
1070 if ((regdump == TRUE) && (regs != NULL)) {
b0d623f7
A
1071#if defined(__x86_64__)
1072 x86_saved_state64_t *ss64p = saved_state64(regs);
1073 kdb_printf(
1074 "RAX: 0x%016llx, RBX: 0x%016llx, RCX: 0x%016llx, RDX: 0x%016llx\n"
1075 "RSP: 0x%016llx, RBP: 0x%016llx, RSI: 0x%016llx, RDI: 0x%016llx\n"
1076 "R8: 0x%016llx, R9: 0x%016llx, R10: 0x%016llx, R11: 0x%016llx\n"
1077 "R12: 0x%016llx, R13: 0x%016llx, R14: 0x%016llx, R15: 0x%016llx\n"
1078 "RFL: 0x%016llx, RIP: 0x%016llx, CS: 0x%016llx, SS: 0x%016llx\n",
1079 ss64p->rax, ss64p->rbx, ss64p->rcx, ss64p->rdx,
1080 ss64p->isf.rsp, ss64p->rbp, ss64p->rsi, ss64p->rdi,
1081 ss64p->r8, ss64p->r9, ss64p->r10, ss64p->r11,
1082 ss64p->r12, ss64p->r13, ss64p->r14, ss64p->r15,
1083 ss64p->isf.rflags, ss64p->isf.rip, ss64p->isf.cs,
1084 ss64p->isf.ss);
1085 PC = ss64p->isf.rip;
1086#else
935ed37a 1087 x86_saved_state32_t *ss32p = saved_state32(regs);
935ed37a
A
1088 kdb_printf(
1089 "EAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x\n"
1090 "CR2: 0x%08x, EBP: 0x%08x, ESI: 0x%08x, EDI: 0x%08x\n"
1091 "EFL: 0x%08x, EIP: 0x%08x, CS: 0x%08x, DS: 0x%08x\n",
1092 ss32p->eax,ss32p->ebx,ss32p->ecx,ss32p->edx,
1093 ss32p->cr2,ss32p->ebp,ss32p->esi,ss32p->edi,
1094 ss32p->efl,ss32p->eip,ss32p->cs, ss32p->ds);
1095 PC = ss32p->eip;
b0d623f7 1096#endif
935ed37a
A
1097 }
1098
1099 kdb_printf("Backtrace (CPU %d), "
b0d623f7 1100#if PRINT_ARGS_FROM_STACK_FRAME
6d2010ae 1101 "Frame : Return Address (4 potential args on stack)\n", cn);
b0d623f7 1102#else
6d2010ae 1103 "Frame : Return Address\n", cn);
b0d623f7 1104#endif
0c530ab8
A
1105
1106 for (frame_index = 0; frame_index < nframes; frame_index++) {
1107 vm_offset_t curframep = (vm_offset_t) frame;
1108
1109 if (!curframep)
1110 break;
1111
1112 if (curframep & 0x3) {
1113 kdb_printf("Unaligned frame\n");
1114 goto invalid;
1115 }
1116
1117 if (!kvtophys(curframep) ||
6d2010ae 1118 !kvtophys(curframep + sizeof(cframe_t) - 1)) {
0c530ab8
A
1119 kdb_printf("No mapping exists for frame pointer\n");
1120 goto invalid;
1121 }
1122
b0d623f7 1123 kdb_printf("%p : 0x%lx ", frame, frame->caller);
0c530ab8
A
1124 if (frame_index < DUMPFRAMES)
1125 raddrs[frame_index] = frame->caller;
1126
b0d623f7 1127#if PRINT_ARGS_FROM_STACK_FRAME
0c530ab8 1128 if (kvtophys((vm_offset_t)&(frame->args[3])))
b0d623f7 1129 kdb_printf("(0x%x 0x%x 0x%x 0x%x) ",
0c530ab8
A
1130 frame->args[0], frame->args[1],
1131 frame->args[2], frame->args[3]);
b0d623f7 1132#endif
0c530ab8
A
1133
1134 /* Display address-symbol translation only if the "keepsyms"
1135 * boot-arg is suppplied, since we unload LINKEDIT otherwise.
1136 * This routine is potentially unsafe; also, function
1137 * boundary identification is unreliable after a strip -x.
1138 */
1139 if (keepsyms)
1140 panic_print_symbol_name((vm_address_t)frame->caller);
1141
b0d623f7
A
1142 kdb_printf("\n");
1143
0c530ab8
A
1144 frame = frame->prev;
1145 }
1146
1147 if (frame_index >= nframes)
1148 kdb_printf("\tBacktrace continues...\n");
1149
1150 goto out;
1151
1152invalid:
2d21ac55 1153 kdb_printf("Backtrace terminated-invalid frame pointer %p\n",frame);
0c530ab8
A
1154out:
1155
1156 /* Identify kernel modules in the backtrace and display their
1157 * load addresses and dependencies. This routine should walk
1158 * the kmod list safely.
1159 */
1160 if (frame_index)
b0d623f7 1161 kmod_panic_dump((vm_offset_t *)&raddrs[0], frame_index);
0c530ab8 1162
935ed37a 1163 if (PC != 0)
b0d623f7 1164 kmod_panic_dump(&PC, 1);
935ed37a 1165
2d21ac55 1166 panic_display_system_configuration();
c910b4d9 1167
0c530ab8
A
1168 /* Release print backtrace lock, to permit other callers in the
1169 * event of panics on multiple processors.
1170 */
1171 hw_lock_unlock(&pbtlock);
1172 hw_atomic_sub(&pbtcnt, 1);
1173 /* Wait for other processors to complete output
1174 * Timeout and continue after PBT_TIMEOUT_CYCLES.
1175 */
1176 bt_tsc_timeout = rdtsc64() + PBT_TIMEOUT_CYCLES;
1177 while(*ppbtcnt && (rdtsc64() < bt_tsc_timeout));
1178}