xref: /linux/arch/arm64/include/asm/vdso/gettimeofday.h (revision e7e86d7697c6ed1dbbde18d7185c35b6967945ed)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2018 ARM Limited
4  */
5 #ifndef __ASM_VDSO_GETTIMEOFDAY_H
6 #define __ASM_VDSO_GETTIMEOFDAY_H
7 
8 #ifndef __ASSEMBLY__
9 
10 #include <asm/alternative.h>
11 #include <asm/arch_timer.h>
12 #include <asm/barrier.h>
13 #include <asm/unistd.h>
14 #include <asm/sysreg.h>
15 
16 #define VDSO_HAS_CLOCK_GETRES		1
17 
18 static __always_inline
19 int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
20 			  struct timezone *_tz)
21 {
22 	register struct timezone *tz asm("x1") = _tz;
23 	register struct __kernel_old_timeval *tv asm("x0") = _tv;
24 	register long ret asm ("x0");
25 	register long nr asm("x8") = __NR_gettimeofday;
26 
27 	asm volatile(
28 	"       svc #0\n"
29 	: "=r" (ret)
30 	: "r" (tv), "r" (tz), "r" (nr)
31 	: "memory");
32 
33 	return ret;
34 }
35 
36 static __always_inline
37 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
38 {
39 	register struct __kernel_timespec *ts asm("x1") = _ts;
40 	register clockid_t clkid asm("x0") = _clkid;
41 	register long ret asm ("x0");
42 	register long nr asm("x8") = __NR_clock_gettime;
43 
44 	asm volatile(
45 	"       svc #0\n"
46 	: "=r" (ret)
47 	: "r" (clkid), "r" (ts), "r" (nr)
48 	: "memory");
49 
50 	return ret;
51 }
52 
53 static __always_inline
54 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
55 {
56 	register struct __kernel_timespec *ts asm("x1") = _ts;
57 	register clockid_t clkid asm("x0") = _clkid;
58 	register long ret asm ("x0");
59 	register long nr asm("x8") = __NR_clock_getres;
60 
61 	asm volatile(
62 	"       svc #0\n"
63 	: "=r" (ret)
64 	: "r" (clkid), "r" (ts), "r" (nr)
65 	: "memory");
66 
67 	return ret;
68 }
69 
70 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
71 						 const struct vdso_time_data *vd)
72 {
73 	/*
74 	 * Core checks for mode already, so this raced against a concurrent
75 	 * update. Return something. Core will do another round and then
76 	 * see the mode change and fallback to the syscall.
77 	 */
78 	if (clock_mode == VDSO_CLOCKMODE_NONE)
79 		return 0;
80 
81 	return __arch_counter_get_cntvct();
82 }
83 
84 #if IS_ENABLED(CONFIG_CC_IS_GCC) && IS_ENABLED(CONFIG_PAGE_SIZE_64KB)
85 static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(void)
86 {
87 	const struct vdso_time_data *ret = &vdso_u_time_data;
88 
89 	/* Work around invalid absolute relocations */
90 	OPTIMIZER_HIDE_VAR(ret);
91 
92 	return ret;
93 }
94 #define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data
95 #endif /* IS_ENABLED(CONFIG_CC_IS_GCC) && IS_ENABLED(CONFIG_PAGE_SIZE_64KB) */
96 
97 #endif /* !__ASSEMBLY__ */
98 
99 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
100