RISC-V Zkr seed CSR is sign-extended instead of zero-extended on RV64
Host environment
- Operating system: Ubuntu 26.04 LTS under WSL2
- OS/kernel version:
Linux QCOM-KSziIaJRXQ 6.18.33.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 18 21:38:49 UTC 2026 aarch64 GNU/Linux - Architecture:
aarch64 - QEMU flavor:
qemu-system-riscv64 - QEMU version:
QEMU emulator version 11.0.3 (v11.0.3) - QEMU command line:
qemu-system-riscv64 -nographic -semihosting -icount shift=1 -machine virt \ -cpu max,pmu-mask=0xfffffff8,smdbltrp=true,ssdbltrp=true \ -bios Zkr-00.elf
Emulated/Virtualized environment
- Operating system: none; bare-metal self-checking riscv-arch-test/ACT4 ELF
- OS/kernel version: N/A
- Architecture:
riscv64
Description of problem
QEMU appears to sign-extend the 32-bit RISC-V Zkr seed CSR value when returning it in an RV64 GPR. The RISC-V ISA specification requires CSR reads to zero-extend 32-bit CSRs to XLEN.
On RV64, a seed value such as 0x8000ABCD should therefore be returned in rd as 0x000000008000ABCD, not 0xFFFFFFFF8000ABCD.
The attached tarball contains Zkr-00.elf, a self-checking RV64 ELF generated from riscv-arch-test ACT4, plus an objdump. The test reads seed, extracts OPST with a logical right shift by 30, and expects OPST == 2 for ES16.
Relevant objdump sequence:
800010a0: 01501373 csrrw x6,seed,x0
800010a4: 01501373 csrrw x6,seed,x0
800010a8: 01e35793 srli x15,x6,0x1e
800010b4: 00200413 addi x8,x0,2
800010b8: 04879463 bne x15,x8,80001100A QEMU debug trace from the attached reproducer shows the failing condition immediately before the srli:
0x800010a8: 01e35793 srli a5,t1,30
...
x6/t1 ffffffff8000aa3fThe low 32-bit seed value is 0x8000aa3f, whose OPST field is 0b10 (ES16). Per the spec, the RV64 GPR value should be 0x000000008000aa3f. Instead QEMU has sign-extended it to 0xffffffff8000aa3f. After srli ..., 30, this produces 0x00000003fffffffe, not 2, so the self-checking test takes the failure path.
The exact entropy value varies between runs, but QEMU consistently returns the RV64 GPR value with bits 63:32 set when bit 31 of the 32-bit seed value is set.