Skip to content

[Bug] First VS-mode sstatus read returns host FS/SD view instead of VS-visible state #3816

Description

@jf-cc727

Bug Description

In H-enabled Rocket, the first VS-mode csrr sstatus after an HS sret can return the HS-level host FS/SD view instead of the guest-visible vsstatus view.

The PoC deliberately makes the two architectural views different before entering VS mode:

  • HS-level host state is forced to FS=Dirty, so host sstatus would report FS=Dirty and SD=1.
  • Guest-visible vsstatus is forced to FS=Initial, so VS-visible sstatus should report FS=Initial and SD=0 before any VS floating-point instruction executes.
  • As a control, HS sscratch is set to 0x1111 while guest vsscratch is set to 0x2222.

After HS sets hstatus.SPV=1 and executes sret, the first VS-side control read:

csrr s4, sscratch

returns the guest-visible vsscratch value 0x2222, showing that the hart is not simply stuck on the HS sscratch view.

However, the very next read:

csrr s0, sstatus

still returns a value whose FS/SD fields match the host view rather than the programmed guest-visible vsstatus view.

The replay shows a specific split: sscratch -> vsscratch substitution succeeds, but sstatus -> vsstatus substitution does not.

Upstream version confirmation: this issue was validated against the official Rocket Chip master line at revision v1.6-819-g55bcad0f5, confirmed at commit 55bcad0f59436de98ea510334121de8546b9e9d7, using freechips.rocketchip.system.HypervisorConfig. No fix revision has been identified yet.

RISC-V Specification Requirement

The RISC-V Privileged ISA hypervisor extension defines two requirements that matter here:

  • When V=1, vsstatus substitutes for the usual sstatus, so instructions that normally access sstatus are required to access the guest-visible vsstatus view instead.
  • When HS software executes SRET with hstatus.SPV=1, the hart returns into a virtualized supervisor context, after which supervisor CSR accesses should follow the VS substitution rules.

Reference: RISC-V Privileged ISA v20260120, Hypervisor Extension

Under those rules, the first VS-side csrr sstatus in this PoC should observe the guest-programmed vsstatus state, not the HS host sstatus state.

Steps to Reproduce

  1. Use the attached minimal PoC (program.S / program.elf).
  2. Run the official Verilator emulator with fixed seed 1:
emulator --seed=1 program.elf
  1. Optionally use the replay harness to capture the value-level mismatch on the first VS-mode sstatus read:
replay_one_source.py --core rocket

The PoC builds the smallest state split needed to expose the problem:

  • Start in M-mode on an H-enabled Rocket configuration and open a permissive PMP region so HS/VS software can execute from the loaded image.
  • Force the HS host view to be obviously dirty:
li   t0, STATUS_FS_MASK
csrc mstatus, t0
li   t0, STATUS_FS_DIRTY
csrs mstatus, t0
  • Program a control pair where host and guest supervisor scratch CSRs differ:
li   t0, HOST_SSCRATCH_VAL
csrw sscratch, t0
li   t0, GUEST_SSCRATCH_VAL
csrw CSR_VSSCRATCH, t0
  • Program guest-visible vsstatus to a clean initial state:
csrw CSR_VSSTATUS, zero
li   t0, STATUS_FS_INITIAL
csrs CSR_VSSTATUS, t0
  • Enter HS with mret, then set hstatus.SPV=1, sstatus.SPP=1, and sepc=vs_entry, and execute sret.
  • In vs_entry, first read sscratch as the control probe and then read sstatus as the target signal:
csrr s4, sscratch
li   t0, GUEST_SSCRATCH_VAL
bne  s4, t0, fail_sscratch_alias

csrr s0, sstatus

Expected Result

After the HS sret, both supervisor CSR reads should use the guest-visible VS substitutions:

  • csrr sscratch should return 0x2222
  • csrr sstatus should report FS=Initial and SD=0

Actual Result

The PoC reaches its failure path because the first VS-mode sstatus read still exposes the host FS/SD view:

[27] commit pc 00000000800000e0 ... csrr    s4, sscratch
     W[r20=0000000000002222]

[31] commit pc 00000000800000fc ... csrr    s0, sstatus
     W[r 8=8000000200006000]

REF s0 = 0x0000000200002000

So the control read already switches sscratch to the guest-visible vsscratch value 0x2222, but the following csrr sstatus still returns the host view (FS=Dirty, SD=1) instead of the guest-visible VS state (FS=Initial, SD=0).

The official emulator run exits through the fail path:

*** FAILED *** (tohost = 31)
*** FAILED *** via dtm (code = 31, seed 1) after 34094 cycles

RK-3.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions