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