Skip to content

[BUG] Rocket DefaultSmallConfig traps S-mode fetch from an X-only PMP region #3810

Open

Description

@KnightGOKU

I found a self-checking bare-metal RV64 test where Rocket DefaultSmallConfig traps an S-mode instruction fetch from a PMP NAPOT region that has execute permission.

The test configures a 4 KiB PMP NAPOT region around fetch_target with X=1, enters S-mode with mret, and jumps to fetch_target. The fetch should be allowed, but Rocket DefaultSmallConfig traps and the test exits with tohost=15, which is the test's fail_allowed_trapped path.

The same ELF passes on Spike, Rocket DefaultConfig, and SmallBoomConfig.

Test case

The test configures:

.equ INIT_CFG0,          7964
.equ FINAL_CFG0,         7964
.equ EXPECT_TRAP,        0

The PMP setup uses pmpaddr0 for a 4 KiB NAPOT region around fetch_target, and pmpaddr1 as a catch-all allow entry:

la      t0, fetch_region
srli    t0, t0, 2
li      t1, 0x1ff
or      t0, t0, t1
csrw    pmpaddr0, t0
li      t0, -1
csrw    pmpaddr1, t0
li      t0, INIT_CFG0
csrw    pmpcfg0, t0

The test then enters S-mode and jumps to the protected target:

la      t0, fetch_probe_entry
csrw    mepc, t0
li      t0, MSTATUS_MPP_MASK
csrc    mstatus, t0
li      t0, MSTATUS_MPP_S
csrs    mstatus, t0
mret

fetch_probe_entry:
    la      t0, fetch_target
    jalr    zero, 0(t0)

Expected: no trap, test exits with tohost=0.

Observed on Rocket DefaultSmallConfig:

*** FAILED *** (tohost = 15)
*** FAILED *** via dtm (code = 15, seed 1780795169) after 161126 cycles

Reproduction commands

Run the test case under different configurations:

timeout 90 ./riscv-isa-sim/install/bin/spike --isa=rv64imac_zicsr --priv=msu ./fetch_allowed_x_should_pass.elf
echo $?

timeout 90 ../../cores/rocket-chip/out/emulator/freechips.rocketchip.system.TestHarness/freechips.rocketchip.system.DefaultSmallConfig/verilator/elf.dest/emulator \
  +max-cycles=2000000 \
  ./fetch_allowed_x_should_pass.elf
echo $?

timeout 90 ../../cores/rocket-chip/out/emulator/freechips.rocketchip.system.TestHarness/freechips.rocketchip.system.DefaultConfig/verilator/elf.dest/emulator \
  +max-cycles=2000000 \
  ./fetch_allowed_x_should_pass.elf
echo $?

timeout 90 ../../cores/chipyard/sims/verilator/simulator-chipyard-SmallBoomConfig \
  +max-cycles=2000000 \
  ./fetch_allowed_x_should_pass.elf
echo $?

Result matrix

Test Spike Rocket DefaultSmallConfig Rocket DefaultConfig SmallBoomConfig
fetch_allowed_x_should_pass.elf pass, exit 0 fail, tohost=15 pass, exit 0 pass, exit 0

Expected behavior

The target PMP entry has execute permission, so the S-mode instruction fetch should complete and the test should exit with tohost=0.

The RISC-V privileged specification says PMP checks apply to S/U effective-privilege instruction fetches, and the PMP X bit grants instruction-execute permission.

Test Case: testcase.zip

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions