Skip to content

PTW PTE-access faults are misreported as load page faults #264

Description

@jf-cc727

Bug Description

During an Sv39 load translation, the root PTE is a valid non-leaf PTE whose PPN points to physical page 0. Accessing the next-level PTE therefore fails the platform's physical access checks.

Spike reports a Load access fault (mcause=5). NutShell reports a Load page fault (mcause=13). The original PTE content is not the reason for failure: the implicit memory access needed to fetch that PTE cannot be performed. These two conditions have different architectural causes.

RISC-V Specification Requirement

The distinction here is between failing to read a PTE and reading a bad PTE. If the page-table walker cannot access the memory containing the next PTE, the fault is an access fault for the original operation. It only becomes a page fault after the PTE has actually been read and its contents are found to be invalid or reserved.

The Supervisor Privileged Specification's virtual-address translation algorithm is explicit:

  • Step 2 accesses the PTE at the computed physical address.
  • If accessing that PTE violates a PMA or PMP check, the implementation raises an access-fault exception corresponding to the original access type.
  • Only after a PTE is successfully read does an invalid/reserved PTE encoding cause a corresponding page-fault exception.

Reference: https://docs.riscv.org/reference/isa/v20260120/priv/supervisor.html#_virtual_address_translation_process

For this original load, a failed implicit PTE read must therefore be cause 5, not cause 13.

Steps to Reproduce

  1. Run the supplied poc/program.elf under difftest.
  2. The test writes a valid non-leaf root PTE with PPN=0 for virtual address 0x40201010.
  3. It enables Sv39 and uses S-mode effective privilege for the data access.
  4. It executes ld t2, 0(0x40201010).

Essential setup:

/* root_pt[ROOT_INDEX] = PTE_V, PPN = 0 */
li t1, 1
sd t1, (ROOT_INDEX * 8)(root_pt)
...
ld t2, 0(a0)

Expected Result

  • mcause = 5 (Load access fault)
  • mepc = load_site
  • mtval = 0x40201010

Actual Result

NutShell labels the fault as cause 13, while Spike reports cause 5:

DUT exception ... cause 000000000000000d ld t2, 0(a0)
REF mcause=0000000000000005 mepc=0000000080000070
REF mtval=0000000040201010
mcause different ... right=5, wrong=d
Image

NS-5.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions