Skip to content

fix: pmp sector walk hang on accesses at the top of the address space - #61

Open
cphurley82 wants to merge 2 commits into
Minres:mainfrom
cphurley82:fix/pmp-top-sector-wrap
Open

cphurley82 wants to merge 2 commits into
Minres:mainfrom
cphurley82:fix/pmp-top-sector-wrap

Conversation

@cphurley82

@cphurley82 cphurley82 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Problem

pmp_check walks every 4-byte sector an access touches, with an address as the loop bound:

for(cur_addr = first_sector; cur_addr <= last_sector; cur_addr += sector_size)

  • If the access touches the top sector of the address space, the step past last_sector wraps cur_addr to 0. That is still <= last_sector, so the loop never ends. The simulator hangs with no trap and no log.
  • A zero-length access at address 0 has the same problem: addr + len - 1 underflows, so last_sector becomes the top sector.
  • The walk only runs for enabled entries, so firmware hits this as soon as it programs any PMP entry and then touches the top of memory.

Fix

  • Bound the walk on a 64-bit byte count from the start of the first sector, not on an address. A byte count can't wrap, whatever the address or len.
  • Counting from the start of the first sector keeps the current behavior for misaligned accesses: a fetch at addr % 4 == 2 still checks both sectors it spans.

Tests

  • New pmp-top-sector-test: programs one NA4 entry well away from the top, then does an M-mode load from the top 4-byte sector. Before the fix this hangs. With the fix, no entry matches and the load completes under the M-mode default.
  • Added to the PMP Functional Tests job.
  • Every riscv-sim step in that job now runs under timeout 60, and the job has a 10-minute limit. A hang like this one now fails CI instead of stalling it.

cphurley82@gmail.com added 2 commits September 30, 2026 18:51
The pmp-tests job set no timeout anywhere, so a firmware test that hangs the
simulator would hold the runner until GitHub's six-hour default. A PMP check
that never terminates produces exactly that: no trap, no log, no exit.

Wrap every riscv-sim invocation in `timeout 60` so a hang fails its own step
with exit 124, and cap the job at ten minutes as a backstop for the steps
around it. Each test runs in under 0.1s locally and the whole job has taken
20 to 40 seconds on recent runs, so neither bound is close.

The no-PMP CSR step, which expects exit 2, still fails on a timeout because
124 is not 2.
pmp_check bounded its sector walk with cur_addr <= last_sector. When the
access touches the top sector, the step past it wraps to 0 and the loop
never ends, hanging the simulation with no trap or log. A zero-length
access at address 0 hangs the same way.

Bound the walk on a 64-bit byte count instead, which cannot wrap. Counting
from the start of the first sector keeps misaligned accesses covering
their last sector.

pmp-top-sector-test loads from the top sector in M mode with one entry
enabled elsewhere. It hung before this change and passes now.
@cphurley82 cphurley82 changed the title Fix/pmp top sector wrap fix: pmp sector walk hang on accesses at the top of the address space Oct 1, 2026
@cphurley82
cphurley82 marked this pull request as ready for review October 1, 2026 23:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant