]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ppc/trap.c
xnu-344.32.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 *
de355530
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 *
de355530
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,
de355530
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>
9bccf70c
A
44#include <ppc/Firmware.h>
45#include <ppc/low_trace.h>
1c79356b
A
46
47#include <sys/kdebug.h>
48
9bccf70c
A
49perfTrap perfTrapHook = 0; /* Pointer to performance trap hook routine */
50
1c79356b
A
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
57boolean_t let_ddb_vm_fault = FALSE;
58boolean_t debug_all_traps_with_kdb = FALSE;
59extern struct db_watchpoint *db_watchpoint_list;
60extern boolean_t db_watchpoints_inserted;
61extern boolean_t db_breakpoints_inserted;
62
63
64
65#endif /* MACH_KDB */
66
67extern int debugger_active[NCPUS];
9bccf70c 68extern task_t bsd_init_task;
1c79356b
A
69extern char init_task_failure_data[];
70
1c79356b 71
9bccf70c 72#define PROT_EXEC (VM_PROT_EXECUTE)
1c79356b
A
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 */
9bccf70c
A
79#define UPDATE_PPC_EXCEPTION_STATE { \
80 thread_act_t thr_act = current_act(); \
de355530 81 thr_act->mact.pcb->save_dar = dar; \
9bccf70c
A
82 thr_act->mact.pcb->save_dsisr = dsisr; \
83 thr_act->mact.pcb->save_exception = trapno / T_VECTOR_SIZE; /* back to powerpc */ \
1c79356b
A
84}
85
86static void unresolved_kernel_trap(int trapno,
9bccf70c 87 struct savearea *ssp,
1c79356b 88 unsigned int dsisr,
de355530 89 unsigned int dar,
1c79356b
A
90 char *message);
91
9bccf70c
A
92struct savearea *trap(int trapno,
93 struct savearea *ssp,
1c79356b 94 unsigned int dsisr,
de355530 95 unsigned int dar)
1c79356b 96{
9bccf70c 97 int exception;
1c79356b
A
98 int code;
99 int subcode;
100 vm_map_t map;
9bccf70c
A
101 unsigned int sp;
102 unsigned int space, space2;
1c79356b 103 unsigned int offset;
9bccf70c 104 thread_act_t thr_act;
1c79356b
A
105 boolean_t intr;
106#ifdef MACH_BSD
107 time_value_t tv;
108#endif /* MACH_BSD */
109
9bccf70c 110 if(perfTrapHook) { /* Is there a hook? */
de355530 111 if(perfTrapHook(trapno, ssp, dsisr, dar) == KERN_SUCCESS) return ssp; /* If it succeeds, we are done... */
9bccf70c
A
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
1c79356b
A
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
9bccf70c 130 intr = (ssp->save_srr1 & MASK(MSR_EE)) != 0; /* Remember if we were enabled */
1c79356b
A
131
132 /* Handle kernel traps first */
133
9bccf70c 134 if (!USER_MODE(ssp->save_srr1)) {
1c79356b
A
135 /*
136 * Trap came from kernel
137 */
138 switch (trapno) {
139
140 case T_PREEMPT: /* Handle a preempt trap */
0b4e3aa0 141 ast_taken(AST_PREEMPT, FALSE);
1c79356b
A
142 break;
143
144 case T_RESET: /* Reset interruption */
de355530
A
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
1c79356b
A
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:
de355530 171 case T_ALIGNMENT:
1c79356b
A
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:
9bccf70c 184 if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
1c79356b
A
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
1c79356b
A
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
d7e50217 208 if(intr) ml_set_interrupts_enabled(TRUE); /* Enable if we were */
de355530
A
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;
1c79356b 215
de355530 216
1c79356b
A
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 */
de355530
A
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 */
1c79356b
A
226 break;
227 }
228
de355530 229 code = vm_fault(map, trunc_page(offset),
1c79356b 230 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
9bccf70c 231 FALSE, THREAD_UNINT, NULL, 0);
1c79356b
A
232
233 if (code != KERN_SUCCESS) {
234 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
235 } else {
9bccf70c 236 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
de355530 237 ssp->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
1c79356b
A
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
de355530
A
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),
1c79356b 252 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
9bccf70c 253 FALSE, THREAD_UNINT, NULL, 0);
1c79356b
A
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);
9bccf70c 263 ssp->save_srr0 = thr_act->thread->recover;
1c79356b
A
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 {
9bccf70c 272 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
de355530 273 ssp->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
1c79356b
A
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
de355530 299 code = vm_fault(map, trunc_page(ssp->save_srr0),
9bccf70c 300 PROT_EXEC, FALSE, THREAD_UNINT, NULL, 0);
1c79356b
A
301
302 if (code != KERN_SUCCESS) {
303 unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
304 } else {
9bccf70c 305 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
de355530 306 ssp->save_srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
1c79356b
A
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
de355530 365 panic("Unexpected user state trap(cpu %d): 0x%08x DSISR=0x%08x DAR=0x%08x PC=0x%08x, MSR=0x%08x\n",
9bccf70c 366 cpu_number(), trapno, dsisr, dar, ssp->save_srr0, ssp->save_srr1);
1c79356b
A
367 break;
368
369 case T_RESET:
de355530
A
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
1c79356b
A
377 break; /* We just ignore these */
378
379 case T_ALIGNMENT:
9bccf70c 380/*
de355530 381* If notifyUnaligned is set, we have actually already emulated the unaligned access.
d7e50217 382* All that we want to do here is to ignore the interrupt. This is to allow logging or
de355530
A
383* tracing of unaligned accesses. Note that if trapUnaligned is also set, it takes
384* precedence and we will take a bad access fault.
d7e50217
A
385*/
386
de355530
A
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 }
1c79356b
A
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
de355530
A
408 case T_INSTRUCTION_BKPT: /* 603 PPC chips */
409 case T_RUNMODE_TRACE: /* 601 PPC chips */
1c79356b
A
410 exception = EXC_BREAKPOINT;
411 code = EXC_PPC_TRACE;
de355530 412 subcode = ssp->save_srr0;
1c79356b
A
413 break;
414
415 case T_PROGRAM:
9bccf70c
A
416 if (ssp->save_srr1 & MASK(SRR1_PRG_FE)) {
417 fpu_save(thr_act->mact.curctx);
1c79356b
A
418 UPDATE_PPC_EXCEPTION_STATE;
419 exception = EXC_ARITHMETIC;
420 code = EXC_ARITHMETIC;
421
422 mp_disable_preemption();
9bccf70c 423 subcode = ssp->save_fpscr;
1c79356b
A
424 mp_enable_preemption();
425 }
9bccf70c 426 else if (ssp->save_srr1 & MASK(SRR1_PRG_ILL_INS)) {
1c79356b
A
427
428 UPDATE_PPC_EXCEPTION_STATE
429 exception = EXC_BAD_INSTRUCTION;
430 code = EXC_PPC_UNIPL_INST;
de355530
A
431 subcode = ssp->save_srr0;
432 } else if (ssp->save_srr1 & MASK(SRR1_PRG_PRV_INS)) {
1c79356b
A
433
434 UPDATE_PPC_EXCEPTION_STATE;
435 exception = EXC_BAD_INSTRUCTION;
436 code = EXC_PPC_PRIVINST;
de355530 437 subcode = ssp->save_srr0;
9bccf70c 438 } else if (ssp->save_srr1 & MASK(SRR1_PRG_TRAP)) {
1c79356b 439 unsigned int inst;
de355530
A
440
441 if (copyin((char *) ssp->save_srr0, (char *) &inst, 4 ))
442 panic("copyin failed\n");
1c79356b
A
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 }
de355530 451 subcode = ssp->save_srr0;
1c79356b
A
452 }
453 break;
454
455 case T_ALTIVEC_ASSIST:
456 UPDATE_PPC_EXCEPTION_STATE;
457 exception = EXC_ARITHMETIC;
458 code = EXC_PPC_ALTIVECASSIST;
de355530 459 subcode = ssp->save_srr0;
1c79356b
A
460 break;
461
462 case T_DATA_ACCESS:
463 map = thr_act->map;
464
de355530 465 code = vm_fault(map, trunc_page(dar),
1c79356b 466 dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
9bccf70c 467 FALSE, THREAD_ABORTSAFE, NULL, 0);
1c79356b
A
468
469 if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
470 UPDATE_PPC_EXCEPTION_STATE;
471 exception = EXC_BAD_ACCESS;
de355530 472 subcode = dar;
1c79356b 473 } else {
9bccf70c 474 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
de355530 475 ssp->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
1c79356b
A
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
de355530 485 code = vm_fault(map, trunc_page(ssp->save_srr0),
9bccf70c 486 PROT_EXEC, FALSE, THREAD_ABORTSAFE, NULL, 0);
1c79356b
A
487
488 if ((code != KERN_SUCCESS) && (code != KERN_ABORTED)) {
489 UPDATE_PPC_EXCEPTION_STATE;
490 exception = EXC_BAD_ACCESS;
de355530 491 subcode = ssp->save_srr0;
1c79356b 492 } else {
9bccf70c 493 ssp->save_hdr.save_flags |= SAVredrive; /* Tell low-level to re-try fault */
de355530 494 ssp->save_srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
1c79356b
A
495 }
496 break;
497
498 case T_AST:
499 ml_set_interrupts_enabled(FALSE);
0b4e3aa0 500 ast_taken(AST_ALL, intr);
1c79356b
A
501 break;
502
503 }
504#ifdef MACH_BSD
505 {
506 void bsd_uprofil(time_value_t *, unsigned int);
507
9bccf70c 508 bsd_uprofil(&tv, ssp->save_srr0);
1c79356b
A
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);
de355530 524 buf += sprintf(buf, "DSISR = 0x%08x, DAR = 0x%08x\n"
1c79356b
A
525 , dsisr, dar);
526
527 for (i=0; i<32; i++) {
528 if ((i % 8) == 0) {
529 buf += sprintf(buf, "\n%4d :",i);
530 }
9bccf70c 531 buf += sprintf(buf, " %08x",*(&ssp->save_r0+i));
1c79356b
A
532 }
533
534 buf += sprintf(buf, "\n\n");
de355530
A
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,
1c79356b
A
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");
9bccf70c
A
547 if (ssp->save_srr1 & MASK(MSR_PR)) {
548 char *addr = (char*)ssp->save_r1;
1c79356b
A
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))) {
de355530 555 buf += sprintf(buf, "0x%08x : 0x%08x\n"
1c79356b
A
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);
9bccf70c 571 if (USER_MODE(ssp->save_srr1))
1c79356b 572 while (ast_needed(cpu_number())) {
0b4e3aa0 573 ast_taken(AST_ALL, intr);
1c79356b
A
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
9bccf70c 584extern int syscall_trace(int, struct savearea *);
1c79356b
A
585
586
587extern int pmdebug;
588
9bccf70c 589int syscall_trace(int retval, struct savearea *ssp)
1c79356b
A
590{
591 int i, argc;
d7e50217 592
de355530
A
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 }
1c79356b
A
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
9bccf70c 616extern int syscall_trace_end(int, struct savearea *);
1c79356b 617
9bccf70c 618int syscall_trace_end(int retval, struct savearea *ssp)
1c79356b 619{
de355530
A
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 }
1c79356b
A
625 return retval;
626}
627
628/*
629 * called from syscall if there is an error
630 */
631
632int syscall_error(
633 int exception,
634 int code,
635 int subcode,
9bccf70c 636 struct savearea *ssp)
1c79356b
A
637{
638 register thread_t thread;
639
640 thread = current_thread();
641
642 if (thread == 0)
643 panic("syscall error in boot phase");
644
9bccf70c 645 if (!USER_MODE(ssp->save_srr1))
1c79356b
A
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 */
654void
655doexception(
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
667char *trap_type[] = {
0b4e3aa0
A
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",
de355530 700 "INVALID EXCEPTION",
0b4e3aa0
A
701 "0x2000 - Run Mode/Trace",
702 "Signal Processor",
703 "Preemption",
704 "Context Switch",
705 "Shutdown",
706 "System Failure"
1c79356b
A
707};
708int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]);
709
710void unresolved_kernel_trap(int trapno,
9bccf70c 711 struct savearea *ssp,
1c79356b 712 unsigned int dsisr,
de355530 713 unsigned int dar,
1c79356b
A
714 char *message)
715{
716 char *trap_name;
9bccf70c 717 extern void print_backtrace(struct savearea *);
1c79356b
A
718 extern unsigned int debug_mode, disableDebugOuput;
719
720 ml_set_interrupts_enabled(FALSE); /* Turn off interruptions */
9bccf70c 721 lastTrace = LLTraceSet(0); /* Disable low-level tracing */
1c79356b 722
9bccf70c
A
723 if( logPanicDataToScreen )
724 disableDebugOuput = FALSE;
725
1c79356b
A
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
de355530 734 kdb_printf("\n\nUnresolved kernel trap(cpu %d): %s DAR=0x%08x PC=0x%08x\n",
9bccf70c 735 cpu_number(), trap_name, dar, ssp->save_srr0);
1c79356b
A
736
737 print_backtrace(ssp);
738
9bccf70c
A
739 draw_panic_dialog();
740
741 if( panicDebugging )
742 (void *)Call_Debugger(trapno, ssp);
1c79356b
A
743 panic(message);
744}
745
746void
747thread_syscall_return(
748 kern_return_t ret)
749{
750 register thread_act_t thr_act = current_act();
9bccf70c 751 register struct savearea *regs = USER_REGS(thr_act);
1c79356b 752
de355530 753 if (kdebug_enable && (regs->save_r0 & 0x80000000)) {
1c79356b 754 /* Mach trap */
9bccf70c 755 KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(regs->save_r0))) | DBG_FUNC_END,
1c79356b
A
756 ret, 0, 0, 0, 0);
757 }
9bccf70c 758 regs->save_r3 = ret;
1c79356b
A
759
760 thread_exception_return();
761 /*NOTREACHED*/
762}
763
764
765#if MACH_KDB
766void
767thread_kdb_return(void)
768{
769 register thread_act_t thr_act = current_act();
770 register thread_t cur_thr = current_thread();
9bccf70c 771 register struct savearea *regs = USER_REGS(thr_act);
1c79356b 772
9bccf70c 773 Call_Debugger(thr_act->mact.pcb->save_exception, regs);
1c79356b
A
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 */