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