Skip to content

RISCV: Illegal instruction delegated to VS mode sets the wrong vscause value

Host environment

  • Operating system: OpenSuse
  • OS/kernel version: 5.14.21
  • Architecture: x86
  • QEMU flavor: qemu-system-riscv64
  • QEMU version: QEMU emulator version 8.0.50 (v8.0.0-244-g1eb95e1b-dirty)
  • QEMU command line: qemu-system-riscv64 -m 32M -nographic -bios none -machine virt,aclint=off,aia=aplic-imsic,aia-guests=3 -smp 1 -d int -cpu rv64,sstc=true,c=false,x-epmp=true,x-smstateen=true,x-smaia=true,x-ssaia=true -kernel hypervisor_tests.elf

Emulated/Virtualized environment

  • Operating system: None
  • OS/kernel version: None
  • Architecture: RISC-V

Description of problem

When delegating an illegal instruction exception caused in VS-mode to VS-mode, the vscause value for an illegal instruction is set incorrectly.

Steps to reproduce:

  1. Delegate 2(,6,10) in medeleg and hedeleg.
  2. Enter VS-mode
  3. Cause an illegal instruction fault, cause 6 can't happen in QEMU since there is misaligned support and 10 can't be delegated to VS mode.
  4. The (v)scause CSR is then set to 1, i.e. instruction access fault which isn't correct.

I have located the issue in the code @ cpu_helper.c:1703

if ((cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT ||
    cause == IRQ_VS_EXT)) {
    cause = cause - 1;
}

The if statement should include a check for the async otherwise the cause shouldn't be altered. The patch I propose is simply to and the current statement with async.

if (async & (cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT ||
    cause == IRQ_VS_EXT)) {
    cause = cause - 1;
}

Additional information

Log where the incorrect cause is set. Note this line: DEBUG: [src/trap_handling.c: 105] Instruction access fault exception: SEPC = 0x80008850, STVAL = 0x0

TRACE: [src/hart_ctrl.c:35] STARTING CPU 0
TRACE: [src/page_tables.c:343] Setting up page tables between 0x80000000 -> 0x81c00000
TRACE: [src/page_tables.c:359] Setting up page tables between 0x81c01000 -> 0x81c02000
TRACE: [src/page_tables.c:374] Setting up page tables for UART 0x10000000
TRACE: [src/page_tables.c:386] Setting up page tables for CLINT 0x2000000
DEBUG: [src/page_tables.c: 406] Mapping IMISIC 0x24000000
DEBUG: [src/page_tables.c: 406] Mapping IMISIC 0x28000000
DEBUG: [src/page_tables.c: 406] Mapping IMISIC 0x28001000
TRACE: [src/main.c:32] STARTING HYPERVISOR TESTS
DEBUG: [src/util_fn.c:1175] pmpcfg0 = 0x00000000000f000f 
DEBUG: [src/util_fn.c:1176] pmpcfg2 = 0x0000000000000000 
PMP Entry     : 0
Low Address   : 0x0
High Address  : 0x81c00000
Address Range : 0x0 - 0x81c00000
Mode          : TOR
Executable    : Yes
Writable      : Yes
Readable      : Yes
Locked        : No
--------------------------------------
PMP Entry     : 2
Low Address   : 0x82000000
High Address  : 0xfffffffffffffffc
Address Range : 0x82000000 - 0xfffffffffffffffc
Mode          : TOR
Executable    : Yes
Writable      : Yes
Readable      : Yes
Locked        : No
--------------------------------------
DEBUG: [src/trap_trigger.c:  85] Switching mode to VS
riscv_cpu_do_interrupt: hart:0, async:0, cause:0000000000000002, epc:0x00000000800062a4, tval:0x0000000000000000, desc=illegal_instruction
DEBUG: [src/trap_handling.c: 102] Illegal instruction exception: MEPC = 0x800062a4, MTVAL = 0x0
TRACE: [src/util_fn.c:374] Done switching mode
riscv_cpu_do_interrupt: hart:0, async:0, cause:0000000000000002, epc:0x0000000080008850, tval:0x0000000000000000, desc=illegal_instruction
DEBUG: [src/trap_handling.c: 105] Instruction access fault exception: SEPC = 0x80008850, STVAL = 0x0
ERROR: [src/trap_handling.c:158] The following assert failed: mask_cause == cause2check
mask_cause = 0x1 ## cause2check = 0x2
DEBUG: [src/trap_trigger.c: 129] Switching mode to M
TRACE: [src/trap_handling.c:30] Program done, exiting
QEMU: Terminated

Result after patch.

TRACE: [src/hart_ctrl.c:35] STARTING CPU 0
TRACE: [src/page_tables.c:343] Setting up page tables between 0x80000000 -> 0x81c00000
TRACE: [src/page_tables.c:359] Setting up page tables between 0x81c01000 -> 0x81c02000
TRACE: [src/page_tables.c:374] Setting up page tables for UART 0x10000000
TRACE: [src/page_tables.c:386] Setting up page tables for CLINT 0x2000000
DEBUG: [src/page_tables.c: 406] Mapping IMISIC 0x24000000
DEBUG: [src/page_tables.c: 406] Mapping IMISIC 0x28000000
DEBUG: [src/page_tables.c: 406] Mapping IMISIC 0x28001000
TRACE: [src/main.c:32] STARTING HYPERVISOR TESTS
DEBUG: [src/util_fn.c:1175] pmpcfg0 = 0x00000000000f000f 
DEBUG: [src/util_fn.c:1176] pmpcfg2 = 0x0000000000000000 
PMP Entry     : 0
Low Address   : 0x0
High Address  : 0x81c00000
Address Range : 0x0 - 0x81c00000
Mode          : TOR
Executable    : Yes
Writable      : Yes
Readable      : Yes
Locked        : No
--------------------------------------
PMP Entry     : 2
Low Address   : 0x82000000
High Address  : 0xfffffffffffffffc
Address Range : 0x82000000 - 0xfffffffffffffffc
Mode          : TOR
Executable    : Yes
Writable      : Yes
Readable      : Yes
Locked        : No
--------------------------------------
DEBUG: [src/trap_trigger.c:  85] Switching mode to VS
riscv_cpu_do_interrupt: hart:0, async:0, cause:0000000000000002, epc:0x00000000800062a4, tval:0x0000000000000000, desc=illegal_instruction
DEBUG: [src/trap_handling.c: 102] Illegal instruction exception: MEPC = 0x800062a4, MTVAL = 0x0
TRACE: [src/util_fn.c:374] Done switching mode
riscv_cpu_do_interrupt: hart:0, async:0, cause:0000000000000002, epc:0x0000000080008850, tval:0x0000000000000000, desc=illegal_instruction
DEBUG: [src/trap_handling.c: 105] Illegal instruction exception: SEPC = 0x80008850, STVAL = 0x0
DEBUG: [src/trap_trigger.c: 129] Switching mode to M
riscv_cpu_do_interrupt: hart:0, async:0, cause:0000000000000002, epc:0x00000000800062a4, tval:0x0000000000000000, desc=illegal_instruction
DEBUG: [src/trap_handling.c:  69] Illegal instruction handling is delegated, falling back to ECALL
riscv_cpu_do_interrupt: hart:0, async:0, cause:000000000000000a, epc:0x00000000800096e4, tval:0x0000000000000000, desc=hypervisor_ecall
DEBUG: [src/trap_handling.c: 102] Environment call from VS-mode exception: MEPC = 0x800096e4, MTVAL = 0x0
DEBUG: [src/trap_handling.c: 105] Illegal instruction exception: SEPC = 0x800062a4, STVAL = 0x0
TRACE: [src/util_fn.c:374] Done switching mode
TRACE: [src/main.c:57] HYPERVISOR TEST FINISHED SUCCESSFULLY
TRACE: [src/trap_handling.c:30] Program done, exiting
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information