riscv: Add option to print registers on exception
authorSean Anderson <seanga2@gmail.com>
Wed, 25 Dec 2019 05:27:44 +0000 (00:27 -0500)
committerAndes <uboot@andestech.com>
Mon, 10 Feb 2020 06:51:08 +0000 (14:51 +0800)
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>
arch/riscv/Kconfig
arch/riscv/cpu/mtrap.S
arch/riscv/lib/interrupts.c

index 85e15ebffa1dfbce3a3c01fb8f5f6400612a110c..3338b788f84abdc33f2570364f5e3a5228dccc96 100644 (file)
@@ -222,6 +222,9 @@ config XIP
          from a NOR flash memory without copying the code to ram.
          Say yes here if U-Boot boots from flash directly.
 
+config SHOW_REGS
+       bool "Show registers on unhandled exception"
+
 config STACK_SIZE_SHIFT
        int
        default 14
index 407ecfa9c07646ddbc556be8802245e233643f04..e40c7bd3f4ff18c83a75c4c13d228e9dc9227356 100644 (file)
@@ -64,7 +64,8 @@ trap_entry:
        SREG x31, 31 * REGBYTES(sp)
        csrr a0, MODE_PREFIX(cause)
        csrr a1, MODE_PREFIX(epc)
-       mv a2, sp
+       csrr a2, MODE_PREFIX(tval)
+       mv a3, sp
        jal handle_trap
        csrw MODE_PREFIX(epc), a0
 
index 512dce061967ce33d4ef4ca53dbb68d084298400..074c70ee77a7b2db835d59af4ded4effb3d35a08 100644 (file)
@@ -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>
 #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 @@ static void _exit_trap(ulong code, ulong epc, struct pt_regs *regs)
                "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 @@ int disable_interrupts(void)
        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 @@ ulong handle_trap(ulong cause, ulong epc, struct pt_regs *regs)
                        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;