The callbacks are based on Linux's implementation: - CNTVCT_EL0 provides direct access to the system virtual timer[1]. - 'yield' serves as a CPU hint with similar semantics as x86's 'pause'[2]. In contrast with the kernel's implementation, there isn't a need for isb() after reading CNTVCT_EL0, this is only needed in-kernel as the register read has to be ordered with a subsequent locking operation. [1] See Linux's '__arch_get_hw_counter()' in arch/arm64/include/asm/vdso/gettimeofday.h [2] See Linux's 1baa82f4803 ("arm64: Implement cpu_relax as yield"). Signed-off-by: Nicolas Saenz Julienne <nsaenzju@xxxxxxxxxx> -- Changes since v1: - Code cleanup - Add compiler barriers src/oslat/oslat.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/oslat/oslat.c b/src/oslat/oslat.c index 33cccd3..c90ec1a 100644 --- a/src/oslat/oslat.c +++ b/src/oslat/oslat.c @@ -71,6 +71,19 @@ static inline void frc(uint64_t *pval) { __asm__ __volatile__("mfspr %0, 268\n" : "=r" (*pval)); } +# elif defined(__aarch64__) +# define relax() __asm__ __volatile("yield" : : : "memory") + +static inline void frc(uint64_t *pval) +{ + /* + * This isb() is required to prevent that the counter value + * is speculated. + */ + __asm__ __volatile__("isb" : : : "memory"); + __asm__ __volatile__("mrs %0, cntvct_el0" : "=r" (*pval) :: "memory"); + +} # else # define relax() do { } while (0) # define frc(x) -- 2.31.1