]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
riscv: add backtrace support
authorBen Dooks <ben.dooks@codethink.co.uk>
Tue, 5 Sep 2023 12:12:53 +0000 (13:12 +0100)
committerLeo Yu-Chi Liang <ycliang@andestech.com>
Tue, 9 Apr 2024 03:29:38 +0000 (11:29 +0800)
When debugging, it is useful to have a backtrace to find
out what is in the call stack as the previous function (RA)
may not have been the culprit.

Since this adds size to the build, do not add it by default
and avoid putting it in the SPL build if not needed.

Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Tested-by: Leo Yu-Chi Liang <ycliang@andestech.com>
arch/riscv/Kconfig
arch/riscv/Makefile
arch/riscv/cpu/start.S
arch/riscv/lib/interrupts.c

index 6c26f91f16695ef8996311d088efb6d5c601163f..1819db1e256e3aef08fa81b82d636e21edd31068 100644 (file)
@@ -119,6 +119,26 @@ config ARCH_RV64I
 
 endchoice
 
+config FRAMEPOINTER
+       bool "Build with frame pointer for stack unwinding"
+       help
+         Choose this option to use the frame pointer so the stack can be
+         unwound if needed. This is useful for tracing where faults came
+         from as the source may be several functions back
+
+         If you say Y here, then the code size will be increased due to
+         having to store the fp.
+
+config SPL_FRAMEPOINTER
+       bool "Build SPL with frame pointer for stack unwinding"
+       help
+         Choose this option to use the frame pointer so the stack can be
+         unwound if needed. This is useful for tracing where faults came
+         from as the source may be several functions back
+
+         If you say Y here, then the code size will be increased due to
+         having to store the fp.
+
 choice
        prompt "Code Model"
        default CMODEL_MEDLOW
index b3ef87078b5d25f48741976fc135cede8c4ce309..c36a8533e0f937a5dc2db3b85f52fa513bc8ad55 100644 (file)
@@ -48,6 +48,10 @@ endif
 ARCH_FLAGS = -march=$(RISCV_MARCH) -mabi=$(ABI) \
             -mcmodel=$(CMODEL)
 
+ifeq ($(CONFIG_$(SPL_)FRAMEPOINTER),y)
+       ARCH_FLAGS += -fno-omit-frame-pointer
+endif
+
 PLATFORM_CPPFLAGS      += $(ARCH_FLAGS)
 CFLAGS_EFI             += $(ARCH_FLAGS)
 
index 6cecadfac56d01714f183312c8e839643fd1b01e..a9e193569287f981b45c90575c3c09b528f8259c 100644 (file)
@@ -418,6 +418,7 @@ call_board_init_r:
  */
        mv      a0, s3                  /* gd_t */
        mv      a1, s4                  /* dest_addr */
+       mv      s0, zero                /* fp == NULL */
 
 /*
  * jump to it ...
index a26ccc721fd982073e93f4074c8b4fcf34793e30..7350e2ced8552ad911c393725c3e568f09ce1dc6 100644 (file)
@@ -60,6 +60,40 @@ static void show_regs(struct pt_regs *regs)
 #endif
 }
 
+#if defined(CONFIG_FRAMEPOINTER) || defined(CONFIG_SPL_FRAMEPOINTER)
+static void show_backtrace(struct pt_regs *regs)
+{
+       uintptr_t *fp = (uintptr_t *)regs->s0;
+       unsigned count = 0;
+       ulong ra;
+
+       printf("backtrace:\n");
+
+       /* there are a few entry points where the s0 register is
+        * set to gd, so to avoid changing those, just abort if
+        * the value is the same */
+       while (fp != NULL && fp != (uintptr_t *)gd) {
+               ra = fp[-1];
+               printf("backtrace %2d: FP: " REG_FMT " RA: " REG_FMT,
+                      count, (ulong)fp, ra);
+
+               if (gd && gd->flags & GD_FLG_RELOC)
+                       printf(" - RA: " REG_FMT " reloc adjusted\n",
+                       ra - gd->reloc_off);
+               else
+                       printf("\n");
+
+               fp = (uintptr_t *)fp[-2];
+               count++;
+       }
+}
+#else
+static void show_backtrace(struct pt_regs *regs)
+{
+       printf("No backtrace support enabled\n");
+}
+#endif
+
 /**
  * instr_len() - get instruction length
  *
@@ -131,6 +165,7 @@ static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs)
                       epc - gd->reloc_off, regs->ra - gd->reloc_off);
 
        show_regs(regs);
+       show_backtrace(regs);
        show_code(epc);
        show_efi_loaded_images(epc);
        panic("\n");