RISC-V: VS external IRQ can be taken in M-mode
Host environment
- Operating system: OpenSuse
- OS/kernel version: 5.14.21
- Architecture: x86
- QEMU flavor: qemu-system-riscv64
- QEMU version: QEMU emulator version 7.2.91 (v8.0.0-rc1-36-g60ca584b)
- QEMU command line:
./qemu-system-riscv64 -m 128M -nographic -bios none -machine virt,aclint=off,aia=aplic-imsic,aia-guests=3 -smp 1 -d int -cpu rv64,sstc=true -kernel main
Emulated/Virtualized environment
- Operating system: None
- OS/kernel version: None
- Architecture: RISC-V
Description of problem
The RISC-V specification states that VS-level interrupts and guest external interrupts are always delegated past M-mode to HS mode.
I happened to come across a situation where QEMU takes the vs_external IRQ in machine mode.
Steps to reproduce
- Enable IRQs globally (mstatus, vsstatus)
- Set hstatus.VGEIN to a legal value
- Write -1 to mie
- Write -1 to hvip
I included a binary that should be able to reproduce the issue.
I use a vectored setup for mtvec and as soon as the VSEIP bit in hvip has been set the machine jumps to mtvec.vsei. To confirm that I actually went to mtvec and not somewhere with a faulty print I also performed an ecall and that was reported as an M mode ecall.
Additional information
TRACE: [hart_ctrl.c:35] STARTING CPU 0
DEBUG: [trap_handling.c: 886] Setting up trap handlers
DEBUG: [aia_ctrl.c: 377] Initializing interrupt controller
TRACE: [main.c:31] Writing -1 to mie
TRACE: [main.c:33] Writing -1 to hvip
riscv_cpu_do_interrupt: hart:0, async:1, cause:000000000000000a, epc:0x0000000080000114, tval:0x0000000000000000, desc=vs_external
ERROR: [trap_handling.c:280] mtvec_vsei should be unreachable
mstatus = 0x0000000a000038a2 hstatus:
SIE = 1 VSXL[1:0] = 2
MIE = 0 VTSR = 0
SPIE = 1 VTW = 0
UBE = 0 VTVM = 0
MPIE = 1 VGEIN[5:0] = 1
SPP = 0 HU = 0
VS = 0 SPVP = 0
MPP = 3 SPV = 0
FS = 1 GVA = 0
MPRV = 0 VSBE = 0
SUM = 0
MXR = 0
TVM = 0
TW = 0
TSR = 0
UXL = 2
SXL = 2
SBE = 0
MBE = 0
GVA = 0
MPV = 0
mie mip mideleg hvip
ssie (1) = 1 ssip (1) = 0 ssi (1) = 0 ssip (1) = 0
vssie(2) = 1 vssip(2) = 1 vssi (2) = 0 vssip(2) = 1
msie (3) = 1 msip (3) = 0 msi (3) = 0 msip (3) = 0
stie (5) = 1 stip (5) = 0 sti (5) = 0 stip (5) = 0
vstie(6) = 1 vstip(6) = 0 vsti (6) = 0 vstip(6) = 0
mtie (7) = 1 mtip (7) = 0 mti (7) = 0 mtip (7) = 0
seie (9) = 1 seip (9) = 0 sei (9) = 0 seip (9) = 0
vseie(10) = 1 vseip(10) = 1 vsei (10) = 0 vseip(10) = 1
meie (11) = 1 meip (11) = 0 mei (11) = 0 meip (11) = 0
sgeie(12) = 1 sgeip(12) = 0 sgei (12) = 0 sgeip(12) = 0
DEBUG: [trap_handling.c: 28] hart_ctrl.kill_hart = 0x8000a00c
TRACE: [trap_handling.c:29] Program done, exiting
QEMU: Terminated
Reproducer of the problem: main