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 |
|
---|