Skip to content

Implement Smstateen and Ssstateen - #1881

Open
davidharrishmc wants to merge 2 commits into
openhwfoundation:mainfrom
davidharrishmc:dh/smstateen
Open

davidharrishmc wants to merge 2 commits into
openhwfoundation:mainfrom
davidharrishmc:dh/smstateen

Conversation

@davidharrishmc

Copy link
Copy Markdown
Contributor

Implements the Smstateen and Ssstateen extensions: the machine- and supervisor-level state enable CSRs. Each bit of a stateen register controls access from less-privileged modes to the state that bit names; machine mode is never restricted by them.

Registers

mstateen0 follows the menvcfg pattern in csrm.sv and is 64 bits wide even on RV32. Bit assignments are taken from the figure in the privileged spec chapter:

Bit Field In Wally
63 SE0 writable; controls access to sstateen0
62 ENVCFG writable; controls access to senvcfg
60 CSRIND gated by SSCSRIND_SUPPORTED
59, 58 AIA, IMSIC gated by SSAIA_SUPPORTED
57 CONTEXT gated by SDTRIG_SUPPORTED
56 P1P13 gated by the new SMP1P13_SUPPORTED
55 SRMCFG gated by SSQOSID_SUPPORTED
54 CTR read-only zero, Smctr not supported
2 JVT gated by ZCMT_SUPPORTED
1 FCSR gated by ZFINX_SUPPORTED
0 C read-only zero, Wally has no custom state

ENVCFG needs no gate: Wally is Sm1p12 compatible, so senvcfg always exists. FCSR is additionally required to be read-only zero when misa.F = 1, which holds here because F and Zfinx are mutually exclusive.

mstateen1-3 are read-only zero. The spec permits that only when the hypervisor extension is absent and the matching sstateen is all read-only zeros, both of which hold. On RV32 the mstateen*h CSRs give access to the upper halves.

sstateen0-3 are added to csrs.sv. Every defined sstateen0 bit (C, FCSR, JVT) is read-only zero in Wally, but the register is built with the write mask and the read masking against mstateen0 that the spec requires, so it stays correct if Zcmt or Zfinx is ever enabled.

Enforcement

The registers are only half the extension; the access control is the other half. With mstateen0.SE0 clear, a supervisor-mode access to sstateen0 raises an illegal instruction, and with mstateen0.ENVCFG clear the same applies to senvcfg. Reads and write enables are both gated, following the existing pattern for satp under mstatus.TVM. sstateen1-3 are reachable only from machine mode, because bit 63 of mstateen1-3 is read-only zero.

Configuration

Nine new parameters. Smstateen and Ssstateen are 1 on rv32gc and rv64gc; every other new parameter is 0 in every config. Assertions require Smstateen to have Zicsr and U, and Ssstateen to have Smstateen and S.

Verification

Check Result
ACT4 Smstateen-00, Ssstateen-00 on cvw-rv64gc both pass
ACT4 Smstateen-00, Ssstateen-00 on cvw-rv32gc both pass
lint-wally, 7 configs clean
regression-wally no new failures

The ACT4 runs need the companion config change in riscv/riscv-arch-test (linked below); without it the reference model does not implement sstateen0, traps on the test's first machine-mode access, and every expected trap signature shifts.

imperas.ic for rv32gc and rv64gc now override Smstateen and Ssstateen so nightly lockstep agrees.

The three regression failures present are all pre-existing on main and unrelated: rv32i, rv64i and rv32e hit the Minstret probe bug that #1878 fixes; arch64vm_sv57 has no test vectors in my environment; and wally64priv fails WALLY-trap-01 result 12 byte-identically to pristine main.

Note for reviewers

This changes observable behavior for supervisor software: with mstateen0 reset to zero, an S-mode access to senvcfg now traps until machine-mode firmware sets the ENVCFG bit. That is what the spec requires, and OpenSBI already detects the extension, now reporting smstateen first in the boot hart ISA string where previously it was absent. A full buildroot Linux boot is running to confirm the kernel's senvcfg use is unaffected; I will report the result here.

🤖 Generated with Claude Code

@davidharrishmc

Copy link
Copy Markdown
Contributor Author

The buildroot boot finished: Linux boots clean with Smstateen enabled.

It reaches WallyHostname login: at 576M instructions, the same string regression-wally greps for on the full-boot test, and ends through the documented normal path (watchdog.sv:80, "This is a normal termination for a full buildroot boot"). No bad page state, oops, panic, call trace or segfault anywhere in the 10389-byte console log.

This was the check worth doing, because enabling Smstateen genuinely changes supervisor behavior: with mstateen0 reset to zero, an S-mode access to senvcfg traps until machine mode grants it. OpenSBI handles that. It now reports the extension first in its ISA string, where it was absent before:

before: Boot HART ISA Extensions    : sstc,zicntr,zihpm,zicboz,zicbom,svpbmt,svade,svadu
after:  Boot HART ISA Extensions    : smstateen,sstc,zicntr,zihpm,zicboz,zicbom,svpbmt,svade,svadu

so firmware detects mstateen0 by trap-probing it and takes responsibility for the enable bits before handing off to the kernel.

The boot tracks the pre-change trajectory almost cycle for cycle, which is what you want from a change that should be invisible once firmware cooperates:

Milestone main this branch
clk: Disabling unused clocks 6.407323 6.407385
Unpacking initramfs... 14.189262 14.191256
Freeing initrd memory 27.267273 27.271751
Run /init as init process 29.371921 29.376817
login prompt 576M instr 576M instr

Userspace does real work before the prompt: creates and moves a file, runs a script and a symlink to it, reports disk usage, and lists processes with kworker/u4:0 alive and scheduling.

Caveat worth keeping in view: this is simulation with OpenSBI as the firmware. Any bare-metal or alternative-firmware supervisor software that writes senvcfg without first setting mstateen0.ENVCFG will now take an illegal instruction trap. That is the spec-required behavior, but it is a real change for such software.

davidharrishmc and others added 2 commits September 16, 2026 09:57
Adds the machine- and supervisor-level state enable CSRs.  Each bit of a stateen
register controls access from less-privileged modes to the state the bit names;
machine mode is never restricted.

mstateen0 is 64 bits wide even on RV32, following the menvcfg pattern, with the
bit assignments from the privileged spec: SE0 (63) controls access to sstateen0
and ENVCFG (62) controls access to senvcfg, both writable.  The remaining defined
bits are read-only zero unless the state they control is implemented: CSRIND (60)
gated by Sscsrind, AIA (59) and IMSIC (58) by Ssaia, CONTEXT (57) by Sdtrig,
P1P13 (56) by the new SMP1P13_SUPPORTED, SRMCFG (55) by Ssqosid, JVT (2) by Zcmt,
and FCSR (1) by Zfinx.  CTR (54) is read-only zero because Smctr is not
supported, and C (0) is read-only zero because Wally has no custom state.
ENVCFG needs no gate because Wally is Sm1p12 compatible, so senvcfg always
exists.  mstateen1-3 are read-only zero, which the spec permits because the
hypervisor extension is not implemented and sstateen1-3 are read-only zero; on
RV32 the mstateen*h CSRs give access to the upper halves.

sstateen0-3 are added to csrs.  Every defined sstateen0 bit (C, FCSR, JVT) is
read-only zero in Wally, but the register is built with the write mask and read
masking against mstateen0 that the spec requires, so it stays correct if Zcmt or
Zfinx is ever enabled.

Enforcement matches the spec as well as the register contents: with mstateen0.SE0
clear, a supervisor-mode access to sstateen0 raises an illegal instruction, and
with mstateen0.ENVCFG clear the same is true for senvcfg.  Both reads and write
enables are gated, following the existing pattern for satp under mstatus.TVM.
sstateen1-3 are reachable only from machine mode because bit 63 of mstateen1-3 is
read-only zero.

Smstateen and Ssstateen are enabled on rv32gc and rv64gc; every new parameter is
zero in all other configs.  Assertions require Smstateen to have Zicsr and U, and
Ssstateen to have Smstateen and S.

Verified with the Smstateen-00 and Ssstateen-00 tests from ACT4, which pass on
both cvw-rv32gc and cvw-rv64gc.  lint-wally is clean and regression-wally shows
no new failures.  OpenSBI now detects the extension and reports smstateen in the
boot hart ISA string.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bit 54 of mstateen0 controls access to the control transfer records added by
Smctr.  It was hardwired to zero; gate it like the other state bits so it becomes
writable if Smctr is ever implemented.  SMCTR_SUPPORTED is zero in every config.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant