RISC-V: mtval/stval is not correctly set to the instruction itself on illegal instructions
Host environment
- Operating system: NixOS unstable, git commit 692517bf851f2d8d999f0ad50f53fa1d2dd5c8f9
- OS/kernel version:
Linux sakuya 5.17.7 #1-NixOS SMP PREEMPT Thu May 12 10:32:48 UTC 2022 x86_64 GNU/Linux
- Architecture: x86-64
- QEMU flavor:
qemu-system-riscv64
- QEMU version: 7.0.0
- QEMU command line:
qemu-system-riscv64 -cpu rv64,h=off -bios mtval-illegal.elf -nographic -icount shift=0 -s -S
Emulated/Virtualized environment
Only a bit of machine mode code in mtval-illegal.elf
. See below.
Description of problem
QEMU 7.0 claims to support stval
/mtval
for illegal instructions, but mtval
/stval
is actually set to 0
Steps to reproduce
-
Assemble and link
mtval-illegal.elf
. The code simply sets up a trap handler and generates an illegal instruction exception -
Start QEMU with:
qemu-system-riscv64 -cpu rv64,h=off -bios mtval-illegal.elf -nographic -icount shift=0 -s -S
- Attach with GDB:
gdb mtval-illegal.elf
# Within GDB
target extended-remote :1234
break trap
disp $mtval
# Keep single stepping until breakpoint
stepi
- When control flow reaches
trap
,mtval
is written with0
instead of the encoding ofcsrw time, x0
(0xc0101073
)
mtval-illegal.elf
:
Code of mtval-illegal.S
.global _start
_start:
lla t0, trap
csrw mtvec, t0
# Set mtval to some garbage
li t0, 0x1234
csrw mtval, t0
# Illegal instruction, should trap
csrw time, x0
loop:
j loop
trap:
j trap
mtval-illegal.lds
SECTIONS {
. = 0x80000000;
.text : {
*(.text);
}
}
Assemble and link with:
riscv64-unknown-linux-gnu-as -o mtval-illegal.o mtval-illegal.S
riscv64-unknown-linux-gnu-ld -T mtval-illegal.lds -o mtval-illegal.elf mtval-illegal.o
Additional information
Writing 0
to mtval
on a illegal instruction trap is allowed by the specs, but since the changelog of QEMU 7.0 says it should be supported, I would consider it a bug.
I encountered this when trying to figure out why my program worked with QEMU 6 but breaks with QEMU 7. It's more complicated, but in that case I managed to get mtval
written with neither 0
nor the actual illegal instruction, but a different illegal instruction. I will try gathering up all the dependencies and write down the steps to reproduce if needed and if I find the time.