git: a745cdc19b7f - main - arm64/vmm: Teach the vtimer about VHE

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

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

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

    arm64/vmm: Teach the vtimer about VHE
    
    Teach the virtual timer about the cnthctl_el2 field layout under VHE.
    As with non-VHE we need to trap the physical timer and not trap the
    virtual timer.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D46074
---
 sys/arm64/include/hypervisor.h |  4 ++++
 sys/arm64/vmm/io/vtimer.c      | 38 +++++++++++++++++++++++++++++++++-----
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/sys/arm64/include/hypervisor.h b/sys/arm64/include/hypervisor.h
index 011f86e83fdf..4c501e2722a9 100644
--- a/sys/arm64/include/hypervisor.h
+++ b/sys/arm64/include/hypervisor.h
@@ -41,6 +41,10 @@
 #define	CNTHCTL_EL1PCTEN	(1 << 0) /* Allow physical counter access */
 #define	CNTHCTL_EL1PCEN		(1 << 1) /* Allow physical timer access */
 /* Valid if HCR_EL2.E2H == 1 */
+#define	CNTHCTL_E2H_EL0PCTEN	(1 << 0) /* Allow EL0 physical counter access */
+#define	CNTHCTL_E2H_EL0VCTEN	(1 << 1) /* Allow EL0 virtual counter access */
+#define	CNTHCTL_E2H_EL0VTEN	(1 << 8)
+#define	CNTHCTL_E2H_EL0PTEN	(1 << 9)
 #define	CNTHCTL_E2H_EL1PCTEN	(1 << 10) /* Allow physical counter access */
 #define	CNTHCTL_E2H_EL1PTEN	(1 << 11) /* Allow physical timer access */
 /* Unconditionally valid */
diff --git a/sys/arm64/vmm/io/vtimer.c b/sys/arm64/vmm/io/vtimer.c
index aa0b3ff1588e..f59d7ebc1ad4 100644
--- a/sys/arm64/vmm/io/vtimer.c
+++ b/sys/arm64/vmm/io/vtimer.c
@@ -129,14 +129,42 @@ vtimer_vminit(struct hyp *hyp)
 {
 	uint64_t now;
 
+	hyp->vtimer.cnthctl_el2 = cnthctl_el2_reg;
+
 	/*
 	 * Configure the Counter-timer Hypervisor Control Register for the VM.
-	 *
-	 * CNTHCTL_EL1PCEN: trap access to CNTP_{CTL, CVAL, TVAL}_EL0 from EL1
-	 * CNTHCTL_EL1PCTEN: trap access to CNTPCT_EL0
 	 */
-	hyp->vtimer.cnthctl_el2 = cnthctl_el2_reg & ~CNTHCTL_EL1PCEN;
-	hyp->vtimer.cnthctl_el2 &= ~CNTHCTL_EL1PCTEN;
+	if (in_vhe()) {
+		/*
+		 * CNTHCTL_E2H_EL0PCTEN: trap EL0 access to CNTP{CT,CTSS}_EL0
+		 * CNTHCTL_E2H_EL1VCTEN: don't trap EL0 access to
+		 *                       CNTV{CT,CTSS}_EL0
+		 * CNTHCTL_E2H_EL0VTEN: don't trap EL0 access to
+		 *                      CNTV_{CTL,CVAL,TVAL}_EL0
+		 * CNTHCTL_E2H_EL0PTEN: trap EL0 access to
+		 *                      CNTP_{CTL,CVAL,TVAL}_EL0
+		 * CNTHCTL_E2H_EL1PCEN: trap EL1 access to
+		                        CNTP_{CTL,CVAL,TVAL}_EL0
+		 * CNTHCTL_E2H_EL1PCTEN: trap access to CNTPCT_EL0
+		 *
+		 * TODO: Don't trap when FEAT_ECV is present
+		 */
+		hyp->vtimer.cnthctl_el2 &= ~CNTHCTL_E2H_EL0PCTEN;
+		hyp->vtimer.cnthctl_el2 |= CNTHCTL_E2H_EL0VCTEN;
+		hyp->vtimer.cnthctl_el2 |= CNTHCTL_E2H_EL0VTEN;
+		hyp->vtimer.cnthctl_el2 &= ~CNTHCTL_E2H_EL0PTEN;
+
+		hyp->vtimer.cnthctl_el2 &= ~CNTHCTL_E2H_EL1PTEN;
+		hyp->vtimer.cnthctl_el2 &= ~CNTHCTL_E2H_EL1PCTEN;
+	} else {
+		/*
+		 * CNTHCTL_EL1PCEN: trap access to CNTP_{CTL, CVAL, TVAL}_EL0
+		 *                  from EL1
+		 * CNTHCTL_EL1PCTEN: trap access to CNTPCT_EL0
+		 */
+		hyp->vtimer.cnthctl_el2 &= ~CNTHCTL_EL1PCEN;
+		hyp->vtimer.cnthctl_el2 &= ~CNTHCTL_EL1PCTEN;
+	}
 
 	now = READ_SPECIALREG(cntpct_el0);
 	hyp->vtimer.cntvoff_el2 = now;