riscv: Add option to print registers on exception

When debugging, it can be helpful to see more information about an
unhandled exception. This patch adds an option to view the registers at
the time of the trap, similar to the linux output on a kernel panic.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Reviewed-by: Rick Chen <rick@andestech.com>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Tested-by: Bin Meng <bmeng.cn@gmail.com>
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
index 512dce06..074c70e 100644
--- a/arch/riscv/lib/interrupts.c
+++ b/arch/riscv/lib/interrupts.c
@@ -5,6 +5,8 @@
  *
  * Copyright (C) 2017 Andes Technology Corporation
  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
+ *
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
  */
 
 #include <common.h>
@@ -14,7 +16,34 @@
 #include <asm/system.h>
 #include <asm/encoding.h>
 
-static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
+static void show_regs(struct pt_regs *regs)
+{
+#ifdef CONFIG_SHOW_REGS
+	printf("RA: " REG_FMT " SP:  " REG_FMT " GP:  " REG_FMT "\n",
+	       regs->ra, regs->sp, regs->gp);
+	printf("TP: " REG_FMT " T0:  " REG_FMT " T1:  " REG_FMT "\n",
+	       regs->tp, regs->t0, regs->t1);
+	printf("T2: " REG_FMT " S0:  " REG_FMT " S1:  " REG_FMT "\n",
+	       regs->t2, regs->s0, regs->s1);
+	printf("A0: " REG_FMT " A1:  " REG_FMT " A2:  " REG_FMT "\n",
+	       regs->a0, regs->a1, regs->a2);
+	printf("A3: " REG_FMT " A4:  " REG_FMT " A5:  " REG_FMT "\n",
+	       regs->a3, regs->a4, regs->a5);
+	printf("A6: " REG_FMT " A7:  " REG_FMT " S2:  " REG_FMT "\n",
+	       regs->a6, regs->a7, regs->s2);
+	printf("S3: " REG_FMT " S4:  " REG_FMT " S5:  " REG_FMT "\n",
+	       regs->s3, regs->s4, regs->s5);
+	printf("S6: " REG_FMT " S7:  " REG_FMT " S8:  " REG_FMT "\n",
+	       regs->s6, regs->s7, regs->s8);
+	printf("S9: " REG_FMT " S10: " REG_FMT " S11: " REG_FMT "\n",
+	       regs->s9, regs->s10, regs->s11);
+	printf("T3: " REG_FMT " T4:  " REG_FMT " T5:  " REG_FMT "\n",
+	       regs->t3, regs->t4, regs->t5);
+	printf("T6: " REG_FMT "\n", regs->t6);
+#endif
+}
+
+static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs)
 {
 	static const char * const exception_code[] = {
 		"Instruction address misaligned",
@@ -35,14 +64,13 @@
 		"Store/AMO page fault",
 	};
 
-	if (code < ARRAY_SIZE(exception_code)) {
-		printf("exception code: %ld , %s , epc %lx , ra %lx\n",
-		       code, exception_code[code], epc, regs->ra);
-	} else {
-		printf("reserved exception code: %ld , epc %lx , ra %lx\n",
-		       code, epc, regs->ra);
-	}
+	if (code < ARRAY_SIZE(exception_code))
+		printf("Unhandled exception: %s\n", exception_code[code]);
+	else
+		printf("Unhandled exception code: %ld\n", code);
 
+	printf("EPC: " REG_FMT " TVAL: " REG_FMT "\n", epc, tval);
+	show_regs(regs);
 	hang();
 }
 
@@ -66,7 +94,7 @@
 	return 0;
 }
 
-ulong handle_trap(ulong cause, ulong epc, struct pt_regs *regs)
+ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs)
 {
 	ulong is_irq, irq;
 
@@ -84,11 +112,11 @@
 			timer_interrupt(0);	/* handle timer interrupt */
 			break;
 		default:
-			_exit_trap(cause, epc, regs);
+			_exit_trap(cause, epc, tval, regs);
 			break;
 		};
 	} else {
-		_exit_trap(cause, epc, regs);
+		_exit_trap(cause, epc, tval, regs);
 	}
 
 	return epc;