162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Fast user context implementation of clock_gettime, gettimeofday, and time. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2019 ARM Limited. 662306a36Sopenharmony_ci * Copyright 2006 Andi Kleen, SUSE Labs. 762306a36Sopenharmony_ci * 32 Bit compat layer by Stefani Seibold <stefani@seibold.net> 862306a36Sopenharmony_ci * sponsored by Rohde & Schwarz GmbH & Co. KG Munich/Germany 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#ifndef __ASM_VDSO_GETTIMEOFDAY_H 1162306a36Sopenharmony_ci#define __ASM_VDSO_GETTIMEOFDAY_H 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <uapi/linux/time.h> 1662306a36Sopenharmony_ci#include <asm/vgtod.h> 1762306a36Sopenharmony_ci#include <asm/vvar.h> 1862306a36Sopenharmony_ci#include <asm/unistd.h> 1962306a36Sopenharmony_ci#include <asm/msr.h> 2062306a36Sopenharmony_ci#include <asm/pvclock.h> 2162306a36Sopenharmony_ci#include <clocksource/hyperv_timer.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define __vdso_data (VVAR(_vdso_data)) 2462306a36Sopenharmony_ci#define __timens_vdso_data (TIMENS(_vdso_data)) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define VDSO_HAS_TIME 1 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define VDSO_HAS_CLOCK_GETRES 1 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* 3162306a36Sopenharmony_ci * Declare the memory-mapped vclock data pages. These come from hypervisors. 3262306a36Sopenharmony_ci * If we ever reintroduce something like direct access to an MMIO clock like 3362306a36Sopenharmony_ci * the HPET again, it will go here as well. 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * A load from any of these pages will segfault if the clock in question is 3662306a36Sopenharmony_ci * disabled, so appropriate compiler barriers and checks need to be used 3762306a36Sopenharmony_ci * to prevent stray loads. 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * These declarations MUST NOT be const. The compiler will assume that 4062306a36Sopenharmony_ci * an extern const variable has genuinely constant contents, and the 4162306a36Sopenharmony_ci * resulting code won't work, since the whole point is that these pages 4262306a36Sopenharmony_ci * change over time, possibly while we're accessing them. 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#ifdef CONFIG_PARAVIRT_CLOCK 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * This is the vCPU 0 pvclock page. We only use pvclock from the vDSO 4862306a36Sopenharmony_ci * if the hypervisor tells us that all vCPUs can get valid data from the 4962306a36Sopenharmony_ci * vCPU 0 page. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ciextern struct pvclock_vsyscall_time_info pvclock_page 5262306a36Sopenharmony_ci __attribute__((visibility("hidden"))); 5362306a36Sopenharmony_ci#endif 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#ifdef CONFIG_HYPERV_TIMER 5662306a36Sopenharmony_ciextern struct ms_hyperv_tsc_page hvclock_page 5762306a36Sopenharmony_ci __attribute__((visibility("hidden"))); 5862306a36Sopenharmony_ci#endif 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#ifdef CONFIG_TIME_NS 6162306a36Sopenharmony_cistatic __always_inline 6262306a36Sopenharmony_ciconst struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci return __timens_vdso_data; 6562306a36Sopenharmony_ci} 6662306a36Sopenharmony_ci#endif 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#ifndef BUILD_VDSO32 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic __always_inline 7162306a36Sopenharmony_cilong clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci long ret; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci asm ("syscall" : "=a" (ret), "=m" (*_ts) : 7662306a36Sopenharmony_ci "0" (__NR_clock_gettime), "D" (_clkid), "S" (_ts) : 7762306a36Sopenharmony_ci "rcx", "r11"); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci return ret; 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic __always_inline 8362306a36Sopenharmony_cilong gettimeofday_fallback(struct __kernel_old_timeval *_tv, 8462306a36Sopenharmony_ci struct timezone *_tz) 8562306a36Sopenharmony_ci{ 8662306a36Sopenharmony_ci long ret; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci asm("syscall" : "=a" (ret) : 8962306a36Sopenharmony_ci "0" (__NR_gettimeofday), "D" (_tv), "S" (_tz) : "memory"); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return ret; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic __always_inline 9562306a36Sopenharmony_cilong clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci long ret; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci asm ("syscall" : "=a" (ret), "=m" (*_ts) : 10062306a36Sopenharmony_ci "0" (__NR_clock_getres), "D" (_clkid), "S" (_ts) : 10162306a36Sopenharmony_ci "rcx", "r11"); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#else 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic __always_inline 10962306a36Sopenharmony_cilong clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci long ret; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci asm ( 11462306a36Sopenharmony_ci "mov %%ebx, %%edx \n" 11562306a36Sopenharmony_ci "mov %[clock], %%ebx \n" 11662306a36Sopenharmony_ci "call __kernel_vsyscall \n" 11762306a36Sopenharmony_ci "mov %%edx, %%ebx \n" 11862306a36Sopenharmony_ci : "=a" (ret), "=m" (*_ts) 11962306a36Sopenharmony_ci : "0" (__NR_clock_gettime64), [clock] "g" (_clkid), "c" (_ts) 12062306a36Sopenharmony_ci : "edx"); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci return ret; 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic __always_inline 12662306a36Sopenharmony_cilong clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci long ret; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci asm ( 13162306a36Sopenharmony_ci "mov %%ebx, %%edx \n" 13262306a36Sopenharmony_ci "mov %[clock], %%ebx \n" 13362306a36Sopenharmony_ci "call __kernel_vsyscall \n" 13462306a36Sopenharmony_ci "mov %%edx, %%ebx \n" 13562306a36Sopenharmony_ci : "=a" (ret), "=m" (*_ts) 13662306a36Sopenharmony_ci : "0" (__NR_clock_gettime), [clock] "g" (_clkid), "c" (_ts) 13762306a36Sopenharmony_ci : "edx"); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return ret; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic __always_inline 14362306a36Sopenharmony_cilong gettimeofday_fallback(struct __kernel_old_timeval *_tv, 14462306a36Sopenharmony_ci struct timezone *_tz) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci long ret; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci asm( 14962306a36Sopenharmony_ci "mov %%ebx, %%edx \n" 15062306a36Sopenharmony_ci "mov %2, %%ebx \n" 15162306a36Sopenharmony_ci "call __kernel_vsyscall \n" 15262306a36Sopenharmony_ci "mov %%edx, %%ebx \n" 15362306a36Sopenharmony_ci : "=a" (ret) 15462306a36Sopenharmony_ci : "0" (__NR_gettimeofday), "g" (_tv), "c" (_tz) 15562306a36Sopenharmony_ci : "memory", "edx"); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci return ret; 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic __always_inline long 16162306a36Sopenharmony_ciclock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci long ret; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci asm ( 16662306a36Sopenharmony_ci "mov %%ebx, %%edx \n" 16762306a36Sopenharmony_ci "mov %[clock], %%ebx \n" 16862306a36Sopenharmony_ci "call __kernel_vsyscall \n" 16962306a36Sopenharmony_ci "mov %%edx, %%ebx \n" 17062306a36Sopenharmony_ci : "=a" (ret), "=m" (*_ts) 17162306a36Sopenharmony_ci : "0" (__NR_clock_getres_time64), [clock] "g" (_clkid), "c" (_ts) 17262306a36Sopenharmony_ci : "edx"); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return ret; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic __always_inline 17862306a36Sopenharmony_cilong clock_getres32_fallback(clockid_t _clkid, struct old_timespec32 *_ts) 17962306a36Sopenharmony_ci{ 18062306a36Sopenharmony_ci long ret; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci asm ( 18362306a36Sopenharmony_ci "mov %%ebx, %%edx \n" 18462306a36Sopenharmony_ci "mov %[clock], %%ebx \n" 18562306a36Sopenharmony_ci "call __kernel_vsyscall \n" 18662306a36Sopenharmony_ci "mov %%edx, %%ebx \n" 18762306a36Sopenharmony_ci : "=a" (ret), "=m" (*_ts) 18862306a36Sopenharmony_ci : "0" (__NR_clock_getres), [clock] "g" (_clkid), "c" (_ts) 18962306a36Sopenharmony_ci : "edx"); 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci return ret; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci#endif 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci#ifdef CONFIG_PARAVIRT_CLOCK 19762306a36Sopenharmony_cistatic u64 vread_pvclock(void) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci const struct pvclock_vcpu_time_info *pvti = &pvclock_page.pvti; 20062306a36Sopenharmony_ci u32 version; 20162306a36Sopenharmony_ci u64 ret; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci /* 20462306a36Sopenharmony_ci * Note: The kernel and hypervisor must guarantee that cpu ID 20562306a36Sopenharmony_ci * number maps 1:1 to per-CPU pvclock time info. 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * Because the hypervisor is entirely unaware of guest userspace 20862306a36Sopenharmony_ci * preemption, it cannot guarantee that per-CPU pvclock time 20962306a36Sopenharmony_ci * info is updated if the underlying CPU changes or that that 21062306a36Sopenharmony_ci * version is increased whenever underlying CPU changes. 21162306a36Sopenharmony_ci * 21262306a36Sopenharmony_ci * On KVM, we are guaranteed that pvti updates for any vCPU are 21362306a36Sopenharmony_ci * atomic as seen by *all* vCPUs. This is an even stronger 21462306a36Sopenharmony_ci * guarantee than we get with a normal seqlock. 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * On Xen, we don't appear to have that guarantee, but Xen still 21762306a36Sopenharmony_ci * supplies a valid seqlock using the version field. 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * We only do pvclock vdso timing at all if 22062306a36Sopenharmony_ci * PVCLOCK_TSC_STABLE_BIT is set, and we interpret that bit to 22162306a36Sopenharmony_ci * mean that all vCPUs have matching pvti and that the TSC is 22262306a36Sopenharmony_ci * synced, so we can just look at vCPU 0's pvti. 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci do { 22662306a36Sopenharmony_ci version = pvclock_read_begin(pvti); 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci if (unlikely(!(pvti->flags & PVCLOCK_TSC_STABLE_BIT))) 22962306a36Sopenharmony_ci return U64_MAX; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci ret = __pvclock_read_cycles(pvti, rdtsc_ordered()); 23262306a36Sopenharmony_ci } while (pvclock_read_retry(pvti, version)); 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci return ret & S64_MAX; 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci#endif 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci#ifdef CONFIG_HYPERV_TIMER 23962306a36Sopenharmony_cistatic u64 vread_hvclock(void) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci u64 tsc, time; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (hv_read_tsc_page_tsc(&hvclock_page, &tsc, &time)) 24462306a36Sopenharmony_ci return time & S64_MAX; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci return U64_MAX; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci#endif 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic inline u64 __arch_get_hw_counter(s32 clock_mode, 25162306a36Sopenharmony_ci const struct vdso_data *vd) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci if (likely(clock_mode == VDSO_CLOCKMODE_TSC)) 25462306a36Sopenharmony_ci return (u64)rdtsc_ordered() & S64_MAX; 25562306a36Sopenharmony_ci /* 25662306a36Sopenharmony_ci * For any memory-mapped vclock type, we need to make sure that gcc 25762306a36Sopenharmony_ci * doesn't cleverly hoist a load before the mode check. Otherwise we 25862306a36Sopenharmony_ci * might end up touching the memory-mapped page even if the vclock in 25962306a36Sopenharmony_ci * question isn't enabled, which will segfault. Hence the barriers. 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_ci#ifdef CONFIG_PARAVIRT_CLOCK 26262306a36Sopenharmony_ci if (clock_mode == VDSO_CLOCKMODE_PVCLOCK) { 26362306a36Sopenharmony_ci barrier(); 26462306a36Sopenharmony_ci return vread_pvclock(); 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci#endif 26762306a36Sopenharmony_ci#ifdef CONFIG_HYPERV_TIMER 26862306a36Sopenharmony_ci if (clock_mode == VDSO_CLOCKMODE_HVCLOCK) { 26962306a36Sopenharmony_ci barrier(); 27062306a36Sopenharmony_ci return vread_hvclock(); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci#endif 27362306a36Sopenharmony_ci return U64_MAX; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic __always_inline const struct vdso_data *__arch_get_vdso_data(void) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci return __vdso_data; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_cistatic inline bool arch_vdso_clocksource_ok(const struct vdso_data *vd) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci return true; 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci#define vdso_clocksource_ok arch_vdso_clocksource_ok 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci/* 28862306a36Sopenharmony_ci * Clocksource read value validation to handle PV and HyperV clocksources 28962306a36Sopenharmony_ci * which can be invalidated asynchronously and indicate invalidation by 29062306a36Sopenharmony_ci * returning U64_MAX, which can be effectively tested by checking for a 29162306a36Sopenharmony_ci * negative value after casting it to s64. 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * This effectively forces a S64_MAX mask on the calculations, unlike the 29462306a36Sopenharmony_ci * U64_MAX mask normally used by x86 clocksources. 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_cistatic inline bool arch_vdso_cycles_ok(u64 cycles) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci return (s64)cycles >= 0; 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci#define vdso_cycles_ok arch_vdso_cycles_ok 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci/* 30362306a36Sopenharmony_ci * x86 specific delta calculation. 30462306a36Sopenharmony_ci * 30562306a36Sopenharmony_ci * The regular implementation assumes that clocksource reads are globally 30662306a36Sopenharmony_ci * monotonic. The TSC can be slightly off across sockets which can cause 30762306a36Sopenharmony_ci * the regular delta calculation (@cycles - @last) to return a huge time 30862306a36Sopenharmony_ci * jump. 30962306a36Sopenharmony_ci * 31062306a36Sopenharmony_ci * Therefore it needs to be verified that @cycles are greater than 31162306a36Sopenharmony_ci * @last. If not then use @last, which is the base time of the current 31262306a36Sopenharmony_ci * conversion period. 31362306a36Sopenharmony_ci * 31462306a36Sopenharmony_ci * This variant also uses a custom mask because while the clocksource mask of 31562306a36Sopenharmony_ci * all the VDSO capable clocksources on x86 is U64_MAX, the above code uses 31662306a36Sopenharmony_ci * U64_MASK as an exception value, additionally arch_vdso_cycles_ok() above 31762306a36Sopenharmony_ci * declares everything with the MSB/Sign-bit set as invalid. Therefore the 31862306a36Sopenharmony_ci * effective mask is S64_MAX. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_cistatic __always_inline 32162306a36Sopenharmony_ciu64 vdso_calc_delta(u64 cycles, u64 last, u64 mask, u32 mult) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci /* 32462306a36Sopenharmony_ci * Due to the MSB/Sign-bit being used as invald marker (see 32562306a36Sopenharmony_ci * arch_vdso_cycles_valid() above), the effective mask is S64_MAX. 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_ci u64 delta = (cycles - last) & S64_MAX; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* 33062306a36Sopenharmony_ci * Due to the above mentioned TSC wobbles, filter out negative motion. 33162306a36Sopenharmony_ci * Per the above masking, the effective sign bit is now bit 62. 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_ci if (unlikely(delta & (1ULL << 62))) 33462306a36Sopenharmony_ci return 0; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci return delta * mult; 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci#define vdso_calc_delta vdso_calc_delta 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ciint __vdso_clock_gettime64(clockid_t clock, struct __kernel_timespec *ts); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ 345