lowRISC / lowRISC/ibex

[pmp/debug]: DRET to U-mode does not clear `mstatus.MPRV`

Open
#2,473 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Type:Bug
Dominant language
SystemVerilog
Stars
2.1k
Forks
810
Avg merge
5d 23h
Merged PRs (30d)
9

Description

Observed Behavior

When Ibex enters Debug Mode from M-mode with mstatus.MPRV=1 and mstatus.MPP=M, a debugger can write DCSR.PRV=U and execute DRET. After DRET, Ibex restores the architectural privilege mode to U-mode, but mstatus.MPRV remains set.

The LSU therefore continues to use M-mode as its effective privilege for PMP checks. A subsequent U-mode load to a PMP region without read permission is issued to the external data interface instead of raising a load access fault.

The following values were observed in a complete ibex_core-level Verilator test:

priv_id=U
priv_lsu=M
mstatus.MPRV=1
mstatus.MPP=M
pmp_err=0
data_req=1

The test used a non-locked NAPOT PMP region covering 0x30000x3fff with execute permission only. The target operation was lw t2, 0(t1) with t1=0x3000 after returning from Debug Mode.

Expected Behavior

According to the RISC-V Debug Specification, when a hart resumes at a privilege mode lower than M-mode, mstatus.MPRV is cleared.

After DRET with DCSR.PRV=U, the expected state is therefore:

priv_id=U
mstatus.MPRV=0
priv_lsu=U

The load to the execute-only PMP region should then raise a PMP load access fault, and no external data request should be issued.

Steps to reproduce the issue

  1. Configure PMP entry 0 as a non-locked NAPOT region covering 0x00000x03ff with execute permission for the program and Debug ROM.
  2. Configure PMP entry 1 as a non-locked NAPOT region covering 0x30000x3fff with execute-only permission.
  3. In M-mode, set mstatus.MPRV=1 and mstatus.MPP=M.
  4. Run the core until a known instruction address and assert the external debug request until the core enters Debug Mode.
  5. In the Debug ROM, execute csrw dcsr, x0 to set DCSR.PRV=U, followed by dret.
  6. Resume at the instruction after the debug entry point and execute lw t2, 0(t1) with t1=0x3000.
  7. Observe priv_mode_id, priv_mode_lsu, mstatus.MPRV, the PMP error signal, and the external data request.

The complete test case reports the following target-load result on the current RTL:

target load: priv_id=0 priv_lsu=3 mprv=1 mpp=3 pmp_err=0 data_req=1

In Ibex's privilege-level encoding, 0 is U-mode and 3 is M-mode. The test intentionally terminates with an architectural assertion failure when the expected PMP fault is not observed. The current RTL exits with code 134 because of this assertion.

The relevant RTL behavior appears to be:

  • The DRET path restores priv_lvl_d from dcsr_q.prv.
  • The corresponding DRET path does not clear mstatus_q.mprv when the restored privilege is below M-mode.
  • priv_mode_lsu_o is computed as mstatus_q.mprv ? mstatus_q.mpp : priv_lvl_q and is passed to the data-side PMP checker.

My Environment

Ibex source revision: 57d37bf9008640415532d23ad59018b795c642aa.

The test was run with Verilator against the real ibex_core using PMPEnable=1, four PMP regions, and the external instruction and data interfaces connected to a cycle-accurate memory model.

The self-contained reproduction consists of:

  • ibex_core_dret_mprv_tb.sv
  • ibex_core_dret_mprv_program.S
  • run_ibex_core_dret_mprv.sh

testcases.zip

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the DRET path that restores priv_lvl_d from dcsr_q.prv and compare it with the mstatus_q.mprv handling; the issue identifies these signals and the priv_mode_lsu_o calculation. Run the provided ibex_core_dret_mprv_tb.sv, ibex_core_dret_mprv_program.S, and run_ibex_core_dret_mprv.sh reproduction. Done means DRET to U-mode clears MPRV, the LSU uses U-mode, and the execute-only PMP load faults without an external data request.

Written by the indexing model from the issue text.

Assessment

Domain
embedded-iot, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.