]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/AT386/model_dep.c
xnu-4570.1.46.tar.gz
[apple/xnu.git] / osfmk / i386 / AT386 / model_dep.c
1 /*
2 * Copyright (c) 2000-2016 Apple 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
70 #define __APPLE_API_PRIVATE 1
71 #define __APPLE_API_UNSTABLE 1
72 #include <kern/debug.h>
73
74 #include <mach/i386/vm_param.h>
75
76 #include <string.h>
77 #include <mach/vm_param.h>
78 #include <mach/vm_prot.h>
79 #include <mach/machine.h>
80 #include <mach/time_value.h>
81 #include <sys/kdebug.h>
82 #include <kern/spl.h>
83 #include <kern/assert.h>
84 #include <kern/misc_protos.h>
85 #include <kern/startup.h>
86 #include <kern/clock.h>
87 #include <kern/cpu_data.h>
88 #include <kern/machine.h>
89 #include <i386/postcode.h>
90 #include <i386/mp_desc.h>
91 #include <i386/misc_protos.h>
92 #include <i386/thread.h>
93 #include <i386/trap.h>
94 #include <i386/machine_routines.h>
95 #include <i386/mp.h> /* mp_rendezvous_break_lock */
96 #include <i386/cpuid.h>
97 #include <i386/fpu.h>
98 #include <i386/machine_cpu.h>
99 #include <i386/pmap.h>
100 #if CONFIG_MTRR
101 #include <i386/mtrr.h>
102 #endif
103 #include <i386/ucode.h>
104 #include <i386/pmCPU.h>
105 #include <i386/panic_hooks.h>
106
107 #include <architecture/i386/pio.h> /* inb() */
108 #include <pexpert/i386/boot.h>
109
110 #include <kdp/kdp_dyld.h>
111 #include <kdp/kdp_core.h>
112 #include <vm/pmap.h>
113 #include <vm/vm_map.h>
114 #include <vm/vm_kern.h>
115
116 #include <IOKit/IOPlatformExpert.h>
117 #include <IOKit/IOHibernatePrivate.h>
118
119 #include <pexpert/i386/efi.h>
120
121 #include <kern/thread.h>
122 #include <kern/sched.h>
123 #include <mach-o/loader.h>
124 #include <mach-o/nlist.h>
125
126 #include <libkern/kernel_mach_header.h>
127 #include <libkern/OSKextLibPrivate.h>
128
129 #include <mach/branch_predicates.h>
130 #include <libkern/section_keywords.h>
131
132 #if DEBUG || DEVELOPMENT
133 #define DPRINTF(x...) kprintf(x)
134 #else
135 #define DPRINTF(x...)
136 #endif
137
138 static void machine_conf(void);
139 void panic_print_symbol_name(vm_address_t search);
140 void RecordPanicStackshot(void);
141
142 extern const char version[];
143 extern char osversion[];
144 extern int max_unsafe_quanta;
145 extern int max_poll_quanta;
146 extern unsigned int panic_is_inited;
147
148 extern int proc_pid(void *p);
149
150 /* Definitions for frame pointers */
151 #define FP_ALIGNMENT_MASK ((uint32_t)(0x3))
152 #define FP_LR_OFFSET ((uint32_t)4)
153 #define FP_LR_OFFSET64 ((uint32_t)8)
154 #define FP_MAX_NUM_TO_EVALUATE (50)
155
156 volatile int pbtcpu = -1;
157 hw_lock_data_t pbtlock; /* backtrace print lock */
158 uint32_t pbtcnt = 0;
159
160 volatile int panic_double_fault_cpu = -1;
161
162 #define PRINT_ARGS_FROM_STACK_FRAME 0
163
164 typedef struct _cframe_t {
165 struct _cframe_t *prev;
166 uintptr_t caller;
167 #if PRINT_ARGS_FROM_STACK_FRAME
168 unsigned args[0];
169 #endif
170 } cframe_t;
171
172 static unsigned panic_io_port;
173 static unsigned commit_paniclog_to_nvram;
174 boolean_t coprocessor_paniclog_flush = FALSE;
175
176 #if DEVELOPMENT || DEBUG
177 struct kcdata_descriptor kc_panic_data;
178 static boolean_t begun_panic_stackshot = FALSE;
179
180 vm_offset_t panic_stackshot_buf = 0;
181 size_t panic_stackshot_len = 0;
182
183 extern kern_return_t do_stackshot(void *);
184 extern void kdp_snapshot_preflight(int pid, void *tracebuf,
185 uint32_t tracebuf_size, uint32_t flags,
186 kcdata_descriptor_t data_p,
187 boolean_t enable_faulting);
188 extern int kdp_stack_snapshot_bytes_traced(void);
189 #endif
190
191 SECURITY_READ_ONLY_LATE(unsigned int) debug_boot_arg;
192
193 /*
194 * Backtrace a single frame.
195 */
196 void
197 print_one_backtrace(pmap_t pmap, vm_offset_t topfp, const char *cur_marker,
198 boolean_t is_64_bit)
199 {
200 int i = 0;
201 addr64_t lr;
202 addr64_t fp;
203 addr64_t fp_for_ppn;
204 ppnum_t ppn;
205 boolean_t dump_kernel_stack;
206
207 fp = topfp;
208 fp_for_ppn = 0;
209 ppn = (ppnum_t)NULL;
210
211 if (fp >= VM_MIN_KERNEL_ADDRESS)
212 dump_kernel_stack = TRUE;
213 else
214 dump_kernel_stack = FALSE;
215
216 do {
217 if ((fp == 0) || ((fp & FP_ALIGNMENT_MASK) != 0))
218 break;
219 if (dump_kernel_stack && ((fp < VM_MIN_KERNEL_ADDRESS) || (fp > VM_MAX_KERNEL_ADDRESS)))
220 break;
221 if ((!dump_kernel_stack) && (fp >=VM_MIN_KERNEL_ADDRESS))
222 break;
223
224 /* Check to see if current address will result in a different
225 ppn than previously computed (to avoid recomputation) via
226 (addr) ^ fp_for_ppn) >> PAGE_SHIFT) */
227
228 if ((((fp + FP_LR_OFFSET) ^ fp_for_ppn) >> PAGE_SHIFT) != 0x0U) {
229 ppn = pmap_find_phys(pmap, fp + FP_LR_OFFSET);
230 fp_for_ppn = fp + (is_64_bit ? FP_LR_OFFSET64 : FP_LR_OFFSET);
231 }
232 if (ppn != (ppnum_t)NULL) {
233 if (is_64_bit) {
234 lr = ml_phys_read_double_64(((((vm_offset_t)ppn) << PAGE_SHIFT)) | ((fp + FP_LR_OFFSET64) & PAGE_MASK));
235 } else {
236 lr = ml_phys_read_word(((((vm_offset_t)ppn) << PAGE_SHIFT)) | ((fp + FP_LR_OFFSET) & PAGE_MASK));
237 }
238 } else {
239 if (is_64_bit) {
240 paniclog_append_noflush("%s\t Could not read LR from frame at 0x%016llx\n", cur_marker, fp + FP_LR_OFFSET64);
241 } else {
242 paniclog_append_noflush("%s\t Could not read LR from frame at 0x%08x\n", cur_marker, (uint32_t)(fp + FP_LR_OFFSET));
243 }
244 break;
245 }
246 if (((fp ^ fp_for_ppn) >> PAGE_SHIFT) != 0x0U) {
247 ppn = pmap_find_phys(pmap, fp);
248 fp_for_ppn = fp;
249 }
250 if (ppn != (ppnum_t)NULL) {
251 if (is_64_bit) {
252 fp = ml_phys_read_double_64(((((vm_offset_t)ppn) << PAGE_SHIFT)) | (fp & PAGE_MASK));
253 } else {
254 fp = ml_phys_read_word(((((vm_offset_t)ppn) << PAGE_SHIFT)) | (fp & PAGE_MASK));
255 }
256 } else {
257 if (is_64_bit) {
258 paniclog_append_noflush("%s\t Could not read FP from frame at 0x%016llx\n", cur_marker, fp);
259 } else {
260 paniclog_append_noflush("%s\t Could not read FP from frame at 0x%08x\n", cur_marker, (uint32_t)fp);
261 }
262 break;
263 }
264
265 if (is_64_bit) {
266 paniclog_append_noflush("%s\t0x%016llx\n", cur_marker, lr);
267 } else {
268 paniclog_append_noflush("%s\t0x%08x\n", cur_marker, (uint32_t)lr);
269 }
270 } while ((++i < FP_MAX_NUM_TO_EVALUATE) && (fp != topfp));
271 }
272 void
273 machine_startup(void)
274 {
275 int boot_arg;
276
277 #if 0
278 if( PE_get_hotkey( kPEControlKey ))
279 halt_in_debugger = halt_in_debugger ? 0 : 1;
280 #endif
281
282 if (PE_parse_boot_argn("debug", &debug_boot_arg, sizeof (debug_boot_arg))) {
283 panicDebugging = TRUE;
284 #if DEVELOPMENT || DEBUG
285 if (debug_boot_arg & DB_HALT) halt_in_debugger=1;
286 #endif
287 #if KDEBUG_MOJO_TRACE
288 if (debug_boot_arg & DB_PRT_KDEBUG) {
289 kdebug_serial = TRUE;
290 }
291 #endif
292 } else {
293 debug_boot_arg = 0;
294 }
295
296 if (!PE_parse_boot_argn("nvram_paniclog", &commit_paniclog_to_nvram, sizeof (commit_paniclog_to_nvram)))
297 commit_paniclog_to_nvram = 1;
298
299 /*
300 * Entering the debugger will put the CPUs into a "safe"
301 * power mode.
302 */
303 if (PE_parse_boot_argn("pmsafe_debug", &boot_arg, sizeof (boot_arg)))
304 pmsafe_debug = boot_arg;
305
306 #if NOTYET
307 hw_lock_init(&debugger_lock); /* initialize debugger lock */
308 #endif
309 hw_lock_init(&pbtlock); /* initialize print backtrace lock */
310
311 if (PE_parse_boot_argn("preempt", &boot_arg, sizeof (boot_arg))) {
312 default_preemption_rate = boot_arg;
313 }
314 if (PE_parse_boot_argn("unsafe", &boot_arg, sizeof (boot_arg))) {
315 max_unsafe_quanta = boot_arg;
316 }
317 if (PE_parse_boot_argn("poll", &boot_arg, sizeof (boot_arg))) {
318 max_poll_quanta = boot_arg;
319 }
320 if (PE_parse_boot_argn("yield", &boot_arg, sizeof (boot_arg))) {
321 sched_poll_yield_shift = boot_arg;
322 }
323 /* The I/O port to issue a read from, in the event of a panic. Useful for
324 * triggering logic analyzers.
325 */
326 if (PE_parse_boot_argn("panic_io_port", &boot_arg, sizeof (boot_arg))) {
327 /*I/O ports range from 0 through 0xFFFF */
328 panic_io_port = boot_arg & 0xffff;
329 }
330
331 machine_conf();
332
333 panic_hooks_init();
334
335 /*
336 * Start the system.
337 */
338 kernel_bootstrap();
339 /*NOTREACHED*/
340 }
341
342
343 static void
344 machine_conf(void)
345 {
346 machine_info.memory_size = (typeof(machine_info.memory_size))mem_size;
347 }
348
349
350 extern void *gPEEFIRuntimeServices;
351 extern void *gPEEFISystemTable;
352
353 /*-
354 * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
355 * code or tables extracted from it, as desired without restriction.
356 *
357 * First, the polynomial itself and its table of feedback terms. The
358 * polynomial is
359 * 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
360 *
361 * Note that we take it "backwards" and put the highest-order term in
362 * the lowest-order bit. The X^32 term is "implied"; the LSB is the
363 * X^31 term, etc. The X^0 term (usually shown as "+1") results in
364 * the MSB being 1
365 *
366 * Note that the usual hardware shift register implementation, which
367 * is what we're using (we're merely optimizing it by doing eight-bit
368 * chunks at a time) shifts bits into the lowest-order term. In our
369 * implementation, that means shifting towards the right. Why do we
370 * do it this way? Because the calculated CRC must be transmitted in
371 * order from highest-order term to lowest-order term. UARTs transmit
372 * characters in order from LSB to MSB. By storing the CRC this way
373 * we hand it to the UART in the order low-byte to high-byte; the UART
374 * sends each low-bit to hight-bit; and the result is transmission bit
375 * by bit from highest- to lowest-order term without requiring any bit
376 * shuffling on our part. Reception works similarly
377 *
378 * The feedback terms table consists of 256, 32-bit entries. Notes
379 *
380 * The table can be generated at runtime if desired; code to do so
381 * is shown later. It might not be obvious, but the feedback
382 * terms simply represent the results of eight shift/xor opera
383 * tions for all combinations of data and CRC register values
384 *
385 * The values must be right-shifted by eight bits by the "updcrc
386 * logic; the shift must be unsigned (bring in zeroes). On some
387 * hardware you could probably optimize the shift in assembler by
388 * using byte-swap instructions
389 * polynomial $edb88320
390 *
391 *
392 * CRC32 code derived from work by Gary S. Brown.
393 */
394
395 static uint32_t crc32_tab[] = {
396 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
397 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
398 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
399 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
400 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
401 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
402 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
403 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
404 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
405 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
406 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
407 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
408 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
409 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
410 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
411 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
412 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
413 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
414 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
415 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
416 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
417 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
418 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
419 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
420 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
421 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
422 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
423 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
424 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
425 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
426 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
427 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
428 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
429 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
430 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
431 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
432 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
433 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
434 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
435 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
436 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
437 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
438 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
439 };
440
441 static uint32_t
442 crc32(uint32_t crc, const void *buf, size_t size)
443 {
444 const uint8_t *p;
445
446 p = buf;
447 crc = crc ^ ~0U;
448
449 while (size--)
450 crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
451
452 return crc ^ ~0U;
453 }
454
455 static void
456 efi_set_tables_64(EFI_SYSTEM_TABLE_64 * system_table)
457 {
458 EFI_RUNTIME_SERVICES_64 *runtime;
459 uint32_t hdr_cksum;
460 uint32_t cksum;
461
462 DPRINTF("Processing 64-bit EFI tables at %p\n", system_table);
463 do {
464 DPRINTF("Header:\n");
465 DPRINTF(" Signature: 0x%016llx\n", system_table->Hdr.Signature);
466 DPRINTF(" Revision: 0x%08x\n", system_table->Hdr.Revision);
467 DPRINTF(" HeaderSize: 0x%08x\n", system_table->Hdr.HeaderSize);
468 DPRINTF(" CRC32: 0x%08x\n", system_table->Hdr.CRC32);
469 DPRINTF("RuntimeServices: 0x%016llx\n", system_table->RuntimeServices);
470 if (system_table->Hdr.Signature != EFI_SYSTEM_TABLE_SIGNATURE) {
471 kprintf("Bad EFI system table signature\n");
472 break;
473 }
474 // Verify signature of the system table
475 hdr_cksum = system_table->Hdr.CRC32;
476 system_table->Hdr.CRC32 = 0;
477 cksum = crc32(0L, system_table, system_table->Hdr.HeaderSize);
478
479 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
480 system_table->Hdr.CRC32 = hdr_cksum;
481 if (cksum != hdr_cksum) {
482 kprintf("Bad EFI system table checksum\n");
483 break;
484 }
485
486 gPEEFISystemTable = system_table;
487
488 if(system_table->RuntimeServices == 0) {
489 kprintf("No runtime table present\n");
490 break;
491 }
492 DPRINTF("RuntimeServices table at 0x%qx\n", system_table->RuntimeServices);
493 // 64-bit virtual address is OK for 64-bit EFI and 64/32-bit kernel.
494 runtime = (EFI_RUNTIME_SERVICES_64 *) (uintptr_t)system_table->RuntimeServices;
495 DPRINTF("Checking runtime services table %p\n", runtime);
496 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
497 kprintf("Bad EFI runtime table signature\n");
498 break;
499 }
500
501 // Verify signature of runtime services table
502 hdr_cksum = runtime->Hdr.CRC32;
503 runtime->Hdr.CRC32 = 0;
504 cksum = crc32(0L, runtime, runtime->Hdr.HeaderSize);
505
506 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
507 runtime->Hdr.CRC32 = hdr_cksum;
508 if (cksum != hdr_cksum) {
509 kprintf("Bad EFI runtime table checksum\n");
510 break;
511 }
512
513 gPEEFIRuntimeServices = runtime;
514 }
515 while (FALSE);
516 }
517
518 static void
519 efi_set_tables_32(EFI_SYSTEM_TABLE_32 * system_table)
520 {
521 EFI_RUNTIME_SERVICES_32 *runtime;
522 uint32_t hdr_cksum;
523 uint32_t cksum;
524
525 DPRINTF("Processing 32-bit EFI tables at %p\n", system_table);
526 do {
527 DPRINTF("Header:\n");
528 DPRINTF(" Signature: 0x%016llx\n", system_table->Hdr.Signature);
529 DPRINTF(" Revision: 0x%08x\n", system_table->Hdr.Revision);
530 DPRINTF(" HeaderSize: 0x%08x\n", system_table->Hdr.HeaderSize);
531 DPRINTF(" CRC32: 0x%08x\n", system_table->Hdr.CRC32);
532 DPRINTF("RuntimeServices: 0x%08x\n", system_table->RuntimeServices);
533 if (system_table->Hdr.Signature != EFI_SYSTEM_TABLE_SIGNATURE) {
534 kprintf("Bad EFI system table signature\n");
535 break;
536 }
537 // Verify signature of the system table
538 hdr_cksum = system_table->Hdr.CRC32;
539 system_table->Hdr.CRC32 = 0;
540 DPRINTF("System table at %p HeaderSize 0x%x\n", system_table, system_table->Hdr.HeaderSize);
541 cksum = crc32(0L, system_table, system_table->Hdr.HeaderSize);
542
543 DPRINTF("System table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
544 system_table->Hdr.CRC32 = hdr_cksum;
545 if (cksum != hdr_cksum) {
546 kprintf("Bad EFI system table checksum\n");
547 break;
548 }
549
550 gPEEFISystemTable = system_table;
551
552 if(system_table->RuntimeServices == 0) {
553 kprintf("No runtime table present\n");
554 break;
555 }
556 DPRINTF("RuntimeServices table at 0x%x\n", system_table->RuntimeServices);
557 // 32-bit virtual address is OK for 32-bit EFI and 32-bit kernel.
558 // For a 64-bit kernel, booter provides a virtual address mod 4G
559 runtime = (EFI_RUNTIME_SERVICES_32 *)
560 (system_table->RuntimeServices | VM_MIN_KERNEL_ADDRESS);
561 DPRINTF("Runtime table addressed at %p\n", runtime);
562 if (runtime->Hdr.Signature != EFI_RUNTIME_SERVICES_SIGNATURE) {
563 kprintf("Bad EFI runtime table signature\n");
564 break;
565 }
566
567 // Verify signature of runtime services table
568 hdr_cksum = runtime->Hdr.CRC32;
569 runtime->Hdr.CRC32 = 0;
570 cksum = crc32(0L, runtime, runtime->Hdr.HeaderSize);
571
572 DPRINTF("Runtime table calculated CRC32 = 0x%x, header = 0x%x\n", cksum, hdr_cksum);
573 runtime->Hdr.CRC32 = hdr_cksum;
574 if (cksum != hdr_cksum) {
575 kprintf("Bad EFI runtime table checksum\n");
576 break;
577 }
578
579 DPRINTF("Runtime functions\n");
580 DPRINTF(" GetTime : 0x%x\n", runtime->GetTime);
581 DPRINTF(" SetTime : 0x%x\n", runtime->SetTime);
582 DPRINTF(" GetWakeupTime : 0x%x\n", runtime->GetWakeupTime);
583 DPRINTF(" SetWakeupTime : 0x%x\n", runtime->SetWakeupTime);
584 DPRINTF(" SetVirtualAddressMap : 0x%x\n", runtime->SetVirtualAddressMap);
585 DPRINTF(" ConvertPointer : 0x%x\n", runtime->ConvertPointer);
586 DPRINTF(" GetVariable : 0x%x\n", runtime->GetVariable);
587 DPRINTF(" GetNextVariableName : 0x%x\n", runtime->GetNextVariableName);
588 DPRINTF(" SetVariable : 0x%x\n", runtime->SetVariable);
589 DPRINTF(" GetNextHighMonotonicCount: 0x%x\n", runtime->GetNextHighMonotonicCount);
590 DPRINTF(" ResetSystem : 0x%x\n", runtime->ResetSystem);
591
592 gPEEFIRuntimeServices = runtime;
593 }
594 while (FALSE);
595 }
596
597
598 /* Map in EFI runtime areas. */
599 static void
600 efi_init(void)
601 {
602 boot_args *args = (boot_args *)PE_state.bootArgs;
603
604 kprintf("Initializing EFI runtime services\n");
605
606 do
607 {
608 vm_offset_t vm_size, vm_addr;
609 vm_map_offset_t phys_addr;
610 EfiMemoryRange *mptr;
611 unsigned int msize, mcount;
612 unsigned int i;
613
614 msize = args->MemoryMapDescriptorSize;
615 mcount = args->MemoryMapSize / msize;
616
617 DPRINTF("efi_init() kernel base: 0x%x size: 0x%x\n",
618 args->kaddr, args->ksize);
619 DPRINTF(" efiSystemTable physical: 0x%x virtual: %p\n",
620 args->efiSystemTable,
621 (void *) ml_static_ptovirt(args->efiSystemTable));
622 DPRINTF(" efiRuntimeServicesPageStart: 0x%x\n",
623 args->efiRuntimeServicesPageStart);
624 DPRINTF(" efiRuntimeServicesPageCount: 0x%x\n",
625 args->efiRuntimeServicesPageCount);
626 DPRINTF(" efiRuntimeServicesVirtualPageStart: 0x%016llx\n",
627 args->efiRuntimeServicesVirtualPageStart);
628 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
629 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
630 if (((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) ) {
631 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
632 vm_addr = (vm_offset_t) mptr->VirtualStart;
633 /* For K64 on EFI32, shadow-map into high KVA */
634 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
635 vm_addr |= VM_MIN_KERNEL_ADDRESS;
636 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
637 DPRINTF(" Type: %x phys: %p EFIv: %p kv: %p size: %p\n",
638 mptr->Type,
639 (void *) (uintptr_t) phys_addr,
640 (void *) (uintptr_t) mptr->VirtualStart,
641 (void *) vm_addr,
642 (void *) vm_size);
643 pmap_map_bd(vm_addr, phys_addr, phys_addr + round_page(vm_size),
644 (mptr->Type == kEfiRuntimeServicesCode) ? VM_PROT_READ | VM_PROT_EXECUTE : VM_PROT_READ|VM_PROT_WRITE,
645 (mptr->Type == EfiMemoryMappedIO) ? VM_WIMG_IO : VM_WIMG_USE_DEFAULT);
646 }
647 }
648
649 if (args->Version != kBootArgsVersion2)
650 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
651
652 DPRINTF("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
653 if (args->efiMode == kBootArgsEfiMode64) {
654 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
655 } else {
656 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
657 }
658 }
659 while (FALSE);
660
661 return;
662 }
663
664 /* Returns TRUE if a page belongs to the EFI Runtime Services (code or data) */
665 boolean_t
666 efi_valid_page(ppnum_t ppn)
667 {
668 boot_args *args = (boot_args *)PE_state.bootArgs;
669 ppnum_t pstart = args->efiRuntimeServicesPageStart;
670 ppnum_t pend = pstart + args->efiRuntimeServicesPageCount;
671
672 return pstart <= ppn && ppn < pend;
673 }
674
675 /* Remap EFI runtime areas. */
676 void
677 hibernate_newruntime_map(void * map, vm_size_t map_size, uint32_t system_table_offset)
678 {
679 boot_args *args = (boot_args *)PE_state.bootArgs;
680
681 kprintf("Reinitializing EFI runtime services\n");
682
683 do
684 {
685 vm_offset_t vm_size, vm_addr;
686 vm_map_offset_t phys_addr;
687 EfiMemoryRange *mptr;
688 unsigned int msize, mcount;
689 unsigned int i;
690
691 gPEEFISystemTable = 0;
692 gPEEFIRuntimeServices = 0;
693
694 system_table_offset += ptoa_32(args->efiRuntimeServicesPageStart);
695
696 kprintf("Old system table 0x%x, new 0x%x\n",
697 (uint32_t)args->efiSystemTable, system_table_offset);
698
699 args->efiSystemTable = system_table_offset;
700
701 kprintf("Old map:\n");
702 msize = args->MemoryMapDescriptorSize;
703 mcount = args->MemoryMapSize / msize;
704 mptr = (EfiMemoryRange *)ml_static_ptovirt(args->MemoryMap);
705 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
706 if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
707
708 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
709 vm_addr = (vm_offset_t) mptr->VirtualStart;
710 /* K64 on EFI32 */
711 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
712 vm_addr |= VM_MIN_KERNEL_ADDRESS;
713 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
714
715 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
716 }
717 }
718
719 pmap_remove(kernel_pmap, i386_ptob(args->efiRuntimeServicesPageStart),
720 i386_ptob(args->efiRuntimeServicesPageStart + args->efiRuntimeServicesPageCount));
721
722 kprintf("New map:\n");
723 msize = args->MemoryMapDescriptorSize;
724 mcount = (unsigned int )(map_size / msize);
725 mptr = map;
726 for (i=0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) {
727 if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
728
729 vm_size = (vm_offset_t)i386_ptob((uint32_t)mptr->NumberOfPages);
730 vm_addr = (vm_offset_t) mptr->VirtualStart;
731 if (vm_addr < VM_MIN_KERNEL_ADDRESS)
732 vm_addr |= VM_MIN_KERNEL_ADDRESS;
733 phys_addr = (vm_map_offset_t) mptr->PhysicalStart;
734
735 kprintf("mapping[%u] %qx @ %lx, %llu\n", mptr->Type, phys_addr, (unsigned long)vm_addr, mptr->NumberOfPages);
736
737 pmap_map(vm_addr, phys_addr, phys_addr + round_page(vm_size),
738 (mptr->Type == kEfiRuntimeServicesCode) ? VM_PROT_READ | VM_PROT_EXECUTE : VM_PROT_READ|VM_PROT_WRITE,
739 (mptr->Type == EfiMemoryMappedIO) ? VM_WIMG_IO : VM_WIMG_USE_DEFAULT);
740 }
741 }
742
743 if (args->Version != kBootArgsVersion2)
744 panic("Incompatible boot args version %d revision %d\n", args->Version, args->Revision);
745
746 kprintf("Boot args version %d revision %d mode %d\n", args->Version, args->Revision, args->efiMode);
747 if (args->efiMode == kBootArgsEfiMode64) {
748 efi_set_tables_64((EFI_SYSTEM_TABLE_64 *) ml_static_ptovirt(args->efiSystemTable));
749 } else {
750 efi_set_tables_32((EFI_SYSTEM_TABLE_32 *) ml_static_ptovirt(args->efiSystemTable));
751 }
752 }
753 while (FALSE);
754
755 kprintf("Done reinitializing EFI runtime services\n");
756
757 return;
758 }
759
760 /*
761 * Find devices. The system is alive.
762 */
763 void
764 machine_init(void)
765 {
766 /* Now with VM up, switch to dynamically allocated cpu data */
767 cpu_data_realloc();
768
769 /* Ensure panic buffer is initialized. */
770 debug_log_init();
771
772 /*
773 * Display CPU identification
774 */
775 cpuid_cpu_display("CPU identification");
776 cpuid_feature_display("CPU features");
777 cpuid_extfeature_display("CPU extended features");
778
779 /*
780 * Initialize EFI runtime services.
781 */
782 efi_init();
783
784 smp_init();
785
786 /*
787 * Set up to use floating point.
788 */
789 init_fpu();
790
791 /*
792 * Configure clock devices.
793 */
794 clock_config();
795
796 #if CONFIG_MTRR
797 /*
798 * Initialize MTRR from boot processor.
799 */
800 mtrr_init();
801
802 /*
803 * Set up PAT for boot processor.
804 */
805 pat_init();
806 #endif
807
808 /*
809 * Free lowmem pages and complete other setup
810 */
811 pmap_lowmem_finalize();
812 }
813
814 /*
815 * Halt a cpu.
816 */
817 void
818 halt_cpu(void)
819 {
820 halt_all_cpus(FALSE);
821 }
822
823 int reset_mem_on_reboot = 1;
824
825 /*
826 * Halt the system or reboot.
827 */
828 __attribute__((noreturn))
829 void
830 halt_all_cpus(boolean_t reboot)
831 {
832 if (reboot) {
833 printf("MACH Reboot\n");
834 PEHaltRestart( kPERestartCPU );
835 } else {
836 printf("CPU halted\n");
837 PEHaltRestart( kPEHaltCPU );
838 }
839 while(1);
840 }
841
842
843 /* Issue an I/O port read if one has been requested - this is an event logic
844 * analyzers can use as a trigger point.
845 */
846
847 void
848 panic_io_port_read(void) {
849 if (panic_io_port)
850 (void)inb(panic_io_port);
851 }
852
853 /* For use with the MP rendezvous mechanism
854 */
855
856 uint64_t panic_restart_timeout = ~(0ULL);
857
858 #define PANIC_RESTART_TIMEOUT (3ULL * NSEC_PER_SEC)
859
860 void
861 RecordPanicStackshot()
862 {
863 #if DEVELOPMENT || DEBUG
864 int err = 0, bytes_traced = 0, bytes_used = 0;
865 /* Try to take a stackshot once at panic time */
866 if (begun_panic_stackshot) {
867 return;
868 }
869 begun_panic_stackshot = TRUE;
870
871 if (panic_stackshot_buf == 0) {
872 kdb_printf("No stackshot buffer allocated, skipping...\n");
873 return;
874 }
875
876 err = kcdata_memory_static_init(&kc_panic_data, (mach_vm_address_t)panic_stackshot_buf, KCDATA_BUFFER_BEGIN_STACKSHOT,
877 PANIC_STACKSHOT_BUFSIZE, KCFLAG_USE_MEMCOPY);
878 if (err != KERN_SUCCESS) {
879 kdb_printf("Failed to initialize kcdata buffer for panic stackshot, skipping ...\n");
880 return;
881 }
882
883 kdp_snapshot_preflight(-1, (void *) panic_stackshot_buf, PANIC_STACKSHOT_BUFSIZE, (STACKSHOT_GET_GLOBAL_MEM_STATS | STACKSHOT_SAVE_LOADINFO | STACKSHOT_KCDATA_FORMAT |
884 STACKSHOT_ENABLE_BT_FAULTING | STACKSHOT_ENABLE_UUID_FAULTING | STACKSHOT_FROM_PANIC | STACKSHOT_NO_IO_STATS
885 | STACKSHOT_THREAD_WAITINFO), &kc_panic_data, 0);
886 err = do_stackshot(NULL);
887 bytes_traced = (int) kdp_stack_snapshot_bytes_traced();
888 if (bytes_traced > 0 && !err) {
889 panic_stackshot_len = bytes_traced;
890 kdb_printf("Panic stackshot succeeded, length: %u bytes\n", bytes_traced);
891 } else {
892 bytes_used = (int) kcdata_memory_get_used_bytes(&kc_panic_data);
893 if (bytes_used > 0) {
894 kdb_printf("Panic stackshot incomplete, consumed %u bytes\n", bytes_used);
895 } else {
896 kdb_printf("Panic stackshot incomplete, consumed %u bytes, error : %d \n", bytes_used, err);
897 }
898 }
899
900 #endif /* DEVELOPMENT || DEBUG */
901 return;
902 }
903
904 void
905 SavePanicInfo(
906 __unused const char *message, uint64_t panic_options)
907 {
908 void *stackptr;
909 int cn = cpu_number();
910
911 /*
912 * Issue an I/O port read if one has been requested - this is an event logic
913 * analyzers can use as a trigger point.
914 */
915 panic_io_port_read();
916
917 /* Obtain current frame pointer */
918 __asm__ volatile("movq %%rbp, %0" : "=m" (stackptr));
919
920 /* Print backtrace - callee is internally synchronized */
921 if (panic_options & DEBUGGER_OPTION_INITPROC_PANIC) {
922 /* Special handling of launchd died panics */
923 print_launchd_info();
924 } else {
925 panic_i386_backtrace(stackptr, ((panic_double_fault_cpu == cn) ? 80: 48), NULL, FALSE, NULL);
926 }
927
928 if (panic_options & DEBUGGER_OPTION_COPROC_INITIATED_PANIC) {
929 panic_info->mph_panic_flags |= MACOS_PANIC_HEADER_FLAG_COPROC_INITIATED_PANIC;
930 }
931
932 /* Flush the paniclog */
933 paniclog_flush();
934
935 /* Try to take a panic stackshot */
936 RecordPanicStackshot();
937 }
938
939 void
940 paniclog_flush()
941 {
942 unsigned long pi_size = 0;
943
944 assert(panic_info != NULL);
945 panic_info->mph_panic_log_len = PE_get_offset_into_panic_region(debug_buf_ptr) - panic_info->mph_panic_log_offset;
946
947 /*
948 * If we've detected that we're on a co-processor system we flush the panic log via the kPEPanicSync
949 * panic callbacks, otherwise we flush via nvram (unless that has been disabled).
950 */
951 if (coprocessor_paniclog_flush) {
952 /* Only need to calculate the CRC for co-processor platforms */
953 panic_info->mph_crc = crc32(0L, &panic_info->mph_version, (debug_buf_size - offsetof(struct macos_panic_header, mph_version)));
954
955 PESavePanicInfoAction(debug_buf, debug_buf_size);
956 } else if(commit_paniclog_to_nvram) {
957 assert(debug_buf_size != 0);
958 unsigned int bufpos;
959 uintptr_t cr0;
960
961 debug_putc(0);
962
963
964 /*
965 * Now call the compressor
966 * XXX Consider using the WKdm compressor in the
967 * future, rather than just packing - would need to
968 * be co-ordinated with crashreporter, which decodes
969 * this post-restart. The compressor should be
970 * capable of in-place compression.
971 *
972 * Don't include the macOS panic header (for co-processor systems only)
973 */
974 bufpos = packA(debug_buf_base, (unsigned int) (debug_buf_ptr - debug_buf_base),
975 debug_buf_size);
976 /*
977 * If compression was successful, use the compressed length
978 */
979 pi_size = bufpos ? bufpos : (unsigned) (debug_buf_ptr - debug_buf_base);
980
981 /*
982 * The following sequence is a workaround for:
983 * <rdar://problem/5915669> SnowLeopard10A67: AppleEFINVRAM should not invoke
984 * any routines that use floating point (MMX in this case) when saving panic
985 * logs to nvram/flash.
986 */
987 cr0 = get_cr0();
988 clear_ts();
989
990 /*
991 * Save panic log to non-volatile store
992 * Panic info handler must truncate data that is
993 * too long for this platform.
994 * This call must save data synchronously,
995 * since we can subsequently halt the system.
996 */
997 kprintf("Attempting to commit panic log to NVRAM\n");
998 pi_size = PESavePanicInfo((unsigned char *)debug_buf_base,
999 (uint32_t)pi_size );
1000 set_cr0(cr0);
1001
1002 /*
1003 * Uncompress in-place, to permit examination of
1004 * the panic log by debuggers.
1005 */
1006 if (bufpos) {
1007 unpackA(debug_buf_base, bufpos);
1008 }
1009 }
1010 }
1011
1012 char *
1013 machine_boot_info(char *buf, __unused vm_size_t size)
1014 {
1015 *buf ='\0';
1016 return buf;
1017 }
1018
1019 /* Routines for address - symbol translation. Not called unless the "keepsyms"
1020 * boot-arg is supplied.
1021 */
1022
1023 static int
1024 panic_print_macho_symbol_name(kernel_mach_header_t *mh, vm_address_t search, const char *module_name)
1025 {
1026 kernel_nlist_t *sym = NULL;
1027 struct load_command *cmd;
1028 kernel_segment_command_t *orig_ts = NULL, *orig_le = NULL;
1029 struct symtab_command *orig_st = NULL;
1030 unsigned int i;
1031 char *strings, *bestsym = NULL;
1032 vm_address_t bestaddr = 0, diff, curdiff;
1033
1034 /* Assume that if it's loaded and linked into the kernel, it's a valid Mach-O */
1035
1036 cmd = (struct load_command *) &mh[1];
1037 for (i = 0; i < mh->ncmds; i++) {
1038 if (cmd->cmd == LC_SEGMENT_KERNEL) {
1039 kernel_segment_command_t *orig_sg = (kernel_segment_command_t *) cmd;
1040
1041 if (strncmp(SEG_TEXT, orig_sg->segname,
1042 sizeof(orig_sg->segname)) == 0)
1043 orig_ts = orig_sg;
1044 else if (strncmp(SEG_LINKEDIT, orig_sg->segname,
1045 sizeof(orig_sg->segname)) == 0)
1046 orig_le = orig_sg;
1047 else if (strncmp("", orig_sg->segname,
1048 sizeof(orig_sg->segname)) == 0)
1049 orig_ts = orig_sg; /* pre-Lion i386 kexts have a single unnamed segment */
1050 }
1051 else if (cmd->cmd == LC_SYMTAB)
1052 orig_st = (struct symtab_command *) cmd;
1053
1054 cmd = (struct load_command *) ((uintptr_t) cmd + cmd->cmdsize);
1055 }
1056
1057 if ((orig_ts == NULL) || (orig_st == NULL) || (orig_le == NULL))
1058 return 0;
1059
1060 if ((search < orig_ts->vmaddr) ||
1061 (search >= orig_ts->vmaddr + orig_ts->vmsize)) {
1062 /* search out of range for this mach header */
1063 return 0;
1064 }
1065
1066 sym = (kernel_nlist_t *)(uintptr_t)(orig_le->vmaddr + orig_st->symoff - orig_le->fileoff);
1067 strings = (char *)(uintptr_t)(orig_le->vmaddr + orig_st->stroff - orig_le->fileoff);
1068 diff = search;
1069
1070 for (i = 0; i < orig_st->nsyms; i++) {
1071 if (sym[i].n_type & N_STAB) continue;
1072
1073 if (sym[i].n_value <= search) {
1074 curdiff = search - (vm_address_t)sym[i].n_value;
1075 if (curdiff < diff) {
1076 diff = curdiff;
1077 bestaddr = sym[i].n_value;
1078 bestsym = strings + sym[i].n_un.n_strx;
1079 }
1080 }
1081 }
1082
1083 if (bestsym != NULL) {
1084 if (diff != 0) {
1085 paniclog_append_noflush("%s : %s + 0x%lx", module_name, bestsym, (unsigned long)diff);
1086 } else {
1087 paniclog_append_noflush("%s : %s", module_name, bestsym);
1088 }
1089 return 1;
1090 }
1091 return 0;
1092 }
1093
1094 extern kmod_info_t * kmod; /* the list of modules */
1095
1096 static void
1097 panic_print_kmod_symbol_name(vm_address_t search)
1098 {
1099 u_int i;
1100
1101 if (gLoadedKextSummaries == NULL)
1102 return;
1103 for (i = 0; i < gLoadedKextSummaries->numSummaries; ++i) {
1104 OSKextLoadedKextSummary *summary = gLoadedKextSummaries->summaries + i;
1105
1106 if ((search >= summary->address) &&
1107 (search < (summary->address + summary->size)))
1108 {
1109 kernel_mach_header_t *header = (kernel_mach_header_t *)(uintptr_t) summary->address;
1110 if (panic_print_macho_symbol_name(header, search, summary->name) == 0) {
1111 paniclog_append_noflush("%s + %llu", summary->name, (unsigned long)search - summary->address);
1112 }
1113 break;
1114 }
1115 }
1116 }
1117
1118 void
1119 panic_print_symbol_name(vm_address_t search)
1120 {
1121 /* try searching in the kernel */
1122 if (panic_print_macho_symbol_name(&_mh_execute_header, search, "mach_kernel") == 0) {
1123 /* that failed, now try to search for the right kext */
1124 panic_print_kmod_symbol_name(search);
1125 }
1126 }
1127
1128 /* Generate a backtrace, given a frame pointer - this routine
1129 * should walk the stack safely. The trace is appended to the panic log
1130 * and conditionally, to the console. If the trace contains kernel module
1131 * addresses, display the module name, load address and dependencies.
1132 */
1133
1134 #define DUMPFRAMES 32
1135 #define PBT_TIMEOUT_CYCLES (5 * 1000 * 1000 * 1000ULL)
1136 void
1137 panic_i386_backtrace(void *_frame, int nframes, const char *msg, boolean_t regdump, x86_saved_state_t *regs)
1138 {
1139 cframe_t *frame = (cframe_t *)_frame;
1140 vm_offset_t raddrs[DUMPFRAMES];
1141 vm_offset_t PC = 0;
1142 int frame_index;
1143 volatile uint32_t *ppbtcnt = &pbtcnt;
1144 uint64_t bt_tsc_timeout;
1145 boolean_t keepsyms = FALSE;
1146 int cn = cpu_number();
1147 boolean_t old_doprnt_hide_pointers = doprnt_hide_pointers;
1148
1149 if(pbtcpu != cn) {
1150 hw_atomic_add(&pbtcnt, 1);
1151 /* Spin on print backtrace lock, which serializes output
1152 * Continue anyway if a timeout occurs.
1153 */
1154 hw_lock_to(&pbtlock, ~0U);
1155 pbtcpu = cn;
1156 }
1157
1158 if (__improbable(doprnt_hide_pointers == TRUE)) {
1159 /* If we're called directly, the Debugger() function will not be called,
1160 * so we need to reset the value in here. */
1161 doprnt_hide_pointers = FALSE;
1162 }
1163
1164 panic_check_hook();
1165
1166 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms));
1167
1168 if (msg != NULL) {
1169 paniclog_append_noflush("%s", msg);
1170 }
1171
1172 if ((regdump == TRUE) && (regs != NULL)) {
1173 x86_saved_state64_t *ss64p = saved_state64(regs);
1174 paniclog_append_noflush(
1175 "RAX: 0x%016llx, RBX: 0x%016llx, RCX: 0x%016llx, RDX: 0x%016llx\n"
1176 "RSP: 0x%016llx, RBP: 0x%016llx, RSI: 0x%016llx, RDI: 0x%016llx\n"
1177 "R8: 0x%016llx, R9: 0x%016llx, R10: 0x%016llx, R11: 0x%016llx\n"
1178 "R12: 0x%016llx, R13: 0x%016llx, R14: 0x%016llx, R15: 0x%016llx\n"
1179 "RFL: 0x%016llx, RIP: 0x%016llx, CS: 0x%016llx, SS: 0x%016llx\n",
1180 ss64p->rax, ss64p->rbx, ss64p->rcx, ss64p->rdx,
1181 ss64p->isf.rsp, ss64p->rbp, ss64p->rsi, ss64p->rdi,
1182 ss64p->r8, ss64p->r9, ss64p->r10, ss64p->r11,
1183 ss64p->r12, ss64p->r13, ss64p->r14, ss64p->r15,
1184 ss64p->isf.rflags, ss64p->isf.rip, ss64p->isf.cs,
1185 ss64p->isf.ss);
1186 PC = ss64p->isf.rip;
1187 }
1188
1189 paniclog_append_noflush("Backtrace (CPU %d), "
1190 #if PRINT_ARGS_FROM_STACK_FRAME
1191 "Frame : Return Address (4 potential args on stack)\n", cn);
1192 #else
1193 "Frame : Return Address\n", cn);
1194 #endif
1195
1196 for (frame_index = 0; frame_index < nframes; frame_index++) {
1197 vm_offset_t curframep = (vm_offset_t) frame;
1198
1199 if (!curframep)
1200 break;
1201
1202 if (curframep & 0x3) {
1203 paniclog_append_noflush("Unaligned frame\n");
1204 goto invalid;
1205 }
1206
1207 if (!kvtophys(curframep) ||
1208 !kvtophys(curframep + sizeof(cframe_t) - 1)) {
1209 paniclog_append_noflush("No mapping exists for frame pointer\n");
1210 goto invalid;
1211 }
1212
1213 paniclog_append_noflush("%p : 0x%lx ", frame, frame->caller);
1214 if (frame_index < DUMPFRAMES)
1215 raddrs[frame_index] = frame->caller;
1216
1217 #if PRINT_ARGS_FROM_STACK_FRAME
1218 if (kvtophys((vm_offset_t)&(frame->args[3])))
1219 paniclog_append_noflush("(0x%x 0x%x 0x%x 0x%x) ",
1220 frame->args[0], frame->args[1],
1221 frame->args[2], frame->args[3]);
1222 #endif
1223
1224 /* Display address-symbol translation only if the "keepsyms"
1225 * boot-arg is suppplied, since we unload LINKEDIT otherwise.
1226 * This routine is potentially unsafe; also, function
1227 * boundary identification is unreliable after a strip -x.
1228 */
1229 if (keepsyms)
1230 panic_print_symbol_name((vm_address_t)frame->caller);
1231
1232 paniclog_append_noflush("\n");
1233
1234 frame = frame->prev;
1235 }
1236
1237 if (frame_index >= nframes)
1238 paniclog_append_noflush("\tBacktrace continues...\n");
1239
1240 goto out;
1241
1242 invalid:
1243 paniclog_append_noflush("Backtrace terminated-invalid frame pointer %p\n",frame);
1244 out:
1245
1246 /* Identify kernel modules in the backtrace and display their
1247 * load addresses and dependencies. This routine should walk
1248 * the kmod list safely.
1249 */
1250 if (frame_index)
1251 kmod_panic_dump((vm_offset_t *)&raddrs[0], frame_index);
1252
1253 if (PC != 0)
1254 kmod_panic_dump(&PC, 1);
1255
1256 panic_display_system_configuration(FALSE);
1257
1258 doprnt_hide_pointers = old_doprnt_hide_pointers;
1259
1260 /* Release print backtrace lock, to permit other callers in the
1261 * event of panics on multiple processors.
1262 */
1263 hw_lock_unlock(&pbtlock);
1264 hw_atomic_sub(&pbtcnt, 1);
1265 /* Wait for other processors to complete output
1266 * Timeout and continue after PBT_TIMEOUT_CYCLES.
1267 */
1268 bt_tsc_timeout = rdtsc64() + PBT_TIMEOUT_CYCLES;
1269 while(*ppbtcnt && (rdtsc64() < bt_tsc_timeout));
1270 }
1271
1272 static boolean_t
1273 debug_copyin(pmap_t p, uint64_t uaddr, void *dest, size_t size)
1274 {
1275 size_t rem = size;
1276 char *kvaddr = dest;
1277
1278 while (rem) {
1279 ppnum_t upn = pmap_find_phys(p, uaddr);
1280 uint64_t phys_src = ptoa_64(upn) | (uaddr & PAGE_MASK);
1281 uint64_t phys_dest = kvtophys((vm_offset_t)kvaddr);
1282 uint64_t src_rem = PAGE_SIZE - (phys_src & PAGE_MASK);
1283 uint64_t dst_rem = PAGE_SIZE - (phys_dest & PAGE_MASK);
1284 size_t cur_size = (uint32_t) MIN(src_rem, dst_rem);
1285 cur_size = MIN(cur_size, rem);
1286
1287 if (upn && pmap_valid_page(upn) && phys_dest) {
1288 bcopy_phys(phys_src, phys_dest, cur_size);
1289 }
1290 else
1291 break;
1292 uaddr += cur_size;
1293 kvaddr += cur_size;
1294 rem -= cur_size;
1295 }
1296 return (rem == 0);
1297 }
1298
1299 void
1300 print_threads_registers(thread_t thread)
1301 {
1302 x86_saved_state_t *savestate;
1303
1304 savestate = get_user_regs(thread);
1305 paniclog_append_noflush(
1306 "\nRAX: 0x%016llx, RBX: 0x%016llx, RCX: 0x%016llx, RDX: 0x%016llx\n"
1307 "RSP: 0x%016llx, RBP: 0x%016llx, RSI: 0x%016llx, RDI: 0x%016llx\n"
1308 "R8: 0x%016llx, R9: 0x%016llx, R10: 0x%016llx, R11: 0x%016llx\n"
1309 "R12: 0x%016llx, R13: 0x%016llx, R14: 0x%016llx, R15: 0x%016llx\n"
1310 "RFL: 0x%016llx, RIP: 0x%016llx, CS: 0x%016llx, SS: 0x%016llx\n\n",
1311 savestate->ss_64.rax, savestate->ss_64.rbx, savestate->ss_64.rcx, savestate->ss_64.rdx,
1312 savestate->ss_64.isf.rsp, savestate->ss_64.rbp, savestate->ss_64.rsi, savestate->ss_64.rdi,
1313 savestate->ss_64.r8, savestate->ss_64.r9, savestate->ss_64.r10, savestate->ss_64.r11,
1314 savestate->ss_64.r12, savestate->ss_64.r13, savestate->ss_64.r14, savestate->ss_64.r15,
1315 savestate->ss_64.isf.rflags, savestate->ss_64.isf.rip, savestate->ss_64.isf.cs,
1316 savestate->ss_64.isf.ss);
1317 }
1318
1319 void
1320 print_tasks_user_threads(task_t task)
1321 {
1322 thread_t thread = current_thread();
1323 x86_saved_state_t *savestate;
1324 pmap_t pmap = 0;
1325 uint64_t rbp;
1326 const char *cur_marker = 0;
1327 int j;
1328
1329 for (j = 0, thread = (thread_t) queue_first(&task->threads); j < task->thread_count;
1330 ++j, thread = (thread_t) queue_next(&thread->task_threads)) {
1331
1332 paniclog_append_noflush("Thread %d: %p\n", j, thread);
1333 pmap = get_task_pmap(task);
1334 savestate = get_user_regs(thread);
1335 rbp = savestate->ss_64.rbp;
1336 paniclog_append_noflush("\t0x%016llx\n", savestate->ss_64.isf.rip);
1337 print_one_backtrace(pmap, (vm_offset_t)rbp, cur_marker, TRUE);
1338 paniclog_append_noflush("\n");
1339 }
1340 }
1341
1342 void
1343 print_thread_num_that_crashed(task_t task)
1344 {
1345 thread_t c_thread = current_thread();
1346 thread_t thread;
1347 int j;
1348
1349 for (j = 0, thread = (thread_t) queue_first(&task->threads); j < task->thread_count;
1350 ++j, thread = (thread_t) queue_next(&thread->task_threads)) {
1351
1352 if (c_thread == thread) {
1353 paniclog_append_noflush("\nThread %d crashed\n", j);
1354 break;
1355 }
1356 }
1357 }
1358
1359 #define PANICLOG_UUID_BUF_SIZE 256
1360
1361 void print_uuid_info(task_t task)
1362 {
1363 uint32_t uuid_info_count = 0;
1364 mach_vm_address_t uuid_info_addr = 0;
1365 boolean_t have_map = (task->map != NULL) && (ml_validate_nofault((vm_offset_t)(task->map), sizeof(struct _vm_map)));
1366 boolean_t have_pmap = have_map && (task->map->pmap != NULL) && (ml_validate_nofault((vm_offset_t)(task->map->pmap), sizeof(struct pmap)));
1367 int task_pid = pid_from_task(task);
1368 char uuidbuf[PANICLOG_UUID_BUF_SIZE] = {0};
1369 char *uuidbufptr = uuidbuf;
1370 uint32_t k;
1371
1372 if (have_pmap && task->active && task_pid > 0) {
1373 /* Read dyld_all_image_infos struct from task memory to get UUID array count & location */
1374 struct user64_dyld_all_image_infos task_image_infos;
1375 if (debug_copyin(task->map->pmap, task->all_image_info_addr,
1376 &task_image_infos, sizeof(struct user64_dyld_all_image_infos))) {
1377 uuid_info_count = (uint32_t)task_image_infos.uuidArrayCount;
1378 uuid_info_addr = task_image_infos.uuidArray;
1379 }
1380
1381 /* If we get a NULL uuid_info_addr (which can happen when we catch dyld
1382 * in the middle of updating this data structure), we zero the
1383 * uuid_info_count so that we won't even try to save load info for this task
1384 */
1385 if (!uuid_info_addr) {
1386 uuid_info_count = 0;
1387 }
1388 }
1389
1390 if (task_pid > 0 && uuid_info_count > 0) {
1391 uint32_t uuid_info_size = sizeof(struct user64_dyld_uuid_info);
1392 uint32_t uuid_array_size = uuid_info_count * uuid_info_size;
1393 uint32_t uuid_copy_size = 0;
1394 uint32_t uuid_image_count = 0;
1395 char *current_uuid_buffer = NULL;
1396 /* Copy in the UUID info array. It may be nonresident, in which case just fix up nloadinfos to 0 */
1397
1398 paniclog_append_noflush("\nuuid info:\n");
1399 while (uuid_array_size) {
1400 if (uuid_array_size <= PANICLOG_UUID_BUF_SIZE) {
1401 uuid_copy_size = uuid_array_size;
1402 uuid_image_count = uuid_array_size/uuid_info_size;
1403 } else {
1404 uuid_image_count = PANICLOG_UUID_BUF_SIZE/uuid_info_size;
1405 uuid_copy_size = uuid_image_count * uuid_info_size;
1406 }
1407 if (have_pmap && !debug_copyin(task->map->pmap, uuid_info_addr, uuidbufptr,
1408 uuid_copy_size)) {
1409 paniclog_append_noflush("Error!! Failed to copy UUID info for task %p pid %d\n", task, task_pid);
1410 uuid_image_count = 0;
1411 break;
1412 }
1413
1414 if (uuid_image_count > 0) {
1415 current_uuid_buffer = uuidbufptr;
1416 for (k = 0; k < uuid_image_count; k++) {
1417 paniclog_append_noflush(" %#llx", *(uint64_t *)current_uuid_buffer);
1418 current_uuid_buffer += sizeof(uint64_t);
1419 uint8_t *uuid = (uint8_t *)current_uuid_buffer;
1420 paniclog_append_noflush("\tuuid = <%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x>\n",
1421 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7], uuid[8],
1422 uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
1423 current_uuid_buffer += 16;
1424 }
1425 bzero(&uuidbuf, sizeof(uuidbuf));
1426 }
1427 uuid_info_addr += uuid_copy_size;
1428 uuid_array_size -= uuid_copy_size;
1429 }
1430 }
1431 }
1432
1433 void print_launchd_info(void)
1434 {
1435 task_t task = current_task();
1436 thread_t thread = current_thread();
1437 volatile uint32_t *ppbtcnt = &pbtcnt;
1438 uint64_t bt_tsc_timeout;
1439 int cn = cpu_number();
1440
1441 if(pbtcpu != cn) {
1442 hw_atomic_add(&pbtcnt, 1);
1443 /* Spin on print backtrace lock, which serializes output
1444 * Continue anyway if a timeout occurs.
1445 */
1446 hw_lock_to(&pbtlock, ~0U);
1447 pbtcpu = cn;
1448 }
1449
1450 print_uuid_info(task);
1451 print_thread_num_that_crashed(task);
1452 print_threads_registers(thread);
1453 print_tasks_user_threads(task);
1454
1455 panic_display_system_configuration(TRUE);
1456
1457 /* Release print backtrace lock, to permit other callers in the
1458 * event of panics on multiple processors.
1459 */
1460 hw_lock_unlock(&pbtlock);
1461 hw_atomic_sub(&pbtcnt, 1);
1462 /* Wait for other processors to complete output
1463 * Timeout and continue after PBT_TIMEOUT_CYCLES.
1464 */
1465 bt_tsc_timeout = rdtsc64() + PBT_TIMEOUT_CYCLES;
1466 while(*ppbtcnt && (rdtsc64() < bt_tsc_timeout));
1467
1468 }