git: 7861ecd18b6f - main - arm64/vmm: Teach the switcher about new registers

From: Andrew Turner <andrew_at_FreeBSD.org>
Date: Tue, 20 Aug 2024 09:02:20 UTC
The branch main has been updated by andrew:

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

commit 7861ecd18b6f15cfe37fc6f51f6ba89b92398648
Author:     Andrew Turner <andrew@FreeBSD.org>
AuthorDate: 2024-08-19 12:43:59 +0000
Commit:     Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2024-08-20 08:49:15 +0000

    arm64/vmm: Teach the switcher about new registers
    
    To support booting the kernel in EL2 some of the EL0 and EL1 registers
    are changed to point to an EL2 version. To get access to the EL0/EL1
    version of these registers we need to use the new EL02 and EL12
    registers, e.g. to access elr_el1 from the host we would use elr_el12.
    
    Add macros that can be different on VHE vs non-VHE code so these
    registers can be accessed in the correct way.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D46078
---
 sys/arm64/vmm/vmm_hyp.c  | 89 +++++++++++++++++++++++++++---------------------
 sys/arm64/vmm/vmm_nvhe.c |  4 +++
 2 files changed, 54 insertions(+), 39 deletions(-)

diff --git a/sys/arm64/vmm/vmm_hyp.c b/sys/arm64/vmm/vmm_hyp.c
index 9341f42daef6..ae0c46331382 100644
--- a/sys/arm64/vmm/vmm_hyp.c
+++ b/sys/arm64/vmm/vmm_hyp.c
@@ -49,11 +49,12 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest)
 	/* Store the guest VFP registers */
 	if (guest) {
 		/* Store the timer registers */
-		hypctx->vtimer_cpu.cntkctl_el1 = READ_SPECIALREG(cntkctl_el1);
+		hypctx->vtimer_cpu.cntkctl_el1 =
+		    READ_SPECIALREG(EL1_REG(CNTKCTL));
 		hypctx->vtimer_cpu.virt_timer.cntx_cval_el0 =
-		    READ_SPECIALREG(cntv_cval_el0);
+		    READ_SPECIALREG(EL0_REG(CNTV_CVAL));
 		hypctx->vtimer_cpu.virt_timer.cntx_ctl_el0 =
-		    READ_SPECIALREG(cntv_ctl_el0);
+		    READ_SPECIALREG(EL0_REG(CNTV_CTL));
 
 		/* Store the GICv3 registers */
 		hypctx->vgic_v3_regs.ich_eisr_el2 =
@@ -222,33 +223,37 @@ vmm_hyp_reg_store(struct hypctx *hypctx, struct hyp *hyp, bool guest)
 	}
 
 	/* Store the guest special registers */
-	hypctx->elr_el1 = READ_SPECIALREG(elr_el1);
 	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->vbar_el1 = READ_SPECIALREG(vbar_el1);
 
 	hypctx->actlr_el1 = READ_SPECIALREG(actlr_el1);
-	hypctx->afsr0_el1 = READ_SPECIALREG(afsr0_el1);
-	hypctx->afsr1_el1 = READ_SPECIALREG(afsr1_el1);
-	hypctx->amair_el1 = READ_SPECIALREG(amair_el1);
-	hypctx->contextidr_el1 = READ_SPECIALREG(contextidr_el1);
-	hypctx->cpacr_el1 = READ_SPECIALREG(cpacr_el1);
 	hypctx->csselr_el1 = READ_SPECIALREG(csselr_el1);
-	hypctx->esr_el1 = READ_SPECIALREG(esr_el1);
-	hypctx->far_el1 = READ_SPECIALREG(far_el1);
-	hypctx->mair_el1 = READ_SPECIALREG(mair_el1);
 	hypctx->mdccint_el1 = READ_SPECIALREG(mdccint_el1);
 	hypctx->mdscr_el1 = READ_SPECIALREG(mdscr_el1);
 	hypctx->par_el1 = READ_SPECIALREG(par_el1);
-	hypctx->sctlr_el1 = READ_SPECIALREG(sctlr_el1);
-	hypctx->spsr_el1 = READ_SPECIALREG(spsr_el1);
-	hypctx->tcr_el1 = READ_SPECIALREG(tcr_el1);
-	/* TODO: Support when this is not res0 */
-	hypctx->tcr2_el1 = 0;
-	hypctx->ttbr0_el1 = READ_SPECIALREG(ttbr0_el1);
-	hypctx->ttbr1_el1 = READ_SPECIALREG(ttbr1_el1);
+
+	if (guest_or_nonvhe(guest)) {
+		hypctx->elr_el1 = READ_SPECIALREG(EL1_REG(ELR));
+		hypctx->vbar_el1 = READ_SPECIALREG(EL1_REG(VBAR));
+
+		hypctx->afsr0_el1 = READ_SPECIALREG(EL1_REG(AFSR0));
+		hypctx->afsr1_el1 = READ_SPECIALREG(EL1_REG(AFSR1));
+		hypctx->amair_el1 = READ_SPECIALREG(EL1_REG(AMAIR));
+		hypctx->contextidr_el1 = READ_SPECIALREG(EL1_REG(CONTEXTIDR));
+		hypctx->cpacr_el1 = READ_SPECIALREG(EL1_REG(CPACR));
+		hypctx->esr_el1 = READ_SPECIALREG(EL1_REG(ESR));
+		hypctx->far_el1 = READ_SPECIALREG(EL1_REG(FAR));
+		hypctx->mair_el1 = READ_SPECIALREG(EL1_REG(MAIR));
+		hypctx->sctlr_el1 = READ_SPECIALREG(EL1_REG(SCTLR));
+		hypctx->spsr_el1 = READ_SPECIALREG(EL1_REG(SPSR));
+		hypctx->tcr_el1 = READ_SPECIALREG(EL1_REG(TCR));
+		/* TODO: Support when this is not res0 */
+		hypctx->tcr2_el1 = 0;
+		hypctx->ttbr0_el1 = READ_SPECIALREG(EL1_REG(TTBR0));
+		hypctx->ttbr1_el1 = READ_SPECIALREG(EL1_REG(TTBR1));
+	}
 
 	hypctx->cptr_el2 = READ_SPECIALREG(cptr_el2);
 	hypctx->hcr_el2 = READ_SPECIALREG(hcr_el2);
@@ -265,32 +270,37 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest)
 	WRITE_SPECIALREG(hcr_el2, hypctx->hcr_el2);
 	isb();
 
-	WRITE_SPECIALREG(elr_el1, hypctx->elr_el1);
 	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(vbar_el1, hypctx->vbar_el1);
 
 	WRITE_SPECIALREG(actlr_el1, hypctx->actlr_el1);
-	WRITE_SPECIALREG(afsr0_el1, hypctx->afsr0_el1);
-	WRITE_SPECIALREG(afsr1_el1, hypctx->afsr1_el1);
-	WRITE_SPECIALREG(amair_el1, hypctx->amair_el1);
-	WRITE_SPECIALREG(contextidr_el1, hypctx->contextidr_el1);
-	WRITE_SPECIALREG(cpacr_el1, hypctx->cpacr_el1);
 	WRITE_SPECIALREG(csselr_el1, hypctx->csselr_el1);
-	WRITE_SPECIALREG(esr_el1, hypctx->esr_el1);
-	WRITE_SPECIALREG(far_el1, hypctx->far_el1);
 	WRITE_SPECIALREG(mdccint_el1, hypctx->mdccint_el1);
 	WRITE_SPECIALREG(mdscr_el1, hypctx->mdscr_el1);
-	WRITE_SPECIALREG(mair_el1, hypctx->mair_el1);
 	WRITE_SPECIALREG(par_el1, hypctx->par_el1);
-	WRITE_SPECIALREG(sctlr_el1, hypctx->sctlr_el1);
-	WRITE_SPECIALREG(tcr_el1, hypctx->tcr_el1);
-	/* TODO: tcr2_el1 */
-	WRITE_SPECIALREG(ttbr0_el1, hypctx->ttbr0_el1);
-	WRITE_SPECIALREG(ttbr1_el1, hypctx->ttbr1_el1);
-	WRITE_SPECIALREG(spsr_el1, hypctx->spsr_el1);
+
+	if (guest_or_nonvhe(guest)) {
+		WRITE_SPECIALREG(EL1_REG(ELR), hypctx->elr_el1);
+		WRITE_SPECIALREG(EL1_REG(VBAR), hypctx->vbar_el1);
+
+		WRITE_SPECIALREG(EL1_REG(AFSR0), hypctx->afsr0_el1);
+		WRITE_SPECIALREG(EL1_REG(AFSR1), hypctx->afsr1_el1);
+		WRITE_SPECIALREG(EL1_REG(AMAIR), hypctx->amair_el1);
+		WRITE_SPECIALREG(EL1_REG(CONTEXTIDR), hypctx->contextidr_el1);
+		WRITE_SPECIALREG(EL1_REG(CPACR), hypctx->cpacr_el1);
+		WRITE_SPECIALREG(EL1_REG(ESR), hypctx->esr_el1);
+		WRITE_SPECIALREG(EL1_REG(FAR), hypctx->far_el1);
+		WRITE_SPECIALREG(EL1_REG(MAIR), hypctx->mair_el1); //
+
+		WRITE_SPECIALREG(EL1_REG(SCTLR), hypctx->sctlr_el1);
+		WRITE_SPECIALREG(EL1_REG(SPSR), hypctx->spsr_el1);
+		WRITE_SPECIALREG(EL1_REG(TCR), hypctx->tcr_el1);
+		/* TODO: tcr2_el1 */
+		WRITE_SPECIALREG(EL1_REG(TTBR0), hypctx->ttbr0_el1);
+		WRITE_SPECIALREG(EL1_REG(TTBR1), hypctx->ttbr1_el1);
+	}
 
 	WRITE_SPECIALREG(cptr_el2, hypctx->cptr_el2);
 	WRITE_SPECIALREG(vpidr_el2, hypctx->vpidr_el2);
@@ -413,10 +423,11 @@ vmm_hyp_reg_restore(struct hypctx *hypctx, struct hyp *hyp, bool guest)
 
 	if (guest) {
 		/* Load the timer registers */
-		WRITE_SPECIALREG(cntkctl_el1, hypctx->vtimer_cpu.cntkctl_el1);
-		WRITE_SPECIALREG(cntv_cval_el0,
+		WRITE_SPECIALREG(EL1_REG(CNTKCTL),
+		    hypctx->vtimer_cpu.cntkctl_el1);
+		WRITE_SPECIALREG(EL0_REG(CNTV_CVAL),
 		    hypctx->vtimer_cpu.virt_timer.cntx_cval_el0);
-		WRITE_SPECIALREG(cntv_ctl_el0,
+		WRITE_SPECIALREG(EL0_REG(CNTV_CTL),
 		    hypctx->vtimer_cpu.virt_timer.cntx_ctl_el0);
 		WRITE_SPECIALREG(cnthctl_el2, hyp->vtimer.cnthctl_el2);
 		WRITE_SPECIALREG(cntvoff_el2, hyp->vtimer.cntvoff_el2);
diff --git a/sys/arm64/vmm/vmm_nvhe.c b/sys/arm64/vmm/vmm_nvhe.c
index 1127a6e37781..025b1308ce68 100644
--- a/sys/arm64/vmm/vmm_nvhe.c
+++ b/sys/arm64/vmm/vmm_nvhe.c
@@ -32,6 +32,10 @@
 #define	VMM_STATIC	static
 #define	VMM_HYP_FUNC(func)	vmm_nvhe_ ## func
 
+#define	guest_or_nonvhe(guest)	(true)
+#define	EL1_REG(reg)		MRS_REG_ALT_NAME(reg ## _EL1)
+#define	EL0_REG(reg)		MRS_REG_ALT_NAME(reg ## _EL0)
+
 #include "vmm_hyp.c"
 
 uint64_t vmm_hyp_enter(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,