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,80001100

A QEMU debug trace from the attached reproducer shows the failing condition immediately before the srli:

0x800010a8:  01e35793          srli                    a5,t1,30
...
x6/t1    ffffffff8000aa3f

The 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.

qemu-zkr-seed-zero-extension-repro.tar.gz