|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: #include <debug.h>
26: #include <cpus.h>
27: #include <kern/thread.h>
28: #include <mach/exception.h>
29: #include <kern/syscall_sw.h>
30: #include <machdep/ppc/cpu_data.h>
31: #include <mach/thread_status.h>
32: #include <vm/vm_fault.h>
33: #include <vm/vm_kern.h> /* For kernel_map */
34: #include <mach/vm_param.h>
35: #include <machdep/ppc/trap.h>
36: #include <machdep/ppc/exception.h>
37: #include <machdep/ppc/proc_reg.h> /* for SR_xxx definitions */
38: #include <machdep/ppc/pmap.h>
39: #include <machine/label_t.h>
40:
41: #include <sys/param.h>
42: #include <sys/proc.h>
43: #include <sys/resourcevar.h>
44:
45: #include <machdep/ppc/ast.h>
46: extern void fpu_save(void);
47: #define NULL 0
48:
49: #if DEBUG
50: #define TRAP_ALL -1
51: #define TRAP_ALIGNMENT 0x01
52: #define TRAP_DATA 0x02
53: #define TRAP_INSTRUCTION 0x04
54: #define TRAP_AST 0x08
55: #define TRAP_TRACE 0x10
56: #define TRAP_PROGRAM 0x20
57: #define TRAP_EXCEPTION 0x40
58: #define TRAP_UNRESOLVED 0x80
59: #define TRAP_SYSCALL 0x100 /* all syscalls */
60: #define TRAP_HW 0x200 /* all in hw_exception.s */
61: #define TRAP_MACH_SYSCALL 0x400
62: #define TRAP_SERVER_SYSCALL 0x800
63:
64: int trapdebug=0;
65:
66: #define TRAP_DEBUG(LEVEL, A) {if ((trapdebug & LEVEL)==LEVEL){kprintf A;}}
67: #else
68: #define TRAP_DEBUG(LEVEL, A)
69: #endif
70:
71: /*
72: * XXX don't pass VM_PROT_EXECUTE to vm_fault(), execute permission is implied
73: * in either R or RW (note: the pmap module knows this). This is done for the
74: * benefit of programs that execute out of their data space (ala lisp).
75: * If we didn't do this in that scenerio, the ITLB miss code would call us
76: * and we would call vm_fault() with RX permission. However, the space was
77: * probably vm_allocate()ed with just RW and vm_fault would fail. The "right"
78: * solution to me is to have the un*x server always allocate data with RWX for
79: * compatibility with existing binaries.
80: */
81:
82: #define PROT_EXEC (VM_PROT_READ)
83: #define PROT_RO (VM_PROT_READ)
84: #define PROT_RW (VM_PROT_READ|VM_PROT_WRITE)
85:
86: #define IS_KLOADED(pc) ((vm_offset_t)pc > VM_MIN_KERNEL_LOADED_ADDRESS)
87:
88: /* A useful macro to update the ppc_exception_state in the PCB
89: * before calling doexception
90: */
91: #define UPDATE_PPC_EXCEPTION_STATE { \
92: thread_t th = current_thread(); \
93: struct ppc_exception_state *es = &th->pcb->es; \
94: es->dar = dar; \
95: es->dsisr = dsisr; \
96: es->exception = trapno / EXC_VECTOR_SIZE; /* back to powerpc */ \
97: }
98:
99: static void unresolved_kernel_trap(int trapno,
100: struct ppc_saved_state *ssp,
101: unsigned int dsisr,
102: unsigned int dar,
103: char *message);
104:
105: struct ppc_saved_state *trap(int trapno,
106: struct ppc_saved_state *ssp,
107: unsigned int dsisr,
108: unsigned int dar)
109: {
110: int exception=0;
111: int code;
112: int subcode;
113: vm_map_t map;
114: unsigned int sp;
115: unsigned int space,space2;
116: unsigned int offset;
117: thread_t th = current_thread();
118: int error;
119: struct proc *p = th->task->proc;
120: struct timeval syst;
121:
122: TRAP_DEBUG(TRAP_ALL,("NMGS TRAP %d srr0=0x%08x, srr1=0x%08x\n",
123: trapno/4,ssp->srr0,ssp->srr1));
124:
125: /* Handle kernel traps first */
126:
127: if (!USER_MODE(ssp->srr1)) {
128: /*
129: * Trap came from system task, ie kernel or collocated server
130: */
131: switch (trapno) {
132: /*
133: * These trap types should never be seen by trap()
134: * in kernel mode, anyway.
135: * Some are interrupts that should be seen by
136: * interrupt() others just don't happen because they
137: * are handled elsewhere. Some could happen but are
138: * considered to be fatal in kernel mode.
139: */
140: case EXC_DECREMENTER:
141: case EXC_INVALID:
142: case EXC_RESET:
143: case EXC_MACHINE_CHECK:
144: case EXC_SYSTEM_MANAGEMENT:
145: case EXC_INTERRUPT:
146: case EXC_FP_UNAVAILABLE:
147: case EXC_IO_ERROR:
148: default:
149: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
150: break;
151:
152: case EXC_TRACE:
153: #if DEBUG
154: enter_debugger(trapno, dsisr, dar, ssp, 0);
155: #else
156: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
157: #endif
158: break;
159:
160: case EXC_RUNMODE_TRACE:
161: case EXC_INSTRUCTION_BKPT:
162: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
163: break;
164:
165: case EXC_PROGRAM:
166: if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
167: #if DEBUG
168: enter_debugger(trapno, dsisr, dar, ssp, 0);
169: #else
170: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
171: #endif /* DEBUG */
172: } else {
173: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
174: }
175: break;
176: case EXC_ALIGNMENT:
177: TRAP_DEBUG(TRAP_ALIGNMENT,
178: ("NMGS KERNEL ALIGNMENT_ACCESS, "
179: "DAR=0x%08x, DSISR = 0x%08X\n",
180: dar, dsisr,
181: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
182: if (alignment(dsisr, dar, ssp)) {
183: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
184: }
185: break;
186: case EXC_DATA_ACCESS:
187: TRAP_DEBUG(TRAP_DATA,
188: ("NMGS KERNEL DATA_ACCESS, DAR=0x%08x,"
189: "DSISR = 0x%08X\n", dar, dsisr,
190: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
191:
192: if (dsisr & MASK(DSISR_WATCH)) {
193: printf("dabr ");
194: #if DEBUG
195: enter_debugger(trapno, dsisr,dar,ssp, 1);
196: #else
197: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
198: #endif
199: break;
200: }
201: /* simple case : not SR_COPYIN segment, from kernel */
202: if ((dar >> 28) != SR_COPYIN) {
203: /* if from kloaded task, use task mapping */
204: #if notdef_next /* NeXT kernloaded modules use the kernel map */
205: if(IS_KLOADED(ssp->srr0))
206: map = th->task->map;
207: else
208: #endif /* notdef_next */
209: map = kernel_map;
210:
211: offset = dar;
212: TRAP_DEBUG(TRAP_DATA,
213: ("SYSTEM FAULT FROM 0x%08x\n",
214: offset));
215: code = vm_fault(map,
216: trunc_page(offset),
217: dsisr & MASK(DSISR_WRITE) ?
218: PROT_RW : PROT_RO,
219: FALSE,
220: &error);
221: if (code != KERN_SUCCESS) {
222: #if DEBUG
223: if (th->recover) {
224: label_t *l = (label_t *)th->recover;
225: th->recover = (vm_offset_t)NULL;
226: longjmp(l,1);
227: } else {
228: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
229: }
230: #else
231: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
232: #endif
233: }
234: break;
235: }
236:
237: /* If we get here, the fault was due to a copyin/out */
238:
239: map = th->task->map;
240:
241: /* Mask out SR_COPYIN and mask in original segment */
242:
243: offset = (dar & 0x0fffffff) |
244: ((mfsrin(dar) & 0xF) << 28);
245:
246: TRAP_DEBUG(TRAP_DATA,
247: ("sr=0x%08x, dar=0x%08x, sp=0x%x\n",
248: mfsrin(dar), dar,map->pmap->space));
249: assert(((mfsrin(dar) & 0x0FFFFFFF) >> 4) ==
250: map->pmap->space);
251: TRAP_DEBUG(TRAP_DATA,
252: ("KERNEL FAULT FROM 0x%x,0x%08x\n",
253: map->pmap->space, offset));
254:
255: code = vm_fault(map,
256: trunc_page(offset),
257: dsisr & MASK(DSISR_WRITE) ?
258: PROT_RW : PROT_RO,
259: FALSE,
260: &error);
261:
262: /* If we failed, there should be a recovery
263: * spot to rfi to.
264: */
265: if (code != KERN_SUCCESS) {
266: TRAP_DEBUG(TRAP_DATA,
267: ("FAULT FAILED- srr0=0x%08x,"
268: "pcb-srr0=0x%08x\n",
269: ssp->srr0,
270: th->pcb->ss.srr0));
271:
272: if (th->recover) {
273: label_t *l = (label_t *)th->recover;
274: th->recover = (vm_offset_t)NULL;
275: longjmp(l, 1);
276: } else {
277: unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point");
278: }
279: }
280: break;
281:
282: case EXC_INSTRUCTION_ACCESS:
283: /* Colocated tasks aren't necessarily wired and
284: * may page fault
285: */
286: TRAP_DEBUG(TRAP_INSTRUCTION,
287: ("NMGS KERNEL INSTRUCTION ACCESS,"
288: "DSISR = 0x%B\n", dsisr,
289: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
290:
291: #if DEBUG
292: enter_debugger(trapno, dsisr,dar,ssp, 1);
293: #else
294: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
295: #endif
296: #if 0
297: /* Make sure it's not the kernel itself faulting */
298: assert ((ssp->srr0 >= VM_MIN_KERNEL_LOADED_ADDRESS) &&
299: (ssp->srr0 < VM_MAX_KERNEL_LOADED_ADDRESS));
300:
301: /* Same as for data access, except fault type
302: * is PROT_EXEC and addr comes from srr0
303: */
304: map = th->task->map;
305: space = PPC_SID_KERNEL;
306:
307: code = vm_fault(map, trunc_page(ssp->srr0),
308: PROT_EXEC, FALSE,
309: &error);
310: if (code != KERN_SUCCESS) {
311: TRAP_DEBUG(TRAP_INSTRUCTION,
312: ("INSTR FAULT FAILED!\n"));
313: exception = EXC_BAD_ACCESS;
314: subcode = ssp->srr0;
315: }
316: #endif
317: break;
318:
319: case EXC_AST:
320: TRAP_DEBUG(TRAP_AST,
321: ("EXC_AST FROM KERNEL MODE\n"));
322: check_for_ast();
323: break;
324: }
325: } else {
326: /*
327: * Trap came from user task
328: */
329:
330: if (p)
331: syst = p->p_stats->p_ru.ru_stime;
332:
333:
334: switch (trapno) {
335: /*
336: * These trap types should never be seen by trap()
337: * Some are interrupts that should be seen by
338: * interrupt() others just don't happen because they
339: * are handled elsewhere.
340: */
341: case EXC_DECREMENTER:
342: case EXC_INVALID:
343: case EXC_MACHINE_CHECK:
344: case EXC_INTERRUPT:
345: case EXC_FP_UNAVAILABLE:
346: case EXC_SYSTEM_MANAGEMENT:
347: case EXC_IO_ERROR:
348:
349: default:
350: panic("Unexpected exception type, %d 0x%x", trapno, trapno);
351: break;
352:
353: case EXC_RESET:
354: powermac_reboot(); /* never returns */
355:
356: case EXC_ALIGNMENT:
357: TRAP_DEBUG(TRAP_ALIGNMENT,
358: ("NMGS USER ALIGNMENT_ACCESS, "
359: "DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,
360: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
361: if (alignment(dsisr, dar, ssp)) {
362: code = EXC_PPC_UNALIGNED;
363: exception = EXC_BAD_ACCESS;
364: subcode = dar;
365: }
366: break;
367:
368: case EXC_TRACE: /* Real PPC chips */
369: case EXC_INSTRUCTION_BKPT: /* 603 PPC chips */
370: case EXC_RUNMODE_TRACE: /* 601 PPC chips */
371: TRAP_DEBUG(TRAP_TRACE,("NMGS TRACE TRAP\n"));
372: exception = EXC_BREAKPOINT;
373: code = EXC_PPC_TRACE;
374: subcode = ssp->srr0;
375: break;
376:
377: case EXC_PROGRAM:
378: TRAP_DEBUG(TRAP_PROGRAM,
379: ("NMGS PROGRAM TRAP\n"));
380: if (ssp->srr1 & MASK(SRR1_PRG_FE)) {
381: TRAP_DEBUG(TRAP_PROGRAM,
382: ("FP EXCEPTION\n"));
383: fpu_save();
384: fpu_disable();
385: UPDATE_PPC_EXCEPTION_STATE;
386: exception = EXC_ARITHMETIC;
387: code = EXC_ARITHMETIC;
388: subcode = per_proc_info[cpu_number()].
389: fpu_pcb->fs.fpscr;
390: } else if (ssp->srr1 & MASK(SRR1_PRG_ILL_INS)) {
391: TRAP_DEBUG(TRAP_PROGRAM,
392: ("ILLEGAL INSTRUCTION\n"));
393:
394: UPDATE_PPC_EXCEPTION_STATE
395: exception = EXC_BAD_INSTRUCTION;
396: code = EXC_PPC_UNIPL_INST;
397: subcode = ssp->srr0;
398: } else if (ssp->srr1 & MASK(SRR1_PRG_PRV_INS)) {
399: TRAP_DEBUG(TRAP_PROGRAM,
400: ("PRIVILEGED INSTRUCTION\n"));
401:
402: UPDATE_PPC_EXCEPTION_STATE;
403: exception = EXC_BAD_INSTRUCTION;
404: code = EXC_PPC_PRIVINST;
405: subcode = ssp->srr0;
406: } else if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) {
407: #if MACH_KGDB
408: /* Give kernel debugger a chance to
409: * claim the breakpoint before passing
410: * it up as an exception
411: */
412: if (kgdb_user_breakpoint(ssp)) {
413: call_kgdb_with_ctx(EXC_PROGRAM,
414: 0,
415: ssp);
416: break;
417: }
418: #endif /* MACH_KGDB */
419:
420: UPDATE_PPC_EXCEPTION_STATE;
421: exception = EXC_BREAKPOINT;
422: code = EXC_PPC_BREAKPOINT;
423: subcode = ssp->srr0;
424: }
425: break;
426:
427: case EXC_DATA_ACCESS:
428: TRAP_DEBUG(TRAP_DATA,
429: ("NMGS USER DATA_ACCESS, DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
430:
431: if (dsisr & MASK(DSISR_WATCH)) {
432: printf("dabr ");
433: #if DEBUG
434: enter_debugger(trapno, dsisr,dar,ssp, 1);
435: #else
436: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL);
437: #endif
438: break;
439: }
440: map = th->task->map;
441: space = map->pmap->space;
442: assert(space != 0);
443: #if DEBUG
444: mfsr(space2, SR_UNUSED_BY_KERN);
445: space2 = (space2 >> 4) & 0x00FFFFFF;
446:
447: /* Do a check that at least SR_UNUSED_BY_KERN
448: * is in the correct user space.
449: * TODO NMGS may not be true as ints are on?.
450: */
451: assert(space2 == space);
452: #if 0
453: TRAP_DEBUG(TRAP_DATA,("map = 0x%08x, space=0x%08x, addr=0x%08x\n",map, space, trunc_page(dar));
454: #endif
455: #endif /* DEBUG */
456:
457: code = vm_fault(map, trunc_page(dar),
458: dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO,
459: FALSE,
460: &error);
461: if (code != KERN_SUCCESS) {
462: TRAP_DEBUG(TRAP_DATA,("FAULT FAILED!\n"));
463: UPDATE_PPC_EXCEPTION_STATE;
464: exception = EXC_BAD_ACCESS;
465: subcode = dar;
466: }
467: break;
468:
469: case EXC_INSTRUCTION_ACCESS:
470: TRAP_DEBUG(TRAP_INSTRUCTION,("NMGS USER INSTRUCTION ACCESS, DSISR = 0x%B\n", dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO"));
471:
472: /* Same as for data access, except fault type
473: * is PROT_EXEC and addr comes from srr0
474: */
475: map = th->task->map;
476: space = map->pmap->space;
477: assert(space != 0);
478: #if DEBUG
479: mfsr(space2, SR_UNUSED_BY_KERN);
480: space2 = (space2 >> 4) & 0x00FFFFFF;
481:
482: /* Do a check that at least SR_UNUSED_BY_KERN
483: * is in the correct user space.
484: * TODO NMGS is this always true now ints are on?
485: */
486: assert(space2 == space);
487: #endif /* DEBUG */
488:
489: code = vm_fault(map, trunc_page(ssp->srr0),
490: PROT_EXEC, FALSE,
491: &error);
492: if (code != KERN_SUCCESS) {
493: TRAP_DEBUG(TRAP_INSTRUCTION,
494: ("INSTR FAULT FAILED!\n"));
495: UPDATE_PPC_EXCEPTION_STATE;
496: exception = EXC_BAD_ACCESS;
497: subcode = ssp->srr0;
498: }
499: break;
500:
501: case EXC_AST:
502: TRAP_DEBUG(TRAP_AST,("EXC_AST FROM USER MODE\n"));
503: check_for_ast();
504: break;
505:
506: }
507: }
508:
509: if (exception) {
510: TRAP_DEBUG(TRAP_EXCEPTION,
511: ("doexception (0x%x, 0x%x, 0x%x, 0x%x, pc = 0x%x in %s)\n",
512: exception,code,subcode, th, th->pcb->ss.srr0,
513: &th->task->proc->p_comm));
514: doexception(exception, code, subcode, th);
515: return ssp;
516: }
517:
518: if (USER_MODE(ssp->srr1)) {
519: if (p && (p->p_flag & P_PROFIL)) {
520: int ticks;
521: struct timeval *tv = &p->p_stats->p_ru.ru_stime;
522:
523: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
524: (tv->tv_usec - syst.tv_usec) / 1000) /
525: (tick / 1000);
526: if (ticks)
527: addupc_task(p, ssp->srr0, ticks);
528: }
529: }
530: return ssp;
531: }
532:
533: #if MACH_ASSERT
534: /* This routine is called from assembly before each and every system call
535: * iff MACH_ASSERT is defined. It must preserve r3.
536: */
537:
538: extern int syscall_trace(int, struct ppc_saved_state *);
539:
540: int syscall_trace(int retval, struct ppc_saved_state *ssp)
541: {
542: int i, argc;
543:
544: if (trapdebug & TRAP_SYSCALL)
545: trapdebug |= (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL);
546:
547: if (!(trapdebug & (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL)))
548: return retval;
549: if (ssp->r0 & 0x80000000) {
550: /* Mach trap */
551: if (!(trapdebug & TRAP_MACH_SYSCALL))
552: return retval;
553:
554: printf("0x%08x : %30s (",
555: ssp->srr0, mach_trap_table[-(ssp->r0)].mach_trap_name);
556: argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count;
557: for (i = 0; i < argc; i++)
558: printf("%08x ",*(&ssp->r3 + i));
559: printf(")\n");
560: } else {
561: if (!(trapdebug & TRAP_SERVER_SYSCALL))
562: return retval;
563: printf("0x%08x : RHAPSODY %3d (", ssp->srr0, ssp->r0);
564: argc = 4; /* print 4 of 'em! */
565: for (i = 0; i < argc; i++)
566: printf("%08x ",*(&ssp->r3 + i));
567: printf(")\n");
568: }
569: return retval;
570: }
571: #endif /* MACH_ASSERT */
572:
573: /*
574: * called from syscall if there is an error
575: */
576:
577: int syscall_error(
578: int exception,
579: int code,
580: int subcode,
581: struct ppc_saved_state *ssp)
582: {
583: register thread_t thread;
584:
585: thread = current_thread();
586:
587: if (thread == 0)
588: panic("syscall error in boot phase");
589:
590: if (!USER_MODE(ssp->srr1))
591: panic("system call called from kernel");
592:
593: doexception(exception, code, subcode, thread);
594:
595: return 0;
596: }
597:
598: /* Pass up a server syscall/exception */
599: void
600: doexception(
601: int exc,
602: int code,
603: int sub,
604: thread_t th)
605: {
606: exception(exc, code, sub);
607: }
608:
609: char *trap_type[] = {
610: "0x0000 INVALID EXCEPTION",
611: "0x0100 System reset",
612: "0x0200 Machine check",
613: "0x0300 Data access",
614: "0x0400 Instruction access",
615: "0x0500 External interrupt",
616: "0x0600 Alignment",
617: "0x0700 Program",
618: "0x0800 Floating point",
619: "0x0900 Decrementer",
620: "0x0A00 I/O controller interface",
621: "0x0B00 INVALID EXCEPTION",
622: "0x0C00 System call exception",
623: "0x0D00 Trace",
624: "0x0E00 FP assist",
625: "0x0F00 Performance monitoring",
626: "0x1000 Instruction PTE miss",
627: "0x1100 Data load PTE miss",
628: "0x1200 Data store PTE miss",
629: "0x1300 Instruction Breakpoint",
630: "0x1400 System Management",
631: "0x1500 INVALID EXCEPTION",
632: "0x1600 INVALID EXCEPTION",
633: "0x1700 INVALID EXCEPTION",
634: "0x1800 INVALID EXCEPTION",
635: "0x1900 INVALID EXCEPTION",
636: "0x1A00 INVALID EXCEPTION",
637: "0x1B00 INVALID EXCEPTION",
638: "0x1C00 INVALID EXCEPTION",
639: "0x1D00 INVALID EXCEPTION",
640: "0x1E00 INVALID EXCEPTION",
641: "0x1F00 INVALID EXCEPTION",
642: "0x2000 Run Mode/Trace"
643: "0x2100 INVALID EXCEPTION",
644: "0x2200 INVALID EXCEPTION",
645: "0x2300 INVALID EXCEPTION",
646: "0x2400 INVALID EXCEPTION",
647: "0x2500 INVALID EXCEPTION",
648: "0x2600 INVALID EXCEPTION",
649: "0x2700 INVALID EXCEPTION",
650: "0x2800 INVALID EXCEPTION",
651: "0x2900 INVALID EXCEPTION",
652: "0x2A00 INVALID EXCEPTION",
653: "0x2B00 INVALID EXCEPTION",
654: "0x2C00 INVALID EXCEPTION",
655: "0x2D00 INVALID EXCEPTION",
656: "0x2E00 INVALID EXCEPTION",
657: "0x2F00 INVALID EXCEPTION",
658: };
659:
660: void unresolved_kernel_trap(int trapno,
661: struct ppc_saved_state *ssp,
662: unsigned int dsisr,
663: unsigned int dar,
664: char *message)
665: {
666: char *trap_name;
667:
668: #if notdef_next
669: if(IS_KLOADED(ssp->srr0)) {
670: int exception;
671:
672: TRAP_DEBUG(TRAP_UNRESOLVED,
673: ("unresolved trap %d in kernel loaded task %d\n",trapno));
674: TRAP_DEBUG(TRAP_UNRESOLVED,
675: ("%s: sending exception message\n", message));
676: switch(trapno) {
677: case EXC_INVALID:
678: case EXC_RESET:
679: case EXC_MACHINE_CHECK:
680: case EXC_INTERRUPT:
681: case EXC_DECREMENTER:
682: case EXC_IO_ERROR:
683: case EXC_SYSTEM_CALL:
684: case EXC_RUNMODE_TRACE:
685: default:
686: exception = EXC_BREAKPOINT;
687: break;
688: case EXC_ALIGNMENT:
689: case EXC_INSTRUCTION_ACCESS:
690: case EXC_DATA_ACCESS:
691: exception = EXC_BAD_ACCESS;
692: break;
693: case EXC_PROGRAM:
694: exception = EXC_BAD_INSTRUCTION;
695: break;
696: case EXC_FP_UNAVAILABLE:
697: /* TODO NMGS - should this generate EXC_ARITHMETIC?*/
698: exception = EXC_ARITHMETIC;
699: break;
700: }
701: UPDATE_PPC_EXCEPTION_STATE;
702: doexception(exception, 0, 0, current_thread());
703: return;
704: }
705: #if DEBUG
706: regDump(ssp);
707: #endif /* DEBUG */
708: #endif /* notdef_next */
709:
710: if ((unsigned)trapno <= EXC_MAX)
711: trap_name = trap_type[trapno / EXC_VECTOR_SIZE];
712: else
713: trap_name = "???? unrecognised exception";
714: if (message == NULL)
715: message = trap_name;
716:
717: /* no KGDB so display a backtrace */
718: printf("\n\nUnresolved kernel trap: %s DSISR=0x%08x DAR=0x%08x\n",
719: trap_name, dsisr, dar);
720:
721: #ifdef DEBUG
722: enter_debugger(trapno, dsisr, dar, ssp, 1);
723: #else
724: {
725: unsigned int* stackptr;
726: int i;
727: printf("generating stack backtrace prior to panic:\n\n");
728:
729: printf("backtrace: 0x%08x ", ssp->srr0);
730:
731: stackptr = (unsigned int *)(ssp->r1);
732:
733: for (i = 0; i < 8; i++) {
734:
735: /* Avoid causing page fault */
736: if (pmap_extract(kernel_pmap, (vm_offset_t)stackptr) == 0)
737: break;
738:
739: stackptr = (unsigned int*)*stackptr;
740: /*
741: * TODO NMGS - use FM_LR_SAVE constant, but asm.h defines
742: * too much (such as r1, used above)
743: */
744:
745: /* Avoid causing page fault */
746: if (pmap_extract(kernel_pmap, (vm_offset_t)stackptr+2) == 0)
747: break;
748:
749: printf("0x%08x ",*(stackptr + 2));
750: }
751: printf("\n\n");
752: }
753: #endif
754:
755: panic(message);
756: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.