Skip to content

riscv64 - executing mret in U-mode does not load the mret opcode in the mtval CSR

Host environment

  • Operating system: macos
  • OS/kernel version: 15.5
  • Architecture: ARM
  • QEMU flavor: qemu-system-riscv64
  • QEMU version: v10.0.2
  • QEMU command line:
    qemu-system-riscv64 -nographic -machine virt

Emulated/Virtualized environment

  • Operating system: No OS (Running firmware only with Miralis)
  • OS/kernel version: Does not apply
  • Architecture: RISC-V 64

Description of problem

Executing mret from U-mode fills the mtval CSR with 0xb60023, expected value is 0x30200073 (the opcode for mret).

Steps to reproduce

I found the bug in the test suite of Miralis (a RISC-V firmware) after upgrading QEMU through Homebrew. The easiest way to reproduce might be run the failing test.

Project link

  1. git clone git@github.com:CharlyCst/miralis.git && cd miralis
  2. Install Rust (if not yet installed)
  3. Install Just (if not yet installed) with cargo install just
  4. Run just install-toolchain to install the required Rust toolchain components.
  5. Run just run mret. This builds all software and prints de QEMU command with the appropriate binary paths (can be run manually to try different versions). The test will fail if the bug is present.
  6. To get more logs, copy this in config.toml at the root of the repo:
    [log]
    level = "trace"

Additional information

The commit introducing the issue is ffe4db11.

In a nutshell, Miralis runs RISC-V M-mode software (such as OpenSBI) in U-mode, traps all illegal instructions, and emulate them. Miralis relies on mtval to read the trapping instruction. The bug can be observed when the software in U-mode executes mret, as is the case in the failing test.

Here is an excerpt from the logs when the test firmware executes mret in U-mode before the bug:

[Trace | miralis] Trapped on hart 0:  illegal instruction
[Trace | miralis]   mstatus: 0xa00000080        mepc: 0x80200130
[Trace | miralis]   mtval:   0x30200073         exits: 5  M-mode <-- See `mtval` has the right value
...
[Trace | miralis::virt::emulator] Faulting instruction: Mret.    <-- Instructions is correctly identified as mret
...

And after the bug is introduced (ffe4db11 onward):

[Trace | miralis] Trapped on hart 0:  illegal instruction
[Trace | miralis]   mstatus: 0xa00000080        mepc: 0x80200130
[Trace | miralis]   mtval:   0xb60023           exits: 5  M-mode <-- Here `mtval` does not have the expected value.
...
[Error | miralis] Panicked at PanicInfo {
    message: assertion `left == right` failed: Precondition violated, this is not an illegal instruction: 0xb60023 <-- We get a crash, because `0xb60023` is not a valid privileged instruction.
...
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information