diff options
| author | Andrew Turner <andrew@FreeBSD.org> | 2025-09-22 17:08:47 +0000 |
|---|---|---|
| committer | Andrew Turner <andrew@FreeBSD.org> | 2025-09-23 17:08:37 +0000 |
| commit | 0efa0fe26b9d980b2862bb58f8484f0123cff19f (patch) | |
| tree | 3d171bfbfcfda97076700acadea11a0cfd1c5fb8 | |
| parent | e38e04a0ba3fdcdc2f3238bf4d962f65fadf527f (diff) | |
arm: Use the Self-Synchronized counter registers
When FEAT_ECV is implemented on arm64 a Self-Synchronized view of the
counter registers are available. These don't need an isb before reading
the count as they are not able to be speculatively executed.
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D51820
| -rw-r--r-- | sys/arm/arm/generic_timer.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c index c4a1f44a0079..e3ba56a6f6ac 100644 --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -231,6 +231,25 @@ get_cntxct(bool physical) return (val); } +#ifdef __aarch64__ +/* + * Read the self-syncronized counter. These cannot be read speculatively so + * don't need an isb before them. + */ +static uint64_t +get_cntxctss(bool physical) +{ + uint64_t val; + + if (physical) + val = READ_SPECIALREG(CNTPCTSS_EL0_REG); + else + val = READ_SPECIALREG(CNTVCTSS_EL0_REG); + + return (val); +} +#endif + static int set_ctrl(uint32_t val, bool physical) { @@ -631,6 +650,7 @@ arm_tmr_attach(device_t dev) pcell_t clock; #endif #ifdef __aarch64__ + uint64_t id_aa64mmfr0_el1; int user_phys; #endif int error; @@ -641,6 +661,11 @@ arm_tmr_attach(device_t dev) return (ENXIO); sc->get_cntxct = &get_cntxct; +#ifdef __aarch64__ + if (get_kernel_reg(ID_AA64MMFR0_EL1, &id_aa64mmfr0_el1) && + ID_AA64MMFR0_ECV_VAL(id_aa64mmfr0_el1) >= ID_AA64MMFR0_ECV_IMPL) + sc->get_cntxct = &get_cntxctss; +#endif #ifdef FDT /* Get the base clock frequency */ node = ofw_bus_get_node(dev); |
