mips: add support to restore exception vector base before booting linux

In U-Boot the exception vector base will be moved to top of memory, to be
used to display register dump when exception occurs.

But some old linux kernel does not honor the base set in CP0_EBASE. A
modified exception vector base will cause kernel crash.

This patch adds an option to enable reset exception vector base to its
previous value, or a user configured value before booting linux kernel.

Reviewed-by: Daniel Schwierzeck <daniel.schwierzeck@gmail.com>
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 8c0d767..f1db6d2 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -294,6 +294,9 @@
 	bootstage_report();
 #endif
 
+	if (CONFIG_IS_ENABLED(RESTORE_EXCEPTION_VECTOR_BASE))
+		trap_restore();
+
 	if (images->ft_len)
 		kernel(-2, (ulong)images->ft_addr, 0, 0);
 	else
diff --git a/arch/mips/lib/traps.c b/arch/mips/lib/traps.c
index b8568c0..8fff754 100644
--- a/arch/mips/lib/traps.c
+++ b/arch/mips/lib/traps.c
@@ -20,6 +20,8 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+static unsigned long saved_ebase;
+
 static void show_regs(const struct pt_regs *regs)
 {
 	const int field = 2 * sizeof(unsigned long);
@@ -102,7 +104,24 @@
 	set_handler(0x180, &except_vec3_generic, 0x80);
 	set_handler(0x280, &except_vec_ejtag_debug, 0x80);
 
+	saved_ebase = read_c0_ebase() & 0xfffff000;
+
 	write_c0_ebase(ebase);
 	clear_c0_status(ST0_BEV);
 	execution_hazard_barrier();
 }
+
+void trap_restore(void)
+{
+	set_c0_status(ST0_BEV);
+	execution_hazard_barrier();
+
+#ifdef CONFIG_OVERRIDE_EXCEPTION_VECTOR_BASE
+	write_c0_ebase(CONFIG_NEW_EXCEPTION_VECTOR_BASE & 0xfffff000);
+#else
+	write_c0_ebase(saved_ebase);
+#endif
+
+	clear_c0_status(ST0_BEV);
+	execution_hazard_barrier();
+}