[PATCH 1/1] riscv: show code leading to exception
Sean Anderson
seanga2 at gmail.com
Fri Aug 13 03:34:58 CEST 2021
On 8/12/21 2:25 PM, Heinrich Schuchardt wrote:
> 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 <xypron.glpk at gmx.de>
> ---
> arch/riscv/lib/interrupts.c | 42 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 42 insertions(+)
>
> diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
> index 7525c152b8..31b8a6603c 100644
> --- a/arch/riscv/lib/interrupts.c
> +++ b/arch/riscv/lib/interrupts.c
> @@ -51,6 +51,47 @@ 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;
> + if ((i & 0x1c) != 0x1c)
Shouldn't this be 1f?
And TBH I would not bother dealing with >48-bit instructions, as not
even 48-bit instructions have been standardized (with the closest
candidate being [1] AFAIK). That would allow for simplification to
i &= 0b11111;
if (i == 0b011111)
return 3;
i &= 0b11;
if (i == 0b11)
return 2;
return 1;
If we ever see a 64-bit instruction, we can come back and modify this.
--Sean
[1] https://github.com/riscv/riscv-code-size-reduction/blob/master/ISA%20proposals/Huawei/48bit_encodings.adoc
> + return 2;
> + if ((i & 0x3f) == 0x1f)
> + return 3;
> + if ((i & 0x7f) == 0x3f)
> + return 4;
> + i = (i >> 12) & 0x07;
> + if (i < 7)
> + return i + 5;
> + /* Encoding for >= 192 bits is not yet defined */
> + return 1;
> +}
> +
> +/**
> + * 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 +126,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");
> }
> --
> 2.30.2
>
More information about the U-Boot
mailing list