Skip to content

Misaligned Sv39 1 GiB superpage leaf is accepted instead of raising load page fault #265

Description

@jf-cc727

Bug Description

NutShell accepts a root-level Sv39 leaf PTE for a 1 GiB mapping even when the lower PPN fields are nonzero. A compliant implementation must treat this as a misaligned superpage and raise a page-fault exception corresponding to the original access type.

In the supplied test program, the test intentionally sets PTE bit 10 (PPN[0] bit 0) in a root-level leaf and then constructs virtual address 0x40002000 so that the malformed 1 GiB mapping aliases the test word at bad_data. Spike raises a precise Load page fault (mcause=13), while NutShell completes the load and returns 0x1122334455667788.

RISC-V Specification Requirement

The Sv39 virtual-address translation algorithm is explicit: after a leaf PTE is found, if the current level represents a superpage and the lower PPN fields are not all zero, the implementation must raise a page-fault exception corresponding to the original access type.

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

Because the original access in this test program is a load, the required architectural exception is Load page fault (mcause=13), not successful completion of the load.

Steps to Reproduce

  1. Run the supplied poc/program.elf under difftest.
  2. M-mode installs a root-level Sv39 leaf in root_pt[1] and deliberately sets a nonzero lower PPN bit, making the 1 GiB superpage leaf misaligned.
  3. The test enables Sv39 with S-mode effective privilege, constructs a VA whose low 30 bits alias bad_data, and executes the faulting load.

Essential setup:

/* root_pt[1] is a malformed 1 GiB leaf: PPN[0] bit 0 is forced to 1. */
la   t0, root_pt
la   t1, bad_data
srli t1, t1, 12
slli t1, t1, 10
ori  t1, t1, PTE_RAD
li   t2, (1 << 10)
or   t1, t1, t2
sd   t1, 8(t0)

/* Build a VPN[2]=1 VA whose low 30 bits alias bad_data. */
la   t0, bad_data
li   t1, 0x3fffffff
and  a0, t0, t1
li   t1, 0x40000000
or   a0, a0, t1
ld   t2, 0(a0)

Expected Result

  • The load does not complete.
  • mcause = 13 (Load page fault).
  • mepc = load_site (0x8000009c in this build).
  • mtval = 0x40002000.
  • The destination register does not receive the value stored at bad_data through the malformed mapping.

Actual Result

NutShell commits the load and returns the value stored at bad_data, while Spike takes the page fault:

[31] commit pc 000000008000009c ... data 1122334455667788 ... ld      t2, 0(a0) <--
pc: 0x00000000800000f0 ... mcause: 0x000000000000000d mepc: 0x000000008000009c
mtval: 0x0000000040002000 ...
t2 different ... right = 0x0000000000000400, wrong = 0x1122334455667788
mtval different ... right = 0x0000000040002000, wrong = 0x0000000000000000
mcause different ... right = 0x000000000000000d, wrong = 0x0000000000000000
Image

NS-6.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