Linux 6.7-rc7
[linux-modified.git] / arch / arm64 / include / asm / vdso / gettimeofday.h
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/barrier.h>
12 #include <asm/unistd.h>
13 #include <asm/sysreg.h>
14
15 #define VDSO_HAS_CLOCK_GETRES           1
16
17 static __always_inline
18 int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
19                           struct timezone *_tz)
20 {
21         register struct timezone *tz asm("x1") = _tz;
22         register struct __kernel_old_timeval *tv asm("x0") = _tv;
23         register long ret asm ("x0");
24         register long nr asm("x8") = __NR_gettimeofday;
25
26         asm volatile(
27         "       svc #0\n"
28         : "=r" (ret)
29         : "r" (tv), "r" (tz), "r" (nr)
30         : "memory");
31
32         return ret;
33 }
34
35 static __always_inline
36 long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
37 {
38         register struct __kernel_timespec *ts asm("x1") = _ts;
39         register clockid_t clkid asm("x0") = _clkid;
40         register long ret asm ("x0");
41         register long nr asm("x8") = __NR_clock_gettime;
42
43         asm volatile(
44         "       svc #0\n"
45         : "=r" (ret)
46         : "r" (clkid), "r" (ts), "r" (nr)
47         : "memory");
48
49         return ret;
50 }
51
52 static __always_inline
53 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
54 {
55         register struct __kernel_timespec *ts asm("x1") = _ts;
56         register clockid_t clkid asm("x0") = _clkid;
57         register long ret asm ("x0");
58         register long nr asm("x8") = __NR_clock_getres;
59
60         asm volatile(
61         "       svc #0\n"
62         : "=r" (ret)
63         : "r" (clkid), "r" (ts), "r" (nr)
64         : "memory");
65
66         return ret;
67 }
68
69 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
70                                                  const struct vdso_data *vd)
71 {
72         u64 res;
73
74         /*
75          * Core checks for mode already, so this raced against a concurrent
76          * update. Return something. Core will do another round and then
77          * see the mode change and fallback to the syscall.
78          */
79         if (clock_mode == VDSO_CLOCKMODE_NONE)
80                 return 0;
81
82         /*
83          * If FEAT_ECV is available, use the self-synchronizing counter.
84          * Otherwise the isb is required to prevent that the counter value
85          * is speculated.
86         */
87         asm volatile(
88         ALTERNATIVE("isb\n"
89                     "mrs %0, cntvct_el0",
90                     "nop\n"
91                     __mrs_s("%0", SYS_CNTVCTSS_EL0),
92                     ARM64_HAS_ECV)
93         : "=r" (res)
94         :
95         : "memory");
96
97         arch_counter_enforce_ordering(res);
98
99         return res;
100 }
101
102 static __always_inline
103 const struct vdso_data *__arch_get_vdso_data(void)
104 {
105         return _vdso_data;
106 }
107
108 #ifdef CONFIG_TIME_NS
109 static __always_inline
110 const struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
111 {
112         return _timens_data;
113 }
114 #endif
115
116 #endif /* !__ASSEMBLY__ */
117
118 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */