zkr: always allow S-mode seed access regardless of mseccfg.SSEED#5
Merged
Conversation
Virtual entropy sources per Section 4.4.3 don't need M-mode firmware
cooperation to grant S-mode the right to poll sentropy — they ARE the
firmware. Gating S-mode access on mseccfg.SSEED in an emulator is
theatre at best and a live-fire footgun at worst:
* We set mseccfg.USEED | mseccfg.SSEED in rvvm_create_machine's hart
init (circa rvvm.c:1223).
* OpenSBI 1.6 clobbers mseccfg during hart bring-up — its PMP
enhancement path writes 0 to the CSR while configuring MML/MMWP,
zeroing our USEED/SSEED bits as collateral.
* By the time Linux 6.18+ runs csrrwi x13, seed, 0 at
start_kernel+0x68a (random_init_early), SSEED is 0, our
riscv_csr_seed_enabled returns false for PRIV_SUPERVISOR, and the
emulator traps the access as illegal instruction. Kernel panics
before the console is even initialized.
Fix: let M and S mode through unconditionally. U-mode still gates on
mseccfg.USEED — that one actually matters (kernels use it to forbid
unprivileged entropy polling), and OpenSBI doesn't interfere with it
post-boot because it's not on the PMP-setup path in the same way.
This keeps the ABI spec-compliant from the kernel's point of view (a
kernel that writes its own SSEED=1 still sees the same behavior) while
removing the OpenSBI ordering hazard.
Empirically verified: before this patch, a Linux 6.18.22 guest oopses
at arch_get_random_seed_longs+0x14 with "Illegal instruction"
(badaddr=015056f3 = csrrwi x13, seed, 0) during start_kernel. After,
it boots through random_init_early and on into userspace.
SolAstrius
added a commit
that referenced
this pull request
Apr 27, 2026
Four small, related fixes that retire every "real bug in handled code" left from the original audit. #5 CORB consumer — sound_hda_corb_wp_write previously fetched only the entry at the new WP and never advanced corb_rp. Linux happens to bump WP after every entry so it worked, but a guest that batches multiple commands before bumping WP (spec §4.4.1.4 says you can) silently dropped all but the last. Now walks RP+1..WP inclusive, dispatching each verb, advancing RP to match — the spec-conformant CORB consumer model. #6 SET_PIN_WIDGET_CTRL on NID 3 — the verb's macro existed but no case dispatched it, and GET hardcoded a constant OUT_ENABLE. So Linux's pin power-up sequence ("write OUT_ENABLE, read back to confirm") happened to round-trip correctly only by accident. Now stores a real per-pin control byte (hda->pin_ctrl, single pin today; multi-pin codecs would key by NID), and GET returns it. Initialised to OUT_ENABLE so probe-time GET behaviour is unchanged for guests that don't write the register first. #12 RUN/SRST ordering — spec §3.3.35 requires "the RUN bit must be cleared before SRST is asserted." We previously accepted both bits set in the same write without enforcement — the worker would keep running with zeroed BDL pointers, spinning against a freshly-reset stream until the guest re-asserted RUN. Now on the SRST 0→1 edge, force-stop the worker (running=0) and override the same write's RUN bit, matching real HW behaviour where SRST clears the engine as part of its "stream registers and FIFO are reset" effect. #14 spinlock-across-pci_send_irq — was flagged as a smell ("could self-deadlock if IRQ delivery is synchronous and re-enters MMIO"). Verified RVVM's pci_send_irq → rvvm_send_irq just queues into the interrupt controller; the vCPU is a separate thread that picks it up later and never re-enters our MMIO synchronously from the calling thread. Documented the safety reasoning at the call site so future readers don't have to re-investigate. Not a bug — just under-documented.
SolAstrius
added a commit
that referenced
this pull request
May 1, 2026
Virtual entropy sources per Section 4.4.3 don't need M-mode firmware
cooperation to grant S-mode the right to poll sentropy — they ARE the
firmware. Gating S-mode access on mseccfg.SSEED in an emulator is
theatre at best and a live-fire footgun at worst:
* We set mseccfg.USEED | mseccfg.SSEED in rvvm_create_machine's hart
init (circa rvvm.c:1223).
* OpenSBI 1.6 clobbers mseccfg during hart bring-up — its PMP
enhancement path writes 0 to the CSR while configuring MML/MMWP,
zeroing our USEED/SSEED bits as collateral.
* By the time Linux 6.18+ runs csrrwi x13, seed, 0 at
start_kernel+0x68a (random_init_early), SSEED is 0, our
riscv_csr_seed_enabled returns false for PRIV_SUPERVISOR, and the
emulator traps the access as illegal instruction. Kernel panics
before the console is even initialized.
Fix: let M and S mode through unconditionally. U-mode still gates on
mseccfg.USEED — that one actually matters (kernels use it to forbid
unprivileged entropy polling), and OpenSBI doesn't interfere with it
post-boot because it's not on the PMP-setup path in the same way.
This keeps the ABI spec-compliant from the kernel's point of view (a
kernel that writes its own SSEED=1 still sees the same behavior) while
removing the OpenSBI ordering hazard.
Empirically verified: before this patch, a Linux 6.18.22 guest oopses
at arch_get_random_seed_longs+0x14 with "Illegal instruction"
(badaddr=015056f3 = csrrwi x13, seed, 0) during start_kernel. After,
it boots through random_init_early and on into userspace.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Remove the `mseccfg.SSEED` gate on S-mode access to the `seed` CSR. U-mode still respects `mseccfg.USEED` (that check actually matters for kernels forbidding unprivileged polling). M and S mode get unconditional access.
Why
Follow-up to #4. After that landed, Linux 6.18.22 still oopsed at `arch_get_random_seed_longs+0x14` with "Illegal instruction" during `start_kernel` / `random_init_early`. Trace:
```
badaddr: 00000000015056f3 cause: 0000000000000002
// 015056f3 = csrrwi x13, seed, 0
epc : arch_get_random_seed_longs+0x14
ra : random_init_early+0x2e
Kernel panic - not syncing: Fatal exception in interrupt
```
Root cause: we set `mseccfg.USEED | mseccfg.SSEED` in `rvvm_create_machine`'s hart init (rvvm.c:1223), but OpenSBI 1.6 clobbers `mseccfg` during hart bring-up — its PMP-enhancement path writes 0 to the CSR while configuring MML/MMWP. By the time Linux runs `csrrwi seed, x0` in S-mode, SSEED is back to 0, `riscv_csr_seed_enabled` returns false, and the emulator traps the access.
A virtual entropy source (Zkr 1.0.1 §4.4.3) doesn't need M-mode firmware cooperation to authorize S-mode access — it is the firmware. This patch lets M and S mode through unconditionally, keeping only the U-mode `mseccfg.USEED` check (which works fine because OpenSBI doesn't touch USEED on its PMP path the same way).
Verified
Test plan