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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions