git: d2e3e76ab902 - main - arm64/vmm: Store non-VNCR registers in an array

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Mon, 06 Jul 2026 15:24:40 UTC
The branch main has been updated by andrew:

URL: https://cgit.FreeBSD.org/src/commit/?id=d2e3e76ab902001c62e8c9a6286d2979b0f2a0de

commit d2e3e76ab902001c62e8c9a6286d2979b0f2a0de
Author:     Kajetan Puchalski <kajetan.puchalski@arm.com>
AuthorDate: 2026-07-06 14:17:03 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-07-06 15:18:30 +0000

    arm64/vmm: Store non-VNCR registers in an array
    
    Move non-VNCR EL0 and EL1 registers into a dedicated array inside of
    hypctx. This enables uniform accesses to both VNCR and non-VNCR guest
    register state through hypctx_[read|write]_sys_reg().
    
    The accessors are _not_ used for non-VNCR EL2 registers in order to
    create a clear separation between guest-visible and guest-invisible
    register state.
    
    Signed-off-by:  Kajetan Puchalski <kajetan.puchalski@arm.com>
    Reviewed by:    andrew
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D56552
---
 sys/arm64/vmm/arm64.h     |  99 +++++++++++++++--------
 sys/arm64/vmm/vmm_hyp.c   | 199 +++++++++++++++++++++++++---------------------
 sys/arm64/vmm/vmm_reset.c |  32 +-------
 3 files changed, 181 insertions(+), 149 deletions(-)

diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h
index 4db26709f21e..b90cc9d8d15f 100644
--- a/sys/arm64/vmm/arm64.h
+++ b/sys/arm64/vmm/arm64.h
@@ -48,7 +48,49 @@ struct vgic_v3_cpu;
 /* Retrieve the VNCR offset from the enum value */
 #define REG_VNCR_OFFSET(val) ((val - VNCR_START) * 8)
 
+/* Accessors for indices of PME and DBG registers */
+#define PMEVCNTR_EL0(n) (PMEVCNTR0_EL0 + MIN(n, 30))
+#define PMEVTYPER_EL0(n) (PMEVTYPER0_EL0 + MIN(n, 30))
+#define DBGBCR_EL1(n) (DBGBCR0_EL1 + MIN(n, 15))
+#define DBGBVR_EL1(n) (DBGBVR0_EL1 + MIN(n, 15))
+#define DBGWCR_EL1(n) (DBGWCR0_EL1 + MIN(n, 15))
+#define DBGWVR_EL1(n) (DBGWVR0_EL1 + MIN(n, 15))
+
 enum hypctx_sysreg {
+	CSSELR_EL1,  /* Cache Size Selection Register */
+	MDCCINT_EL1, /* Monitor DCC Interrupt Enable Register */
+	PAR_EL1,     /* Physical Address Register */
+
+	/* PMU Registers */
+	PMCR_EL0,	/* Performance Monitors Control Register */
+	PMCCNTR_EL0,
+	PMCCFILTR_EL0,
+	PMUSERENR_EL0,
+	PMSELR_EL0,
+	PMXEVCNTR_EL0,
+	PMCNTENSET_EL0,
+	PMINTENSET_EL1,
+	PMOVSSET_EL0,
+	/* Access these through macros defined above, e.g. PMEVCNTR_EL0(5) */
+	PMEVCNTR0_EL0,
+	PMEVCNTR30_EL0 = PMEVCNTR0_EL0 + 30,
+	PMEVTYPER0_EL0,
+	PMEVTYPER30_EL0 = PMEVTYPER0_EL0 + 30,
+
+	/* DBG Registers */
+	DBGCLAIMSET_EL1,
+	/* Access these through macros defined above, e.g. DBGBCR_EL1(5) */
+	DBGBCR0_EL1,	/* Debug Breakpoint Control Registers */
+	DBGBCR15_EL1 = DBGBCR0_EL1 + 15,
+	DBGBVR0_EL1,	/* Debug Breakpoint Value Registers */
+	DBGBVR15_EL1 = DBGBVR0_EL1 + 15,
+	DBGWCR0_EL1,	/* Debug Watchpoint Control Registers */
+	DBGWCR15_EL1 = DBGWCR0_EL1 + 15,
+	DBGWVR0_EL1,	/* Debug Watchpoint Value Registers */
+	DBGWVR15_EL1 = DBGWVR0_EL1 + 15,
+
+	NR_NON_VNCR_REGS,
+
 	/* VNCR Registers */
 	VNCR_START,
 
@@ -140,6 +182,16 @@ enum hypctx_sysreg {
 	VNCR_REG(GCSCR_EL1),
 	VNCR_REG(BRBCR_EL1),
 	VNCR_REG(SPMACCESSR_EL1),
+
+	/* Virtual-address-sized registers */
+	VA_REGS_START,
+
+	SP_EL0,	     /* Stack pointer */
+	TPIDR_EL0,   /* EL0 Software ID Register */
+	TPIDRRO_EL0, /* Read-only Thread ID Register */
+	TPIDR_EL1,   /* EL1 Software ID Register */
+
+	VA_REGS_END,
 };
 
 /*
@@ -147,37 +199,12 @@ enum hypctx_sysreg {
  */
 struct hypctx {
 	struct trapframe tf;
+	/* Virtual-address-sized registers */
+	uint64_t va_regs[VA_REGS_END - VA_REGS_START - 1];
+	/* Non-VNCR guest register state */
+	uint64_t sys_regs[NR_NON_VNCR_REGS];
 
-	/*
-	 * EL1 & EL0 registers.
-	 */
-	uint64_t	sp_el0;		/* Stack pointer */
-	uint64_t	tpidr_el0;	/* EL0 Software ID Register */
-	uint64_t	tpidrro_el0;	/* Read-only Thread ID Register */
-	uint64_t	tpidr_el1;	/* EL1 Software ID Register */
-	uint64_t	csselr_el1;	/* Cache Size Selection Register */
-	uint64_t	mdccint_el1;	/* Monitor DCC Interrupt Enable Register */
-	uint64_t	par_el1;	/* Physical Address Register */
-
-	uint64_t	pmcr_el0;	/* Performance Monitors Control Register */
-	uint64_t	pmccntr_el0;
-	uint64_t	pmccfiltr_el0;
-	uint64_t	pmuserenr_el0;
-	uint64_t	pmselr_el0;
-	uint64_t	pmxevcntr_el0;
-	uint64_t	pmcntenset_el0;
-	uint64_t	pmintenset_el1;
-	uint64_t	pmovsset_el0;
-	uint64_t	pmevcntr_el0[31];
-	uint64_t	pmevtyper_el0[31];
-
-	uint64_t	dbgclaimset_el1;
-	uint64_t	dbgbcr_el1[16];	/* Debug Breakpoint Control Registers */
-	uint64_t	dbgbvr_el1[16];	/* Debug Breakpoint Value Registers */
-	uint64_t	dbgwcr_el1[16];	/* Debug Watchpoint Control Registers */
-	uint64_t	dbgwvr_el1[16];	/* Debug Watchpoint Value Registers */
-
-	/* EL2 control registers */
+	/* EL2 registers which we use to control the guest but do not expose to it */
 	uint64_t	cptr_el2;	/* Architectural Feature Trap Register */
 	uint64_t	hcr_el2;	/* Hypervisor Configuration Register */
 	uint64_t	hcrx_el2;	/* Extended Hypervisor Configuration Register */
@@ -242,13 +269,21 @@ struct hypctx {
 	((uint64_t *)((char *)hypctx->vncr_regs + REG_VNCR_OFFSET(reg)))
 #endif
 
+#ifndef __hypctx_va_sysreg
+#define __hypctx_va_sysreg(hypctx, reg)		\
+	(&hypctx->va_regs[reg - VA_REGS_START - 1])
+#endif
+
 static inline uint64_t *
 hypctx_sys_reg(struct hypctx *hypctx, int reg /* enum hypctx_sysreg  */)
 {
+	/* Extract this into a separate helper when we actually support 128-bit regs */
+	if (reg > VA_REGS_START)
+		return (__hypctx_va_sysreg(hypctx, reg));
 	if (reg > VNCR_START)
 		return (__hypctx_vncr_sysreg(hypctx, reg));
-	/* TODO: uniform handling for non-VNCR registers */
-	return (NULL);
+	/* Calling this with reg=VNCR_START or reg=NR_NON_VNCR_REGS is a bad idea */
+	return (&hypctx->sys_regs[reg]);
 }
 
 static inline void
diff --git a/sys/arm64/vmm/vmm_hyp.c b/sys/arm64/vmm/vmm_hyp.c
index bde283a077c8..469ae8b90d9e 100644
--- a/sys/arm64/vmm/vmm_hyp.c
+++ b/sys/arm64/vmm/vmm_hyp.c
@@ -120,16 +120,17 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 		}
 	}
 
-	hypctx->dbgclaimset_el1 = READ_SPECIALREG(dbgclaimset_el1);
+	hypctx_write_sys_reg(hypctx, DBGCLAIMSET_EL1,
+	    READ_SPECIALREG(dbgclaimset_el1));
 
 	dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
 	switch (ID_AA64DFR0_BRPs_VAL(dfr0) - 1) {
-#define	STORE_DBG_BRP(x)						\
-	case x:								\
-		hypctx->dbgbcr_el1[x] =					\
-		    READ_SPECIALREG(dbgbcr ## x ## _el1);		\
-		hypctx->dbgbvr_el1[x] =					\
-		    READ_SPECIALREG(dbgbvr ## x ## _el1)
+#define	STORE_DBG_BRP(x)					\
+	case x:							\
+		hypctx_write_sys_reg(hypctx, DBGBCR_EL1(x),	\
+		    READ_SPECIALREG(dbgbcr ## x ## _el1));	\
+		hypctx_write_sys_reg(hypctx, DBGBVR_EL1(x),	\
+		    READ_SPECIALREG(dbgbvr ## x ## _el1))
 	STORE_DBG_BRP(15);
 	STORE_DBG_BRP(14);
 	STORE_DBG_BRP(13);
@@ -151,12 +152,12 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 	}
 
 	switch (ID_AA64DFR0_WRPs_VAL(dfr0) - 1) {
-#define	STORE_DBG_WRP(x)						\
-	case x:								\
-		hypctx->dbgwcr_el1[x] =					\
-		    READ_SPECIALREG(dbgwcr ## x ## _el1);		\
-		hypctx->dbgwvr_el1[x] =					\
-		    READ_SPECIALREG(dbgwvr ## x ## _el1)
+#define	STORE_DBG_WRP(x)					\
+	case x:							\
+		hypctx_write_sys_reg(hypctx, DBGWCR_EL1(x),	\
+		    READ_SPECIALREG(dbgwcr ## x ## _el1));	\
+		hypctx_write_sys_reg(hypctx, DBGWVR_EL1(x),	\
+		    READ_SPECIALREG(dbgwvr ## x ## _el1))
 	STORE_DBG_WRP(15);
 	STORE_DBG_WRP(14);
 	STORE_DBG_WRP(13);
@@ -178,23 +179,33 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 	}
 
 	/* Store the PMU registers */
-	hypctx->pmcr_el0 = READ_SPECIALREG(pmcr_el0);
-	hypctx->pmccntr_el0 = READ_SPECIALREG(pmccntr_el0);
-	hypctx->pmccfiltr_el0 = READ_SPECIALREG(pmccfiltr_el0);
-	hypctx->pmuserenr_el0 = READ_SPECIALREG(pmuserenr_el0);
-	hypctx->pmselr_el0 = READ_SPECIALREG(pmselr_el0);
-	hypctx->pmxevcntr_el0 = READ_SPECIALREG(pmxevcntr_el0);
-	hypctx->pmcntenset_el0 = READ_SPECIALREG(pmcntenset_el0);
-	hypctx->pmintenset_el1 = READ_SPECIALREG(pmintenset_el1);
-	hypctx->pmovsset_el0 = READ_SPECIALREG(pmovsset_el0);
-
-	switch ((hypctx->pmcr_el0 & PMCR_N_MASK) >> PMCR_N_SHIFT) {
+	hypctx_write_sys_reg(hypctx, PMCR_EL0,
+	    READ_SPECIALREG(pmcr_el0));
+	hypctx_write_sys_reg(hypctx, PMCCNTR_EL0,
+	    READ_SPECIALREG(pmccntr_el0));
+	hypctx_write_sys_reg(hypctx, PMCCFILTR_EL0,
+	    READ_SPECIALREG(pmccfiltr_el0));
+	hypctx_write_sys_reg(hypctx, PMUSERENR_EL0,
+	    READ_SPECIALREG(pmuserenr_el0));
+	hypctx_write_sys_reg(hypctx, PMSELR_EL0,
+	    READ_SPECIALREG(pmselr_el0));
+	hypctx_write_sys_reg(hypctx, PMXEVCNTR_EL0,
+	    READ_SPECIALREG(pmxevcntr_el0));
+	hypctx_write_sys_reg(hypctx, PMCNTENSET_EL0,
+	    READ_SPECIALREG(pmcntenset_el0));
+	hypctx_write_sys_reg(hypctx, PMINTENSET_EL1,
+	    READ_SPECIALREG(pmintenset_el1));
+	hypctx_write_sys_reg(hypctx, PMOVSSET_EL0,
+	    READ_SPECIALREG(pmovsset_el0));
+
+	switch ((hypctx_read_sys_reg(hypctx, PMCR_EL0) & PMCR_N_MASK) >>
+			PMCR_N_SHIFT) {
 #define	STORE_PMU(x)							\
 	case (x + 1):							\
-		hypctx->pmevcntr_el0[x] =				\
-		    READ_SPECIALREG(pmevcntr ## x ## _el0);		\
-		hypctx->pmevtyper_el0[x] =				\
-		    READ_SPECIALREG(pmevtyper ## x ## _el0)
+		hypctx_write_sys_reg(hypctx, PMEVCNTR_EL0(x),		\
+		    READ_SPECIALREG(pmevcntr ## x ## _el0));		\
+		hypctx_write_sys_reg(hypctx, PMEVTYPER_EL0(x),		\
+		    READ_SPECIALREG(pmevtyper ## x ## _el0))
 	STORE_PMU(30);
 	STORE_PMU(29);
 	STORE_PMU(28);
@@ -237,53 +248,53 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 	hypctx->tf.tf_spsr = READ_SPECIALREG(spsr_el2);
 	if (guest) {
 		hypctx->tf.tf_esr = READ_SPECIALREG(esr_el2);
-		hypctx->par_el1 = READ_SPECIALREG(par_el1);
+		hypctx_write_sys_reg(hypctx, PAR_EL1, READ_SPECIALREG(par_el1));
 	}
 
 	/* Store the guest special registers */
-	hypctx->sp_el0 = READ_SPECIALREG(sp_el0);
-	hypctx->tpidr_el0 = READ_SPECIALREG(tpidr_el0);
-	hypctx->tpidrro_el0 = READ_SPECIALREG(tpidrro_el0);
-	hypctx->tpidr_el1 = READ_SPECIALREG(tpidr_el1);
+	hypctx_write_sys_reg(hypctx, SP_EL0, READ_SPECIALREG(sp_el0));
+	hypctx_write_sys_reg(hypctx, TPIDR_EL0, READ_SPECIALREG(tpidr_el0));
+	hypctx_write_sys_reg(hypctx, TPIDRRO_EL0, READ_SPECIALREG(tpidrro_el0));
+	hypctx_write_sys_reg(hypctx, TPIDR_EL1, READ_SPECIALREG(tpidr_el1));
 
 	hypctx_write_sys_reg(hypctx, ACTLR_EL1, READ_SPECIALREG(actlr_el1));
-	hypctx->csselr_el1 = READ_SPECIALREG(csselr_el1);
-	hypctx->mdccint_el1 = READ_SPECIALREG(mdccint_el1);
+	hypctx_write_sys_reg(hypctx, CSSELR_EL1, READ_SPECIALREG(csselr_el1));
+	hypctx_write_sys_reg(hypctx, MDCCINT_EL1, READ_SPECIALREG(mdccint_el1));
 	hypctx_write_sys_reg(hypctx, MDSCR_EL1, READ_SPECIALREG(mdscr_el1));
 
 	if (guest_or_nonvhe(guest)) {
 		hypctx_write_sys_reg(hypctx, ELR_EL1,
-				     READ_SPECIALREG(EL1_REG(ELR)));
+		    READ_SPECIALREG(EL1_REG(ELR)));
 		hypctx_write_sys_reg(hypctx, VBAR_EL1,
-				     READ_SPECIALREG(EL1_REG(VBAR)));
+		    READ_SPECIALREG(EL1_REG(VBAR)));
 		hypctx_write_sys_reg(hypctx, AFSR0_EL1,
-				     READ_SPECIALREG(EL1_REG(AFSR0)));
+		    READ_SPECIALREG(EL1_REG(AFSR0)));
 		hypctx_write_sys_reg(hypctx, AFSR1_EL1,
-				     READ_SPECIALREG(EL1_REG(AFSR1)));
+		    READ_SPECIALREG(EL1_REG(AFSR1)));
 		hypctx_write_sys_reg(hypctx, AMAIR_EL1,
-				     READ_SPECIALREG(EL1_REG(AMAIR)));
+		    READ_SPECIALREG(EL1_REG(AMAIR)));
 		hypctx_write_sys_reg(hypctx, CONTEXTIDR_EL1,
-				     READ_SPECIALREG(EL1_REG(CONTEXTIDR)));
+		    READ_SPECIALREG(EL1_REG(CONTEXTIDR)));
 		hypctx_write_sys_reg(hypctx, CPACR_EL1,
-				     READ_SPECIALREG(EL1_REG(CPACR)));
+		    READ_SPECIALREG(EL1_REG(CPACR)));
 		hypctx_write_sys_reg(hypctx, ESR_EL1,
-				     READ_SPECIALREG(EL1_REG(ESR)));
+		    READ_SPECIALREG(EL1_REG(ESR)));
 		hypctx_write_sys_reg(hypctx, FAR_EL1,
-				     READ_SPECIALREG(EL1_REG(FAR)));
+		    READ_SPECIALREG(EL1_REG(FAR)));
 		hypctx_write_sys_reg(hypctx, MAIR_EL1,
-				     READ_SPECIALREG(EL1_REG(MAIR)));
+		    READ_SPECIALREG(EL1_REG(MAIR)));
 		hypctx_write_sys_reg(hypctx, SCTLR_EL1,
-				     READ_SPECIALREG(EL1_REG(SCTLR)));
+		    READ_SPECIALREG(EL1_REG(SCTLR)));
 		hypctx_write_sys_reg(hypctx, SPSR_EL1,
-				     READ_SPECIALREG(EL1_REG(SPSR)));
+		    READ_SPECIALREG(EL1_REG(SPSR)));
 		hypctx_write_sys_reg(hypctx, TCR_EL1,
-				     READ_SPECIALREG(EL1_REG(TCR)));
+		    READ_SPECIALREG(EL1_REG(TCR)));
 		/* TODO: Support when this is not res0 */
 		hypctx_write_sys_reg(hypctx, TCR2_EL1, 0);
 		hypctx_write_sys_reg(hypctx, TTBR0_EL1,
-				     READ_SPECIALREG(EL1_REG(TTBR0)));
+		    READ_SPECIALREG(EL1_REG(TTBR0)));
 		hypctx_write_sys_reg(hypctx, TTBR1_EL1,
-				     READ_SPECIALREG(EL1_REG(TTBR1)));
+		    READ_SPECIALREG(EL1_REG(TTBR1)));
 	}
 
 	hypctx->cptr_el2 = READ_SPECIALREG(cptr_el2);
@@ -329,52 +340,52 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 	}
 #endif
 
-	WRITE_SPECIALREG(sp_el0, hypctx->sp_el0);
-	WRITE_SPECIALREG(tpidr_el0, hypctx->tpidr_el0);
-	WRITE_SPECIALREG(tpidrro_el0, hypctx->tpidrro_el0);
-	WRITE_SPECIALREG(tpidr_el1, hypctx->tpidr_el1);
+	WRITE_SPECIALREG(sp_el0, hypctx_read_sys_reg(hypctx, SP_EL0));
+	WRITE_SPECIALREG(tpidr_el0, hypctx_read_sys_reg(hypctx, TPIDR_EL0));
+	WRITE_SPECIALREG(tpidrro_el0, hypctx_read_sys_reg(hypctx, TPIDRRO_EL0));
+	WRITE_SPECIALREG(tpidr_el1, hypctx_read_sys_reg(hypctx, TPIDR_EL1));
 
 	WRITE_SPECIALREG(actlr_el1, hypctx_read_sys_reg(hypctx, ACTLR_EL1));
-	WRITE_SPECIALREG(csselr_el1, hypctx->csselr_el1);
-	WRITE_SPECIALREG(mdccint_el1, hypctx->mdccint_el1);
+	WRITE_SPECIALREG(csselr_el1, hypctx_read_sys_reg(hypctx, CSSELR_EL1));
+	WRITE_SPECIALREG(mdccint_el1, hypctx_read_sys_reg(hypctx, MDCCINT_EL1));
 	WRITE_SPECIALREG(mdscr_el1, hypctx_read_sys_reg(hypctx, MDSCR_EL1));
 
 	if (guest_or_nonvhe(guest)) {
 		WRITE_SPECIALREG(EL1_REG(ELR),
-				 hypctx_read_sys_reg(hypctx, ELR_EL1));
+		    hypctx_read_sys_reg(hypctx, ELR_EL1));
 		WRITE_SPECIALREG(EL1_REG(VBAR),
-				 hypctx_read_sys_reg(hypctx, VBAR_EL1));
+		    hypctx_read_sys_reg(hypctx, VBAR_EL1));
 		WRITE_SPECIALREG(EL1_REG(AFSR0),
-				 hypctx_read_sys_reg(hypctx, AFSR0_EL1));
+		    hypctx_read_sys_reg(hypctx, AFSR0_EL1));
 		WRITE_SPECIALREG(EL1_REG(AFSR1),
-				 hypctx_read_sys_reg(hypctx, AFSR1_EL1));
+		    hypctx_read_sys_reg(hypctx, AFSR1_EL1));
 		WRITE_SPECIALREG(EL1_REG(AMAIR),
-				 hypctx_read_sys_reg(hypctx, AMAIR_EL1));
+		    hypctx_read_sys_reg(hypctx, AMAIR_EL1));
 		WRITE_SPECIALREG(EL1_REG(CONTEXTIDR),
-				 hypctx_read_sys_reg(hypctx, CONTEXTIDR_EL1));
+		    hypctx_read_sys_reg(hypctx, CONTEXTIDR_EL1));
 		WRITE_SPECIALREG(EL1_REG(CPACR),
-				 hypctx_read_sys_reg(hypctx, CPACR_EL1));
+		    hypctx_read_sys_reg(hypctx, CPACR_EL1));
 		WRITE_SPECIALREG(EL1_REG(ESR),
-				 hypctx_read_sys_reg(hypctx, ESR_EL1));
+		    hypctx_read_sys_reg(hypctx, ESR_EL1));
 		WRITE_SPECIALREG(EL1_REG(FAR),
-				 hypctx_read_sys_reg(hypctx, FAR_EL1));
+		    hypctx_read_sys_reg(hypctx, FAR_EL1));
 		WRITE_SPECIALREG(EL1_REG(MAIR),
-				 hypctx_read_sys_reg(hypctx, MAIR_EL1));
+		    hypctx_read_sys_reg(hypctx, MAIR_EL1));
 		WRITE_SPECIALREG(EL1_REG(SCTLR),
-				 hypctx_read_sys_reg(hypctx, SCTLR_EL1));
+		    hypctx_read_sys_reg(hypctx, SCTLR_EL1));
 		WRITE_SPECIALREG(EL1_REG(SPSR),
-				 hypctx_read_sys_reg(hypctx, SPSR_EL1));
+		    hypctx_read_sys_reg(hypctx, SPSR_EL1));
 		WRITE_SPECIALREG(EL1_REG(TCR),
-				 hypctx_read_sys_reg(hypctx, TCR_EL1));
+		    hypctx_read_sys_reg(hypctx, TCR_EL1));
 		/* TODO: tcr2_el1 */
 		WRITE_SPECIALREG(EL1_REG(TTBR0),
-				 hypctx_read_sys_reg(hypctx, TTBR0_EL1));
+		    hypctx_read_sys_reg(hypctx, TTBR0_EL1));
 		WRITE_SPECIALREG(EL1_REG(TTBR1),
-				 hypctx_read_sys_reg(hypctx, TTBR1_EL1));
+		    hypctx_read_sys_reg(hypctx, TTBR1_EL1));
 	}
 
 	if (guest) {
-		WRITE_SPECIALREG(par_el1, hypctx->par_el1);
+		WRITE_SPECIALREG(par_el1, hypctx_read_sys_reg(hypctx, PAR_EL1));
 	}
 
 	WRITE_SPECIALREG(cptr_el2, hypctx->cptr_el2);
@@ -387,27 +398,36 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 	WRITE_SPECIALREG(spsr_el2, hypctx->tf.tf_spsr);
 
 	/* Restore the PMU registers */
-	WRITE_SPECIALREG(pmcr_el0, hypctx->pmcr_el0);
-	WRITE_SPECIALREG(pmccntr_el0, hypctx->pmccntr_el0);
-	WRITE_SPECIALREG(pmccfiltr_el0, hypctx->pmccfiltr_el0);
-	WRITE_SPECIALREG(pmuserenr_el0, hypctx->pmuserenr_el0);
-	WRITE_SPECIALREG(pmselr_el0, hypctx->pmselr_el0);
-	WRITE_SPECIALREG(pmxevcntr_el0, hypctx->pmxevcntr_el0);
+	WRITE_SPECIALREG(pmcr_el0,
+	    hypctx_read_sys_reg(hypctx, PMCR_EL0));
+	WRITE_SPECIALREG(pmccntr_el0,
+	    hypctx_read_sys_reg(hypctx, PMCCNTR_EL0));
+	WRITE_SPECIALREG(pmccfiltr_el0,
+	    hypctx_read_sys_reg(hypctx, PMCCFILTR_EL0));
+	WRITE_SPECIALREG(pmuserenr_el0,
+	    hypctx_read_sys_reg(hypctx, PMUSERENR_EL0));
+	WRITE_SPECIALREG(pmselr_el0,
+	    hypctx_read_sys_reg(hypctx, PMSELR_EL0));
+	WRITE_SPECIALREG(pmxevcntr_el0,
+	    hypctx_read_sys_reg(hypctx, PMXEVCNTR_EL0));
 	/* Clear all events/interrupts then enable them */
 	WRITE_SPECIALREG(pmcntenclr_el0, ~0ul);
-	WRITE_SPECIALREG(pmcntenset_el0, hypctx->pmcntenset_el0);
+	WRITE_SPECIALREG(pmcntenset_el0,
+	    hypctx_read_sys_reg(hypctx, PMCNTENSET_EL0));
 	WRITE_SPECIALREG(pmintenclr_el1, ~0ul);
-	WRITE_SPECIALREG(pmintenset_el1, hypctx->pmintenset_el1);
+	WRITE_SPECIALREG(pmintenset_el1,
+	    hypctx_read_sys_reg(hypctx, PMINTENSET_EL1));
 	WRITE_SPECIALREG(pmovsclr_el0, ~0ul);
-	WRITE_SPECIALREG(pmovsset_el0, hypctx->pmovsset_el0);
+	WRITE_SPECIALREG(pmovsset_el0,
+	    hypctx_read_sys_reg(hypctx, PMOVSSET_EL0));
 
-	switch ((hypctx->pmcr_el0 & PMCR_N_MASK) >> PMCR_N_SHIFT) {
+	switch ((hypctx_read_sys_reg(hypctx, PMCR_EL0) & PMCR_N_MASK) >> PMCR_N_SHIFT) {
 #define	LOAD_PMU(x)							\
 	case (x + 1):							\
 		WRITE_SPECIALREG(pmevcntr ## x ## _el0,			\
-		    hypctx->pmevcntr_el0[x]);				\
+		    hypctx_read_sys_reg(hypctx, PMEVCNTR_EL0(x)));	\
 		WRITE_SPECIALREG(pmevtyper ## x ## _el0,		\
-		    hypctx->pmevtyper_el0[x])
+		    hypctx_read_sys_reg(hypctx, PMEVTYPER_EL0(x)))
 	LOAD_PMU(30);
 	LOAD_PMU(29);
 	LOAD_PMU(28);
@@ -445,16 +465,17 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 	}
 
 	WRITE_SPECIALREG(dbgclaimclr_el1, ~0ul);
-	WRITE_SPECIALREG(dbgclaimclr_el1, hypctx->dbgclaimset_el1);
+	WRITE_SPECIALREG(dbgclaimclr_el1,
+	    hypctx_read_sys_reg(hypctx, DBGCLAIMSET_EL1));
 
 	dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
 	switch (ID_AA64DFR0_BRPs_VAL(dfr0) - 1) {
 #define	LOAD_DBG_BRP(x)							\
 	case x:								\
 		WRITE_SPECIALREG(dbgbcr ## x ## _el1,			\
-		    hypctx->dbgbcr_el1[x]);				\
+		    hypctx_read_sys_reg(hypctx, DBGBCR_EL1(x)));	\
 		WRITE_SPECIALREG(dbgbvr ## x ## _el1,			\
-		    hypctx->dbgbvr_el1[x])
+		    hypctx_read_sys_reg(hypctx, DBGBVR_EL1(x)))
 	LOAD_DBG_BRP(15);
 	LOAD_DBG_BRP(14);
 	LOAD_DBG_BRP(13);
@@ -479,9 +500,9 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest,
 #define	LOAD_DBG_WRP(x)							\
 	case x:								\
 		WRITE_SPECIALREG(dbgwcr ## x ## _el1,			\
-		    hypctx->dbgwcr_el1[x]);				\
+		    hypctx_read_sys_reg(hypctx, DBGWCR_EL1(x)));	\
 		WRITE_SPECIALREG(dbgwvr ## x ## _el1,			\
-		    hypctx->dbgwvr_el1[x])
+		    hypctx_read_sys_reg(hypctx, DBGWVR_EL1(x)))
 	LOAD_DBG_WRP(15);
 	LOAD_DBG_WRP(14);
 	LOAD_DBG_WRP(13);
diff --git a/sys/arm64/vmm/vmm_reset.c b/sys/arm64/vmm/vmm_reset.c
index 4966de5c8fa5..1280fe64277a 100644
--- a/sys/arm64/vmm/vmm_reset.c
+++ b/sys/arm64/vmm/vmm_reset.c
@@ -55,10 +55,6 @@ reset_vm_el01_regs(void *vcpu)
 
 	set_arch_unknown(el2ctx->tf);
 
-	set_arch_unknown(el2ctx->csselr_el1);
-	set_arch_unknown(el2ctx->mdccint_el1);
-	set_arch_unknown(el2ctx->par_el1);
-
 	/*
 	 * Guest starts with:
 	 * ~SCTLR_M: MMU off
@@ -70,29 +66,9 @@ reset_vm_el01_regs(void *vcpu)
 	*hypctx_sys_reg(el2ctx, SCTLR_EL1) &= ~SCTLR_M & ~SCTLR_C & ~SCTLR_I;
 	*hypctx_sys_reg(el2ctx, SCTLR_EL1) |= SCTLR_CP15BEN;
 
-	set_arch_unknown(el2ctx->sp_el0);
-	set_arch_unknown(el2ctx->tpidr_el0);
-	set_arch_unknown(el2ctx->tpidr_el1);
-	set_arch_unknown(el2ctx->tpidrro_el0);
-
-	set_arch_unknown(el2ctx->dbgbcr_el1);
-	set_arch_unknown(el2ctx->dbgbvr_el1);
-	set_arch_unknown(el2ctx->dbgwcr_el1);
-	set_arch_unknown(el2ctx->dbgwvr_el1);
-
-	el2ctx->pmcr_el0 = READ_SPECIALREG(pmcr_el0) & PMCR_N_MASK;
-	/* PMCR_LC is unknown when AArch32 is supported or RES1 otherwise */
-	el2ctx->pmcr_el0 |= PMCR_LC;
-	set_arch_unknown(el2ctx->pmccntr_el0);
-	set_arch_unknown(el2ctx->pmccfiltr_el0);
-	set_arch_unknown(el2ctx->pmuserenr_el0);
-	set_arch_unknown(el2ctx->pmselr_el0);
-	set_arch_unknown(el2ctx->pmxevcntr_el0);
-	set_arch_unknown(el2ctx->pmcntenset_el0);
-	set_arch_unknown(el2ctx->pmintenset_el1);
-	set_arch_unknown(el2ctx->pmovsset_el0);
-	memset(el2ctx->pmevcntr_el0, 0, sizeof(el2ctx->pmevcntr_el0));
-	memset(el2ctx->pmevtyper_el0, 0, sizeof(el2ctx->pmevtyper_el0));
+	hypctx_write_sys_reg(el2ctx, PMCR_EL0,
+	    /* PMCR_LC is unknown when AArch32 is supported or RES1 otherwise */
+	    (READ_SPECIALREG(pmcr_el0) & PMCR_N_MASK) | PMCR_LC);
 }
 
 void
@@ -133,7 +109,7 @@ reset_vm_el2_regs(void *vcpu)
 	el2ctx->mdcr_el2 = MDCR_EL2_TDOSA | MDCR_EL2_TDRA | MDCR_EL2_TPMS |
 	    MDCR_EL2_TTRF;
 	/* PMCR_EL0.N is read from MDCR_EL2.HPMN */
-	el2ctx->mdcr_el2 |= (el2ctx->pmcr_el0 & PMCR_N_MASK) >> PMCR_N_SHIFT;
+	el2ctx->mdcr_el2 |= (hypctx_read_sys_reg(el2ctx, PMCR_EL0) & PMCR_N_MASK) >> PMCR_N_SHIFT;
 
 	el2ctx->vmpidr_el2 = VMPIDR_EL2_RES1;
 	/* The guest will detect a multi-core, single-threaded CPU */