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