]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/AT386/model_dep.c
6315fc5e9be83f3aa55be6e90aaa3e0082ef62bf
[apple/xnu.git] / osfmk / i386 / AT386 / model_dep.c
1 /*
2 * Copyright (c) 2000-2010 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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
69 #include <platforms.h>
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>
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>
84 #include <kern/cpu_data.h>
85 #include <kern/machine.h>
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>
94 #include <i386/fpu.h>
95 #include <i386/machine_cpu.h>
96 #include <i386/pmap.h>
97 #if CONFIG_MTRR
98 #include <i386/mtrr.h>
99 #endif
100 #include <i386/ucode.h>
101 #include <i386/pmCPU.h>
102 #include <architecture/i386/pio.h> /* inb() */
103 #include <pexpert/i386/boot.h>
104
105 #include <vm/pmap.h>
106 #include <vm/vm_map.h>
107 #include <vm/vm_kern.h>
108
109 #include <IOKit/IOPlatformExpert.h>
110 #include <IOKit/IOHibernatePrivate.h>
111
112 #include <pexpert/i386/efi.h>
113
114 #include <kern/thread.h>
115 #include <kern/sched.h>
116 #include <mach-o/loader.h>
117 #include <mach-o/nlist.h>
118
119 #include <libkern/kernel_mach_header.h>
120 #include <libkern/OSKextLibPrivate.h>
121
122 #if DEBUG
123 #define DPRINTF(x...) kprintf(x)
124 #else
125 #define DPRINTF(x...)
126 #endif
127
128 static void machine_conf(void);
129
130 extern int max_unsafe_quanta;
131 extern int max_poll_quanta;
132 extern unsigned int panic_is_inited;
133
134 int db_run_mode;
135
136 volatile int pbtcpu = -1;
137 hw_lock_data_t pbtlock; /* backtrace print lock */
138 uint32_t pbtcnt = 0;
139
140 volatile int panic_double_fault_cpu = -1;
141
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
150 typedef struct _cframe_t {
151 struct _cframe_t *prev;
152 uintptr_t caller;
153 #if PRINT_ARGS_FROM_STACK_FRAME
154 unsigned args[0];
155 #endif
156 } cframe_t;
157
158 static unsigned panic_io_port;
159 static unsigned commit_paniclog_to_nvram;
160
161 unsigned int debug_boot_arg;
162
163 void
164 machine_startup(void)
165 {
166 int boot_arg;
167
168 #if 0
169 if( PE_get_hotkey( kPEControlKey ))
170 halt_in_debugger = halt_in_debugger ? 0 : 1;
171 #endif
172
173 if (PE_parse_boot_argn("debug", &debug_boot_arg, sizeof (debug_boot_arg))) {
174 panicDebugging = TRUE;
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;
178 if (debug_boot_arg & DB_LOG_PI_SCRN) logPanicDataToScreen=TRUE;
179 } else {
180 debug_boot_arg = 0;
181 }
182
183 if (!PE_parse_boot_argn("nvram_paniclog", &commit_paniclog_to_nvram, sizeof (commit_paniclog_to_nvram)))
184 commit_paniclog_to_nvram = 1;
185
186 /*
187 * Entering the debugger will put the CPUs into a "safe"
188 * power mode.
189 */
190 if (PE_parse_boot_argn("pmsafe_debug", &boot_arg, sizeof (boot_arg)))
191 pmsafe_debug = boot_arg;
192
193 #if NOTYET
194 hw_lock_init(&debugger_lock); /* initialize debugger lock */
195 #endif
196 hw_lock_init(&pbtlock); /* initialize print backtrace lock */
197
198 if (PE_parse_boot_argn("preempt", &boot_arg, sizeof (boot_arg))) {
199 default_preemption_rate = boot_arg;
200 }
201 if (PE_parse_boot_argn("unsafe", &boot_arg, sizeof (boot_arg))) {
202 max_unsafe_quanta = boot_arg;
203 }
204 if (PE_parse_boot_argn("poll", &boot_arg, sizeof (boot_arg))) {
205 max_poll_quanta = boot_arg;
206 }
207 if (PE_parse_boot_argn("yield", &boot_arg, sizeof (boot_arg))) {
208 sched_poll_yield_shift = boot_arg;
209 }
210 /* The I/O port to issue a read from, in the event of a panic. Useful for
211 * triggering logic analyzers.
212 */
213 if (PE_parse_boot_argn("panic_io_port", &boot_arg, sizeof (boot_arg))) {
214 /*I/O ports range from 0 through 0xFFFF */
215 panic_io_port = boot_arg & 0xffff;
216 }
217
218 machine_conf();
219
220 #if NOTYET
221 ml_thrm_init(); /* Start thermal monitoring on this processor */
222 #endif
223
224 /*
225 * Start the system.
226 */
227 kernel_bootstrap();
228 /*NOTREACHED*/
229 }
230
231
232 static void
233 machine_conf(void)
234 {
235 machine_info.memory_size = (typeof(machine_info.memory_size))mem_size;
236 }
237
238
239 extern void *gPEEFIRuntimeServices;
240 extern 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
284 static 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
330 static uint32_t
331 crc32(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
344 static void
345 efi_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
351 DPRINTF("Processing 64-bit EFI tables at %p\n", system_table);
352 do {
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);
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
368 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
369 system_table->Hdr.CRC32 = hdr_cksum;
370 if (cksum != hdr_cksum) {
371 kprintf("Bad EFI system table checksum\n");
372 break;
373 }
374
375 gPEEFISystemTable = system_table;
376
377 if (!cpu_mode_is64bit()) {
378 kprintf("Skipping 64-bit EFI runtime services for 32-bit legacy mode\n");
379 break;
380 }
381
382 if(system_table->RuntimeServices == 0) {
383 kprintf("No runtime table present\n");
384 break;
385 }
386 DPRINTF("RuntimeServices table at 0x%qx\n", system_table->RuntimeServices);
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;
389 DPRINTF("Checking runtime services table %p\n", runtime);
390 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
391 kprintf("Bad EFI runtime table signature\n");
392 break;
393 }
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
400 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
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
412 static void
413 efi_set_tables_32(EFI_SYSTEM_TABLE_32 * system_table)
414 {
415 EFI_RUNTIME_SERVICES_32 *runtime;
416 uint32_t hdr_cksum;
417 uint32_t cksum;
418
419 DPRINTF("Processing 32-bit EFI tables at %p\n", system_table);
420 do {
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);
427 if (system_table->Hdr.Signature != EFI_SYSTEM_TABLE_SIGNATURE) {
428 kprintf("Bad EFI system table signature\n");
429 break;
430 }
431 // Verify signature of the system table
432 hdr_cksum = system_table->Hdr.CRC32;
433 system_table->Hdr.CRC32 = 0;
434 DPRINTF("System table at %p HeaderSize 0x%x\n", system_table, system_table->Hdr.HeaderSize);
435 cksum = crc32(0L, system_table, system_table->Hdr.HeaderSize);
436
437 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
438 system_table->Hdr.CRC32 = hdr_cksum;
439 if (cksum != hdr_cksum) {
440 kprintf("Bad EFI system table checksum\n");
441 break;
442 }
443
444 gPEEFISystemTable = system_table;
445
446 if(system_table->RuntimeServices == 0) {
447 kprintf("No runtime table present\n");
448 break;
449 }
450 DPRINTF("RuntimeServices table at 0x%x\n", system_table->RuntimeServices);
451 // 32-bit virtual address is OK for 32-bit EFI and 32-bit kernel.
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);
460 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
461 kprintf("Bad EFI runtime table signature\n");
462 break;
463 }
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
470 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
471 runtime->Hdr.CRC32 = hdr_cksum;
472 if (cksum != hdr_cksum) {
473 kprintf("Bad EFI runtime table checksum\n");
474 break;
475 }
476
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
490 gPEEFIRuntimeServices = runtime;
491 }
492 while (FALSE);
493 }
494
495
496 /* Map in EFI runtime areas. */
497 static void
498 efi_init(void)
499 {
500 boot_args *args = (boot_args *)PE_state.bootArgs;
501
502 kprintf("Initializing EFI runtime services\n");
503
504 do
505 {
506 vm_offset_t vm_size, vm_addr;
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
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);
526 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
527 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
528 if (((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) ) {
529 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
530 vm_addr = (vm_offset_t) mptr->VirtualStart;
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;
535 #endif
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);
543 pmap_map_bd(vm_addr, phys_addr, phys_addr + round_page(vm_size),
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
549 if (args->Version != kBootArgsVersion2)
550 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
551
552 DPRINTF("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
553 if (args->efiMode == kBootArgsEfiMode64) {
554 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
555 } else {
556 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
557 }
558 }
559 while (FALSE);
560
561 return;
562 }
563
564 /* Remap EFI runtime areas. */
565 void
566 hibernate_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
572 do
573 {
574 vm_offset_t vm_size, vm_addr;
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
585 kprintf("Old system table 0x%x, new 0x%x\n",
586 (uint32_t)args->efiSystemTable, system_table_offset);
587
588 args->efiSystemTable = system_table_offset;
589
590 kprintf("Old map:\n");
591 msize = args->MemoryMapDescriptorSize;
592 mcount = args->MemoryMapSize / msize;
593 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
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
597 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
598 vm_addr = (vm_offset_t) mptr->VirtualStart;
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
604 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
605
606 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
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;
615 mcount = (unsigned int )(map_size / msize);
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
620 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
621 vm_addr = (vm_offset_t) mptr->VirtualStart;
622 #ifdef __x86_64__
623 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
624 vm_addr |= VM_MIN_KERNEL_ADDRESS;
625 #endif
626 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
627
628 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
629
630 pmap_map(vm_addr, phys_addr, phys_addr + round_page(vm_size),
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
636 if (args->Version != kBootArgsVersion2)
637 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
638
639 kprintf("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
640 if (args->efiMode == kBootArgsEfiMode64) {
641 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
642 } else {
643 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
644 }
645 }
646 while (FALSE);
647
648 kprintf("Done reinitializing EFI runtime services\n");
649
650 return;
651 }
652
653 /*
654 * Find devices. The system is alive.
655 */
656 void
657 machine_init(void)
658 {
659 #if __x86_64__
660 /* Now with VM up, switch to dynamically allocated cpu data */
661 cpu_data_realloc();
662 #endif
663
664 /* Ensure panic buffer is initialized. */
665 debug_log_init();
666
667 /*
668 * Display CPU identification
669 */
670 cpuid_cpu_display("CPU identification");
671 cpuid_feature_display("CPU features");
672 cpuid_extfeature_display("CPU extended features");
673
674 /*
675 * Initialize EFI runtime services.
676 */
677 efi_init();
678
679 smp_init();
680
681 /*
682 * Set up to use floating point.
683 */
684 init_fpu();
685
686 /*
687 * Configure clock devices.
688 */
689 clock_config();
690
691 #if CONFIG_MTRR
692 /*
693 * Initialize MTRR from boot processor.
694 */
695 mtrr_init();
696
697 /*
698 * Set up PAT for boot processor.
699 */
700 pat_init();
701 #endif
702
703 /*
704 * Free lowmem pages and complete other setup
705 */
706 pmap_lowmem_finalize();
707 }
708
709 /*
710 * Halt a cpu.
711 */
712 void
713 halt_cpu(void)
714 {
715 halt_all_cpus(FALSE);
716 }
717
718 int reset_mem_on_reboot = 1;
719
720 /*
721 * Halt the system or reboot.
722 */
723 void
724 halt_all_cpus(boolean_t reboot)
725 {
726 if (reboot) {
727 printf("MACH Reboot\n");
728 PEHaltRestart( kPERestartCPU );
729 } else {
730 printf("CPU halted\n");
731 PEHaltRestart( kPEHaltCPU );
732 }
733 while(1);
734 }
735
736
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
741 void
742 panic_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
750 uint64_t panic_restart_timeout = ~(0ULL);
751
752 #define PANIC_RESTART_TIMEOUT (3ULL * NSEC_PER_SEC)
753
754 static void
755 machine_halt_cpu(void) {
756 uint64_t deadline;
757
758 panic_io_port_read();
759
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;
764 }
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 */
779 if (PE_halt_restart)
780 (*PE_halt_restart)(kPERestartCPU);
781 pmCPUHalt(PM_HALT_DEBUG);
782 }
783
784 void
785 DebuggerWithContext(
786 __unused unsigned int reason,
787 __unused void *ctx,
788 const char *message)
789 {
790 Debugger(message);
791 }
792
793 void
794 Debugger(
795 const char *message)
796 {
797 unsigned long pi_size = 0;
798 void *stackptr;
799 int cn = cpu_number();
800
801 hw_atomic_add(&debug_mode, 1);
802 if (!panic_is_inited) {
803 postcode(PANIC_HLT);
804 asm("hlt");
805 }
806
807 printf("Debugger called: <%s>\n", message);
808 kprintf("Debugger called: <%s>\n", message);
809
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 */
826 #if defined (__i386__)
827 __asm__ volatile("movl %%ebp, %0" : "=m" (stackptr));
828 #elif defined (__x86_64__)
829 __asm__ volatile("movq %%rbp, %0" : "=m" (stackptr));
830 #endif
831
832 /* Print backtrace - callee is internally synchronized */
833 panic_i386_backtrace(stackptr, ((panic_double_fault_cpu == cn) ? 80: 48), NULL, FALSE, NULL);
834
835 /* everything should be printed now so copy to NVRAM
836 */
837
838 if( debug_buf_size > 0) {
839 /* Optionally sync the panic log, if any, to NVRAM
840 * This is the default.
841 */
842 if (commit_paniclog_to_nvram) {
843 unsigned int bufpos;
844 uintptr_t cr0;
845
846 debug_putc(0);
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
852 * this post-restart. The compressor should be
853 * capable of in-place compression.
854 */
855 bufpos = packA(debug_buf,
856 (unsigned int) (debug_buf_ptr - debug_buf), debug_buf_size);
857 /* If compression was successful,
858 * use the compressed length
859 */
860 pi_size = bufpos ? bufpos : (unsigned) (debug_buf_ptr - debug_buf);
861
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 */
868
869
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();
877
878 kprintf("Attempting to commit panic log to NVRAM\n");
879 pi_size = PESavePanicInfo((unsigned char *)debug_buf,
880 (uint32_t)pi_size );
881 set_cr0(cr0);
882
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 }
890 }
891 }
892
893 if (!panicDebugging) {
894 unsigned cnum;
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();
899
900 /* Non-maskably interrupt all other processors
901 * If a restart timeout is specified, this processor
902 * will attempt a restart.
903 */
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();
911 /* NOT REACHED */
912 }
913 }
914
915 __asm__("int3");
916 hw_atomic_sub(&debug_mode, 1);
917 }
918
919 char *
920 machine_boot_info(char *buf, __unused vm_size_t size)
921 {
922 *buf ='\0';
923 return buf;
924 }
925
926 /* Routines for address - symbol translation. Not called unless the "keepsyms"
927 * boot-arg is supplied.
928 */
929
930 static int
931 panic_print_macho_symbol_name(kernel_mach_header_t *mh, vm_address_t search, const char *module_name)
932 {
933 kernel_nlist_t *sym = NULL;
934 struct load_command *cmd;
935 kernel_segment_command_t *orig_ts = NULL, *orig_le = NULL;
936 struct symtab_command *orig_st = NULL;
937 unsigned int i;
938 char *strings, *bestsym = NULL;
939 vm_address_t bestaddr = 0, diff, curdiff;
940
941 /* Assume that if it's loaded and linked into the kernel, it's a valid Mach-O */
942
943 cmd = (struct load_command *) &mh[1];
944 for (i = 0; i < mh->ncmds; i++) {
945 if (cmd->cmd == LC_SEGMENT_KERNEL) {
946 kernel_segment_command_t *orig_sg = (kernel_segment_command_t *) cmd;
947
948 if (strncmp(SEG_TEXT, orig_sg->segname,
949 sizeof(orig_sg->segname)) == 0)
950 orig_ts = orig_sg;
951 else if (strncmp(SEG_LINKEDIT, orig_sg->segname,
952 sizeof(orig_sg->segname)) == 0)
953 orig_le = orig_sg;
954 else if (strncmp("", orig_sg->segname,
955 sizeof(orig_sg->segname)) == 0)
956 orig_ts = orig_sg; /* pre-Lion i386 kexts have a single unnamed segment */
957 }
958 else if (cmd->cmd == LC_SYMTAB)
959 orig_st = (struct symtab_command *) cmd;
960
961 cmd = (struct load_command *) ((uintptr_t) cmd + cmd->cmdsize);
962 }
963
964 if ((orig_ts == NULL) || (orig_st == NULL) || (orig_le == NULL))
965 return 0;
966
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
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);
975 diff = search;
976
977 for (i = 0; i < orig_st->nsyms; i++) {
978 if (sym[i].n_type & N_STAB) continue;
979
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) {
992 kdb_printf("%s : %s + 0x%lx", module_name, bestsym, (unsigned long)diff);
993 } else {
994 kdb_printf("%s : %s", module_name, bestsym);
995 }
996 return 1;
997 }
998 return 0;
999 }
1000
1001 extern kmod_info_t * kmod; /* the list of modules */
1002
1003 static void
1004 panic_print_kmod_symbol_name(vm_address_t search)
1005 {
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 }
1020 break;
1021 }
1022 }
1023 }
1024
1025 static void
1026 panic_print_symbol_name(vm_address_t search)
1027 {
1028 /* try searching in the kernel */
1029 if (panic_print_macho_symbol_name(&_mh_execute_header, search, "mach_kernel") == 0) {
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)
1043 void
1044 panic_i386_backtrace(void *_frame, int nframes, const char *msg, boolean_t regdump, x86_saved_state_t *regs)
1045 {
1046 cframe_t *frame = (cframe_t *)_frame;
1047 vm_offset_t raddrs[DUMPFRAMES];
1048 vm_offset_t PC = 0;
1049 int frame_index;
1050 volatile uint32_t *ppbtcnt = &pbtcnt;
1051 uint64_t bt_tsc_timeout;
1052 boolean_t keepsyms = FALSE;
1053 int cn = cpu_number();
1054
1055 if(pbtcpu != cn) {
1056 hw_atomic_add(&pbtcnt, 1);
1057 /* Spin on print backtrace lock, which serializes output
1058 * Continue anyway if a timeout occurs.
1059 */
1060 hw_lock_to(&pbtlock, LockTimeOutTSC*2);
1061 pbtcpu = cn;
1062 }
1063
1064 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms));
1065
1066 if (msg != NULL) {
1067 kdb_printf("%s", msg);
1068 }
1069
1070 if ((regdump == TRUE) && (regs != NULL)) {
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
1087 x86_saved_state32_t *ss32p = saved_state32(regs);
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;
1096 #endif
1097 }
1098
1099 kdb_printf("Backtrace (CPU %d), "
1100 #if PRINT_ARGS_FROM_STACK_FRAME
1101 "Frame : Return Address (4 potential args on stack)\n", cn);
1102 #else
1103 "Frame : Return Address\n", cn);
1104 #endif
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) ||
1118 !kvtophys(curframep + sizeof(cframe_t) - 1)) {
1119 kdb_printf("No mapping exists for frame pointer\n");
1120 goto invalid;
1121 }
1122
1123 kdb_printf("%p : 0x%lx ", frame, frame->caller);
1124 if (frame_index < DUMPFRAMES)
1125 raddrs[frame_index] = frame->caller;
1126
1127 #if PRINT_ARGS_FROM_STACK_FRAME
1128 if (kvtophys((vm_offset_t)&(frame->args[3])))
1129 kdb_printf("(0x%x 0x%x 0x%x 0x%x) ",
1130 frame->args[0], frame->args[1],
1131 frame->args[2], frame->args[3]);
1132 #endif
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
1142 kdb_printf("\n");
1143
1144 frame = frame->prev;
1145 }
1146
1147 if (frame_index >= nframes)
1148 kdb_printf("\tBacktrace continues...\n");
1149
1150 goto out;
1151
1152 invalid:
1153 kdb_printf("Backtrace terminated-invalid frame pointer %p\n",frame);
1154 out:
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)
1161 kmod_panic_dump((vm_offset_t *)&raddrs[0], frame_index);
1162
1163 if (PC != 0)
1164 kmod_panic_dump(&PC, 1);
1165
1166 panic_display_system_configuration();
1167
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 }