#include <linux/ptrace.h>
#include <linux/kgdb.h>
#include <linux/kdebug.h>
+#include <linux/kprobes.h>
#include <linux/notifier.h>
#include <linux/kdb.h>
__show_regs((struct pt_regs *)regs);
}
-void show_registers(const struct pt_regs *regs)
+void show_registers(struct pt_regs *regs)
{
const int field = 2 * sizeof(unsigned long);
printk("\n");
}
+static int regs_to_trapnr(struct pt_regs *regs)
+{
+ return (regs->cp0_cause >> 2) & 0x1f;
+}
+
static DEFINE_SPINLOCK(die_lock);
-void __noreturn die(const char * str, struct pt_regs * regs)
+void __noreturn die(const char *str, struct pt_regs *regs)
{
static int die_counter;
int sig = SIGSEGV;
unsigned long dvpret = dvpe();
#endif /* CONFIG_MIPS_MT_SMTC */
- notify_die(DIE_OOPS, str, (struct pt_regs *)regs, SIGSEGV, 0, 0);
+ notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV);
console_verbose();
spin_lock_irq(&die_lock);
mips_mt_regdump(dvpret);
#endif /* CONFIG_MIPS_MT_SMTC */
- if (notify_die(DIE_OOPS, str, regs, 0, current->thread.trap_no, SIGSEGV) == NOTIFY_STOP)
+ if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
sig = 0;
printk("%s[#%d]:\n", str, ++die_counter);
printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n",
data ? "Data" : "Instruction",
field, regs->cp0_epc, field, regs->regs[31]);
- if (notify_die(DIE_OOPS, "bus error", regs, SIGBUS, 0, 0)
+ if (notify_die(DIE_OOPS, "bus error", regs, 0, regs_to_trapnr(regs), SIGBUS)
== NOTIFY_STOP)
return;
{
siginfo_t info;
- if (notify_die(DIE_FP, "FP exception", regs, SIGFPE, 0, 0)
+ if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
== NOTIFY_STOP)
return;
die_if_kernel("FP exception in kernel code", regs);
char b[40];
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
- if (kgdb_ll_trap(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP)
+ if (kgdb_ll_trap(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
return;
#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
- if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP)
+ if (notify_die(DIE_TRAP, str, regs, code, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
return;
/*
if (bcode >= (1 << 10))
bcode >>= 10;
+ /*
+ * notify the kprobe handlers, if instruction is likely to
+ * pertain to them.
+ */
+ switch (bcode) {
+ case BRK_KPROBE_BP:
+ if (notify_die(DIE_BREAK, "debug", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+ return;
+ else
+ break;
+ case BRK_KPROBE_SSTEPBP:
+ if (notify_die(DIE_SSTEPBP, "single_step", regs, bcode, regs_to_trapnr(regs), SIGTRAP) == NOTIFY_STOP)
+ return;
+ else
+ break;
+ default:
+ break;
+ }
+
do_trap_or_bp(regs, bcode, "Break");
return;
unsigned int opcode = 0;
int status = -1;
- if (notify_die(DIE_RI, "RI Fault", regs, SIGSEGV, 0, 0)
+ if (notify_die(DIE_RI, "RI Fault", regs, 0, regs_to_trapnr(regs), SIGILL)
== NOTIFY_STOP)
return;
return NOTIFY_OK;
}
-static struct notifier_block default_cu2_notifier = {
- .notifier_call = default_cu2_call,
- .priority = 0x80000000, /* Run last */
-};
-
asmlinkage void do_cpu(struct pt_regs *regs)
{
unsigned int __user *epc;
case 2:
raw_notifier_call_chain(&cu2_chain, CU2_EXCEPTION, regs);
- break;
+ return;
case 3:
break;
sort_extable(__start___dbe_table, __stop___dbe_table);
- register_cu2_notifier(&default_cu2_notifier);
+ cu2_notifier(default_cu2_call, 0x80000000); /* Run last */
}