Raise illegal-instruction (not virtual) for indirect-CSR permission failures under V=1#2290
Open
jameshippisley wants to merge 2 commits into
Open
Raise illegal-instruction (not virtual) for indirect-CSR permission failures under V=1#2290jameshippisley wants to merge 2 commits into
jameshippisley wants to merge 2 commits into
Conversation
added 2 commits
May 7, 2026 23:54
sscsrind_reg_csr_t serves both Sscsrind (sireg, vsireg — S/HS-priv) and Smcsrind (mireg — M-priv). Its verify_permissions accumulated three H-extension V=1 illegal->virtual conversions (Smstateen hstateen0.CSRIND gate, the unconditional VU rule from PR riscv-software-src#2221, and the base csr_t::verify_permissions S/HS conversion). All three are correct for the S/HS-priv siblings but spec-violating for the M-priv mireg: the H-ext conversion is restricted to csr_priv <= HS, so M-priv access from below M must continue to raise illegal-instruction. Add an early carve-out at the top of verify_permissions so any M-priv access from below M short-circuits to illegal before the V=1 conversion machinery runs. The downstream rules then only execute on S/HS-priv CSRs where their conversions are spec-correct, and don't need to special-case csr_priv themselves. Address bits [9:8] are used to derive the CSR's priv class because csr_priv is private to csr_t.
sireg / vsireg are wrapped in virtualized_indirect_csr_t to alias sireg -> vsireg under V=1. The wrapper's verify_permissions called the base priv check first, so a VU access to sireg with mstateen0.CSRIND=0 hit the H-ext priv-class conversion (csr_priv=S, V=1) and trapped virtual-instruction. Per Smstateen the bit-clear case must raise illegal-instruction regardless of V — the inner sscsrind_reg_csr_t::verify_permissions enforces this but never runs once the wrapper has thrown. Add the Smstateen.CSRIND check at the top of the wrapper so it fires before the priv-class conversion. The inner copy stays in place for mireg / mireg2..6 and vsireg / vsireg2..6, which are registered without this wrapper.
aswaterman
reviewed
May 11, 2026
aswaterman
left a comment
Collaborator
There was a problem hiding this comment.
@binno @chihminchao can you review this and make sure you agree?
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
sscsrind_reg_csr_t::verify_permissionsand thevirtualized_indirect_csr_twrapper aroundsireg/vsiregcontain three H-extensionV=1illegal→virtual conversions that misfire on cases the spec says should be illegal-instruction:VU
miregreturns virtual instead of illegal. The unconditionalstate->v && state->prv == PRV_U → virtualrule added in Fix: Enforce virtual_instruction trap for VU-mode indirect CSR access #2221 for the S/HS-priv siblings also fires for the M-privmireg, whichsscsrind_reg_csr_talso serves.VS
miregwithhstateen0.CSRIND=0returns virtual instead of illegal — same class, same root cause: the Smstateen H-ext gate fires for M-privmireg.VU
siregwithmstateen0.CSRIND=0returns virtual instead of illegal.virtualized_indirect_csr_tcalls the basevirtualized_csr_t::verify_permissionsfirst, which runs the H-ext priv-class conversion before the innersscsrind_reg_csr_tever gets to enforce Smstateen.The H-ext
csr_priv ≤ HSconversion rule does not apply to M-priv CSRs, and Smstateen requires illegal regardless ofV. Both cases must short-circuit to illegal-instruction.Fix
Two commits, one bug class each:
Keep M-priv access to indirect CSRs as illegal-instruction — early carve-out at the top of
sscsrind_reg_csr_t::verify_permissionsforcsr_priv == M && prv < M. Address bits[9:8]are used to derive the CSR's priv class becausecsr_privis private tocsr_t. Fixes (1) and (2).Honor
mstateen0.CSRINDinvirtualized_indirect_csr_twrapper — Smstateen check at the top of the wrapper, before the priv-class conversion runs. Fixes (3). The inner copy insscsrind_reg_csr_tstays in place formireg/mireg2..6andvsireg/vsireg2..6, which are registered without this wrapper; leaving both is idempotent.Testing
Three-phase RV64GH assembly testcase, each phase expects
mcause=2(illegal-instruction):mireg,mstateen=1,hstateen=1— exercises (1)mireg,mstateen=1,hstateen=0— exercises (2)sireg,mstateen=0— exercises (3)Build:
Run:
Testcase source (
spike-mireg-vu-bug.S)