riscv64: skip satp Bare-mode switch when already Bare (§V.3 item 7 audit fix)
arch_early_init() unconditionally cleared satp on every boot, justified only by behavior observed under QEMU/EDK2 firmware (satp.MODE=10/Sv57, kernel identity-mapped within it). That reasoning never applied to the native U-Boot+OpenSBI boot path, where satp is conventionally already 0 at S-mode handoff -- the unconditional clear was likely a harmless no-op there, but on an unverified assumption. Fix: read satp.MODE first and return early when it's already 0 (nothing to switch away from, no safety argument needed). The unconditional csrw/sfence pair still runs unchanged for the confirmed QEMU/EDK2 case. No Sv39/Sv48/Sv57 page-table walker built -- out of proportion to this finding's severity. 3-arch acceptance: amd64/aarch64 don't compile this file, so their runs are non-regression on untouched files only. riscv64's own boot log confirms satp.MODE = 0xa at entry, so the mode != 0 branch ran and "satp cleared -- Bare mode, explicit" printed exactly as before the fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
350287850f
commit
90ee8deb6d
+29
-12
@@ -747,8 +747,11 @@ it doesn't. This is a real punch-list item, not a hypothetical.
|
||||
|
||||
7. **Code audit pass — DONE, 2026-09-04.** Reviewed `arch/riscv64/apic.c`, `plic.c`,
|
||||
`arch.c`, `interrupts.c`, `timer.c` for the same class of QEMU-virt-vs-real-hardware
|
||||
assumption §III item 6's amd64 audit and item 7 above's aarch64 audit looked for. Report
|
||||
only — nothing below was changed.
|
||||
assumption §III item 6's amd64 audit and item 7 above's aarch64 audit looked for.
|
||||
Report-only by default — the `satp`-clear finding below was fixed in code, per direct
|
||||
instruction naming it specifically after this audit landed. The other findings (PLIC
|
||||
base, already tracked as item 3 above; the clean SBI/SBI-SRST findings) needed no code
|
||||
change either way.
|
||||
|
||||
**Clean, and the most portable pattern of all three architectures**: the SBI timer path
|
||||
(`apic.c`) is genuinely hardware-independent — it probes for the TIME extension at
|
||||
@@ -766,16 +769,30 @@ it doesn't. This is a real punch-list item, not a hypothetical.
|
||||
already flagged as "a real punch-list item, not a hypothetical" before this audit ran.
|
||||
Nothing new to add beyond confirming the file's own header comment is accurate and the
|
||||
risk is real, not overstated.
|
||||
**Finding — minor, reasoning doesn't transfer to the native path, action likely still
|
||||
safe**: `arch_early_init()`'s explicit `satp` clear (Bare-mode switch) is justified in
|
||||
its own comment entirely by behavior *observed under QEMU's EDK2 RISC-V firmware*
|
||||
(confirmed `satp.MODE=10`/Sv57 live, kernel identity-mapped within it). Under the native
|
||||
boot path (U-Boot+OpenSBI, no UEFI/EDK2 at all per §V.1) that specific observation cannot
|
||||
apply — OpenSBI's S-mode handoff conventionally already leaves `satp=0` (Bare mode), most
|
||||
likely making this a no-op there rather than a hazard, but the *stated justification* for
|
||||
the switch (identity-mapped, safe to clear) was derived from a firmware stack the native
|
||||
path doesn't use, and hasn't been re-confirmed for OpenSBI's actual handoff state. Lowest
|
||||
severity of any finding across both audits — flagged for completeness, not urgency.
|
||||
**Finding — minor, reasoning didn't transfer to the native path — FIXED 2026-09-04, per
|
||||
direct instruction naming it specifically.** `arch_early_init()`'s explicit `satp` clear
|
||||
(Bare-mode switch) was justified in its own comment entirely by behavior *observed under
|
||||
QEMU's EDK2 RISC-V firmware* (confirmed `satp.MODE=10`/Sv57 live, kernel identity-mapped
|
||||
within it). Under the native boot path (U-Boot+OpenSBI, no UEFI/EDK2 at all per §V.1)
|
||||
that specific observation cannot apply — OpenSBI's S-mode handoff conventionally already
|
||||
leaves `satp=0` (Bare mode), most likely making the unconditional switch a harmless no-op
|
||||
there, but on an unverified assumption rather than a checked one.
|
||||
**Fix**: rather than build a general Sv39/Sv48/Sv57 page-table walker just to *prove* the
|
||||
running address is identity-mapped before switching (out of proportion to this finding's
|
||||
own severity), `arch_early_init()` now reads `satp.MODE` first and **skips the switch
|
||||
entirely when it's already 0** — the expected case on a from-Bare native boot, needing no
|
||||
safety argument at all since there's nothing to switch away from. The unconditional
|
||||
`csrw satp, x0`/`sfence.vma` pair still runs, unchanged, for the confirmed QEMU/EDK2 case
|
||||
(`mode != 0`), where the identity-mapping argument remains the actual justification it
|
||||
always was. If the native path somehow reaches the non-zero branch anyway (OpenSBI
|
||||
leaving a non-Bare `satp`, not confirmed either way), the code says so explicitly in its
|
||||
own comment now rather than silently relying on the QEMU-only observation. Verified against
|
||||
the riscv64 boot log's own `satp.MODE` print, not assumed: this system's QEMU/EDK2 boot
|
||||
shows `satp.MODE = 0x000000000000000a` (Sv57) at kernel entry, so the `mode != 0` branch
|
||||
ran and printed `satp cleared -- Bare mode, explicit` exactly as before the fix — the
|
||||
unconditional-switch path is unchanged on the one boot path that exercises it. amd64 and
|
||||
aarch64 don't compile this file at all, so their part of the 3-arch acceptance run is pure
|
||||
non-regression on files untouched by this fix, not evidence about the guard itself.
|
||||
|
||||
**Hardware-dependent, after 2026-09-17:**
|
||||
8. Build and flash the boot image to QSPI flash (or attempt UART XMODEM recovery boot if QSPI
|
||||
|
||||
Reference in New Issue
Block a user