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