masking mode field in mepc before mret
Host environment
- Operating system: all
- OS/kernel version: all
- QEMU flavor: qemu-system-riscv64
- QEMU version: QEMU emulator version 9.2.0 (v9.2.0)
Emulated/Virtualized environment
- Operating system: qemu-system-riscv64
- OS/kernel version: qemu-system-riscv64
- Architecture: riscv
Description of problem
I thought I found a bug in OpenSBI (https://github.com/riscv-software-src/opensbi/issues/391) but it actually is a QEMU bug. It is described here: https://lists.infradead.org/pipermail/opensbi/2025-March/008166.html
Steps to reproduce
- use an application with vectored mode enabled (The RISC-V Instruction Set Manual: Volume II: Privileged Architecture / chapter 10.1.2) in QEMU
- trigger an illegal instruction interrupt (handle it in machine mode - not by medeleg)
- in a machine mode trap: Store STVEC in MEPC.
- do a mret
- the first bits of mepc are not masked so the address in mepc (comming from (v)stvec) will be false after mret
Additional information
My guess is that the instructions from the following quote (masking of lower bits in mepc) from the official spec must be implemented here: https://gitlab.com/qemu-project/qemu/-/blob/master/target/riscv/op_helper.c?ref_type=heads#L387 Maybe also somewhere else.
3.1.14. Machine Exception Program Counter (mepc)
mepc is an MXLEN-bit read/write register formatted as shown in Figure 21. The low bit of mepc (mepc[0]) is always zero. On implementations that support only IALIGN=32, the two low bits (mepc[1:0]) are always zero.
If an implementation allows IALIGN to be either 16 or 32 (by changing CSR misa, for example), then, whenever IALIGN=32, bit mepc[1] is masked on reads so that it appears to be 0. This masking occurs also for the implicit read by the MRET instruction. Though masked, mepc[1] remains writable when IALIGN=32.
mepc is a WARL register that must be able to hold all valid virtual addresses. It need not be capable of holding all possible invalid addresses. Prior to writing mepc, implementations may convert an invalid address into some other invalid address that mepc is capable of holding.