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