No. 52 / project of 147 on the ladder

Sv32 page-table walker

introduces — 2-level Sv32 walker for 4 KiB pages, load/store translation in S-mode, page-fault traps with VA in stval

harden statelast run2026-05-03
areaunknownμm²
signoff
  • DRCNOT RUN
  • LVSNOT RUN
  • antennaNOT RUN

P52 is the big one. The chip consumes Sv32 page tables when running in S-mode with satp.MODE=1. Two new FSM states walk the L1 then L0 page tables, check permissions, and resume the original load/store at the translated physical address.

Status: RTL pass. Walker probe (load + store + page-fault path) PASS at 5,245,499 clocks. FreeRTOS demo still halts cleanly afterwards.

Scope (minimum-viable)

  • 4 KiB pages only (no megapages).
  • Load + store translation. Instruction fetch and AMO ops are not translated yet.
  • Software pre-sets PTE.A and PTE.D; walker faults if unset rather than updating in hardware.
  • No TLB. Every load/store walks fresh.
  • No SUM/MXR/MPRV. S faults on U pages. M never translates.

When satp.MODE=0 or cur_priv != S, no translation happens.

What’s in the RTL

  • New page-fault causes (12 instr, 13 load, 15 store).
  • New states S_PTW1, S_PTW0. State register widened from 4 to 5 bits.
  • ptw_va_q register: original VA, saved for mtval/stval on a page fault.
  • ptw_l1_ppn register: PPN from the L1 PTE, carried to the L0 fetch.
  • S_EXECUTE → S_PTW1 if translation active and the op is load/store.
  • S_PTW0 handler: full leaf-PTE permission check (R/W bits match access; A bit set; D bit set for stores; U bit rejected from S; pointer-at-leaf rejected).

A timing bug found during bring-up

ptw_va_q <= alu_y_q was wrong: in the same cycle that alu_y_q <= alu_y fires, the read of alu_y_q returns the previous instruction’s value. Test 1 (load) passed by coincidence because the prior li t0, TEST_VA had set alu_y_q to exactly TEST_VA. Test 2 (store) failed because a li t1, 0xCAFEBABE had landed in alu_y_q first. Fixed by reading the combinational alu_y directly.

What’s tested

sv32_walker_probe (codes 130-135):

  1. Load via VA 0x12345678 returns the value planted at the translated PA.
  2. Store via VA writes to the translated PA.
  3. Clearing PTE.V triggers a load page fault (cause 13) with VA in mtval.

The P47 satp storage probe was updated to clear satp after its round-trip (otherwise its 0xC0DE0009 canary leaves MODE=1 set, which then breaks subsequent S-mode probes).

What does not work yet

  • Instruction fetch translation (kernel code stays at identity-mapped PA).
  • Megapages (4 MiB leaves at L1).
  • Hardware A/D bit updates (software must pre-set).
  • TLB.
  • sfence.vma decoding.
  • AMO translation in S-mode.
  • SUM/MXR/MPRV.

Files

  • src/top.sv - walker FSM + permission check
  • app/main.c - sv32_walker_probe

Harden

NOT RUN. Estimated +400-600 cells over P51 — the walker is the largest single addition since the A extension.

What just happened?

The chip now consumes page tables. With the Phase-1 ISA extensions, Phase-2 priv machinery, and now Sv32 paging, the chip has the architectural pieces a small RV32 Linux kernel needs. The remaining work is platform-shape (CLINT, PLIC, larger memory model, device tree, SBI), then the actual kernel bring-up.

We’re past the “correctness ladder” — from here forward, the rungs are increasingly about integration: making the chip look enough like a generic RV32 Linux platform that an off-the-shelf kernel will boot.