How to determine the current execution privilege mode


Hi everybody,

if you wanted to determine the execution privilege mode a RISC-V is currently running in
(without knowing it beforehand), how would you do this?

The RISC-V ISA Manual Volume II says, on page 15: “In addition to the machine-level CSRs […], M-mode can access all CSRs at lower privilege levels.”

So we tested reading registers {m,s,u}status and {m,s,u}epc. We added inline assembler to some software we are trying to understand, like so:

asm volatile(“csrr %0, mepc” : “=r”(stat) :);

Contrary to expectations, this worked only with mstatus and mepc. Trying to read {s,u}status or {s,u}epc always led to a hang.

This seems to contradict the manual. What are we doing wrong here?

Platform: SiFive U540 (HiFive Unleashed)

Any help would be greatly appreciated. Thanks for your attention.


(Bruce Hoult) #2

Hi Mike,

Reading {s,u}status and {s,u}epc should work IF they exist. If they don’t exist then you should get an illegal instruction exception. This could look like a hang if you haven’t set up an appropriate interrupt handler.

uepc doesn’t exist unless the N extension for delegating selected exceptions to U mode handlers is implemented. Currently, none of our cores implement this, including those on the FU540.

sstatus and sepc exist if S mode is implemented. This is the case on the U54 cores (harts 1…4) on the FU540, but not on the E51 core (hart 0) on the FU540.

I suspect you are running your test code on hart 0.

RISC-V deliberately doesn’t make it easy for code to discover what mode it is running it because this is a virtualisation hole. As a general principle, code should be designed for and implicitly know what mode it will run in. Applications code should assume it is in U mode. The operating system should assume it is in S mode (it might in fact be virtualised and running in U mode, with things U mode can’t do trapped and emulated by the hypervisor).

It would be possible to create an operating system call or SBI call that extracted the previous mode from MPP or SPP in mstatus and returned that as the result. But it’s not recommended to do this.


Thanks for a most informative answer. Yes, the code was running on hart 0.