[RFC PATCH v2 1/8] lib: sbi: Preserve hypervisor state across domain switches

Theodorus Wensan Februanto theodoruswensanfebruanto025 at gmail.com
Fri Oct 23 00:09:18 PDT 2026


The domain context switch saves several supervisor CSRs but leaves
hypervisor trap, delegation, interrupt, and translation state shared
between domains.

Exchange core writable H-extension CSRs when H is available. Use a
64-bit exchange for henvcfg and check Smaia before accessing RV32
high-half AIA registers.

The domain protection reconfiguration performs SFENCE/HFENCE after
the CSR exchange.

Link: https://github.com/riscv-software-src/opensbi/issues/433
Signed-off-by: Theodorus Wensan Februanto <theodoruswensanfebruanto025 at gmail.com>
---
 lib/sbi/sbi_domain_context.c | 70 ++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/lib/sbi/sbi_domain_context.c b/lib/sbi/sbi_domain_context.c
index 0861d541..4bafda5b 100644
--- a/lib/sbi/sbi_domain_context.c
+++ b/lib/sbi/sbi_domain_context.c
@@ -21,6 +21,34 @@
 #include <sbi/sbi_vector.h>
 #include <sbi/sbi_fp.h>
 
+struct hart_context_hext {
+	unsigned long hstatus;
+	unsigned long hedeleg;
+	unsigned long hideleg;
+	unsigned long hie;
+	unsigned long hgeie;
+	u64 henvcfg;
+	unsigned long htval;
+	unsigned long htinst;
+	unsigned long hvip;
+	unsigned long hgatp;
+#if __riscv_xlen == 32
+	unsigned long hidelegh;
+	unsigned long hviph;
+#endif
+	unsigned long hcounteren;
+	u64 htimedelta;
+	unsigned long vsstatus;
+	unsigned long vsie;
+	unsigned long vstvec;
+	unsigned long vsscratch;
+	unsigned long vsepc;
+	unsigned long vscause;
+	unsigned long vstval;
+	unsigned long vsip;
+	unsigned long vsatp;
+};
+
 /** Context representation for a hart within a domain */
 struct hart_context {
 	/** Trap-related states such as GPRs, mepc, and mstatus */
@@ -44,6 +72,8 @@ struct hart_context {
 	unsigned long sip;
 	/** Supervisor address translation and protection register */
 	unsigned long satp;
+
+	struct hart_context_hext hext;
 	/** Counter-enable register */
 	unsigned long scounteren;
 	/** Supervisor environment configuration register */
@@ -139,6 +169,46 @@ static int switch_to_next_domain_context(struct hart_context *ctx,
 	ctx->stval	= csr_swap(CSR_STVAL, dom_ctx->stval);
 	ctx->sip	= csr_swap(CSR_SIP, dom_ctx->sip);
 	ctx->satp	= csr_swap(CSR_SATP, dom_ctx->satp);
+
+	if (misa_extension('H')) {
+		ctx->hext.hstatus = csr_swap(CSR_HSTATUS, dom_ctx->hext.hstatus);
+		ctx->hext.hedeleg = csr_swap(CSR_HEDELEG, dom_ctx->hext.hedeleg);
+		ctx->hext.hideleg = csr_swap(CSR_HIDELEG, dom_ctx->hext.hideleg);
+		ctx->hext.hie = csr_swap(CSR_HIE, dom_ctx->hext.hie);
+		ctx->hext.hgeie = csr_swap(CSR_HGEIE, dom_ctx->hext.hgeie);
+		ctx->hext.henvcfg = csr_swap64(CSR_HENVCFG, dom_ctx->hext.henvcfg);
+		ctx->hext.htval = csr_swap(CSR_HTVAL, dom_ctx->hext.htval);
+		ctx->hext.htinst = csr_swap(CSR_HTINST, dom_ctx->hext.htinst);
+		ctx->hext.hvip = csr_swap(CSR_HVIP, dom_ctx->hext.hvip);
+		ctx->hext.hgatp = csr_swap(CSR_HGATP, dom_ctx->hext.hgatp);
+		ctx->hext.hcounteren = csr_swap(CSR_HCOUNTEREN, dom_ctx->hext.hcounteren);
+		ctx->hext.htimedelta = csr_swap64(CSR_HTIMEDELTA, dom_ctx->hext.htimedelta);
+		ctx->hext.vsstatus = csr_swap(CSR_VSSTATUS,
+					 dom_ctx->hext.vsstatus);
+		ctx->hext.vsie = csr_swap(CSR_VSIE,
+					 dom_ctx->hext.vsie);
+		ctx->hext.vstvec = csr_swap(CSR_VSTVEC,
+					 dom_ctx->hext.vstvec);
+		ctx->hext.vsscratch = csr_swap(CSR_VSSCRATCH,
+					 dom_ctx->hext.vsscratch);
+		ctx->hext.vsepc = csr_swap(CSR_VSEPC,
+					 dom_ctx->hext.vsepc);
+		ctx->hext.vscause = csr_swap(CSR_VSCAUSE,
+					 dom_ctx->hext.vscause);
+		ctx->hext.vstval = csr_swap(CSR_VSTVAL,
+					 dom_ctx->hext.vstval);
+		ctx->hext.vsip = csr_swap(CSR_VSIP,
+					 dom_ctx->hext.vsip);
+		ctx->hext.vsatp = csr_swap(CSR_VSATP,
+					 dom_ctx->hext.vsatp);
+#if __riscv_xlen == 32
+		if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SMAIA)) {
+			ctx->hext.hidelegh = csr_swap(CSR_HIDELEGH,
+						dom_ctx->hext.hidelegh);
+			ctx->hext.hviph = csr_swap(CSR_HVIPH, dom_ctx->hext.hviph);
+		}
+#endif
+	}
 	if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_10)
 		ctx->scounteren = csr_swap(CSR_SCOUNTEREN, dom_ctx->scounteren);
 	if (sbi_hart_priv_version(scratch) >= SBI_HART_PRIV_VER_1_12)
-- 
2.43.0




More information about the opensbi mailing list