From f6431e8fb358e2fdd01692604cd5796a1b7c10a0 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 4 Sep 2021 10:36:49 +0200 Subject: riscv: show code leading to exception To make analyzing exceptions easier output the code that leads to it. We already do the same on the ARM platform. Here is an example: => exception ebreak Unhandled exception: Breakpoint EPC: 000000008ff5d50e RA: 000000008ff5d62c TVAL: 0000000000000000 EPC: 000000008020b50e RA: 000000008020b62c reloc adjusted Code: 2785 0693 07a0 dce3 fef6 47a5 d563 00e7 (9002) To disassemble the code we can use the decodecode script: $ echo 'Code: 2785 0693 07a0 dce3 fef6 47a5 d563 00e7 (9002)' | \ CROSS_COMPILE=riscv64-linux-gnu- scripts/decodecode Code: 2785 0693 07a0 dce3 fef6 47a5 d563 00e7 (9002) All code ======== 0: 2785 addiw a5,a5,1 2: 07a00693 li a3,122 6: fef6dce3 bge a3,a5,0xfffffffffffffffe a: 47a5 li a5,9 c: 00e7d563 bge a5,a4,0x16 10:* 9002 ebreak <-- trapping instruction ... Code starting with the faulting instruction =========================================== 0: 9002 ebreak ... As it is not always clear if the first 16 bits are at the start or in the middle of a 32bit instruction it may become necessary to strip the first u16 from the output before calling decodecode to get the correct disassembled code. Signed-off-by: Heinrich Schuchardt Reviewed-by: Bin Meng Reviewed-by: Sean Anderson --- arch/riscv/lib/interrupts.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'arch/riscv/lib/interrupts.c') diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c index 7525c152b89..100be2e9662 100644 --- a/arch/riscv/lib/interrupts.c +++ b/arch/riscv/lib/interrupts.c @@ -51,6 +51,38 @@ static void show_regs(struct pt_regs *regs) #endif } +/** + * instr_len() - get instruction length + * + * @i: low 16 bits of the instruction + * Return: number of u16 in instruction + */ +static int instr_len(u16 i) +{ + if ((i & 0x03) != 0x03) + return 1; + /* Instructions with more than 32 bits are not yet specified */ + return 2; +} + +/** + * show_code() - display code leading to exception + * + * @epc: program counter + */ +static void show_code(ulong epc) +{ + u16 *pos = (u16 *)(epc & ~1UL); + int i, len = instr_len(*pos); + + printf("\nCode: "); + for (i = -8; i; ++i) + printf("%04x ", pos[i]); + printf("("); + for (i = 0; i < len; ++i) + printf("%04x%s", pos[i], i + 1 == len ? ")\n" : " "); +} + static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs) { static const char * const exception_code[] = { @@ -85,6 +117,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_code(epc); show_efi_loaded_images(epc); panic("\n"); } -- cgit v1.2.3