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
- Run the supplied
poc/program.elf under difftest.
- 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.
- 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
NS-6.zip
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
0x40002000so that the malformed 1 GiB mapping aliases the test word atbad_data. Spike raises a precise Load page fault (mcause=13), while NutShell completes the load and returns0x1122334455667788.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
poc/program.elfunder difftest.root_pt[1]and deliberately sets a nonzero lower PPN bit, making the 1 GiB superpage leaf misaligned.bad_data, and executes the faulting load.Essential setup:
Expected Result
mcause = 13(Load page fault).mepc = load_site(0x8000009cin this build).mtval = 0x40002000.bad_datathrough the malformed mapping.Actual Result
NutShell commits the load and returns the value stored at
bad_data, while Spike takes the page fault:NS-6.zip