15.1-4"H" I: Modes, hstatus, Delegation, Hypervisor Interrupts

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

  • hypervisor extension

The H extension (misa bit 7 — preferably not hardwired) makes guests architectural: S-mode becomes HS-mode, and a new virtualization bit V spawns two guest modes. It requires full RV32I/RV64I (not E), a non-zero mtval, and paging (Sv32, or ≥Sv39 on RV64). An unmodified S-mode OS boots identically in HS-mode or as a VS-mode guest — that’s the design test.

Table 44 — privilege modes with H (HS > VS > VU)
VNominal privTwo-stage translation
M-mode0Moff
HS-mode — hypervisor-extended supervisor0Soff
U-mode0Uoff
VS-mode — virtual supervisor (guest kernel)1Son
VU-mode — virtual user (guest userspace)1Uon
Dotted-underlined cells have explanations — click one.

The CSR substitution scheme

HS-mode gets additional CSRs (hstatus, hedeleg/hideleg, hvip/hip/hie, hgeip/hgeie, henvcfg, hcounteren, htimedelta, htval, htinst, hgatp). And the trap-critical supervisor CSRs get VS twins — vsstatus, vsip/vsie, vstvec, vsscratch, vsepc, vscause, vstval, vsatp, vstimecmp. When V=1, an access to sstatus transparently reads vsstatus, and so on; the vs* CSRs’ own addresses trap from VS (virtual-instruction) and answer only to M/HS. CSRs without twins (senvcfg, scounteren…) stay live under V=1 with VS/VU substituting for HS/U — hypervisors swap those manually at world switch. The duplication criterion: only CSRs that traps write, or that must be correct in the first instructions of a handler, get hardware twins.

hstatus

hstatus (0x600), HSXLEN=64 — Figure 48

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

Delegation: three levels deep

Traps from V=1 route M → (medeleg/mideleg) → HS → (hedeleg/hideleg) → VS. hedeleg mirrors medeleg’s layout, but Table 45 pins the policy: bits 1–8, 12, 13, 15, 18, 19 must be writable (plus bit 0 if IALIGN=32); ecalls from HS/VS/M (9/10/11), double trap (16), guest-page faults (20/21/23), and virtual instruction (22) are read-only zero — those are the hypervisor interface, so pushing them into the guest would be circular. In hideleg, VS interrupts (bits 10/6/2) are writable and, when delegated, renumber on the way down: VSEI (10) presents to the guest as SEI (9), VSTI (6) as STI (5), VSSI (2) as SSI (1) — vscause included. The guest sees a plain S-mode world.

The hypervisor interrupt registers

hvip is the injection register: writable VSEIP[10]/VSTIP[6]/VSSIP[2] assert virtual interrupts for the guest. hip/hie supplement sip/sie with the hypervisor interrupts — and their active bits are required to be disjoint from sip/sie’s (an emulability guarantee: S-mode software can’t have its sip bits re-purposed):

hip standard bits (interrupt i traps to HS iff pending∧enabled in sip/sie or hip/hie, not hideleg-delegated, and (HS ∧ sstatus.SIE) ∨ priv < HS)
Source / behavior
SGEIP [12] (RO)1 iff hgeip & hgeie ≠ 0 — the hypervisor’s own “some guest device needs routing” interrupt.
VSEIP [10] (RO)OR of: hvip.VSEIP (software-injected) | hgeip bit selected by VGEIN (pass-through) | platform signals.
VSTIP [6] (RO)hvip.VSTIP | vstimecmp comparator output (Sstc). Defined even while V=0.
VSSIP [2] (RW)Writable alias of hvip.VSSIP.
Dotted-underlined cells have explanations — click one.

HS-mode interrupt priority: SEI, SSI, STI, SGEI, VSEI, VSSI, VSTI, LCOFI — host before guest.

hgeip/hgeie (guest external interrupts) exist for device pass-through: bit i aggregates all pending interrupts an interrupt controller has collected for virtual hart i. GEILEN (0…31/63) bits are implemented from bit 1 up. hgeie picks which of them wake the hypervisor (SGEI); hstatus.VGEIN picks the one wired through as the guest’s external interrupt — two independent consumers of the same pending bits.

Hardware Designer Notes

The expensive parts of H live in later pages (two-stage TLB, the G-stage walker). This page’s state is cheap: one V flop, ~10 new CSRs, and mux trees. Get the substitution architecture right first — every later feature keys off “which world am I in”.

Minimal Linux-boot hart MUST

  • Make V fan into four muxes: CSR address remap (s* → vs*), trap-target resolution (M/HS/VS by the three delegation levels), translation-enable selection, and virtual-vs-illegal exception choice
  • Keep hip/hie active bits disjoint from sip/sie, with the VSEIP/VSTIP OR-trees exactly as specified
  • Implement the interrupt renumbering (10→9, 6→5, 2→1) on VS delivery, including the vscause value

MAY simplify / trap-and-emulate

  • Hardwire GEILEN=0 (no pass-through; VGEIN RO-0) — KVM works fine with hvip injection only
  • Hardwire VSXL/VSBE (single XLEN, little-endian)
  • Omit H entirely for a Linux-boot v1 — misa.H=0; the extension was designed to be trap-and-emulated on top of plain S-mode when needed

Check yourself — H modes, hstatus, delegation

1.A guest kernel in VS-mode executes `csrr t0, sstatus`. What does hardware actually do?

2.Why does hstatus need SPVP when sstatus already has SPP?

3.Which hedeleg bits MUST be read-only zero, and what's the pattern?

4.How does hip.VSEIP get asserted?

5.Why are hip/hie's active bits required to be DISJOINT from sip/sie's, rather than merged into them?

5 questions