Merge branch 'fix-BPF-offload-related-bugs'
[linux-2.6-microblaze.git] / arch / mips / include / asm / vdso / gettimeofday.h
1 /*
2  * Copyright (C) 2018 ARM Limited
3  * Copyright (C) 2015 Imagination Technologies
4  * Author: Alex Smith <alex.smith@imgtec.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation;  either version 2 of the  License, or (at your
9  * option) any later version.
10  */
11 #ifndef __ASM_VDSO_GETTIMEOFDAY_H
12 #define __ASM_VDSO_GETTIMEOFDAY_H
13
14 #ifndef __ASSEMBLY__
15
16 #include <linux/compiler.h>
17 #include <linux/time.h>
18
19 #include <asm/vdso/vdso.h>
20 #include <asm/clocksource.h>
21 #include <asm/io.h>
22 #include <asm/unistd.h>
23 #include <asm/vdso.h>
24
25 #define VDSO_HAS_CLOCK_GETRES           1
26
27 #ifdef CONFIG_MIPS_CLOCK_VSYSCALL
28
29 static __always_inline long gettimeofday_fallback(
30                                 struct __kernel_old_timeval *_tv,
31                                 struct timezone *_tz)
32 {
33         register struct timezone *tz asm("a1") = _tz;
34         register struct __kernel_old_timeval *tv asm("a0") = _tv;
35         register long ret asm("v0");
36         register long nr asm("v0") = __NR_gettimeofday;
37         register long error asm("a3");
38
39         asm volatile(
40         "       syscall\n"
41         : "=r" (ret), "=r" (error)
42         : "r" (tv), "r" (tz), "r" (nr)
43         : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
44           "$14", "$15", "$24", "$25", "hi", "lo", "memory");
45
46         return error ? -ret : ret;
47 }
48
49 #else
50
51 static __always_inline long gettimeofday_fallback(
52                                 struct __kernel_old_timeval *_tv,
53                                 struct timezone *_tz)
54 {
55         return -1;
56 }
57
58 #endif
59
60 static __always_inline long clock_gettime_fallback(
61                                         clockid_t _clkid,
62                                         struct __kernel_timespec *_ts)
63 {
64         register struct __kernel_timespec *ts asm("a1") = _ts;
65         register clockid_t clkid asm("a0") = _clkid;
66         register long ret asm("v0");
67 #if _MIPS_SIM == _MIPS_SIM_ABI64
68         register long nr asm("v0") = __NR_clock_gettime;
69 #else
70         register long nr asm("v0") = __NR_clock_gettime64;
71 #endif
72         register long error asm("a3");
73
74         asm volatile(
75         "       syscall\n"
76         : "=r" (ret), "=r" (error)
77         : "r" (clkid), "r" (ts), "r" (nr)
78         : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
79           "$14", "$15", "$24", "$25", "hi", "lo", "memory");
80
81         return error ? -ret : ret;
82 }
83
84 static __always_inline int clock_getres_fallback(
85                                         clockid_t _clkid,
86                                         struct __kernel_timespec *_ts)
87 {
88         register struct __kernel_timespec *ts asm("a1") = _ts;
89         register clockid_t clkid asm("a0") = _clkid;
90         register long ret asm("v0");
91 #if _MIPS_SIM == _MIPS_SIM_ABI64
92         register long nr asm("v0") = __NR_clock_getres;
93 #else
94         register long nr asm("v0") = __NR_clock_getres_time64;
95 #endif
96         register long error asm("a3");
97
98         asm volatile(
99         "       syscall\n"
100         : "=r" (ret), "=r" (error)
101         : "r" (clkid), "r" (ts), "r" (nr)
102         : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
103           "$14", "$15", "$24", "$25", "hi", "lo", "memory");
104
105         return error ? -ret : ret;
106 }
107
108 #if _MIPS_SIM != _MIPS_SIM_ABI64
109
110 #define VDSO_HAS_32BIT_FALLBACK 1
111
112 static __always_inline long clock_gettime32_fallback(
113                                         clockid_t _clkid,
114                                         struct old_timespec32 *_ts)
115 {
116         register struct old_timespec32 *ts asm("a1") = _ts;
117         register clockid_t clkid asm("a0") = _clkid;
118         register long ret asm("v0");
119         register long nr asm("v0") = __NR_clock_gettime;
120         register long error asm("a3");
121
122         asm volatile(
123         "       syscall\n"
124         : "=r" (ret), "=r" (error)
125         : "r" (clkid), "r" (ts), "r" (nr)
126         : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
127           "$14", "$15", "$24", "$25", "hi", "lo", "memory");
128
129         return error ? -ret : ret;
130 }
131
132 static __always_inline int clock_getres32_fallback(
133                                         clockid_t _clkid,
134                                         struct old_timespec32 *_ts)
135 {
136         register struct old_timespec32 *ts asm("a1") = _ts;
137         register clockid_t clkid asm("a0") = _clkid;
138         register long ret asm("v0");
139         register long nr asm("v0") = __NR_clock_getres;
140         register long error asm("a3");
141
142         asm volatile(
143         "       syscall\n"
144         : "=r" (ret), "=r" (error)
145         : "r" (clkid), "r" (ts), "r" (nr)
146         : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
147           "$14", "$15", "$24", "$25", "hi", "lo", "memory");
148
149         return error ? -ret : ret;
150 }
151 #endif
152
153 #ifdef CONFIG_CSRC_R4K
154
155 static __always_inline u64 read_r4k_count(void)
156 {
157         unsigned int count;
158
159         __asm__ __volatile__(
160         "       .set push\n"
161         "       .set mips32r2\n"
162         "       rdhwr   %0, $2\n"
163         "       .set pop\n"
164         : "=r" (count));
165
166         return count;
167 }
168
169 #endif
170
171 #ifdef CONFIG_CLKSRC_MIPS_GIC
172
173 static __always_inline u64 read_gic_count(const struct vdso_data *data)
174 {
175         void __iomem *gic = get_gic(data);
176         u32 hi, hi2, lo;
177
178         do {
179                 hi = __raw_readl(gic + sizeof(lo));
180                 lo = __raw_readl(gic);
181                 hi2 = __raw_readl(gic + sizeof(lo));
182         } while (hi2 != hi);
183
184         return (((u64)hi) << 32) + lo;
185 }
186
187 #endif
188
189 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
190 {
191 #ifdef CONFIG_CLKSRC_MIPS_GIC
192         const struct vdso_data *data = get_vdso_data();
193 #endif
194         u64 cycle_now;
195
196         switch (clock_mode) {
197 #ifdef CONFIG_CSRC_R4K
198         case VDSO_CLOCK_R4K:
199                 cycle_now = read_r4k_count();
200                 break;
201 #endif
202 #ifdef CONFIG_CLKSRC_MIPS_GIC
203         case VDSO_CLOCK_GIC:
204                 cycle_now = read_gic_count(data);
205                 break;
206 #endif
207         default:
208                 cycle_now = 0;
209                 break;
210         }
211
212         return cycle_now;
213 }
214
215 static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
216 {
217         return get_vdso_data();
218 }
219
220 #endif /* !__ASSEMBLY__ */
221
222 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */