|
@@ -222,8 +222,9 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|
|
unsigned long address = 0;
|
|
|
bundle_bits instr;
|
|
|
|
|
|
- /* Re-enable interrupts. */
|
|
|
- local_irq_enable();
|
|
|
+ /* Re-enable interrupts, if they were previously enabled. */
|
|
|
+ if (!(regs->flags & PT_FLAGS_DISABLE_IRQ))
|
|
|
+ local_irq_enable();
|
|
|
|
|
|
/*
|
|
|
* If it hits in kernel mode and we can't fix it up, just exit the
|
|
@@ -231,7 +232,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|
|
*/
|
|
|
if (!user_mode(regs)) {
|
|
|
const char *name;
|
|
|
- if (fixup_exception(regs)) /* only UNALIGN_DATA in practice */
|
|
|
+ char buf[100];
|
|
|
+ if (fixup_exception(regs)) /* ILL_TRANS or UNALIGN_DATA */
|
|
|
return;
|
|
|
if (fault_num >= 0 &&
|
|
|
fault_num < sizeof(int_name)/sizeof(int_name[0]) &&
|
|
@@ -239,10 +241,16 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|
|
name = int_name[fault_num];
|
|
|
else
|
|
|
name = "Unknown interrupt";
|
|
|
- pr_alert("Kernel took bad trap %d (%s) at PC %#lx\n",
|
|
|
- fault_num, name, regs->pc);
|
|
|
if (fault_num == INT_GPV)
|
|
|
- pr_alert("GPV_REASON is %#lx\n", reason);
|
|
|
+ snprintf(buf, sizeof(buf), "; GPV_REASON %#lx", reason);
|
|
|
+#ifdef __tilegx__
|
|
|
+ else if (fault_num == INT_ILL_TRANS)
|
|
|
+ snprintf(buf, sizeof(buf), "; address %#lx", reason);
|
|
|
+#endif
|
|
|
+ else
|
|
|
+ buf[0] = '\0';
|
|
|
+ pr_alert("Kernel took bad trap %d (%s) at PC %#lx%s\n",
|
|
|
+ fault_num, name, regs->pc, buf);
|
|
|
show_regs(regs);
|
|
|
do_exit(SIGKILL); /* FIXME: implement i386 die() */
|
|
|
return;
|
|
@@ -324,11 +332,8 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
|
|
|
fill_ra_stack();
|
|
|
|
|
|
signo = SIGSEGV;
|
|
|
+ address = reason;
|
|
|
code = SEGV_MAPERR;
|
|
|
- if (reason & SPR_ILL_TRANS_REASON__I_STREAM_VA_RMASK)
|
|
|
- address = regs->pc;
|
|
|
- else
|
|
|
- address = 0; /* FIXME: GX: single-step for address */
|
|
|
break;
|
|
|
}
|
|
|
#endif
|