ajxs
ajxs

Reputation: 3618

RISC-V: Illegal instruction exception when switching to supervisor mode

When setting the mstatus.mpp field to switch to supervisor mode, I'm getting an illegal instruction exception when calling mret. I'm testing this in qemu-system-riscv64 version 6.1 with the riscv64-softmmu system. I recently upgraded from QEMU 5.0 to 6.1. Prior to this upgrade my code worked. I can't see anything relevant in the changelog. I'm assuming that there's a problem in my code that the newer version simply doesn't tolerate.

Here is a snippet of assembly that shows what's happening (unrelated boot code removed):

.setup_hart:
    csrw satp, zero                                # Disable address translation.

    li   t0, (1 << 11)                             # Supervisor mode.
    csrw mstatus, t0

    csrw mie, zero                                 # Disable interrupts.

    la  sp, __stack_top                            # Setup stack pointer.

    la   t0, asm_trap_vector
    csrw mtvec, t0

    la   t0, kernel_main                           # Jump to kernel_main on trap return.
    csrw mepc, t0

    la   ra, cpu_halt                              # If we return from main, halt.
    mret

If I set the mstatus.mpp field to 0b11 for machine mode, I can get to kernel_main without any problem.

Here's the output from QEMU showing the exception information:

riscv_cpu_do_interrupt: hart:0, async:0, cause:0000000000000002, epc:0x000000008000006c, tval:0x0000000000000000, desc=illegal_instruction

mepc points to the address of the mret instruction where the exception occurs. I've tested that the machine supports supervisor mode by writing and retrieving the value in mstatus.mpp successfully.

Is there something obvious I'm missing? My code seems very similar to the few examples I can find online, such as https://osblog.stephenmarz.com/ch3.2.html. Any help would be greatly appreciated.

Upvotes: 5

Views: 2480

Answers (1)

ajxs
ajxs

Reputation: 3618

The issue turned out to be RISC-V's Physical Memory Protection (PMP). QEMU will raise an illegal instruction exception when executing an MRET instruction if no PMP rules have been defined. Adding a PMP entry resolved the issue.

This was confusing, as this behaviour is not specified in the Privileged Architecture manual's section on mret.

Upvotes: 7

Related Questions