scoutos / prex-0.9.0 / bsp / hal / x86 / arch / trap.c @ 03e9c04a
History | View | Annotate | Download (5.47 KB)
1 |
/*-
|
---|---|
2 |
* Copyright (c) 2005-2009, Kohsuke Ohtani
|
3 |
* All rights reserved.
|
4 |
*
|
5 |
* Redistribution and use in source and binary forms, with or without
|
6 |
* modification, are permitted provided that the following conditions
|
7 |
* are met:
|
8 |
* 1. Redistributions of source code must retain the above copyright
|
9 |
* notice, this list of conditions and the following disclaimer.
|
10 |
* 2. Redistributions in binary form must reproduce the above copyright
|
11 |
* notice, this list of conditions and the following disclaimer in the
|
12 |
* documentation and/or other materials provided with the distribution.
|
13 |
* 3. Neither the name of the author nor the names of any co-contributors
|
14 |
* may be used to endorse or promote products derived from this software
|
15 |
* without specific prior written permission.
|
16 |
*
|
17 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
21 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
27 |
* SUCH DAMAGE.
|
28 |
*/
|
29 |
|
30 |
/*
|
31 |
* trap.c - called from the trap handler when a processor trap occurs.
|
32 |
*/
|
33 |
|
34 |
#include <sys/signal.h> |
35 |
#include <kernel.h> |
36 |
#include <hal.h> |
37 |
#include <exception.h> |
38 |
#include <task.h> |
39 |
#include <cpu.h> |
40 |
#include <trap.h> |
41 |
#include <cpufunc.h> |
42 |
#include <context.h> |
43 |
#include <locore.h> |
44 |
|
45 |
#ifdef DEBUG
|
46 |
/*
|
47 |
* Trap name.
|
48 |
*/
|
49 |
static const char *const trap_name[] = { |
50 |
"Divide error", /* 0 */ |
51 |
"Debug trap", /* 1 */ |
52 |
"NMI", /* 2 */ |
53 |
"Breakpoint", /* 3 */ |
54 |
"Overflow", /* 4 */ |
55 |
"Bounds check", /* 5 */ |
56 |
"Invalid opecode", /* 6 */ |
57 |
"Device not available", /* 7 */ |
58 |
"Double fault", /* 8 */ |
59 |
"Coprocessor overrun", /* 9 */ |
60 |
"Invalid TSS", /* 10 */ |
61 |
"Segment not present", /* 11 */ |
62 |
"Stack bounds", /* 12 */ |
63 |
"General Protection", /* 13 */ |
64 |
"Page fault", /* 14 */ |
65 |
"Reserved", /* 15 */ |
66 |
"Coprocessor error", /* 16 */ |
67 |
"Alignment check", /* 17 */ |
68 |
"Cache flush denied" /* 18 */ |
69 |
}; |
70 |
#define MAXTRAP (sizeof(trap_name) / sizeof(void *) - 1) |
71 |
#endif /* DEBUG */ |
72 |
|
73 |
/*
|
74 |
* Trap/exception mapping table.
|
75 |
* x86 trap code is translated to the architecture
|
76 |
* independent exception code.
|
77 |
*/
|
78 |
static const int exception_map[] = { |
79 |
SIGFPE, /* 0: Divide error */
|
80 |
SIGTRAP, /* 1: Debug trap */
|
81 |
SIGILL, /* 2: NMI */
|
82 |
SIGTRAP, /* 3: Breakpoint */
|
83 |
SIGFPE, /* 4: Overflow */
|
84 |
SIGILL, /* 5: Bounds check */
|
85 |
SIGILL, /* 6: Invalid opecode */
|
86 |
SIGFPE, /* 7: Device not available */
|
87 |
SIGILL, /* 8: Double fault */
|
88 |
SIGFPE, /* 9: Coprocessor overrun */
|
89 |
SIGSEGV, /* 10: Invalid TSS */
|
90 |
SIGSEGV, /* 11: Segment not present */
|
91 |
SIGSEGV, /* 12: Stack bounds */
|
92 |
SIGILL, /* 13: General Protection fault */
|
93 |
SIGSEGV, /* 14: Page fault */
|
94 |
SIGILL, /* 15: Reserved */
|
95 |
SIGFPE, /* 16: Coprocessor error */
|
96 |
SIGILL, /* 17: Alignment check */
|
97 |
SIGILL, /* 18: Cache flush denied */
|
98 |
}; |
99 |
|
100 |
/*
|
101 |
* Trap handler
|
102 |
* Invoke the exception handler if it is needed.
|
103 |
*/
|
104 |
void
|
105 |
trap_handler(struct cpu_regs *regs)
|
106 |
{ |
107 |
u_long trap_no = regs->trap_no; |
108 |
|
109 |
if (trap_no > 18) |
110 |
panic("Unknown trap");
|
111 |
else if (trap_no == 2) |
112 |
panic("NMI");
|
113 |
|
114 |
/*
|
115 |
* Check whether this trap is kernel page fault caused
|
116 |
* by known routine to access user space like copyin().
|
117 |
* If so, we change the return address of this exception.
|
118 |
*/
|
119 |
if (trap_no == 14 && regs->cs == KERNEL_CS && |
120 |
(regs->eip == (uint32_t)known_fault1 || |
121 |
regs->eip == (uint32_t)known_fault2 || |
122 |
regs->eip == (uint32_t)known_fault3)) { |
123 |
DPRINTF(("\n*** Detect Fault! address=%x task=%s ***\n",
|
124 |
get_cr2(), curtask->name)); |
125 |
regs->eip = (uint32_t)copy_fault; |
126 |
return;
|
127 |
} |
128 |
#ifdef DEBUG
|
129 |
printf("============================\n");
|
130 |
printf("Trap %x: %s\n", (u_int)trap_no, trap_name[trap_no]);
|
131 |
if (trap_no == 14) |
132 |
printf(" Fault address=%x\n", get_cr2());
|
133 |
printf("============================\n");
|
134 |
trap_dump(regs); |
135 |
if (regs->cs == KERNEL_CS) {
|
136 |
printf("Trap in kernel!\n");
|
137 |
interrupt_mask(0);
|
138 |
spl0(); |
139 |
} |
140 |
for (;;) ;
|
141 |
#endif
|
142 |
if (regs->cs == KERNEL_CS)
|
143 |
panic("Kernel exception");
|
144 |
|
145 |
exception_mark(exception_map[trap_no]); |
146 |
exception_deliver(); |
147 |
} |
148 |
|
149 |
#ifdef DEBUG
|
150 |
void
|
151 |
trap_dump(struct cpu_regs *r)
|
152 |
{ |
153 |
uint32_t ss, esp, *fp; |
154 |
u_int i; |
155 |
int spl;
|
156 |
|
157 |
/* Get current spl */
|
158 |
spl = splhigh(); |
159 |
splx(spl); |
160 |
|
161 |
if (r->cs & 3) { |
162 |
ss = r->ss; |
163 |
esp = r->esp; |
164 |
} else {
|
165 |
ss = r->ds; |
166 |
esp = (uint32_t)r; |
167 |
} |
168 |
printf("Trap frame %08lx error %x\n", (long)r, r->err_code); |
169 |
printf(" eax %08x ebx %08x ecx %08x edx %08x esi %08x edi %08x\n",
|
170 |
r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi); |
171 |
printf(" eip %08x esp %08x ebp %08x eflags %08x\n",
|
172 |
r->eip, esp, r->ebp, r->eflags); |
173 |
printf(" cs %08x ss %08x ds %08x es %08x esp0 %08x\n",
|
174 |
r->cs, ss, r->ds, r->es, tss_get()); |
175 |
|
176 |
printf(" >> interrupt is %s\n", (spl == 0) ? "enabled" : "disabled"); |
177 |
|
178 |
printf(" >> task=%s\n", curtask->name);
|
179 |
|
180 |
if (r->cs == KERNEL_CS) {
|
181 |
printf("Stack trace:\n");
|
182 |
fp = (uint32_t *)r->ebp; |
183 |
for (i = 0; i < 8; i++) { |
184 |
if (user_area(fp))
|
185 |
break;
|
186 |
fp = (uint32_t *)(*fp); /* XXX: may cause fault */
|
187 |
if (!(*(fp + 1) && *fp)) |
188 |
break;
|
189 |
printf(" %08x\n", *(fp + 1)); |
190 |
} |
191 |
} |
192 |
} |
193 |
#endif /* !DEBUG */ |