Skip to content

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

  1. Assemble and link mtval-illegal.elf. The code simply sets up a trap handler and generates an illegal instruction exception

  2. Start QEMU with:

qemu-system-riscv64 -cpu rv64,h=off -bios mtval-illegal.elf -nographic -icount shift=0 -s -S
  1. Attach with GDB:
gdb mtval-illegal.elf

# Within GDB
target extended-remote :1234
break trap
disp $mtval

# Keep single stepping until breakpoint
stepi
  1. When control flow reaches trap, mtval is written with 0 instead of the encoding of csrw time, x0 (0xc0101073)

Code of mtval-illegal.elf:

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.

Edited by dramforever
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information