|
|
1.1 root 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/fpu_protos.h>
45:
46: #include <sys/kdebug.h>
47:
48: #if MACH_KDB
49: #include <ddb/db_watch.h>
50: #include <ddb/db_run.h>
51: #include <ddb/db_break.h>
52: #include <ddb/db_trap.h>
53:
54: boolean_t let_ddb_vm_fault = FALSE;
55: boolean_t debug_all_traps_with_kdb = FALSE;
56: extern struct db_watchpoint *db_watchpoint_list;
57: extern boolean_t db_watchpoints_inserted;
58: extern boolean_t db_breakpoints_inserted;
59:
60:
61: #endif /* MACH_KDB */
62:
63: extern int debugger_active[NCPUS];
64:
65: #if DEBUG || MACH_ASSERT
66: #define TRAP_ALL -1
67: #define TRAP_ALIGNMENT 0x01
68: #define TRAP_DATA 0x02
69: #define TRAP_INSTRUCTION 0x04
70: #define TRAP_AST 0x08
71: #define TRAP_TRACE 0x10
72: #define TRAP_PROGRAM 0x20
73: #define TRAP_EXCEPTION 0x40
74: #define TRAP_UNRESOLVED 0x80
75: #define TRAP_SYSCALL 0x100 /* all syscalls */
76: #define TRAP_HW 0x200 /* all in hw_exception.s */
77: #define TRAP_MACH_SYSCALL 0x400
78: #define TRAP_SERVER_SYSCALL 0x800
79:
80: int trapdebug=0; /* TRAP_SERVER_SYSCALL;*/
81:
82: #define TRAP_DEBUG(LEVEL, A) {if ((trapdebug & LEVEL)==LEVEL){printf A;}}
83: #else
84: #define TRAP_DEBUG(LEVEL, A)
85: #endif
86:
87: /*
88: * XXX don't pass VM_PROT_EXECUTE to vm_fault(), execute permission is implied
89: * in either R or RW (note: the pmap module knows this). This is done for the
90: * benefit of programs that execute out of their data space (ala lisp).
91: * If we didn't do this in that scenerio, the ITLB miss code would call us
92: * and we would call vm_fault() with RX permission. However, the space was
93: * probably vm_allocate()ed with just RW and vm_fault would fail. The "right"
94: * solution to me is to have the un*x server always allocate data with RWX for
95: * compatibility with existing binaries.
96: */
97:
98: #define PROT_EXEC (VM_PROT_READ)
99: #define PROT_RO (VM_PROT_READ)
100: #define PROT_RW (VM_PROT_READ|VM_PROT_WRITE)
101:
102: /* A useful macro to update the ppc_exception_state in the PCB
103: * before calling doexception
104: */
105: #define UPDATE_PPC_EXCEPTION_STATE { \
106: thread_act_t thr_act = current_act(); \
107: struct ppc_exception_state *es = &thr_act->mact.pcb->es; \
108: es->dar = dar; \
109: es->dsisr = dsisr; \
110: es->exception = trapno / T_VECTOR_SIZE; /* back to powerpc */ \
111: }
112:
113: static void unresolved_kernel_trap(int trapno,
114: struct ppc_saved_state *ssp,
115: unsigned int dsisr,
116: unsigned int dar,
117: char *message);
118:
119: struct ppc_saved_state *trap(int trapno,
120: struct ppc_saved_state *ssp,
121: unsigned int dsisr,
122: unsigned int dar)
123: {
124: int exception=0;
125: int code;
126: int subcode;
127: vm_map_t map;
128: unsigned int sp;
129: unsigned int space,space2;
130: unsigned int offset;
131: thread_act_t thr_act = current_act();
132: #ifdef MACH_BSD
133: time_value_t tv;
134: #endif /* MACH_BSD */
135:
136:
137: TRAP_DEBUG(TRAP_ALL,("NMGS TRAP %d srr0=0x%08x, srr1=0x%08x\n",
138: trapno/4,ssp->srr0,ssp->srr1));
139:
140: #if DEBUG
141: {
142: /* make sure we're not near to overflowing kernel stack */
143: int sp;
144: mp_disable_preemption(); /* Make sure we don't preempt */
145: #ifdef __ELF__
146: __asm__ volatile("mr %0, 1" : "=r" (sp));
147: #else
148: __asm__ volatile("mr %0, r1" : "=r" (sp));
149: #endif
150: if (sp <
151: (cpu_data[cpu_number()].active_thread->kernel_stack +
152: sizeof(struct ppc_saved_state)+256)) {
153: printf("TRAP - LOW ON KERNEL STACK!\n");
154: }
155: mp_enable_preemption(); /* Preemption is cool now */
156: }
157: #endif /* DEBUG */
158: /* Handle kernel traps first */
159:
160: if (!USER_MODE(ssp->srr1)) {
161: /*
162: * Trap came from system task, ie kernel or collocated server
163: */
164: switch (trapno) {
165:
166: case T_PREEMPT: /* Handle a preempt trap */
167: mp_disable_preemption(); /* since preemption is not enabled */
168: ast_off(AST_URGENT); /* clear urgent and let it sched */
169: mp_enable_preemption(); /* normally... */
170: break; /* Do nothing, just check... */
171:
172: /*
173: * These trap types should never be seen by trap()
174: * in kernel mode, anyway.
175: * Some are interrupts that should be seen by
176: * interrupt() others just don't happen because they
177: * are handled elsewhere. Some could happen but are
178: * considered to be fatal in kernel mode.
179: */
180: case T_DECREMENTER:
181: case T_IN_VAIN: /* Shouldn't ever see this, lowmem_vectors eats it */
182: case T_RESET:
183: case T_MACHINE_CHECK:
184: case T_SYSTEM_MANAGEMENT:
185: case T_ALTIVEC_ASSIST:
186: case T_INTERRUPT:
187: case T_FP_UNAVAILABLE:
188: case T_IO_ERROR:
189: case T_RESERVED:
190: default:
191: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
192: break;
193:
194: case T_TRACE:
195: case T_RUNMODE_TRACE:
196: case T_INSTRUCTION_BKPT:
197: #if MACH_KDP || MACH_KDB
198: if (!Call_Debugger(trapno, ssp))
199: #endif
200: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
201: break;
202:
203: case T_PROGRAM:
204: if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
205: #if MACH_KDP || MACH_KDB
206: if (!Call_Debugger(trapno, ssp))
207: #endif
208: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
209: } else {
210: unresolved_kernel_trap(trapno, ssp,
211: dsisr, dar, NULL);
212: }
213: break;
214: case T_ALIGNMENT:
215: TRAP_DEBUG(TRAP_ALIGNMENT,
216: ("NMGS KERNEL ALIGNMENT_ACCESS, "
217: "DAR=0x%08x, DSISR = 0x%B\n",
218: dar, dsisr,
219: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
220: if (alignment(dsisr, dar, ssp)) {
221: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
222: }
223: break;
224: case T_DATA_ACCESS:
225: TRAP_DEBUG(TRAP_DATA,
226: ("NMGS KERNEL DATA_ACCESS, DAR=0x%08x,"
227: "DSISR = 0x%B\n", dar, dsisr,
228: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
229:
230: #if MACH_KDB
231: mp_disable_preemption();
232: if (debug_mode
233: #if NCPUS > 1
234: && debugger_active[cpu_number()]
235: #endif /* NCPUS > 1 */
236: && !let_ddb_vm_fault) {
237: /*
238: * Force kdb to handle this one.
239: */
240: kdb_trap(trapno, ssp);
241: }
242: mp_enable_preemption();
243: #endif /* MACH_KDB */
244:
245: /* simple case : not SR_COPYIN segment, from kernel */
246: if ((dar >> 28) != SR_COPYIN_NUM) {
247: map = kernel_map;
248:
249: offset = dar;
250:
251:
252: /*
253: * Note: Some ROM device drivers will access page 0 when they start. The IOKit will
254: * set a flag to tell us to ignore any access fault on page 0. After the driver is
255: * opened, it will clear the flag.
256: */
257: if((0 == (dar & -PAGE_SIZE)) && /* Check for access of page 0 and */
258: ((thr_act->mact.specFlags) & ignoreZeroFault)) {
259: /* special case of ignoring page zero faults */
260: ssp->srr0 += 4; /* Point to next instruction */
261: break;
262: }
263:
264: TRAP_DEBUG(TRAP_DATA,
265: ("SYSTEM FAULT FROM 0x%08x\n",
266: offset));
267:
268: code = vm_fault(map,
269: trunc_page(offset),
270: dsisr & MASK(DSISR_WRITE) ?
271: PROT_RW : PROT_RO,
272: FALSE);
273: if (code != KERN_SUCCESS) {
274: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
275: }
276: else {
277: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */
278: ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
279: }
280: break;
281: }
282:
283: /* If we get here, the fault was due to a copyin/out */
284:
285: map = thr_act->map;
286:
287: /* Mask out SR_COPYIN and mask in original segment */
288:
289: offset = (dar & 0x0fffffff) |
290: ((mfsrin(dar)<<8) & 0xF0000000);
291:
292: TRAP_DEBUG(TRAP_DATA,
293: ("sr=0x%08x, dar=0x%08x, sp=0x%x\n",
294: mfsrin(dar), dar,map->pmap->space));
295: assert((mfsrin(dar) & 0x000FFFFF) ==
296: map->pmap->space);
297: TRAP_DEBUG(TRAP_DATA,
298: ("KERNEL FAULT FROM 0x%x,0x%08x\n",
299: map->pmap->space, offset));
300:
301: code = vm_fault(map,
302: trunc_page(offset),
303: dsisr & MASK(DSISR_WRITE) ?
304: PROT_RW : PROT_RO,
305: FALSE);
306:
307: /* If we failed, there should be a recovery
308: * spot to rfi to.
309: */
310: if (code != KERN_SUCCESS) {
311: TRAP_DEBUG(TRAP_DATA,
312: ("FAULT FAILED- srr0=0x%08x,"
313: "pcb-srr0=0x%08x\n",
314: ssp->srr0,
315: thr_act->mact.pcb->ss.srr0));
316:
317: if (thr_act->thread->recover) {
318:
319: #if 0
320: __asm__ volatile("tweq r1,r1"); /* (TEST/DEBUG) */
321: #endif
322:
323: act_lock_thread(thr_act);
324: ssp->srr0 = thr_act->thread->recover;
325: thr_act->thread->recover =
326: (vm_offset_t)NULL;
327: act_unlock_thread(thr_act);
328: } else {
329: unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point");
330: }
331: }
332: else {
333: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */
334: ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
335: }
336:
337: break;
338:
339: case T_INSTRUCTION_ACCESS:
340:
341: TRAP_DEBUG(TRAP_INSTRUCTION,
342: ("NMGS KERNEL INSTRUCTION ACCESS,"
343: "DSISR = 0x%B\n", dsisr,
344: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
345:
346: #if MACH_KDB
347: if (debug_mode
348: #if NCPUS > 1
349: && debugger_active[cpu_number()]
350: #endif /* NCPUS > 1 */
351: && !let_ddb_vm_fault) {
352: /*
353: * Force kdb to handle this one.
354: */
355: kdb_trap(trapno, ssp);
356: }
357: #endif /* MACH_KDB */
358:
359: /* Same as for data access, except fault type
360: * is PROT_EXEC and addr comes from srr0
361: */
362: map = thr_act->map;
363:
364: code = vm_fault(map, trunc_page(ssp->srr0),
365: PROT_EXEC, FALSE);
366: if (code != KERN_SUCCESS) {
367: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
368: }
369: else {
370: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */
371: ssp->srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
372: }
373: break;
374:
375: /* Usually shandler handles all the system calls, but the
376: * atomic thread switcher may throwup (via thandler) and
377: * have to pass it up to the exception handler.
378: */
379:
380: case T_SYSTEM_CALL:
381: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
382: break;
383:
384: case T_AST:
385: TRAP_DEBUG(TRAP_AST,
386: ("T_AST FROM KERNEL MODE\n"));
387: ast_taken(FALSE, AST_ALL, 0);
388: break;
389: }
390: } else {
391: #ifdef MACH_BSD
392: {
393: void get_procrustime(time_value_t *);
394:
395: get_procrustime(&tv);
396: }
397: #endif /* MACH_BSD */
398:
399:
400: /*
401: * Trap came from user task
402: */
403:
404: switch (trapno) {
405: case T_PREEMPT: /* Handle a preempt trap */
406: break; /* Do nothing, just check... */
407:
408: /*
409: * These trap types should never be seen by trap()
410: * Some are interrupts that should be seen by
411: * interrupt() others just don't happen because they
412: * are handled elsewhere.
413: */
414: case T_DECREMENTER:
415: case T_IN_VAIN: /* Shouldn't ever see this, lowmem_vectors eats it */
416: case T_MACHINE_CHECK:
417: case T_INTERRUPT:
418: case T_FP_UNAVAILABLE:
419: case T_SYSTEM_MANAGEMENT:
420: case T_RESERVED:
421: case T_IO_ERROR:
422:
423: default:
424: panic("Unexpected exception type");
425: break;
426:
427: case T_RESET:
428: halt_all_cpus(TRUE); /* never returns */
429:
430: case T_ALIGNMENT:
431: TRAP_DEBUG(TRAP_ALIGNMENT,
432: ("NMGS USER ALIGNMENT_ACCESS, "
433: "DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,
434: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
435: if (alignment(dsisr, dar, ssp)) {
436: code = EXC_PPC_UNALIGNED;
437: exception = EXC_BAD_ACCESS;
438: subcode = dar;
439: }
440: break;
441:
442: case T_TRACE: /* Real PPC chips */
443: case T_INSTRUCTION_BKPT: /* 603 PPC chips */
444: case T_RUNMODE_TRACE: /* 601 PPC chips */
445: TRAP_DEBUG(TRAP_TRACE,("NMGS TRACE TRAP\n"));
446:
447: exception = EXC_BREAKPOINT;
448: code = EXC_PPC_TRACE;
449: subcode = ssp->srr0;
450: break;
451:
452: case T_PROGRAM:
453: TRAP_DEBUG(TRAP_PROGRAM,
454: ("NMGS PROGRAM TRAP\n"));
455: if (ssp->srr1 & MASK(SRR1_PRG_FE)) {
456: TRAP_DEBUG(TRAP_PROGRAM,
457: ("FP EXCEPTION\n"));
458: fpu_save();
459: UPDATE_PPC_EXCEPTION_STATE;
460: exception = EXC_ARITHMETIC;
461: code = EXC_ARITHMETIC;
462:
463: mp_disable_preemption();
464: subcode = current_act()->mact.FPU_pcb->fs.fpscr;
465: mp_enable_preemption();
466: }
467: else if (ssp->srr1 & MASK(SRR1_PRG_ILL_INS)) {
468:
469: TRAP_DEBUG(TRAP_PROGRAM,
470: ("ILLEGAL INSTRUCTION\n"));
471:
472: UPDATE_PPC_EXCEPTION_STATE
473: exception = EXC_BAD_INSTRUCTION;
474: code = EXC_PPC_UNIPL_INST;
475: subcode = ssp->srr0;
476: } else if (ssp->srr1 & MASK(SRR1_PRG_PRV_INS)) {
477: TRAP_DEBUG(TRAP_PROGRAM,
478: ("PRIVILEGED INSTRUCTION\n"));
479:
480: UPDATE_PPC_EXCEPTION_STATE;
481: exception = EXC_BAD_INSTRUCTION;
482: code = EXC_PPC_PRIVINST;
483: subcode = ssp->srr0;
484: } else if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
485: unsigned int inst;
486:
487: if (copyin((char *) ssp->srr0, (char *) &inst, 4 ))
488: panic("copyin failed\n");
489: UPDATE_PPC_EXCEPTION_STATE;
490: if (inst == 0x7FE00008) {
491: exception = EXC_BREAKPOINT;
492: code = EXC_PPC_BREAKPOINT;
493: } else {
494: exception = EXC_SOFTWARE;
495: code = EXC_PPC_TRAP;
496: }
497: subcode = ssp->srr0;
498: }
499: break;
500:
501: case T_ALTIVEC_ASSIST:
502: UPDATE_PPC_EXCEPTION_STATE;
503: exception = EXC_ARITHMETIC;
504: code = EXC_PPC_ALTIVECASSIST;
505: subcode = ssp->srr0;
506: break;
507:
508: case T_DATA_ACCESS:
509: TRAP_DEBUG(TRAP_DATA,
510: ("NMGS USER DATA_ACCESS, DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
511:
512: map = thr_act->map;
513:
514: code = vm_fault(map, trunc_page(dar),
515: dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
516: FALSE);
517: if (code != KERN_SUCCESS) {
518:
519: TRAP_DEBUG(TRAP_DATA,("FAULT FAILED!\n"));
520: UPDATE_PPC_EXCEPTION_STATE;
521: exception = EXC_BAD_ACCESS;
522: subcode = dar;
523: }
524: else {
525: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */
526: ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
527: }
528: break;
529:
530: case T_INSTRUCTION_ACCESS:
531: TRAP_DEBUG(TRAP_INSTRUCTION,("NMGS USER INSTRUCTION ACCESS, DSISR = 0x%B\n", dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
532:
533: /* Same as for data access, except fault type
534: * is PROT_EXEC and addr comes from srr0
535: */
536: map = thr_act->map;
537:
538: code = vm_fault(map, trunc_page(ssp->srr0),
539: PROT_EXEC, FALSE);
540: if (code != KERN_SUCCESS) {
541:
542:
543: TRAP_DEBUG(TRAP_INSTRUCTION,
544: ("INSTR FAULT FAILED!\n"));
545: UPDATE_PPC_EXCEPTION_STATE;
546: exception = EXC_BAD_ACCESS;
547: subcode = ssp->srr0;
548: }
549: else {
550: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */
551: ssp->srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */
552: }
553: break;
554:
555: case T_AST:
556: TRAP_DEBUG(TRAP_AST,("T_AST FROM USER MODE\n"));
557: ast_taken(FALSE, AST_ALL, 0);
558: break;
559:
560: }
561: #ifdef MACH_BSD
562: {
563: void bsd_uprofil(time_value_t *, unsigned int);
564:
565: bsd_uprofil(&tv, ssp->srr0);
566: }
567: #endif /* MACH_BSD */
568: }
569:
570: if (exception) {
571: TRAP_DEBUG(TRAP_EXCEPTION,
572: ("doexception (0x%x, 0x%x, 0x%x\n",
573: exception,code,subcode));
574:
575: #if 0
576: __asm__ volatile("tweq r1,r1"); /* (TEST/DEBUG) */
577: #endif
578:
579: doexception(exception, code, subcode);
580: return ssp;
581: }
582: /* AST delivery
583: * Check to see if we need an AST, if so take care of it here
584: */
585:
586: mp_disable_preemption(); /* We can't preempt here */
587: while (ast_needed(cpu_number()) && USER_MODE(ssp->srr1)) {
588: mp_enable_preemption(); /* ast_taken doesn't expect preemption disabled */
589: ast_taken(FALSE, AST_ALL, 0);
590: mp_disable_preemption(); /* Disable pretemption for check */
591: }
592: mp_enable_preemption(); /* Preemption be cool again */
593:
594: return ssp;
595: }
596:
597: /* This routine is called from assembly before each and every system call.
598: * It must preserve r3.
599: */
600:
601: extern int syscall_trace(int, struct ppc_saved_state *);
602:
603:
604: extern int pmdebug;
605:
606: int syscall_trace(int retval, struct ppc_saved_state *ssp)
607: {
608: int i, argc;
609:
610: int kdarg[3];
611: /* Always prepare to trace mach system calls */
612: if (kdebug_enable && (ssp->r0 & 0x80000000)) {
613: /* Mach trap */
614: kdarg[0]=0;
615: kdarg[1]=0;
616: kdarg[2]=0;
617: argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count;
618: if (argc > 3)
619: argc = 3;
620: for (i=0; i < argc; i++)
621: kdarg[i] = (int)*(&ssp->r3 + i);
622: KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC, (-(ssp->r0))) | DBG_FUNC_START,
623: kdarg[0], kdarg[1], kdarg[2], 0, 0);
624: }
625:
626: #if MACH_ASSERT
627: if (trapdebug & TRAP_SYSCALL)
628: trapdebug |= (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL);
629:
630: if (!(trapdebug & (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL)))
631: return retval;
632: if (ssp->r0 & 0x80000000) {
633: /* Mach trap */
634: if (!(trapdebug & TRAP_MACH_SYSCALL))
635: return retval;
636:
637: printf("0x%08x : %30s (",
638: ssp->srr0, mach_trap_table[-(ssp->r0)].mach_trap_name);
639: argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count;
640: for (i = 0; i < argc; i++)
641: printf("%08x ",*(&ssp->r3 + i));
642: printf(")\n");
643: } else {
644: if (!(trapdebug & TRAP_SERVER_SYSCALL))
645: return retval;
646: printf("0x%08x : UNIX %3d (", ssp->srr0, ssp->r0);
647: argc = 4; /* print 4 of 'em! */
648: for (i = 0; i < argc; i++)
649: printf("%08x ",*(&ssp->r3 + i));
650: printf(")\n");
651: }
652: #endif /* MACH_ASSERT */
653: return retval;
654: }
655:
656: /* This routine is called from assembly after each mach system call
657: * It must preserve r3.
658: */
659:
660: extern int syscall_trace_end(int, struct ppc_saved_state *);
661:
662: int syscall_trace_end(int retval, struct ppc_saved_state *ssp)
663: {
664: if (kdebug_enable && (ssp->r0 & 0x80000000)) {
665: /* Mach trap */
666: KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(ssp->r0))) | DBG_FUNC_END,
667: retval, 0, 0, 0, 0);
668: }
669: return retval;
670: }
671:
672: /*
673: * called from syscall if there is an error
674: */
675:
676: int syscall_error(
677: int exception,
678: int code,
679: int subcode,
680: struct ppc_saved_state *ssp)
681: {
682: register thread_t thread;
683:
684: thread = current_thread();
685:
686: if (thread == 0)
687: panic("syscall error in boot phase");
688:
689: if (!USER_MODE(ssp->srr1))
690: panic("system call called from kernel");
691:
692: doexception(exception, code, subcode);
693:
694: return 0;
695: }
696:
697: /* Pass up a server syscall/exception */
698: void
699: doexception(
700: int exc,
701: int code,
702: int sub)
703: {
704: exception_data_type_t codes[EXCEPTION_CODE_MAX];
705:
706: codes[0] = code;
707: codes[1] = sub;
708: exception(exc, codes, 2);
709: }
710:
711: char *trap_type[] = {
712: "0x000 Interrupt in vain",
713: "0x100 System reset",
714: "0x200 Machine check",
715: "0x300 Data access",
716: "0x400 Instruction access",
717: "0x500 External interrupt",
718: "0x600 Alignment",
719: "0x700 Program",
720: "0x800 Floating point",
721: "0x900 Decrementer",
722: "0xA00 I/O controller interface",
723: "0xB00 INVALID EXCEPTION",
724: "0xC00 System call exception",
725: "0xD00 Trace",
726: "0xE00 FP assist",
727: "0xF20 VMX",
728: "0xF00 INVALID EXCEPTION",
729: "0x1000 Instruction PTE miss",
730: "0x1100 Data load PTE miss",
731: "0x1200 Data store PTE miss",
732: "0x1300 Instruction Breakpoint",
733: "0x1400 System Management",
734: "0x1500 INVALID EXCEPTION",
735: "0x1600 Altivec Assist",
736: "0x1700 INVALID EXCEPTION",
737: "0x1800 INVALID EXCEPTION",
738: "0x1900 INVALID EXCEPTION",
739: "0x1A00 INVALID EXCEPTION",
740: "0x1B00 INVALID EXCEPTION",
741: "0x1C00 INVALID EXCEPTION",
742: "0x1D00 INVALID EXCEPTION",
743: "0x1E00 INVALID EXCEPTION",
744: "0x1F00 INVALID EXCEPTION",
745: "0x2000 Run Mode/Trace"
746: };
747: int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]);
748:
749: void unresolved_kernel_trap(int trapno,
750: struct ppc_saved_state *ssp,
751: unsigned int dsisr,
752: unsigned int dar,
753: char *message)
754: {
755: unsigned int* stackptr;
756: char *trap_name;
757: int i, lr;
758: extern void print_backtrace(struct ppc_saved_state *);
759: extern unsigned int debug_mode, disableDebugOuput;
760:
761: disableDebugOuput = FALSE;
762: debug_mode++;
763: if ((unsigned)trapno <= T_MAX)
764: trap_name = trap_type[trapno / T_VECTOR_SIZE];
765: else
766: trap_name = "???? unrecognized exception";
767: if (message == NULL)
768: message = trap_name;
769:
770: printf("\n\nUnresolved kernel trap: %s DSISR=0x%08x DAR=0x%08x PC=0x%08x\n"
771: "generating stack backtrace prior to panic:\n\n",
772: trap_name, dsisr, dar, ssp->srr0);
773:
774: printf("backtrace: %08x ", ssp->srr0);
775:
776: stackptr = (unsigned int *)(ssp->r1);
777:
778: #ifdef __ELF__
779: lr = 1;
780: #else
781: lr = 2;
782: #endif
783:
784: print_backtrace(ssp);
785:
786: #if MACH_KDB || MACH_KDP
787: (void *)Call_Debugger(trapno, ssp);
788: #endif
789: panic(message);
790: }
791:
792: #if MACH_KDB
793: void
794: thread_kdb_return(void)
795: {
796: register thread_act_t thr_act = current_act();
797: register thread_t cur_thr = current_thread();
798: register struct ppc_saved_state *regs = USER_REGS(thr_act);
799:
800: Call_Debugger(thr_act->mact.pcb->es.exception, regs);
801: #if MACH_LDEBUG
802: assert(cur_thr->mutex_count == 0);
803: #endif /* MACH_LDEBUG */
804: check_simple_locks();
805: thread_exception_return();
806: /*NOTREACHED*/
807: }
808: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.