[PATCH 1/1] riscv: show code leading to exception

Heinrich Schuchardt xypron.glpk at gmx.de
Fri Aug 13 04:25:27 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