diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/tile/kernel/traps.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'arch/tile/kernel/traps.c')
-rw-r--r-- | arch/tile/kernel/traps.c | 51 |
1 files changed, 8 insertions, 43 deletions
diff --git a/arch/tile/kernel/traps.c b/arch/tile/kernel/traps.c index 5b19a23c890..f9803dfa735 100644 --- a/arch/tile/kernel/traps.c +++ b/arch/tile/kernel/traps.c | |||
@@ -19,13 +19,13 @@ | |||
19 | #include <linux/reboot.h> | 19 | #include <linux/reboot.h> |
20 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include <linux/ptrace.h> | 21 | #include <linux/ptrace.h> |
22 | #include <asm/opcode-tile.h> | ||
23 | #include <asm/opcode_constants.h> | ||
22 | #include <asm/stack.h> | 24 | #include <asm/stack.h> |
23 | #include <asm/traps.h> | 25 | #include <asm/traps.h> |
24 | #include <asm/setup.h> | ||
25 | 26 | ||
26 | #include <arch/interrupts.h> | 27 | #include <arch/interrupts.h> |
27 | #include <arch/spr_def.h> | 28 | #include <arch/spr_def.h> |
28 | #include <arch/opcode.h> | ||
29 | 29 | ||
30 | void __init trap_init(void) | 30 | void __init trap_init(void) |
31 | { | 31 | { |
@@ -135,7 +135,7 @@ static int special_ill(bundle_bits bundle, int *sigp, int *codep) | |||
135 | if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1) | 135 | if (get_UnaryOpcodeExtension_X1(bundle) != ILL_UNARY_OPCODE_X1) |
136 | return 0; | 136 | return 0; |
137 | #else | 137 | #else |
138 | if (bundle & TILEPRO_BUNDLE_Y_ENCODING_MASK) | 138 | if (bundle & TILE_BUNDLE_Y_ENCODING_MASK) |
139 | return 0; | 139 | return 0; |
140 | if (get_Opcode_X1(bundle) != SHUN_0_OPCODE_X1) | 140 | if (get_Opcode_X1(bundle) != SHUN_0_OPCODE_X1) |
141 | return 0; | 141 | return 0; |
@@ -195,31 +195,12 @@ static int special_ill(bundle_bits bundle, int *sigp, int *codep) | |||
195 | return 1; | 195 | return 1; |
196 | } | 196 | } |
197 | 197 | ||
198 | static const char *const int_name[] = { | ||
199 | [INT_MEM_ERROR] = "Memory error", | ||
200 | [INT_ILL] = "Illegal instruction", | ||
201 | [INT_GPV] = "General protection violation", | ||
202 | [INT_UDN_ACCESS] = "UDN access", | ||
203 | [INT_IDN_ACCESS] = "IDN access", | ||
204 | #if CHIP_HAS_SN() | ||
205 | [INT_SN_ACCESS] = "SN access", | ||
206 | #endif | ||
207 | [INT_SWINT_3] = "Software interrupt 3", | ||
208 | [INT_SWINT_2] = "Software interrupt 2", | ||
209 | [INT_SWINT_0] = "Software interrupt 0", | ||
210 | [INT_UNALIGN_DATA] = "Unaligned data", | ||
211 | [INT_DOUBLE_FAULT] = "Double fault", | ||
212 | #ifdef __tilegx__ | ||
213 | [INT_ILL_TRANS] = "Illegal virtual address", | ||
214 | #endif | ||
215 | }; | ||
216 | |||
217 | void __kprobes do_trap(struct pt_regs *regs, int fault_num, | 198 | void __kprobes do_trap(struct pt_regs *regs, int fault_num, |
218 | unsigned long reason) | 199 | unsigned long reason) |
219 | { | 200 | { |
220 | siginfo_t info = { 0 }; | 201 | siginfo_t info = { 0 }; |
221 | int signo, code; | 202 | int signo, code; |
222 | unsigned long address = 0; | 203 | unsigned long address; |
223 | bundle_bits instr; | 204 | bundle_bits instr; |
224 | 205 | ||
225 | /* Re-enable interrupts. */ | 206 | /* Re-enable interrupts. */ |
@@ -230,17 +211,10 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
230 | * current process and hope for the best. | 211 | * current process and hope for the best. |
231 | */ | 212 | */ |
232 | if (!user_mode(regs)) { | 213 | if (!user_mode(regs)) { |
233 | const char *name; | ||
234 | if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */ | 214 | if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */ |
235 | return; | 215 | return; |
236 | if (fault_num >= 0 && | 216 | pr_alert("Kernel took bad trap %d at PC %#lx\n", |
237 | fault_num < sizeof(int_name)/sizeof(int_name[0]) && | 217 | fault_num, regs->pc); |
238 | int_name[fault_num] != NULL) | ||
239 | name = int_name[fault_num]; | ||
240 | else | ||
241 | name = "Unknown interrupt"; | ||
242 | pr_alert("Kernel took bad trap %d (%s) at PC %#lx\n", | ||
243 | fault_num, name, regs->pc); | ||
244 | if (fault_num == INT_GPV) | 218 | if (fault_num == INT_GPV) |
245 | pr_alert("GPV_REASON is %#lx\n", reason); | 219 | pr_alert("GPV_REASON is %#lx\n", reason); |
246 | show_regs(regs); | 220 | show_regs(regs); |
@@ -249,10 +223,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
249 | } | 223 | } |
250 | 224 | ||
251 | switch (fault_num) { | 225 | switch (fault_num) { |
252 | case INT_MEM_ERROR: | ||
253 | signo = SIGBUS; | ||
254 | code = BUS_OBJERR; | ||
255 | break; | ||
256 | case INT_ILL: | 226 | case INT_ILL: |
257 | if (copy_from_user(&instr, (void __user *)regs->pc, | 227 | if (copy_from_user(&instr, (void __user *)regs->pc, |
258 | sizeof(instr))) { | 228 | sizeof(instr))) { |
@@ -319,10 +289,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
319 | address = regs->pc; | 289 | address = regs->pc; |
320 | break; | 290 | break; |
321 | #ifdef __tilegx__ | 291 | #ifdef __tilegx__ |
322 | case INT_ILL_TRANS: { | 292 | case INT_ILL_TRANS: |
323 | /* Avoid a hardware erratum with the return address stack. */ | ||
324 | fill_ra_stack(); | ||
325 | |||
326 | signo = SIGSEGV; | 293 | signo = SIGSEGV; |
327 | code = SEGV_MAPERR; | 294 | code = SEGV_MAPERR; |
328 | if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK) | 295 | if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK) |
@@ -330,7 +297,6 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
330 | else | 297 | else |
331 | address = 0; /* FIXME: GX: single-step for address */ | 298 | address = 0; /* FIXME: GX: single-step for address */ |
332 | break; | 299 | break; |
333 | } | ||
334 | #endif | 300 | #endif |
335 | default: | 301 | default: |
336 | panic("Unexpected do_trap interrupt number %d", fault_num); | 302 | panic("Unexpected do_trap interrupt number %d", fault_num); |
@@ -342,8 +308,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num, | |||
342 | info.si_addr = (void __user *)address; | 308 | info.si_addr = (void __user *)address; |
343 | if (signo == SIGILL) | 309 | if (signo == SIGILL) |
344 | info.si_trapno = fault_num; | 310 | info.si_trapno = fault_num; |
345 | if (signo != SIGTRAP) | 311 | trace_unhandled_signal("trap", regs, address, signo); |
346 | trace_unhandled_signal("trap", regs, address, signo); | ||
347 | force_sig_info(signo, &info, current); | 312 | force_sig_info(signo, &info, current); |
348 | } | 313 | } |
349 | 314 | ||