]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/AT386/model_dep.c
xnu-1228.12.14.tar.gz
[apple/xnu.git] / osfmk / i386 / AT386 / model_dep.c
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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
1c79356b 69#include <platforms.h>
1c79356b 70#include <mach_kdb.h>
1c79356b
A
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>
1c79356b
A
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>
1c79356b 85#include <kern/cpu_data.h>
91447636 86#include <kern/machine.h>
1c79356b 87#include <i386/fpu.h>
1c79356b 88#include <i386/ipl.h>
1c79356b 89#include <i386/misc_protos.h>
91447636 90#include <i386/mtrr.h>
0c530ab8
A
91#include <i386/machine_routines.h>
92#include <i386/pmCPU.h>
91447636 93#include <i386/postcode.h>
2d21ac55
A
94#include <i386/trap.h>
95#include <i386/mp.h> /* mp_rendezvous_break_lock */
0c530ab8 96#include <architecture/i386/pio.h> /* inb() */
55e303ae 97#include <pexpert/i386/boot.h>
1c79356b
A
98#if MACH_KDB
99#include <ddb/db_aout.h>
100#endif /* MACH_KDB */
1c79356b 101
0c530ab8
A
102#include <vm/pmap.h>
103#include <vm/vm_map.h>
104#include <vm/vm_kern.h>
105
1c79356b 106#include <i386/mp_desc.h>
55e303ae 107#include <i386/mp.h>
0c530ab8 108#include <i386/cpuid.h>
1c79356b 109
9bccf70c 110#include <IOKit/IOPlatformExpert.h>
0c530ab8
A
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>
9bccf70c 119
91447636
A
120void enable_bluebox(void);
121void disable_bluebox(void);
122
55e303ae 123static void machine_conf(void);
1c79356b 124
91447636
A
125extern int default_preemption_rate;
126extern int max_unsafe_quanta;
127extern int max_poll_quanta;
91447636
A
128extern unsigned int panic_is_inited;
129
0c530ab8
A
130int db_run_mode;
131
0c530ab8
A
132volatile int pbtcpu = -1;
133hw_lock_data_t pbtlock; /* backtrace print lock */
134uint32_t pbtcnt = 0;
135
0c530ab8
A
136typedef struct _cframe_t {
137 struct _cframe_t *prev;
138 unsigned caller;
139 unsigned args[0];
140} cframe_t;
141
2d21ac55
A
142static unsigned panic_io_port;
143static unsigned commit_paniclog_to_nvram;
0c530ab8 144
c910b4d9
A
145int debug_boot_arg;
146
1c79356b 147void
2d21ac55 148machine_startup(void)
1c79356b 149{
55e303ae 150 int boot_arg;
1c79356b 151
55e303ae
A
152#if 0
153 if( PE_get_hotkey( kPEControlKey ))
154 halt_in_debugger = halt_in_debugger ? 0 : 1;
1c79356b
A
155#endif
156
593a1d5f 157 if (PE_parse_boot_argn("debug", &boot_arg, sizeof (boot_arg))) {
55e303ae 158 if (boot_arg & DB_HALT) halt_in_debugger=1;
2d21ac55 159 if (boot_arg & DB_PRT) disable_debug_output=FALSE;
55e303ae
A
160 if (boot_arg & DB_SLOG) systemLogDiags=TRUE;
161 if (boot_arg & DB_NMI) panicDebugging=TRUE;
c910b4d9
A
162 if (boot_arg & DB_LOG_PI_SCRN) logPanicDataToScreen=TRUE;
163 debug_boot_arg = boot_arg;
55e303ae 164 }
1c79356b 165
593a1d5f 166 if (!PE_parse_boot_argn("nvram_paniclog", &commit_paniclog_to_nvram, sizeof (commit_paniclog_to_nvram)))
2d21ac55
A
167 commit_paniclog_to_nvram = 1;
168
169 /*
170 * Entering the debugger will put the CPUs into a "safe"
171 * power mode.
172 */
593a1d5f 173 if (PE_parse_boot_argn("pmsafe_debug", &boot_arg, sizeof (boot_arg)))
2d21ac55
A
174 pmsafe_debug = boot_arg;
175
55e303ae
A
176#if NOTYET
177 hw_lock_init(&debugger_lock); /* initialize debugger lock */
6601e61a 178#endif
0c530ab8 179 hw_lock_init(&pbtlock); /* initialize print backtrace lock */
1c79356b
A
180
181#if MACH_KDB
1c79356b 182 /*
55e303ae 183 * Initialize KDB
1c79356b 184 */
55e303ae
A
185#if DB_MACHINE_COMMANDS
186 db_machine_commands_install(ppc_db_commands);
187#endif /* DB_MACHINE_COMMANDS */
1c79356b
A
188 ddb_init();
189
55e303ae
A
190 if (boot_arg & DB_KDB)
191 current_debugger = KDB_CUR_DB;
192
1c79356b
A
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.
1c79356b 197 */
55e303ae
A
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
593a1d5f 205 if (PE_parse_boot_argn("preempt", &boot_arg, sizeof (boot_arg))) {
55e303ae 206 default_preemption_rate = boot_arg;
1c79356b 207 }
593a1d5f 208 if (PE_parse_boot_argn("unsafe", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
209 max_unsafe_quanta = boot_arg;
210 }
593a1d5f 211 if (PE_parse_boot_argn("poll", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
212 max_poll_quanta = boot_arg;
213 }
593a1d5f 214 if (PE_parse_boot_argn("yield", &boot_arg, sizeof (boot_arg))) {
55e303ae
A
215 sched_poll_yield_shift = boot_arg;
216 }
593a1d5f 217 if (PE_parse_boot_argn("idlehalt", &boot_arg, sizeof (boot_arg))) {
91447636
A
218 idlehalt = boot_arg;
219 }
0c530ab8
A
220/* The I/O port to issue a read from, in the event of a panic. Useful for
221 * triggering logic analyzers.
222 */
593a1d5f 223 if (PE_parse_boot_argn("panic_io_port", &boot_arg, sizeof (boot_arg))) {
0c530ab8
A
224 /*I/O ports range from 0 through 0xFFFF */
225 panic_io_port = boot_arg & 0xffff;
226 }
227
55e303ae
A
228 machine_conf();
229
230#if NOTYET
231 ml_thrm_init(); /* Start thermal monitoring on this processor */
1c79356b
A
232#endif
233
234 /*
235 * Start the system.
236 */
91447636
A
237 kernel_bootstrap();
238 /*NOTREACHED*/
1c79356b
A
239}
240
55e303ae
A
241
242static void
243machine_conf(void)
1c79356b 244{
55e303ae 245 machine_info.memory_size = mem_size;
1c79356b
A
246}
247
0c530ab8
A
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
2d21ac55 361 kprintf("Processing 64-bit EFI tables at %p\n", system_table);
0c530ab8
A
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);
2d21ac55
A
382 runtime = (EFI_RUNTIME_SERVICES_64 *) (uintptr_t)system_table->RuntimeServices; // XXX
383 kprintf("Checking runtime services table %p\n", runtime);
0c530ab8
A
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
2d21ac55 413 kprintf("Processing 32-bit EFI tables at %p\n", system_table);
0c530ab8
A
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
2d21ac55 433 kprintf("RuntimeServices table at %p\n", system_table->RuntimeServices);
0c530ab8
A
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 {
2d21ac55 468 vm_offset_t vm_size, vm_addr;
0c530ab8
A
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 {
2d21ac55 516 vm_offset_t vm_size, vm_addr;
0c530ab8
A
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
2d21ac55
A
527 kprintf("Old system table 0x%x, new 0x%x\n",
528 (uint32_t)args->efiSystemTable, system_table_offset);
0c530ab8 529
2d21ac55 530 args->efiSystemTable = system_table_offset;
0c530ab8
A
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
2d21ac55 543 kprintf("mapping[%u] %qx @ %x, %llu\n", mptr->Type, phys_addr, vm_addr, mptr->NumberOfPages);
0c530ab8
A
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
2d21ac55 561 kprintf("mapping[%u] %qx @ %x, %llu\n", mptr->Type, phys_addr, vm_addr, mptr->NumberOfPages);
0c530ab8
A
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
1c79356b
A
586/*
587 * Find devices. The system is alive.
588 */
589void
590machine_init(void)
591{
0c530ab8
A
592 /* Ensure panic buffer is initialized. */
593 debug_log_init();
594
1c79356b
A
595 /*
596 * Display CPU identification
597 */
0c530ab8
A
598 cpuid_cpu_display("CPU identification");
599 cpuid_feature_display("CPU features");
600 cpuid_extfeature_display("CPU extended features");
1c79356b 601
0c530ab8
A
602 /*
603 * Initialize EFI runtime services.
604 */
605 efi_init();
55e303ae 606
55e303ae 607 smp_init();
1c79356b
A
608
609 /*
610 * Set up to use floating point.
611 */
612 init_fpu();
613
1c79356b
A
614 /*
615 * Configure clock devices.
616 */
617 clock_config();
91447636
A
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();
1c79356b
A
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
9bccf70c 650halt_all_cpus(boolean_t reboot)
1c79356b 651{
55e303ae 652 if (reboot) {
55e303ae
A
653 printf("MACH Reboot\n");
654 PEHaltRestart( kPERestartCPU );
655 } else {
656 printf("CPU halted\n");
657 PEHaltRestart( kPEHaltCPU );
1c79356b 658 }
55e303ae 659 while(1);
1c79356b
A
660}
661
2d21ac55 662
0c530ab8
A
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
4a3eedf9 676#if !CONFIG_EMBEDDED
0c530ab8
A
677static void
678machine_halt_cpu(__unused void *arg) {
679 panic_io_port_read();
2d21ac55 680 pmCPUHalt(PM_HALT_DEBUG);
1c79356b 681}
4a3eedf9 682#endif
1c79356b
A
683
684void
685Debugger(
686 const char *message)
687{
0c530ab8
A
688 unsigned long pi_size = 0;
689 void *stackptr;
91447636 690
0c530ab8 691 hw_atomic_add(&debug_mode, 1);
91447636
A
692 if (!panic_is_inited) {
693 postcode(PANIC_HLT);
694 asm("hlt");
695 }
696
0c530ab8 697
1c79356b 698 printf("Debugger called: <%s>\n", message);
91447636 699 kprintf("Debugger called: <%s>\n", message);
1c79356b 700
0c530ab8
A
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 */
935ed37a 720 panic_i386_backtrace(stackptr, 16, NULL, FALSE, NULL);
0c530ab8
A
721
722 /* everything should be printed now so copy to NVRAM
723 */
724
725 if( debug_buf_size > 0) {
2d21ac55
A
726 /* Optionally sync the panic log, if any, to NVRAM
727 * This is the default.
728 */
729 if (commit_paniclog_to_nvram) {
0c530ab8 730 unsigned int bufpos;
935ed37a 731 uintptr_t cr0;
2d21ac55 732
0c530ab8
A
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
2d21ac55
A
739 * this post-restart. The compressor should be
740 * capable of in-place compression.
0c530ab8 741 */
2d21ac55
A
742 bufpos = packA(debug_buf,
743 (unsigned int) (debug_buf_ptr - debug_buf), debug_buf_size);
0c530ab8
A
744 /* If compression was successful,
745 * use the compressed length
746 */
2d21ac55
A
747 pi_size = bufpos ? bufpos : (unsigned) (debug_buf_ptr - debug_buf);
748
0c530ab8
A
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 */
2d21ac55 755 kprintf("Attempting to commit panic log to NVRAM\n");
935ed37a
A
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
0c530ab8
A
764 pi_size = PESavePanicInfo((unsigned char *)debug_buf,
765 pi_size );
935ed37a 766 set_cr0(cr0);
2d21ac55
A
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 }
0c530ab8
A
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();
2d21ac55
A
784#if CONFIG_EMBEDDED
785 PEHaltRestart(kPEPanicRestartCPU);
786#else
0c530ab8
A
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);
2d21ac55 793#endif
0c530ab8
A
794 /* NOT REACHED */
795 }
796 }
55e303ae 797
1c79356b 798 __asm__("int3");
0c530ab8 799 hw_atomic_sub(&debug_mode, 1);
1c79356b
A
800}
801
802void
91447636 803enable_bluebox(void)
1c79356b 804{
1c79356b 805}
0c530ab8 806
91447636
A
807void
808disable_bluebox(void)
1c79356b
A
809{
810}
811
812char *
91447636 813machine_boot_info(char *buf, __unused vm_size_t size)
1c79356b
A
814{
815 *buf ='\0';
816 return buf;
817}
818
0c530ab8
A
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
0c530ab8
A
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
2d21ac55
A
858 if (strncmp(SEG_TEXT, orig_sg->segname,
859 sizeof(orig_sg->segname)) == 0)
0c530ab8 860 orig_ts = orig_sg;
2d21ac55
A
861 else if (strncmp(SEG_LINKEDIT, orig_sg->segname,
862 sizeof(orig_sg->segname)) == 0)
0c530ab8 863 orig_le = orig_sg;
2d21ac55
A
864 else if (strncmp("", orig_sg->segname,
865 sizeof(orig_sg->segname)) == 0)
0c530ab8
A
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) {
2d21ac55 906 kdb_printf("%s + 0x%08x \n", bestsym, diff);
0c530ab8 907 } else {
2d21ac55 908 kdb_printf("%s \n", bestsym);
0c530ab8
A
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 */
2d21ac55 930 kdb_printf("%s + %d \n", current_kmod->name, search - current_kmod->address);
0c530ab8
A
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
935ed37a 955panic_i386_backtrace(void *_frame, int nframes, const char *msg, boolean_t regdump, x86_saved_state_t *regs)
0c530ab8
A
956{
957 cframe_t *frame = (cframe_t *)_frame;
958 vm_offset_t raddrs[DUMPFRAMES];
935ed37a 959 vm_offset_t PC = 0;
0c530ab8
A
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 */
2d21ac55 970 hw_lock_to(&pbtlock, LockTimeOutTSC);
0c530ab8
A
971 pbtcpu = cpu_number();
972 }
973
593a1d5f 974 PE_parse_boot_argn("keepsyms", &keepsyms, sizeof (keepsyms));
0c530ab8 975
935ed37a
A
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());
0c530ab8
A
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
2d21ac55 1013 kdb_printf("%p : 0x%x ", frame, frame->caller);
0c530ab8
A
1014 if (frame_index < DUMPFRAMES)
1015 raddrs[frame_index] = frame->caller;
1016
1017 if (kvtophys((vm_offset_t)&(frame->args[3])))
2d21ac55 1018 kdb_printf("(0x%x 0x%x 0x%x 0x%x) \n",
0c530ab8
A
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:
2d21ac55 1044 kdb_printf("Backtrace terminated-invalid frame pointer %p\n",frame);
0c530ab8
A
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
935ed37a
A
1054 if (PC != 0)
1055 kmod_dump(&PC, 1);
1056
2d21ac55 1057 panic_display_system_configuration();
c910b4d9
A
1058 panic_display_zprint();
1059 dump_kext_info(&kdb_log);
1060
0c530ab8
A
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}