15.2.5-13"H" II: henvcfg, htimedelta, hgatp, vsstatus, vsip/vsie

Part II Linux boot: optional Vol. II (Privileged) pp. 157–164 · ~5 min read

  • vmid

henvcfg — the guest environment dial

The envcfg cascade gains its hypervisor tier: henvcfg governs execution when V=1, sitting between menvcfg (which must grant first) and senvcfg (which the guest uses to govern VU).

henvcfg (0x60A) — Figure 59

STCE63PBMTE62ADUE61DTE59PMM3332CBZE7CBCFE6CBIE54SSE3LPE2FIOM0
WPRI/RO WLRL WARL RW
Click a field for semantics, reset state, and the minimal-implementation note.

hcounteren repeats the scounteren pattern for V=1: a counter read in VS needs mcounteren AND hcounteren bits (VU adds scounteren); blocked-but-M-granted reads raise virtual-instruction. Its TM bit additionally gates guest access to vstimecmp-via-stimecmp. htimedelta shifts the guest’s clock: VS/VU reads of time return time + htimedelta (64-bit wrap → negative offsets), keeping virtual time continuous across migration.

htval and htinst

On a trap into HS, htval carries the guest physical address for guest-page faults, shifted right 2 bits (GPAs may be 2 bits wider than XLEN; same encoding as PMP/PTE addresses). The low 2 bits equal stval’s — except when the fault hit an implicit VS-stage page-table access, where htval holds the PT access’s GPA (the original GPA is unknowable mid-walk) and htinst disambiguates with a pseudoinstruction (the traps page has the format). htval is WARL and may hold only the GPAs the hart can actually fault on.

hgatp — the G-stage root

hgatp (0x680), HSXLEN=64 — Figure 65

MODE6360VMID5744PPN430
WPRI/RO WLRL WARL RW
Click a field for semantics, reset state, and the minimal-implementation note.

hgatp is active unless effective privilege is U with hstatus.HU=0 (so speculative HLV/HSV execution stays simple), and — like satp — writing it flushes nothing: VMID -tagged TLBs or HFENCE.GVMA handle staleness.

vsstatus, vsip, vsie

vsstatus is a full sstatus layout with three twists. FS/VS are doubly-gated: when V=1, an FP/vector instruction traps (illegal-instruction — never virtual, a codified legacy rule) if either vsstatus.FS or the HS-level sstatus.FS is Off, and dirtying sets both. That’s what lets hypervisor and guest each run independent lazy-switch protocols — the hypervisor can’t trust vsstatus.FS (the guest scribbles on it), and the guest can’t see sstatus.FS. SD/XS summarize only the VS view; UXL may be hardwired to hstatus.VSXL, UBE to VSBE; SDT exists when henvcfg.DTE grants it.

vsip/vsie — the guest’s sip/sie, wired per hideleg
When delegated (hideleg bit set) / when not
SEIP/SEIE ← hideleg[10]Alias of hip.VSEIP / hie.VSEIE — the renumbered VS external interrupt. Not delegated → read-only zero.
STIP/STIE ← hideleg[6]Alias of hip.VSTIP / hie.VSTIE.
SSIP/SSIE ← hideleg[2]Alias of hip.VSSIP / hie.VSSIE.
LCOFIP/LCOFIE ← hideleg[13]Only with Shlcofideleg (hideleg[13] writable): aliases of sip.LCOFIP / sie.LCOFIE — the guest samples its own perf counters. Else RO-0.
Dotted-underlined cells have explanations — click one.

Hardware Designer Notes

The dual-FS gating is the one piece here that touches the datapath rather than CSR plumbing: the FP-issue legality check becomes (vsstatus.FS ≠ Off) ∧ (sstatus.FS ≠ Off) when V=1, and the dirty update fans out to both fields. Everything else on this page is address decode, muxes, and one 64-bit adder on the time bus.

Minimal Linux-boot hart MUST

  • Implement the two-level counter gate (m ∧ h, plus s for VU) with virtual-instruction on the h/s-denied cases
  • Add htimedelta into both the time read path (V=1) and the vstimecmp comparator
  • Enforce the 16 KiB root alignment for Sv*x4 (PPN[1:0] treatment) and the GPA>>2 encoding in htval

MAY simplify / trap-and-emulate

  • Hardwire VMIDLEN=0 — correct but forces full G-stage TLB flushes on world switch; add VMIDs when VM density matters
  • Pin henvcfg extension bits (PBMTE/ADUE/DTE/SSE/LPE/PMM) to zero when the underlying extensions are absent — each is independently optional
  • Make vsstatus.UXL/UBE read-only copies of hstatus.VSXL/VSBE

Check yourself — henvcfg, hgatp, vsstatus

1.How does hgatp's response to an unsupported MODE write differ from satp's, and why does its PPN have a special constraint?

2.When V=1, a guest sets vsstatus.FS=Off but the hypervisor's sstatus.FS=Dirty. A guest FP instruction executes. What happens?

3.Why is a guest physical address in htval shifted right by 2 bits?

4.What does vsip.SEIP actually read when hideleg bit 10 is set?

5.What does htimedelta accomplish, and how are negative offsets represented?

5 questions