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