The branch main has been updated by andrew:

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

commit f4c3458ab3ce52ba9b234bee7711d0cb9a0745ac
Author:     Kajetan Puchalski <[email protected]>
AuthorDate: 2026-07-06 14:17:58 +0000
Commit:     Andrew Turner <[email protected]>
CommitDate: 2026-07-06 15:18:30 +0000

    arm64/vmm: Move vttbr_el2 & vtimer into struct hypctx
    
    Move vttbr_el2 & vtimer from struct hyp into struct hypctx to streamline
    the logic and handle them in the same way as other *_el2 registers are
    already being handled.
    
    Signed-off-by:  Kajetan Puchalski <[email protected]>
    Reviewed by:    andrew
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D56554
---
 sys/arm64/vmm/arm64.h     |  6 ++-
 sys/arm64/vmm/io/vtimer.c | 99 ++++++++++++++++++++---------------------------
 sys/arm64/vmm/io/vtimer.h |  1 -
 sys/arm64/vmm/vmm_arm64.c |  4 +-
 sys/arm64/vmm/vmm_hyp.c   | 21 +++++-----
 5 files changed, 56 insertions(+), 75 deletions(-)

diff --git a/sys/arm64/vmm/arm64.h b/sys/arm64/vmm/arm64.h
index 2b69f86da321..c43034454808 100644
--- a/sys/arm64/vmm/arm64.h
+++ b/sys/arm64/vmm/arm64.h
@@ -229,6 +229,8 @@ struct hypctx {
        uint64_t        hfgrtr2_el2;
        uint64_t        hfgwtr2_el2;
 
+       uint64_t        vttbr_el2;
+
        /* Storage for *host* timer registers */
        struct {
                uint64_t cnthctl_el2;
@@ -242,6 +244,7 @@ struct hypctx {
                uint64_t        hpfar_el2;      /* Hypervisor IPA Fault Address 
Register */
        } exit_info;
 
+       struct vtimer   vtimer;
        struct vtimer_cpu       vtimer_cpu;
 
        uint64_t                setcaps;        /* Currently enabled 
capabilities. */
@@ -307,9 +310,8 @@ hypctx_read_sys_reg(struct hypctx *hypctx, enum 
hypctx_sysreg reg)
 
 struct hyp {
        struct vm       *vm;
-       struct vtimer   vtimer;
        uint64_t        vmid_generation;
-       uint64_t        vttbr_el2;
+       uint64_t        cntvoff_el2;    /* VM-wide virtual timer offset */
        uint64_t        el2_addr;       /* The address of this in el2 space */
        uint64_t        feats;          /* Which features are enabled */
 #define        HYP_FEAT_HCX            (0x1ul << 0)
diff --git a/sys/arm64/vmm/io/vtimer.c b/sys/arm64/vmm/io/vtimer.c
index d1c489463882..ff29a06751e0 100644
--- a/sys/arm64/vmm/io/vtimer.c
+++ b/sys/arm64/vmm/io/vtimer.c
@@ -97,7 +97,7 @@ vtimer_virtual_timer_intr(void *arg)
        }
 
        cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
-           hypctx->hyp->vtimer.cntvoff_el2;
+           hypctx->vtimer.cntvoff_el2;
        if (hypctx->vtimer_cpu.virt_timer.cntx_cval_el0 < cntpct_el0)
                vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu),
                    GT_VIRT_IRQ, true);
@@ -133,14 +133,35 @@ vtimer_init(void)
 }
 
 void
-vtimer_vminit(struct hyp *hyp)
+vtimer_cpuinit(struct hypctx *hypctx)
 {
-       uint64_t now;
+       struct vtimer_cpu *vtimer_cpu;
        bool ecv_poff;
 
+       vtimer_cpu = &hypctx->vtimer_cpu;
+       /*
+        * Configure physical timer interrupts for the VCPU.
+        *
+        * CNTP_CTL_IMASK: mask interrupts
+        * ~CNTP_CTL_ENABLE: disable the timer
+        */
+       vtimer_cpu->phys_timer.cntx_ctl_el0 = CNTP_CTL_IMASK & ~CNTP_CTL_ENABLE;
+
+       mtx_init(&vtimer_cpu->phys_timer.mtx, "vtimer phys callout mutex", NULL,
+           MTX_DEF);
+       callout_init_mtx(&vtimer_cpu->phys_timer.callout,
+           &vtimer_cpu->phys_timer.mtx, 0);
+       vtimer_cpu->phys_timer.irqid = GT_PHYS_NS_IRQ;
+
+       mtx_init(&vtimer_cpu->virt_timer.mtx, "vtimer virt callout mutex", NULL,
+           MTX_DEF);
+       callout_init_mtx(&vtimer_cpu->virt_timer.callout,
+           &vtimer_cpu->virt_timer.mtx, 0);
+       vtimer_cpu->virt_timer.irqid = GT_VIRT_IRQ;
+
        ecv_poff = false;
 
-       if (allow_ecv_phys && (hyp->feats & HYP_FEAT_ECV_POFF) != 0)
+       if (allow_ecv_phys && (hypctx->hyp->feats & HYP_FEAT_ECV_POFF) != 0)
                ecv_poff = true;
 
        /*
@@ -165,17 +186,17 @@ vtimer_vminit(struct hyp *hyp)
                 *
                 * TODO: Don't trap when FEAT_ECV is present
                 */
-               hyp->vtimer.cnthctl_el2 =
+               hypctx->vtimer.cnthctl_el2 =
                    CNTHCTL_E2H_EL0VCTEN_NOTRAP |
                    CNTHCTL_E2H_EL0VTEN_NOTRAP;
                if (ecv_poff) {
-                       hyp->vtimer.cnthctl_el2 |=
+                       hypctx->vtimer.cnthctl_el2 |=
                            CNTHCTL_E2H_EL0PCTEN_NOTRAP |
                            CNTHCTL_E2H_EL0PTEN_NOTRAP |
                            CNTHCTL_E2H_EL1PCTEN_NOTRAP |
                            CNTHCTL_E2H_EL1PTEN_NOTRAP;
                } else {
-                       hyp->vtimer.cnthctl_el2 |=
+                       hypctx->vtimer.cnthctl_el2 |=
                            CNTHCTL_E2H_EL0PCTEN_TRAP |
                            CNTHCTL_E2H_EL0PTEN_TRAP |
                            CNTHCTL_E2H_EL1PCTEN_TRAP |
@@ -188,50 +209,20 @@ vtimer_vminit(struct hyp *hyp)
                 * CNTHCTL_EL1PCTEN: trap access to CNTPCT_EL0
                 */
                if (ecv_poff) {
-                       hyp->vtimer.cnthctl_el2 =
+                       hypctx->vtimer.cnthctl_el2 =
                            CNTHCTL_EL1PCTEN_NOTRAP |
                            CNTHCTL_EL1PCEN_NOTRAP;
                } else {
-                       hyp->vtimer.cnthctl_el2 =
+                       hypctx->vtimer.cnthctl_el2 =
                            CNTHCTL_EL1PCTEN_TRAP |
                            CNTHCTL_EL1PCEN_TRAP;
                }
        }
 
        if (ecv_poff)
-               hyp->vtimer.cnthctl_el2 |= CNTHCTL_ECV_EN;
-
-       now = READ_SPECIALREG(cntpct_el0);
-       hyp->vtimer.cntvoff_el2 = now;
+               hypctx->vtimer.cnthctl_el2 |= CNTHCTL_ECV_EN;
 
-       return;
-}
-
-void
-vtimer_cpuinit(struct hypctx *hypctx)
-{
-       struct vtimer_cpu *vtimer_cpu;
-
-       vtimer_cpu = &hypctx->vtimer_cpu;
-       /*
-        * Configure physical timer interrupts for the VCPU.
-        *
-        * CNTP_CTL_IMASK: mask interrupts
-        * ~CNTP_CTL_ENABLE: disable the timer
-        */
-       vtimer_cpu->phys_timer.cntx_ctl_el0 = CNTP_CTL_IMASK & ~CNTP_CTL_ENABLE;
-
-       mtx_init(&vtimer_cpu->phys_timer.mtx, "vtimer phys callout mutex", NULL,
-           MTX_DEF);
-       callout_init_mtx(&vtimer_cpu->phys_timer.callout,
-           &vtimer_cpu->phys_timer.mtx, 0);
-       vtimer_cpu->phys_timer.irqid = GT_PHYS_NS_IRQ;
-
-       mtx_init(&vtimer_cpu->virt_timer.mtx, "vtimer virt callout mutex", NULL,
-           MTX_DEF);
-       callout_init_mtx(&vtimer_cpu->virt_timer.callout,
-           &vtimer_cpu->virt_timer.mtx, 0);
-       vtimer_cpu->virt_timer.irqid = GT_VIRT_IRQ;
+       hypctx->vtimer.cntvoff_el2 = hypctx->hyp->cntvoff_el2;
 }
 
 void
@@ -289,10 +280,10 @@ vtimer_sync_hwstate(struct hypctx *hypctx)
        uint64_t cntpct_el0;
 
        cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
-           hypctx->hyp->vtimer.cntvoff_el2;
+           hypctx->vtimer.cntvoff_el2;
        vtime_sync_timer(hypctx, &hypctx->vtimer_cpu.virt_timer, cntpct_el0);
        /* If FEAT_ECV_POFF is in use then we need to sync the physical timer */
-       if ((hypctx->hyp->vtimer.cnthctl_el2 & CNTHCTL_ECV_EN) != 0) {
+       if ((hypctx->vtimer.cnthctl_el2 & CNTHCTL_ECV_EN) != 0) {
                vtime_sync_timer(hypctx, &hypctx->vtimer_cpu.phys_timer,
                    cntpct_el0);
        }
@@ -331,7 +322,7 @@ vtimer_schedule_irq(struct hypctx *hypctx, bool phys)
        else
                timer = &hypctx->vtimer_cpu.virt_timer;
        cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
-           hypctx->hyp->vtimer.cntvoff_el2;
+           hypctx->vtimer.cntvoff_el2;
        if (timer->cntx_cval_el0 < cntpct_el0) {
                /* Timer set in the past, trigger interrupt */
                vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu),
@@ -381,16 +372,14 @@ vtimer_remove_irq(struct hypctx *hypctx, struct vcpu 
*vcpu)
 int
 vtimer_phys_ctl_read(struct vcpu *vcpu, uint64_t *rval, void *arg)
 {
-       struct hyp *hyp;
        struct hypctx *hypctx;
        struct vtimer_cpu *vtimer_cpu;
        uint64_t cntpct_el0;
 
        hypctx = vcpu_get_cookie(vcpu);
-       hyp = hypctx->hyp;
        vtimer_cpu = &hypctx->vtimer_cpu;
 
-       cntpct_el0 = READ_SPECIALREG(cntpct_el0) - hyp->vtimer.cntvoff_el2;
+       cntpct_el0 = READ_SPECIALREG(cntpct_el0) - hypctx->vtimer.cntvoff_el2;
        if (vtimer_cpu->phys_timer.cntx_cval_el0 < cntpct_el0)
                /* Timer condition met */
                *rval = vtimer_cpu->phys_timer.cntx_ctl_el0 | CNTP_CTL_ISTATUS;
@@ -430,12 +419,10 @@ vtimer_phys_ctl_write(struct vcpu *vcpu, uint64_t wval, 
void *arg)
 int
 vtimer_phys_cnt_read(struct vcpu *vcpu, uint64_t *rval, void *arg)
 {
-       struct vm *vm;
-       struct hyp *hyp;
+       struct hypctx *hypctx;
 
-       vm = vcpu_vm(vcpu);
-       hyp = vm_get_cookie(vm);
-       *rval = READ_SPECIALREG(cntpct_el0) - hyp->vtimer.cntvoff_el2;
+       hypctx = vcpu_get_cookie(vcpu);
+       *rval = READ_SPECIALREG(cntpct_el0) - hypctx->vtimer.cntvoff_el2;
        return (0);
 }
 
@@ -481,13 +468,11 @@ vtimer_phys_cval_write(struct vcpu *vcpu, uint64_t wval, 
void *arg)
 int
 vtimer_phys_tval_read(struct vcpu *vcpu, uint64_t *rval, void *arg)
 {
-       struct hyp *hyp;
        struct hypctx *hypctx;
        struct vtimer_cpu *vtimer_cpu;
        uint32_t cntpct_el0;
 
        hypctx = vcpu_get_cookie(vcpu);
-       hyp = hypctx->hyp;
        vtimer_cpu = &hypctx->vtimer_cpu;
 
        if (!(vtimer_cpu->phys_timer.cntx_ctl_el0 & CNTP_CTL_ENABLE)) {
@@ -500,7 +485,7 @@ vtimer_phys_tval_read(struct vcpu *vcpu, uint64_t *rval, 
void *arg)
                *rval = (uint32_t)RES1;
        } else {
                cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
-                   hyp->vtimer.cntvoff_el2;
+                   hypctx->vtimer.cntvoff_el2;
                *rval = vtimer_cpu->phys_timer.cntx_cval_el0 - cntpct_el0;
        }
 
@@ -510,16 +495,14 @@ vtimer_phys_tval_read(struct vcpu *vcpu, uint64_t *rval, 
void *arg)
 int
 vtimer_phys_tval_write(struct vcpu *vcpu, uint64_t wval, void *arg)
 {
-       struct hyp *hyp;
        struct hypctx *hypctx;
        struct vtimer_cpu *vtimer_cpu;
        uint64_t cntpct_el0;
 
        hypctx = vcpu_get_cookie(vcpu);
-       hyp = hypctx->hyp;
        vtimer_cpu = &hypctx->vtimer_cpu;
 
-       cntpct_el0 = READ_SPECIALREG(cntpct_el0) - hyp->vtimer.cntvoff_el2;
+       cntpct_el0 = READ_SPECIALREG(cntpct_el0) - hypctx->vtimer.cntvoff_el2;
        vtimer_cpu->phys_timer.cntx_cval_el0 = (int32_t)wval + cntpct_el0;
 
        vtimer_remove_irq(hypctx, vcpu);
diff --git a/sys/arm64/vmm/io/vtimer.h b/sys/arm64/vmm/io/vtimer.h
index 92ce025968d2..d415afa47acc 100644
--- a/sys/arm64/vmm/io/vtimer.h
+++ b/sys/arm64/vmm/io/vtimer.h
@@ -67,7 +67,6 @@ struct vtimer_cpu {
 };
 
 int    vtimer_init(void);
-void   vtimer_vminit(struct hyp *);
 void   vtimer_cpuinit(struct hypctx *);
 void   vtimer_cpucleanup(struct hypctx *);
 void   vtimer_vmcleanup(struct hyp *);
diff --git a/sys/arm64/vmm/vmm_arm64.c b/sys/arm64/vmm/vmm_arm64.c
index 3615d2da66cc..43f45dc596c9 100644
--- a/sys/arm64/vmm/vmm_arm64.c
+++ b/sys/arm64/vmm/vmm_arm64.c
@@ -542,7 +542,7 @@ vmmops_init(struct vm *vm, pmap_t pmap)
        if (ID_AA64MMFR1_HCX_VAL(idreg) >= ID_AA64MMFR1_HCX_IMPL)
                hyp->feats |= HYP_FEAT_HCX;
 
-       vtimer_vminit(hyp);
+       hyp->cntvoff_el2 = READ_SPECIALREG(cntpct_el0);
        vgic_vminit(hyp);
 
        if (!in_vhe())
@@ -1170,7 +1170,7 @@ vmmops_run(void *vcpui, register_t pc, pmap_t pmap, 
struct vm_eventinfo *evinfo)
 
                /* Activate the stage2 pmap so the vmid is valid */
                pmap_activate_vm(pmap);
-               hyp->vttbr_el2 = pmap_to_ttbr0(pmap);
+               hypctx->vttbr_el2 = pmap_to_ttbr0(pmap);
 
                /*
                 * TODO: What happens if a timer interrupt is asserted exactly
diff --git a/sys/arm64/vmm/vmm_hyp.c b/sys/arm64/vmm/vmm_hyp.c
index 25b04d14dca8..070142199c44 100644
--- a/sys/arm64/vmm/vmm_hyp.c
+++ b/sys/arm64/vmm/vmm_hyp.c
@@ -241,13 +241,13 @@ vmm_hyp_reg_store_timer(struct hypctx *hypctx, struct hyp 
*hyp, bool guest)
        } else {
                hypctx->vtimer_cpu.cntkctl_el1 =
                    READ_SPECIALREG(cntkctl_el1);
-               hypctx->host_timer_regs.cnthctl_el2 =
+               hypctx->vtimer.cnthctl_el2 =
                    READ_SPECIALREG(cnthctl_el2);
-               hypctx->host_timer_regs.cntvoff_el2 =
+               hypctx->vtimer.cntvoff_el2 =
                    READ_SPECIALREG(cntvoff_el2);
        }
 
-       ecv_poff = (hyp->vtimer.cnthctl_el2 & CNTHCTL_ECV_EN) != 0;
+       ecv_poff = (hypctx->vtimer.cnthctl_el2 & CNTHCTL_ECV_EN) != 0;
 
        if (guest_or_nonvhe(guest) && ecv_poff) {
                /*
@@ -565,11 +565,12 @@ static void
 vmm_hyp_reg_restore_timer(struct hypctx *hypctx, struct hyp *hyp, bool guest)
 {
        bool ecv_poff;
-       ecv_poff = (hyp->vtimer.cnthctl_el2 & CNTHCTL_ECV_EN) != 0;
+       ecv_poff = (hypctx->vtimer.cnthctl_el2 & CNTHCTL_ECV_EN) != 0;
+
+       WRITE_SPECIALREG(cnthctl_el2, hypctx->vtimer.cnthctl_el2);
+       WRITE_SPECIALREG(cntvoff_el2, hypctx->vtimer.cntvoff_el2);
 
        if (guest) {
-               WRITE_SPECIALREG(cnthctl_el2, hyp->vtimer.cnthctl_el2);
-               WRITE_SPECIALREG(cntvoff_el2, hyp->vtimer.cntvoff_el2);
                WRITE_SPECIALREG(EL1_REG(CNTKCTL),
                    hypctx->vtimer_cpu.cntkctl_el1);
                WRITE_SPECIALREG(EL0_REG(CNTV_CVAL),
@@ -583,14 +584,10 @@ vmm_hyp_reg_restore_timer(struct hypctx *hypctx, struct 
hyp *hyp, bool guest)
                         * to keep in sync.
                         */
                        WRITE_SPECIALREG(CNTPOFF_EL2_REG,
-                           hyp->vtimer.cntvoff_el2);
+                           hypctx->vtimer.cntvoff_el2);
                        isb();
                }
        } else {
-               WRITE_SPECIALREG(cnthctl_el2,
-                   hypctx->host_timer_regs.cnthctl_el2);
-               WRITE_SPECIALREG(cntvoff_el2,
-                   hypctx->host_timer_regs.cntvoff_el2);
                WRITE_SPECIALREG(cntkctl_el1, hypctx->vtimer_cpu.cntkctl_el1);
        }
        if (guest_or_nonvhe(guest) && ecv_poff) {
@@ -736,7 +733,7 @@ static uint64_t
 __vmm_hyp_call_guest(struct hypctx *hypctx, struct hypctx *host_hypctx)
 {
        uint64_t ret;
-       WRITE_SPECIALREG(vttbr_el2, hypctx->hyp->vttbr_el2);
+       WRITE_SPECIALREG(vttbr_el2, hypctx->vttbr_el2);
        WRITE_SPECIALREG(mdcr_el2, hypctx->mdcr_el2);
        /* Call into the guest */
        ret = VMM_HYP_FUNC(do_call_guest)(hypctx);

Reply via email to