target/riscv: reserved bit 63 of sstateen1-3 is writable on RV64
Host environment
- Operating system: Rocky Linux 9 (x86_64)
- QEMU version: 11.1.2; the code is unchanged on master
Emulated/Virtualized environment
- Operating system: bare metal
- Machine type: virt,
-cpu max(RV64)
Description of problem
On RV64, bit 63 of sstateen1, sstateen2 and sstateen3 becomes writable whenever bit 63 of the matching mstateenN is set. sstateen1-3 have no defined bits, so they must always read 0.
write_sstateen_1_3() in target/riscv/tcg/csr.c passes SMSTATEEN_STATEEN (bit 63) as the write mask:
return write_sstateen(env, csrno, SMSTATEEN_STATEEN, new_val);Bit 63 is the SE control bit only in mstateenN/hstateenN, where it gates access to sstateenN. The sstateen CSRs are 32 bits wide in practice: smstateen.adoc says no sstateen high-half CSRs exist for RV32 "because it is expected the upper 32 bits of these registers will always be zeros", and "all reserved bits not yet given a defined meaning are also read-only zeros" (norm:stateen_reserved_roz). The mask appears to have been copied from the mstateen/hstateen case.
Steps to reproduce
- Unpack the attached tarball and run
./run.sh(it runsqemu-system-riscv64 -nographic -semihosting -machine virt -cpu max -bios sstateen1-bit63.elf). - In M-mode, the test sets bit 63 of mstateen1-3, writes all ones to sstateen1-3, and reads them back.
- QEMU prints
FAIL: sstateen1-3 bit 63 is writable (expected read-only zero). Expected:PASS: sstateen1-3 read 0.
2026-10-19-qemu-sstateen123-bit63.tar.gz
Additional information
Suggested fix: use a write mask of 0 for sstateen1-3 until bits are defined there. Found by the RISC-V architectural tests (riscv-arch-test Smstateen/Ssstateen, https://github.com/riscv/riscv-arch-test/pull/2874).