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