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