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