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