mips,kgdb: kdb low level trap catch and stack trace
[sfrench/cifs-2.6.git] / arch / mips / kernel / kgdb.c
index 50c9bb880667560bbb6f869e8b6af60a60d2a66e..9b78ff6e9b846fadcb135413b1f1ba7aa3c04fe4 100644 (file)
@@ -180,6 +180,11 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
        *(ptr++) = regs->cp0_epc;
 }
 
+void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
+{
+       regs->cp0_epc = pc;
+}
+
 /*
  * Calls linux_debug_hook before the kernel dies. If KGDB is enabled,
  * then try to fall into the debugger
@@ -198,7 +203,7 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
        if (atomic_read(&kgdb_active) != -1)
                kgdb_nmicallback(smp_processor_id(), regs);
 
-       if (kgdb_handle_exception(trap, compute_signal(trap), 0, regs))
+       if (kgdb_handle_exception(trap, compute_signal(trap), cmd, regs))
                return NOTIFY_DONE;
 
        if (atomic_read(&kgdb_setting_breakpoint))
@@ -212,6 +217,26 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd,
        return NOTIFY_STOP;
 }
 
+#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
+int kgdb_ll_trap(int cmd, const char *str,
+                struct pt_regs *regs, long err, int trap, int sig)
+{
+       struct die_args args = {
+               .regs   = regs,
+               .str    = str,
+               .err    = err,
+               .trapnr = trap,
+               .signr  = sig,
+
+       };
+
+       if (!kgdb_io_module_registered)
+               return NOTIFY_DONE;
+
+       return kgdb_mips_notify(NULL, cmd, &args);
+}
+#endif /* CONFIG_KGDB_LOW_LEVEL_TRAP */
+
 static struct notifier_block kgdb_notifier = {
        .notifier_call = kgdb_mips_notify,
 };