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