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