No. 51 / project of 147 on the ladder

CSR privilege check + sie/sip subset

introduces — priv-check on CSR access, mret/sret priv guard, sie/sip as subset views of mie/mip

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

P51 enforces RISC-V’s CSR-access privilege rules and finishes the sstatus/sie/sip subset-view work.

Status: RTL pass. All probes (csr-access priv check, mret/sret priv guard, sie/sip subset behavior) PASS at 5,103,089 clocks. FreeRTOS demo runs to halt cleanly afterwards.

What changed

Three things in src/top.sv:

  1. CSR-access priv check. csr_addr[9:8] is the minimum priv level needed (00=U, 01=S, 11=M). If cur_priv < required, illegal-instr trap. From S, writes to mstatus, medeleg, mtvec etc. now correctly trap.

  2. mret/sret priv check. mret only legal in M; sret legal in M or S.

  3. sie/sip as subset views of mie/mip. sie reads mie & SIE_MASK; writes only update SIE_MASK bits. sip reads mip & SIE_MASK (mip is wire-driven from pending lines). The P47 standalone storage is gone.

What’s tested

csr_priv_check_probe (error codes 120-123):

  • mret to S, csrw medeleg, x0 from S → illegal-instr trap; M handler captures cause=2, MPP=S.
  • mret to S, sscratch round-trip from S (legal S-CSR access), ebreak to escape; verify sscratch holds the S-mode write.

The P50 trap_delegation_probe still passes (full M→S→trap→sret →S→trap-to-M→mret→M).

The P47 sstatus/sie storage probe was updated to expect subset behavior.

A clobber-list bug found along the way

The probe trap handlers use t0 and t1 as scratch. Earlier asm volatile blocks declared only t0 in their clobber list. GCC was keeping a live local in t1 across the asm — and the handler trampled it. Symptom under P51 priv check: corrupted saved_mtvec/saved_mstatus, broken FreeRTOS startup.

Fix: every asm block that may trigger a probe-handler trap declares both t0 and t1 clobbered. csr_priv_check_probe step 2 also keeps the probe trap handler installed across step 1 (otherwise its ebreak would land in the FreeRTOS handler).

What still doesn’t work

  • No PMP / Sv32 — S-mode can still read/write any physical address. Linux tolerates a correct kernel; PMP comes after Sv32.
  • No U-mode hardware. ECALL_FROM_U and PMP access-fault tests are blocked on that.
  • sip is read-mostly. Software interrupts (writes to mip.SSIP) not yet implemented.

Files

  • src/top.sv - priv check + sie/sip subset
  • app/main.c - csr_priv_check_probe + clobber-list fix

Harden

NOT RUN. Estimated +30 cells over P50.

What just happened?

S-mode is now confined to its priv level for CSR access. The kernel (S) cannot accidentally clobber M-state. Combined with P50’s trap delegation, P51 gives us the priv-isolation half of the privileged architecture. Next major rung: Sv32 paging.