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