]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ppc/trap.c
xnu-344.tar.gz
[apple/xnu.git] / osfmk / ppc / trap.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 * @OSF_COPYRIGHT@
24 */
25
26 #include <mach_kdb.h>
27 #include <mach_kdp.h>
28 #include <debug.h>
29 #include <cpus.h>
30 #include <kern/thread.h>
31 #include <kern/exception.h>
32 #include <kern/syscall_sw.h>
33 #include <kern/cpu_data.h>
34 #include <kern/debug.h>
35 #include <mach/thread_status.h>
36 #include <vm/vm_fault.h>
37 #include <vm/vm_kern.h> /* For kernel_map */
38 #include <ppc/misc_protos.h>
39 #include <ppc/trap.h>
40 #include <ppc/exception.h>
41 #include <ppc/proc_reg.h> /* for SR_xxx definitions */
42 #include <ppc/pmap.h>
43 #include <ppc/mem.h>
44 #include <ppc/Firmware.h>
45 #include <ppc/low_trace.h>
46
47 #include <sys/kdebug.h>
48
49 perfTrap perfTrapHook = 0; /* Pointer to performance trap hook routine */
50
51 #if MACH_KDB
52 #include <ddb/db_watch.h>
53 #include <ddb/db_run.h>
54 #include <ddb/db_break.h>
55 #include <ddb/db_trap.h>
56
57 boolean_t let_ddb_vm_fault = FALSE;
58 boolean_t debug_all_traps_with_kdb = FALSE;
59 extern struct db_watchpoint *db_watchpoint_list;
60 extern boolean_t db_watchpoints_inserted;
61 extern boolean_t db_breakpoints_inserted;
62
63
64
65 #endif /* MACH_KDB */
66
67 extern int debugger_active[NCPUS];
68 extern task_t bsd_init_task;
69 extern char init_task_failure_data[];
70
71
72 #define PROT_EXEC (VM_PROT_EXECUTE)
73 #define PROT_RO (VM_PROT_READ)
74 #define PROT_RW (VM_PROT_READ|VM_PROT_WRITE)
75
76 /* A useful macro to update the ppc_exception_state in the PCB
77 * before calling doexception
78 */
79 #define UPDATE_PPC_EXCEPTION_STATE { \
80 thread_act_t thr_act = current_act(); \
81 thr_act->mact.pcb->save_dar = dar; \
82 thr_act->mact.pcb->save_dsisr = dsisr; \
83 thr_act->mact.pcb->save_exception = trapno / T_VECTOR_SIZE; /* back to powerpc */ \
84 }
85
86 static void unresolved_kernel_trap(int trapno,
87 struct savearea *ssp,
88 unsigned int dsisr,
89 unsigned int dar,
90 char *message);
91
92 struct savearea *trap(int trapno,
93 struct savearea *ssp,
94 unsigned int dsisr,
95 unsigned int dar)
96 {
97 int exception;
98 int code;
99 int subcode;
100 vm_map_t map;
101 unsigned int sp;
102 unsigned int space, space2;
103 unsigned int offset;
104 thread_act_t thr_act;
105 boolean_t intr;
106 #ifdef MACH_BSD
107 time_value_t tv;
108 #endif /* MACH_BSD */
109
110 if(perfTrapHook) { /* Is there a hook? */
111 if(perfTrapHook(trapno, ssp, dsisr, dar) == KERN_SUCCESS) return ssp; /* If it succeeds, we are done... */
112 }
113
114 #if 0
115 {
116 extern void fctx_text(void);
117 fctx_test();
118 }
119 #endif
120
121 thr_act = current_act(); /* Get current activation */
122 exception = 0; /* Clear exception for now */
123
124 /*
125 * Remember that we are disabled for interruptions when we come in here. Because
126 * of latency concerns, we need to enable interruptions in the interrupted process
127 * was enabled itself as soon as we can.
128 */
129
130 intr = (ssp->save_srr1 & MASK(MSR_EE)) != 0; /* Remember if we were enabled */
131
132 /* Handle kernel traps first */
133
134 if (!USER_MODE(ssp->save_srr1)) {
135 /*
136 * Trap came from kernel
137 */
138 switch (trapno) {
139
140 case T_PREEMPT: /* Handle a preempt trap */
141 ast_taken(AST_PREEMPT, FALSE);
142 break;
143
144 case T_RESET: /* Reset interruption */
145 #if 0
146 kprintf("*** Reset exception ignored; srr0 = %08X, srr1 = %08X\n",
147 ssp->save_srr0, ssp->save_srr1);
148 #else
149 panic("Unexpected Reset exception; srr0 = %08X, srr1 = %08X\n",
150 ssp->save_srr0, ssp->save_srr1);
151 #endif
152 break; /* We just ignore these */
153
154 /*
155 * These trap types should never be seen by trap()
156 * in kernel mode, anyway.
157 * Some are interrupts that should be seen by
158 * interrupt() others just don't happen because they
159 * are handled elsewhere. Some could happen but are
160 * considered to be fatal in kernel mode.
161 */
162 case T_DECREMENTER:
163 case T_IN_VAIN: /* Shouldn't ever see this, lowmem_vectors eats it */
164 case T_MACHINE_CHECK:
165 case T_SYSTEM_MANAGEMENT:
166 case T_ALTIVEC_ASSIST:
167 case T_INTERRUPT:
168 case T_FP_UNAVAILABLE:
169 case T_IO_ERROR:
170 case T_RESERVED:
171 case T_ALIGNMENT:
172 default:
173 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
174 break;
175
176 case T_TRACE:
177 case T_RUNMODE_TRACE:
178 case T_INSTRUCTION_BKPT:
179 if (!Call_Debugger(trapno, ssp))
180 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
181 break;
182
183 case T_PROGRAM:
184 if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
185 if (!Call_Debugger(trapno, ssp))
186 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
187 } else {
188 unresolved_kernel_trap(trapno, ssp,
189 dsisr, dar, NULL);
190 }
191 break;
192
193 case T_DATA_ACCESS:
194
195 #if MACH_KDB
196 mp_disable_preemption();
197 if (debug_mode
198 && debugger_active[cpu_number()]
199 && !let_ddb_vm_fault) {
200 /*
201 * Force kdb to handle this one.
202 */
203 kdb_trap(trapno, ssp);
204 }
205 mp_enable_preemption();
206 #endif /* MACH_KDB */
207
208 if(intr) ml_set_interrupts_enabled(TRUE); /* Enable if we were */
209
210 /* simple case : not SR_COPYIN segment, from kernel */
211 if ((dar >> 28) != SR_COPYIN_NUM) {
212 map = kernel_map;
213
214 offset = dar;
215
216
217 /*
218 * Note: Some ROM device drivers will access page 0 when they start. The IOKit will
219 * set a flag to tell us to ignore any access fault on page 0. After the driver is
220 * opened, it will clear the flag.
221 */
222 if((0 == (dar & -PAGE_SIZE)) && /* Check for access of page 0 and */
223 ((thr_act->mact.specFlags) & ignoreZeroFault)) {
224 /* special case of ignoring page zero faults */
225 ssp->save_srr0 += 4; /* Point to next instruction */
226 break;
227 }
228
229 code = vm_fault(map, trunc_page(offset),
230 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
231 FALSE, THREAD_UNINT, NULL, 0);
232
233 if (code != KERN_SUCCESS) {
234 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
235 } else {
236 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
237 ssp->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
238 }
239 break;
240 }
241
242 /* If we get here, the fault was due to a copyin/out */
243
244 map = thr_act->map;
245
246 /* Mask out SR_COPYIN and mask in original segment */
247
248 offset = (dar & 0x0fffffff) |
249 ((mfsrin(dar)<<8) & 0xF0000000);
250
251 code = vm_fault(map, trunc_page(offset),
252 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
253 FALSE, THREAD_UNINT, NULL, 0);
254
255 /* If we failed, there should be a recovery
256 * spot to rfi to.
257 */
258 if (code != KERN_SUCCESS) {
259
260 if (thr_act->thread->recover) {
261
262 act_lock_thread(thr_act);
263 ssp->save_srr0 = thr_act->thread->recover;
264 thr_act->thread->recover =
265 (vm_offset_t)NULL;
266 act_unlock_thread(thr_act);
267 } else {
268 unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point");
269 }
270 }
271 else {
272 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
273 ssp->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
274 }
275
276 break;
277
278 case T_INSTRUCTION_ACCESS:
279
280 #if MACH_KDB
281 if (debug_mode
282 && debugger_active[cpu_number()]
283 && !let_ddb_vm_fault) {
284 /*
285 * Force kdb to handle this one.
286 */
287 kdb_trap(trapno, ssp);
288 }
289 #endif /* MACH_KDB */
290
291 /* Same as for data access, except fault type
292 * is PROT_EXEC and addr comes from srr0
293 */
294
295 if(intr) ml_set_interrupts_enabled(TRUE); /* Enable if we were */
296
297 map = kernel_map;
298
299 code = vm_fault(map, trunc_page(ssp->save_srr0),
300 PROT_EXEC, FALSE, THREAD_UNINT, NULL, 0);
301
302 if (code != KERN_SUCCESS) {
303 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
304 } else {
305 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
306 ssp->save_srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
307 }
308 break;
309
310 /* Usually shandler handles all the system calls, but the
311 * atomic thread switcher may throwup (via thandler) and
312 * have to pass it up to the exception handler.
313 */
314
315 case T_SYSTEM_CALL:
316 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
317 break;
318
319 case T_AST:
320 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
321 break;
322 }
323 } else {
324
325 ml_set_interrupts_enabled(TRUE); /* Processing for user state traps is always enabled */
326
327 #ifdef MACH_BSD
328 {
329 void get_procrustime(time_value_t *);
330
331 get_procrustime(&tv);
332 }
333 #endif /* MACH_BSD */
334
335
336 /*
337 * Trap came from user task
338 */
339
340 switch (trapno) {
341
342 case T_PREEMPT:
343 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
344 break;
345
346 /*
347 * These trap types should never be seen by trap()
348 * Some are interrupts that should be seen by
349 * interrupt() others just don't happen because they
350 * are handled elsewhere.
351 */
352 case T_DECREMENTER:
353 case T_IN_VAIN: /* Shouldn't ever see this, lowmem_vectors eats it */
354 case T_MACHINE_CHECK:
355 case T_INTERRUPT:
356 case T_FP_UNAVAILABLE:
357 case T_SYSTEM_MANAGEMENT:
358 case T_RESERVED:
359 case T_IO_ERROR:
360
361 default:
362
363 ml_set_interrupts_enabled(FALSE); /* Turn off interruptions */
364
365 panic("Unexpected user state trap(cpu %d): 0x%08x DSISR=0x%08x DAR=0x%08x PC=0x%08x, MSR=0x%08x\n",
366 cpu_number(), trapno, dsisr, dar, ssp->save_srr0, ssp->save_srr1);
367 break;
368
369 case T_RESET:
370 #if 0
371 kprintf("*** Reset exception ignored; srr0 = %08X, srr1 = %08X\n",
372 ssp->save_srr0, ssp->save_srr1);
373 #else
374 panic("Unexpected Reset exception: srr0 = %0x08x, srr1 = %0x08x\n",
375 ssp->save_srr0, ssp->save_srr1);
376 #endif
377 break; /* We just ignore these */
378
379 case T_ALIGNMENT:
380 /*
381 * If notifyUnaligned is set, we have actually already emulated the unaligned access.
382 * All that we want to do here is to ignore the interrupt. This is to allow logging or
383 * tracing of unaligned accesses. Note that if trapUnaligned is also set, it takes
384 * precedence and we will take a bad access fault.
385 */
386
387 if(thr_act->mact.specFlags & notifyUnalign) {
388
389 KERNEL_DEBUG_CONSTANT(
390 MACHDBG_CODE(DBG_MACH_EXCP_ALNG, 0) | DBG_FUNC_NONE,
391 (int)ssp->save_srr0, (int)dar, (int)dsisr, (int)ssp->save_lr, 0);
392 }
393
394 if((!(thr_act->mact.specFlags & notifyUnalign)) || (thr_act->mact.specFlags & trapUnalign)) {
395 code = EXC_PPC_UNALIGNED;
396 exception = EXC_BAD_ACCESS;
397 subcode = dar;
398 }
399 break;
400
401 case T_TRACE: /* Real PPC chips */
402 if (be_tracing()) {
403 add_pcbuffer();
404 return ssp;
405 }
406 /* fall through */
407
408 case T_INSTRUCTION_BKPT: /* 603 PPC chips */
409 case T_RUNMODE_TRACE: /* 601 PPC chips */
410 exception = EXC_BREAKPOINT;
411 code = EXC_PPC_TRACE;
412 subcode = ssp->save_srr0;
413 break;
414
415 case T_PROGRAM:
416 if (ssp->save_srr1 & MASK(SRR1_PRG_FE)) {
417 fpu_save(thr_act->mact.curctx);
418 UPDATE_PPC_EXCEPTION_STATE;
419 exception = EXC_ARITHMETIC;
420 code = EXC_ARITHMETIC;
421
422 mp_disable_preemption();
423 subcode = ssp->save_fpscr;
424 mp_enable_preemption();
425 }
426 else if (ssp->save_srr1 & MASK(SRR1_PRG_ILL_INS)) {
427
428 UPDATE_PPC_EXCEPTION_STATE
429 exception = EXC_BAD_INSTRUCTION;
430 code = EXC_PPC_UNIPL_INST;
431 subcode = ssp->save_srr0;
432 } else if (ssp->save_srr1 & MASK(SRR1_PRG_PRV_INS)) {
433
434 UPDATE_PPC_EXCEPTION_STATE;
435 exception = EXC_BAD_INSTRUCTION;
436 code = EXC_PPC_PRIVINST;
437 subcode = ssp->save_srr0;
438 } else if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
439 unsigned int inst;
440
441 if (copyin((char *) ssp->save_srr0, (char *) &inst, 4 ))
442 panic("copyin failed\n");
443 UPDATE_PPC_EXCEPTION_STATE;
444 if (inst == 0x7FE00008) {
445 exception = EXC_BREAKPOINT;
446 code = EXC_PPC_BREAKPOINT;
447 } else {
448 exception = EXC_SOFTWARE;
449 code = EXC_PPC_TRAP;
450 }
451 subcode = ssp->save_srr0;
452 }
453 break;
454
455 case T_ALTIVEC_ASSIST:
456 UPDATE_PPC_EXCEPTION_STATE;
457 exception = EXC_ARITHMETIC;
458 code = EXC_PPC_ALTIVECASSIST;
459 subcode = ssp->save_srr0;
460 break;
461
462 case T_DATA_ACCESS:
463 map = thr_act->map;
464
465 code = vm_fault(map, trunc_page(dar),
466 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
467 FALSE, THREAD_ABORTSAFE, NULL, 0);
468
469 if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
470 UPDATE_PPC_EXCEPTION_STATE;
471 exception = EXC_BAD_ACCESS;
472 subcode = dar;
473 } else {
474 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
475 ssp->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
476 }
477 break;
478
479 case T_INSTRUCTION_ACCESS:
480 /* Same as for data access, except fault type
481 * is PROT_EXEC and addr comes from srr0
482 */
483 map = thr_act->map;
484
485 code = vm_fault(map, trunc_page(ssp->save_srr0),
486 PROT_EXEC, FALSE, THREAD_ABORTSAFE, NULL, 0);
487
488 if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
489 UPDATE_PPC_EXCEPTION_STATE;
490 exception = EXC_BAD_ACCESS;
491 subcode = ssp->save_srr0;
492 } else {
493 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
494 ssp->save_srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
495 }
496 break;
497
498 case T_AST:
499 ml_set_interrupts_enabled(FALSE);
500 ast_taken(AST_ALL, intr);
501 break;
502
503 }
504 #ifdef MACH_BSD
505 {
506 void bsd_uprofil(time_value_t *, unsigned int);
507
508 bsd_uprofil(&tv, ssp->save_srr0);
509 }
510 #endif /* MACH_BSD */
511 }
512
513 if (exception) {
514 /* if this is the init task, save the exception information */
515 /* this probably is a fatal exception */
516 if(bsd_init_task == current_task()) {
517 char *buf;
518 int i;
519
520 buf = init_task_failure_data;
521
522
523 buf += sprintf(buf, "Exception Code = 0x%x, Subcode = 0x%x\n", code, subcode);
524 buf += sprintf(buf, "DSISR = 0x%08x, DAR = 0x%08x\n"
525 , dsisr, dar);
526
527 for (i=0; i<32; i++) {
528 if ((i % 8) == 0) {
529 buf += sprintf(buf, "\n%4d :",i);
530 }
531 buf += sprintf(buf, " %08x",*(&ssp->save_r0+i));
532 }
533
534 buf += sprintf(buf, "\n\n");
535 buf += sprintf(buf, "cr = 0x%08x\t\t",ssp->save_cr);
536 buf += sprintf(buf, "xer = 0x%08x\n",ssp->save_xer);
537 buf += sprintf(buf, "lr = 0x%08x\t\t",ssp->save_lr);
538 buf += sprintf(buf, "ctr = 0x%08x\n",ssp->save_ctr);
539 buf += sprintf(buf, "srr0(iar) = 0x%08x\t\t",ssp->save_srr0);
540 buf += sprintf(buf, "srr1(msr) = 0x%08B\n",ssp->save_srr1,
541 "\x10\x11""EE\x12PR\x13""FP\x14ME\x15""FE0\x16SE\x18"
542 "FE1\x19""AL\x1a""EP\x1bIT\x1c""DT");
543 buf += sprintf(buf, "\n\n");
544
545 /* generate some stack trace */
546 buf += sprintf(buf, "Application level back trace:\n");
547 if (ssp->save_srr1 & MASK(MSR_PR)) {
548 char *addr = (char*)ssp->save_r1;
549 unsigned int stack_buf[3];
550 for (i = 0; i < 8; i++) {
551 if (addr == (char*)NULL)
552 break;
553 if (!copyin(addr,(char*)stack_buf,
554 3 * sizeof(int))) {
555 buf += sprintf(buf, "0x%08x : 0x%08x\n"
556 ,addr,stack_buf[2]);
557 addr = (char*)stack_buf[0];
558 } else {
559 break;
560 }
561 }
562 }
563 buf[0] = '\0';
564 }
565 doexception(exception, code, subcode);
566 }
567 /* AST delivery
568 * Check to see if we need an AST, if so take care of it here
569 */
570 ml_set_interrupts_enabled(FALSE);
571 if (USER_MODE(ssp->save_srr1))
572 while (ast_needed(cpu_number())) {
573 ast_taken(AST_ALL, intr);
574 ml_set_interrupts_enabled(FALSE);
575 }
576
577 return ssp;
578 }
579
580 /* This routine is called from assembly before each and every system call.
581 * It must preserve r3.
582 */
583
584 extern int syscall_trace(int, struct savearea *);
585
586
587 extern int pmdebug;
588
589 int syscall_trace(int retval, struct savearea *ssp)
590 {
591 int i, argc;
592
593 int kdarg[3];
594 /* Always prepare to trace mach system calls */
595 if (kdebug_enable && (ssp->save_r0 & 0x80000000)) {
596 /* Mach trap */
597 kdarg[0]=0;
598 kdarg[1]=0;
599 kdarg[2]=0;
600 argc = mach_trap_table[-(ssp->save_r0)].mach_trap_arg_count;
601 if (argc > 3)
602 argc = 3;
603 for (i=0; i < argc; i++)
604 kdarg[i] = (int)*(&ssp->save_r3 + i);
605 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC, (-(ssp->save_r0))) | DBG_FUNC_START,
606 kdarg[0], kdarg[1], kdarg[2], 0, 0);
607 }
608
609 return retval;
610 }
611
612 /* This routine is called from assembly after each mach system call
613 * It must preserve r3.
614 */
615
616 extern int syscall_trace_end(int, struct savearea *);
617
618 int syscall_trace_end(int retval, struct savearea *ssp)
619 {
620 if (kdebug_enable && (ssp->save_r0 & 0x80000000)) {
621 /* Mach trap */
622 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(ssp->save_r0))) | DBG_FUNC_END,
623 retval, 0, 0, 0, 0);
624 }
625 return retval;
626 }
627
628 /*
629 * called from syscall if there is an error
630 */
631
632 int syscall_error(
633 int exception,
634 int code,
635 int subcode,
636 struct savearea *ssp)
637 {
638 register thread_t thread;
639
640 thread = current_thread();
641
642 if (thread == 0)
643 panic("syscall error in boot phase");
644
645 if (!USER_MODE(ssp->save_srr1))
646 panic("system call called from kernel");
647
648 doexception(exception, code, subcode);
649
650 return 0;
651 }
652
653 /* Pass up a server syscall/exception */
654 void
655 doexception(
656 int exc,
657 int code,
658 int sub)
659 {
660 exception_data_type_t codes[EXCEPTION_CODE_MAX];
661
662 codes[0] = code;
663 codes[1] = sub;
664 exception(exc, codes, 2);
665 }
666
667 char *trap_type[] = {
668 "Unknown",
669 "0x100 - System reset",
670 "0x200 - Machine check",
671 "0x300 - Data access",
672 "0x400 - Inst access",
673 "0x500 - Ext int",
674 "0x600 - Alignment",
675 "0x700 - Program",
676 "0x800 - Floating point",
677 "0x900 - Decrementer",
678 "0xA00 - n/a",
679 "0xB00 - n/a",
680 "0xC00 - System call",
681 "0xD00 - Trace",
682 "0xE00 - FP assist",
683 "0xF00 - Perf mon",
684 "0xF20 - VMX",
685 "INVALID EXCEPTION",
686 "INVALID EXCEPTION",
687 "INVALID EXCEPTION",
688 "0x1300 - Inst bkpnt",
689 "0x1400 - Sys mgmt",
690 "0x1600 - Altivec Assist",
691 "0x1700 - Thermal",
692 "INVALID EXCEPTION",
693 "INVALID EXCEPTION",
694 "INVALID EXCEPTION",
695 "INVALID EXCEPTION",
696 "INVALID EXCEPTION",
697 "INVALID EXCEPTION",
698 "INVALID EXCEPTION",
699 "INVALID EXCEPTION",
700 "INVALID EXCEPTION",
701 "0x2000 - Run Mode/Trace",
702 "Signal Processor",
703 "Preemption",
704 "Context Switch",
705 "Shutdown",
706 "System Failure"
707 };
708 int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]);
709
710 void unresolved_kernel_trap(int trapno,
711 struct savearea *ssp,
712 unsigned int dsisr,
713 unsigned int dar,
714 char *message)
715 {
716 char *trap_name;
717 extern void print_backtrace(struct savearea *);
718 extern unsigned int debug_mode, disableDebugOuput;
719
720 ml_set_interrupts_enabled(FALSE); /* Turn off interruptions */
721 lastTrace = LLTraceSet(0); /* Disable low-level tracing */
722
723 if( logPanicDataToScreen )
724 disableDebugOuput = FALSE;
725
726 debug_mode++;
727 if ((unsigned)trapno <= T_MAX)
728 trap_name = trap_type[trapno / T_VECTOR_SIZE];
729 else
730 trap_name = "???? unrecognized exception";
731 if (message == NULL)
732 message = trap_name;
733
734 kdb_printf("\n\nUnresolved kernel trap(cpu %d): %s DAR=0x%08x PC=0x%08x\n",
735 cpu_number(), trap_name, dar, ssp->save_srr0);
736
737 print_backtrace(ssp);
738
739 draw_panic_dialog();
740
741 if( panicDebugging )
742 (void *)Call_Debugger(trapno, ssp);
743 panic(message);
744 }
745
746 void
747 thread_syscall_return(
748 kern_return_t ret)
749 {
750 register thread_act_t thr_act = current_act();
751 register struct savearea *regs = USER_REGS(thr_act);
752
753 if (kdebug_enable && (regs->save_r0 & 0x80000000)) {
754 /* Mach trap */
755 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(regs->save_r0))) | DBG_FUNC_END,
756 ret, 0, 0, 0, 0);
757 }
758 regs->save_r3 = ret;
759
760 thread_exception_return();
761 /*NOTREACHED*/
762 }
763
764
765 #if MACH_KDB
766 void
767 thread_kdb_return(void)
768 {
769 register thread_act_t thr_act = current_act();
770 register thread_t cur_thr = current_thread();
771 register struct savearea *regs = USER_REGS(thr_act);
772
773 Call_Debugger(thr_act->mact.pcb->save_exception, regs);
774 #if MACH_LDEBUG
775 assert(cur_thr->mutex_count == 0);
776 #endif /* MACH_LDEBUG */
777 check_simple_locks();
778 thread_exception_return();
779 /*NOTREACHED*/
780 }
781 #endif /* MACH_KDB */