Misaligned floating point store emulation is broken ?
Hi,
On a RV32IMAFD config (VexRIscv), running linux, i got the following trap from opensbi (0.8, compiled by buildroot) :
sbi_trap_error: hart0: trap handler failed (error -2)
sbi_trap_error: hart0: mcause=0x00000005 mtval=0x00000078
sbi_trap_error: hart0: mepc=0x80f89540 mstatus=0x80007822
sbi_trap_error: hart0: ra=0x80f89668 sp=0x80f95ee4
sbi_trap_error: hart0: gp=0x000a6120 tp=0x95836b10
sbi_trap_error: hart0: s0=0x80f95f34 s1=0x00000000
sbi_trap_error: hart0: a0=0x00000078 a1=0x80f95ef0
sbi_trap_error: hart0: a2=0x80006022 a3=0x00003027
sbi_trap_error: hart0: a4=0x00002000 a5=0x80f8a5ac
sbi_trap_error: hart0: a6=0x80f805a8 a7=0x000a0000
sbi_trap_error: hart0: s2=0x004003f4 s3=0x80f95f74
sbi_trap_error: hart0: s4=0x00000000 s5=0x00f6b027
sbi_trap_error: hart0: s6=0x80f8d028 s7=0x80f8d02c
sbi_trap_error: hart0: s8=0x80f8d030 s9=0x80f8d024
sbi_trap_error: hart0: s10=0x80f95ef0 s11=0x0000006b
sbi_trap_error: hart0: t0=0x80f89540 t1=0x9370ebdc
sbi_trap_error: hart0: t2=0x0000000a t3=0x958d6ea8
sbi_trap_error: hart0: t4=0x00000000 t5=0x00397144
sbi_trap_error: hart0: t6=0x0000000c
Where mepc refer to this opensbi code sequances :
80f89528: 00000013 nop
val.data_u64 = GET_F64_RS2(insn, regs);
80f8952c: 011ad513 srli a0,s5,0x11
80f89530: 0f857513 andi a0,a0,248
80f89534: 00001797 auipc a5,0x1
80f89538: 00a787b3 add a5,a5,a0
80f8953c: 064782e7 jalr t0,100(a5) # 80f8a598 <get_f64_reg>
80f89540: 00052703 lw a4,0(a0)
80f89544: 00452783 lw a5,4(a0)
80f89548: fae42823 sw a4,-80(s0)
80f8954c: faf42a23 sw a5,-76(s0)
asm("nop");
80f89550: 00000013 nop
Which refer to this C code ( i added the nop probe stuff ):
asm("nop");
val.data_u64 = GET_F64_RS2(insn, regs);
asm("nop");
Which is part of the sbi_misaligned_store_handler function. (i linked the assembly code in the issue). trying to emulate a 0: 00f6b027 fsd f15,0(x13) from some software running in userspace (i guess)
This sequance of assembly code seems to me broken as :
the faulty instruction use a0 80f89540: 00052703 lw a4,0(a0)
which is masked above by : 80f89530: 0f857513 andi a0,a0,248
which will never produce any proper address to load something. (unless opensbi changed the MMU setup ?? i guess it does not do that)
Also, get_f64_reg do not write any register in anyway.
This maybe due to https://github.com/riscv/opensbi/blob/0f18b3fe0adda745b3ac80f7b79ce2b8512e2e95/include/sbi/riscv_fp.h#L47
Which may override a0 without having the compiler taking care of not erasing stuff ? ( I may be wrong on this )
If you want to reproduce in your environnement, i guess that editing : https://github.com/riscv/opensbi/blob/4ef2f5d3e6b25356a8fab19574bed76ce60edeee/lib/sbi/sbi_misaligned_ldst.c#L183 by putting the two asm("nop") around and compiling it with any RISC-V arch which has float/double will produce a similar "broken" assembly.
Let's me know your toughts, and if you need any more info.