Date: Mon, 06 Jul 2026 15:24:42 +0000 From: Andrew Turner <andrew@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Kajetan Puchalski <kajetan.puchalski@arm.com> Subject: git: f4c3458ab3ce - main - arm64/vmm: Move vttbr_el2 & vtimer into struct hypctx Message-ID: <6a4bc8ba.1dd46.19bb853a@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=f4c3458ab3ce52ba9b234bee7711d0cb9a0745ac commit f4c3458ab3ce52ba9b234bee7711d0cb9a0745ac Author: Kajetan Puchalski <kajetan.puchalski@arm.com> AuthorDate: 2026-07-06 14:17:58 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> 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 <kajetan.puchalski@arm.com> 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);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a4bc8ba.1dd46.19bb853a>
