[MIPS] kgdb: add arch support for the kernel's kgdb core

The new kgdb architecture specific handler registers and unregisters
dynamically for exceptions depending on when you configure a kgdb I/O
driver.

Aside from initializing the exceptions earlier in the boot process,
kgdb should have no impact on a device when it is compiled in so long
as an I/O module is not configured for use.

There have been quite a number of contributors during the existence of
this patch (see arch/mips/kernel/kgdb.c).  Most recently Jason
re-wrote the mips kgdb logic to use the die notification handlers.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index b8ea4e9..426cced 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -23,6 +23,8 @@
 #include <linux/bootmem.h>
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
+#include <linux/kgdb.h>
+#include <linux/kdebug.h>
 
 #include <asm/bootinfo.h>
 #include <asm/branch.h>
@@ -425,6 +427,10 @@
 	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)
+	    == NOTIFY_STOP)
+		return;
+
 	die_if_kernel("Oops", regs);
 	force_sig(SIGBUS, current);
 }
@@ -623,6 +629,9 @@
 {
 	siginfo_t info;
 
+	if (notify_die(DIE_FP, "FP exception", regs, SIGFPE, 0, 0)
+	    == NOTIFY_STOP)
+		return;
 	die_if_kernel("FP exception in kernel code", regs);
 
 	if (fcr31 & FPU_CSR_UNI_X) {
@@ -682,6 +691,9 @@
 	siginfo_t info;
 	char b[40];
 
+	if (notify_die(DIE_TRAP, str, regs, code, 0, 0) == NOTIFY_STOP)
+		return;
+
 	/*
 	 * A short test says that IRIX 5.3 sends SIGTRAP for all trap
 	 * insns, even for trap and break codes that indicate arithmetic
@@ -762,6 +774,10 @@
 	unsigned int opcode = 0;
 	int status = -1;
 
+	if (notify_die(DIE_RI, "RI Fault", regs, SIGSEGV, 0, 0)
+	    == NOTIFY_STOP)
+		return;
+
 	die_if_kernel("Reserved instruction in kernel code", regs);
 
 	if (unlikely(compute_return_epc(regs) < 0))
@@ -1537,6 +1553,11 @@
 	extern char except_vec4;
 	unsigned long i;
 
+#if defined(CONFIG_KGDB)
+	if (kgdb_early_setup)
+		return;	/* Already done */
+#endif
+
 	if (cpu_has_veic || cpu_has_vint)
 		ebase = (unsigned long) alloc_bootmem_low_pages(0x200 + VECTORSPACING*64);
 	else