[PATCH 1/1] riscv: show code leading to exception
Sean Anderson
seanga2 at gmail.com
Fri Aug 13 05:40:58 CEST 2021
Am 13. August 2021 03:34:58 MESZ schrieb Sean Anderson <seanga2 at gmail.com>:
>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?
We already know that bits 0 and 1 are set here. We only have to check that not all of bits 2 - 4 are set.
>
>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.
Won't extending [1] to load 64 bit values result in 80 bit instructions?
Best regards
Heinrich
>
>--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