git: 67242cc4284e - main - arm64/vmm: vtimer: Read CNTPCT_EL0 through a dedicated macro
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 17 Sep 2026 09:56:06 UTC
The branch main has been updated by andrew:
URL: https://cgit.FreeBSD.org/src/commit/?id=67242cc4284e44936068945d9960c8f1fef136c1
commit 67242cc4284e44936068945d9960c8f1fef136c1
Author: Kajetan Puchalski <kajetan.puchalski@arm.com>
AuthorDate: 2026-05-12 16:12:04 +0000
Commit: Andrew Turner <andrew@FreeBSD.org>
CommitDate: 2026-09-17 09:20:22 +0000
arm64/vmm: vtimer: Read CNTPCT_EL0 through a dedicated macro
CNTPCT_EL0 needs to be read after an ISB in order to ensure a consistent
value irrespective of speculative execution.
Make existing reads of CNTPCT_EL0 use a new dedicated accessor macro
that expands to the correct instruction sequence.
Signed-off-by: Kajetan Puchalski <kajetan.puchalski@arm.com>
Reviewed by: andrew
Sponsored by: Arm Ltd
Pull Request: https://github.com/freebsd/freebsd-src/pull/2423
---
sys/arm64/include/_armreg.h | 7 +++++++
sys/arm64/vmm/io/vtimer.c | 14 +++++++-------
sys/arm64/vmm/vmm_arm64.c | 2 +-
3 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/sys/arm64/include/_armreg.h b/sys/arm64/include/_armreg.h
index 0ade9e6168c9..e00a2b2033af 100644
--- a/sys/arm64/include/_armreg.h
+++ b/sys/arm64/include/_armreg.h
@@ -80,6 +80,13 @@
_val; \
})
+/* TODO: Use CNTPCTSS when FEAT_ECV is available */
+#define READ_CNTPCT() \
+({ uint64_t _val; \
+ __asm __volatile("isb\nmrs %0, cntpct_el0" : "=&r" (_val));\
+ _val; \
+})
+
#define UL(x) UINT64_C(x)
#endif /* !_MACHINE__ARMREG_H_ */
diff --git a/sys/arm64/vmm/io/vtimer.c b/sys/arm64/vmm/io/vtimer.c
index 509e52947524..00767d3b59b5 100644
--- a/sys/arm64/vmm/io/vtimer.c
+++ b/sys/arm64/vmm/io/vtimer.c
@@ -96,7 +96,7 @@ vtimer_virtual_timer_intr(void *arg)
goto out;
}
- cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
+ cntpct_el0 = READ_CNTPCT() -
hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2);
if (hypctx->vtimer_cpu.virt_timer.cntx_cval_el0 < cntpct_el0)
vgic_inject_irq(hypctx->hyp, vcpu_vcpuid(hypctx->vcpu),
@@ -279,7 +279,7 @@ vtimer_sync_hwstate(struct hypctx *hypctx)
{
uint64_t cntpct_el0;
- cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
+ cntpct_el0 = READ_CNTPCT() -
hypctx_read_sys_reg(hypctx, HOST_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 */
@@ -321,7 +321,7 @@ vtimer_schedule_irq(struct hypctx *hypctx, bool phys)
timer = &hypctx->vtimer_cpu.phys_timer;
else
timer = &hypctx->vtimer_cpu.virt_timer;
- cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
+ cntpct_el0 = READ_CNTPCT() -
hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2);
if (timer->cntx_cval_el0 < cntpct_el0) {
/* Timer set in the past, trigger interrupt */
@@ -379,7 +379,7 @@ vtimer_phys_ctl_read(struct vcpu *vcpu, uint64_t *rval, void *arg)
hypctx = vcpu_get_cookie(vcpu);
vtimer_cpu = &hypctx->vtimer_cpu;
- cntpct_el0 = READ_SPECIALREG(cntpct_el0) - hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2);
+ cntpct_el0 = READ_CNTPCT() - hypctx_read_sys_reg(hypctx, HOST_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;
@@ -422,7 +422,7 @@ vtimer_phys_cnt_read(struct vcpu *vcpu, uint64_t *rval, void *arg)
struct hypctx *hypctx;
hypctx = vcpu_get_cookie(vcpu);
- *rval = READ_SPECIALREG(cntpct_el0) - hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2);
+ *rval = READ_CNTPCT() - hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2);
return (0);
}
@@ -484,7 +484,7 @@ vtimer_phys_tval_read(struct vcpu *vcpu, uint64_t *rval, void *arg)
*/
*rval = (uint32_t)RES1;
} else {
- cntpct_el0 = READ_SPECIALREG(cntpct_el0) -
+ cntpct_el0 = READ_CNTPCT() -
hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2);
*rval = vtimer_cpu->phys_timer.cntx_cval_el0 - cntpct_el0;
}
@@ -502,7 +502,7 @@ vtimer_phys_tval_write(struct vcpu *vcpu, uint64_t wval, void *arg)
hypctx = vcpu_get_cookie(vcpu);
vtimer_cpu = &hypctx->vtimer_cpu;
- cntpct_el0 = READ_SPECIALREG(cntpct_el0) - hypctx_read_sys_reg(hypctx, HOST_CNTVOFF_EL2);
+ cntpct_el0 = READ_CNTPCT() - hypctx_read_sys_reg(hypctx, HOST_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/vmm_arm64.c b/sys/arm64/vmm/vmm_arm64.c
index e2d667575706..8b405b49fc84 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;
- hyp->cntvoff_el2 = READ_SPECIALREG(cntpct_el0);
+ hyp->cntvoff_el2 = READ_CNTPCT();
vgic_vminit(hyp);
if (!in_vhe())