aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/traps.c
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-17 16:15:55 -0500
commit8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch)
treea8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /arch/tile/kernel/traps.c
parent406089d01562f1e2bf9f089fd7637009ebaad589 (diff)
Patched in Tegra support.
Diffstat (limited to 'arch/tile/kernel/traps.c')
-rw-r--r--arch/tile/kernel/traps.c51
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
30void __init trap_init(void) 30void __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
198static 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
217void __kprobes do_trap(struct pt_regs *regs, int fault_num, 198void __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