18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2018 ARM Limited
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci#ifndef __ASM_VDSO_GETTIMEOFDAY_H
68c2ecf20Sopenharmony_ci#define __ASM_VDSO_GETTIMEOFDAY_H
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <asm/barrier.h>
118c2ecf20Sopenharmony_ci#include <asm/unistd.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define VDSO_HAS_CLOCK_GETRES		1
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic __always_inline
168c2ecf20Sopenharmony_ciint gettimeofday_fallback(struct __kernel_old_timeval *_tv,
178c2ecf20Sopenharmony_ci			  struct timezone *_tz)
188c2ecf20Sopenharmony_ci{
198c2ecf20Sopenharmony_ci	register struct timezone *tz asm("x1") = _tz;
208c2ecf20Sopenharmony_ci	register struct __kernel_old_timeval *tv asm("x0") = _tv;
218c2ecf20Sopenharmony_ci	register long ret asm ("x0");
228c2ecf20Sopenharmony_ci	register long nr asm("x8") = __NR_gettimeofday;
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci	asm volatile(
258c2ecf20Sopenharmony_ci	"       svc #0\n"
268c2ecf20Sopenharmony_ci	: "=r" (ret)
278c2ecf20Sopenharmony_ci	: "r" (tv), "r" (tz), "r" (nr)
288c2ecf20Sopenharmony_ci	: "memory");
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	return ret;
318c2ecf20Sopenharmony_ci}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic __always_inline
348c2ecf20Sopenharmony_cilong clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	register struct __kernel_timespec *ts asm("x1") = _ts;
378c2ecf20Sopenharmony_ci	register clockid_t clkid asm("x0") = _clkid;
388c2ecf20Sopenharmony_ci	register long ret asm ("x0");
398c2ecf20Sopenharmony_ci	register long nr asm("x8") = __NR_clock_gettime;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	asm volatile(
428c2ecf20Sopenharmony_ci	"       svc #0\n"
438c2ecf20Sopenharmony_ci	: "=r" (ret)
448c2ecf20Sopenharmony_ci	: "r" (clkid), "r" (ts), "r" (nr)
458c2ecf20Sopenharmony_ci	: "memory");
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	return ret;
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic __always_inline
518c2ecf20Sopenharmony_ciint clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	register struct __kernel_timespec *ts asm("x1") = _ts;
548c2ecf20Sopenharmony_ci	register clockid_t clkid asm("x0") = _clkid;
558c2ecf20Sopenharmony_ci	register long ret asm ("x0");
568c2ecf20Sopenharmony_ci	register long nr asm("x8") = __NR_clock_getres;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	asm volatile(
598c2ecf20Sopenharmony_ci	"       svc #0\n"
608c2ecf20Sopenharmony_ci	: "=r" (ret)
618c2ecf20Sopenharmony_ci	: "r" (clkid), "r" (ts), "r" (nr)
628c2ecf20Sopenharmony_ci	: "memory");
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	return ret;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
688c2ecf20Sopenharmony_ci						 const struct vdso_data *vd)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	u64 res;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	/*
738c2ecf20Sopenharmony_ci	 * Core checks for mode already, so this raced against a concurrent
748c2ecf20Sopenharmony_ci	 * update. Return something. Core will do another round and then
758c2ecf20Sopenharmony_ci	 * see the mode change and fallback to the syscall.
768c2ecf20Sopenharmony_ci	 */
778c2ecf20Sopenharmony_ci	if (clock_mode == VDSO_CLOCKMODE_NONE)
788c2ecf20Sopenharmony_ci		return 0;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	/*
818c2ecf20Sopenharmony_ci	 * This isb() is required to prevent that the counter value
828c2ecf20Sopenharmony_ci	 * is speculated.
838c2ecf20Sopenharmony_ci	 */
848c2ecf20Sopenharmony_ci	isb();
858c2ecf20Sopenharmony_ci	asm volatile("mrs %0, cntvct_el0" : "=r" (res) :: "memory");
868c2ecf20Sopenharmony_ci	arch_counter_enforce_ordering(res);
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	return res;
898c2ecf20Sopenharmony_ci}
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistatic __always_inline
928c2ecf20Sopenharmony_ciconst struct vdso_data *__arch_get_vdso_data(void)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	return _vdso_data;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci#ifdef CONFIG_TIME_NS
988c2ecf20Sopenharmony_cistatic __always_inline
998c2ecf20Sopenharmony_ciconst struct vdso_data *__arch_get_timens_vdso_data(void)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	return _timens_data;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci#endif
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
108