[4] | 1 | /* This file contains a simple exception handler. Exceptions in user
|
---|
| 2 | * processes are converted to signals. Exceptions in a kernel task cause
|
---|
| 3 | * a panic.
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | #include "kernel.h"
|
---|
| 7 | #include <signal.h>
|
---|
| 8 | #include "proc.h"
|
---|
| 9 |
|
---|
| 10 | /*===========================================================================*
|
---|
| 11 | * exception *
|
---|
| 12 | *===========================================================================*/
|
---|
| 13 | PUBLIC void exception(vec_nr)
|
---|
| 14 | unsigned vec_nr;
|
---|
| 15 | {
|
---|
| 16 | /* An exception or unexpected interrupt has occurred. */
|
---|
| 17 |
|
---|
| 18 | struct ex_s {
|
---|
| 19 | char *msg;
|
---|
| 20 | int signum;
|
---|
| 21 | int minprocessor;
|
---|
| 22 | };
|
---|
| 23 | static struct ex_s ex_data[] = {
|
---|
| 24 | { "Divide error", SIGFPE, 86 },
|
---|
| 25 | { "Debug exception", SIGTRAP, 86 },
|
---|
| 26 | { "Nonmaskable interrupt", SIGBUS, 86 },
|
---|
| 27 | { "Breakpoint", SIGEMT, 86 },
|
---|
| 28 | { "Overflow", SIGFPE, 86 },
|
---|
| 29 | { "Bounds check", SIGFPE, 186 },
|
---|
| 30 | { "Invalid opcode", SIGILL, 186 },
|
---|
| 31 | { "Coprocessor not available", SIGFPE, 186 },
|
---|
| 32 | { "Double fault", SIGBUS, 286 },
|
---|
| 33 | { "Copressor segment overrun", SIGSEGV, 286 },
|
---|
| 34 | { "Invalid TSS", SIGSEGV, 286 },
|
---|
| 35 | { "Segment not present", SIGSEGV, 286 },
|
---|
| 36 | { "Stack exception", SIGSEGV, 286 }, /* STACK_FAULT already used */
|
---|
| 37 | { "General protection", SIGSEGV, 286 },
|
---|
| 38 | { "Page fault", SIGSEGV, 386 }, /* not close */
|
---|
| 39 | { NIL_PTR, SIGILL, 0 }, /* probably software trap */
|
---|
| 40 | { "Coprocessor error", SIGFPE, 386 },
|
---|
| 41 | };
|
---|
| 42 | register struct ex_s *ep;
|
---|
| 43 | struct proc *saved_proc;
|
---|
| 44 |
|
---|
| 45 | /* Save proc_ptr, because it may be changed by debug statements. */
|
---|
| 46 | saved_proc = proc_ptr;
|
---|
| 47 |
|
---|
| 48 | ep = &ex_data[vec_nr];
|
---|
| 49 |
|
---|
| 50 | if (vec_nr == 2) { /* spurious NMI on some machines */
|
---|
| 51 | kprintf("got spurious NMI\n");
|
---|
| 52 | return;
|
---|
| 53 | }
|
---|
| 54 |
|
---|
| 55 | /* If an exception occurs while running a process, the k_reenter variable
|
---|
| 56 | * will be zero. Exceptions in interrupt handlers or system traps will make
|
---|
| 57 | * k_reenter larger than zero.
|
---|
| 58 | */
|
---|
| 59 | if (k_reenter == 0 && ! iskernelp(saved_proc)) {
|
---|
| 60 | cause_sig(proc_nr(saved_proc), ep->signum);
|
---|
| 61 | return;
|
---|
| 62 | }
|
---|
| 63 |
|
---|
| 64 | /* Exception in system code. This is not supposed to happen. */
|
---|
| 65 | if (ep->msg == NIL_PTR || machine.processor < ep->minprocessor)
|
---|
| 66 | kprintf("\nIntel-reserved exception %d\n", vec_nr);
|
---|
| 67 | else
|
---|
| 68 | kprintf("\n%s\n", ep->msg);
|
---|
| 69 | kprintf("k_reenter = %d ", k_reenter);
|
---|
| 70 | kprintf("process %d (%s), ", proc_nr(saved_proc), saved_proc->p_name);
|
---|
| 71 | kprintf("pc = %u:0x%x", (unsigned) saved_proc->p_reg.cs,
|
---|
| 72 | (unsigned) saved_proc->p_reg.pc);
|
---|
| 73 |
|
---|
| 74 | panic("exception in a kernel task", NO_NUM);
|
---|
| 75 | }
|
---|
| 76 |
|
---|