journal 2026-05-03

P51 - priv-check on CSR access + the t1 clobber bug

p51riscvprivcsrautonomous-mode

Autonomous-mode rung, 7th past P45.

What landed

Three changes in src/top.sv:

  1. CSR-access priv check via csr_addr[9:8]. From S, csrw to mstatus/medeleg/mtvec etc. raises illegal-instr.
  2. mret only legal in M; sret only legal in M or S.
  3. sie/sip become real subset views of mie/mip (the standalone storage from P47 went away).

csr_priv_check_probe verifies both the trap path (csrw medeleg from S → illegal-instr → captured cause=2 in M handler) and the allow path (sscratch round-trip from S works because S-CSRs are S-priv).

The clobber-list bug

While bringing P51 up, FreeRTOS started hanging after the probes ran. Tracked it down with markers, found the chip was fine — the bug was in the test harness.

The probe trap handlers (M-handler and S-handler in app/main.c) use t0 and t1 as scratch. The asm volatile blocks that trigger traps were declaring only t0 in the clobber list. GCC’s register allocator was keeping live locals in t1 across the asm, the handler trampled t1, and probes returned corrupted saved_mtvec/saved_mstatus to the chip’s mtvec/mstatus on restore. Then FreeRTOS’s vTaskStartScheduler would mret to a trap vector pointing at the probe handler (instead of FreeRTOS’s handler), and the chip would loop forever.

Fix: add "t1" to every asm block that might trigger a probe- handler trap. This was always required; P49 and P50 happened to not hit the bug because GCC’s register choice was different in those simpler probes.

The other ordering bug in csr_priv_check_probe: step 2’s ebreak needs the probe trap handler still installed in mtvec, so the restore moves to AFTER step 2 instead of between the two steps.

Wart count

Same one open: the P46 gcc-zbb-auto-emit-sext.b hang.

What’s still missing for Linux

The big one: Sv32 paging. The chip has satp storage from P47 but no page-table walker. After that, PMP for physical-memory protection, then platform glue (CLINT, PLIC), then a real kernel.