Skip to content

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

  1. Enable IRQs globally (mstatus, vsstatus)
  2. Set hstatus.VGEIN to a legal value
  3. Write -1 to mie
  4. 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

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