Am 13. August 2021 03:34:58 MESZ schrieb Sean Anderson <sean...@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.g...@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 >> >