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.
git clone git@github.com:CharlyCst/miralis.git && cd miralis- Install Rust (if not yet installed)
- Install Just (if not yet installed) with
cargo install just - Run
just install-toolchainto install the required Rust toolchain components. - 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. - To get more logs, copy this in
config.tomlat 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.
...