5

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.

1 Answer 1

7

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.

Sign up to request clarification or add additional context in comments.

4 Comments

I am trying to run some code on qemu-riscv32 and also get an Illegal instruction (core dumped). It appears that the instruction causing the issue is a write to mstatus. How did you go about creating a PMP entry?
I guess qemu is running in S or U mode. How can I get qemu to run in M mode?
RISC-V systems enter M mode on initialisation. Your question is more complicated than I can answer here. It depends on so many other factors. Your best bet is to ask a full question about this.
Thanks for figuring that out. I had the exact same issue and configuring the PMP solved it!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.