1
2
3
4
5
6 #ifndef _ASM_RISCV_CMPXCHG_H
7 #define _ASM_RISCV_CMPXCHG_H
8
9 #include <linux/bug.h>
10
11 #include <asm/barrier.h>
12 #include <asm/fence.h>
13
14 #define __xchg_relaxed(ptr, new, size) \
15 ({ \
16 __typeof__(ptr) __ptr = (ptr); \
17 __typeof__(new) __new = (new); \
18 __typeof__(*(ptr)) __ret; \
19 switch (size) { \
20 case 4: \
21 __asm__ __volatile__ ( \
22 " amoswap.w %0, %2, %1\n" \
23 : "=r" (__ret), "+A" (*__ptr) \
24 : "r" (__new) \
25 : "memory"); \
26 break; \
27 case 8: \
28 __asm__ __volatile__ ( \
29 " amoswap.d %0, %2, %1\n" \
30 : "=r" (__ret), "+A" (*__ptr) \
31 : "r" (__new) \
32 : "memory"); \
33 break; \
34 default: \
35 BUILD_BUG(); \
36 } \
37 __ret; \
38 })
39
40 #define xchg_relaxed(ptr, x) \
41 ({ \
42 __typeof__(*(ptr)) _x_ = (x); \
43 (__typeof__(*(ptr))) __xchg_relaxed((ptr), \
44 _x_, sizeof(*(ptr))); \
45 })
46
47 #define __xchg_acquire(ptr, new, size) \
48 ({ \
49 __typeof__(ptr) __ptr = (ptr); \
50 __typeof__(new) __new = (new); \
51 __typeof__(*(ptr)) __ret; \
52 switch (size) { \
53 case 4: \
54 __asm__ __volatile__ ( \
55 " amoswap.w %0, %2, %1\n" \
56 RISCV_ACQUIRE_BARRIER \
57 : "=r" (__ret), "+A" (*__ptr) \
58 : "r" (__new) \
59 : "memory"); \
60 break; \
61 case 8: \
62 __asm__ __volatile__ ( \
63 " amoswap.d %0, %2, %1\n" \
64 RISCV_ACQUIRE_BARRIER \
65 : "=r" (__ret), "+A" (*__ptr) \
66 : "r" (__new) \
67 : "memory"); \
68 break; \
69 default: \
70 BUILD_BUG(); \
71 } \
72 __ret; \
73 })
74
75 #define xchg_acquire(ptr, x) \
76 ({ \
77 __typeof__(*(ptr)) _x_ = (x); \
78 (__typeof__(*(ptr))) __xchg_acquire((ptr), \
79 _x_, sizeof(*(ptr))); \
80 })
81
82 #define __xchg_release(ptr, new, size) \
83 ({ \
84 __typeof__(ptr) __ptr = (ptr); \
85 __typeof__(new) __new = (new); \
86 __typeof__(*(ptr)) __ret; \
87 switch (size) { \
88 case 4: \
89 __asm__ __volatile__ ( \
90 RISCV_RELEASE_BARRIER \
91 " amoswap.w %0, %2, %1\n" \
92 : "=r" (__ret), "+A" (*__ptr) \
93 : "r" (__new) \
94 : "memory"); \
95 break; \
96 case 8: \
97 __asm__ __volatile__ ( \
98 RISCV_RELEASE_BARRIER \
99 " amoswap.d %0, %2, %1\n" \
100 : "=r" (__ret), "+A" (*__ptr) \
101 : "r" (__new) \
102 : "memory"); \
103 break; \
104 default: \
105 BUILD_BUG(); \
106 } \
107 __ret; \
108 })
109
110 #define xchg_release(ptr, x) \
111 ({ \
112 __typeof__(*(ptr)) _x_ = (x); \
113 (__typeof__(*(ptr))) __xchg_release((ptr), \
114 _x_, sizeof(*(ptr))); \
115 })
116
117 #define __xchg(ptr, new, size) \
118 ({ \
119 __typeof__(ptr) __ptr = (ptr); \
120 __typeof__(new) __new = (new); \
121 __typeof__(*(ptr)) __ret; \
122 switch (size) { \
123 case 4: \
124 __asm__ __volatile__ ( \
125 " amoswap.w.aqrl %0, %2, %1\n" \
126 : "=r" (__ret), "+A" (*__ptr) \
127 : "r" (__new) \
128 : "memory"); \
129 break; \
130 case 8: \
131 __asm__ __volatile__ ( \
132 " amoswap.d.aqrl %0, %2, %1\n" \
133 : "=r" (__ret), "+A" (*__ptr) \
134 : "r" (__new) \
135 : "memory"); \
136 break; \
137 default: \
138 BUILD_BUG(); \
139 } \
140 __ret; \
141 })
142
143 #define xchg(ptr, x) \
144 ({ \
145 __typeof__(*(ptr)) _x_ = (x); \
146 (__typeof__(*(ptr))) __xchg((ptr), _x_, sizeof(*(ptr))); \
147 })
148
149 #define xchg32(ptr, x) \
150 ({ \
151 BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
152 xchg((ptr), (x)); \
153 })
154
155 #define xchg64(ptr, x) \
156 ({ \
157 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
158 xchg((ptr), (x)); \
159 })
160
161
162
163
164
165
166 #define __cmpxchg_relaxed(ptr, old, new, size) \
167 ({ \
168 __typeof__(ptr) __ptr = (ptr); \
169 __typeof__(*(ptr)) __old = (old); \
170 __typeof__(*(ptr)) __new = (new); \
171 __typeof__(*(ptr)) __ret; \
172 register unsigned int __rc; \
173 switch (size) { \
174 case 4: \
175 __asm__ __volatile__ ( \
176 "0: lr.w %0, %2\n" \
177 " bne %0, %z3, 1f\n" \
178 " sc.w %1, %z4, %2\n" \
179 " bnez %1, 0b\n" \
180 "1:\n" \
181 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
182 : "rJ" (__old), "rJ" (__new) \
183 : "memory"); \
184 break; \
185 case 8: \
186 __asm__ __volatile__ ( \
187 "0: lr.d %0, %2\n" \
188 " bne %0, %z3, 1f\n" \
189 " sc.d %1, %z4, %2\n" \
190 " bnez %1, 0b\n" \
191 "1:\n" \
192 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
193 : "rJ" (__old), "rJ" (__new) \
194 : "memory"); \
195 break; \
196 default: \
197 BUILD_BUG(); \
198 } \
199 __ret; \
200 })
201
202 #define cmpxchg_relaxed(ptr, o, n) \
203 ({ \
204 __typeof__(*(ptr)) _o_ = (o); \
205 __typeof__(*(ptr)) _n_ = (n); \
206 (__typeof__(*(ptr))) __cmpxchg_relaxed((ptr), \
207 _o_, _n_, sizeof(*(ptr))); \
208 })
209
210 #define __cmpxchg_acquire(ptr, old, new, size) \
211 ({ \
212 __typeof__(ptr) __ptr = (ptr); \
213 __typeof__(*(ptr)) __old = (old); \
214 __typeof__(*(ptr)) __new = (new); \
215 __typeof__(*(ptr)) __ret; \
216 register unsigned int __rc; \
217 switch (size) { \
218 case 4: \
219 __asm__ __volatile__ ( \
220 "0: lr.w %0, %2\n" \
221 " bne %0, %z3, 1f\n" \
222 " sc.w %1, %z4, %2\n" \
223 " bnez %1, 0b\n" \
224 RISCV_ACQUIRE_BARRIER \
225 "1:\n" \
226 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
227 : "rJ" (__old), "rJ" (__new) \
228 : "memory"); \
229 break; \
230 case 8: \
231 __asm__ __volatile__ ( \
232 "0: lr.d %0, %2\n" \
233 " bne %0, %z3, 1f\n" \
234 " sc.d %1, %z4, %2\n" \
235 " bnez %1, 0b\n" \
236 RISCV_ACQUIRE_BARRIER \
237 "1:\n" \
238 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
239 : "rJ" (__old), "rJ" (__new) \
240 : "memory"); \
241 break; \
242 default: \
243 BUILD_BUG(); \
244 } \
245 __ret; \
246 })
247
248 #define cmpxchg_acquire(ptr, o, n) \
249 ({ \
250 __typeof__(*(ptr)) _o_ = (o); \
251 __typeof__(*(ptr)) _n_ = (n); \
252 (__typeof__(*(ptr))) __cmpxchg_acquire((ptr), \
253 _o_, _n_, sizeof(*(ptr))); \
254 })
255
256 #define __cmpxchg_release(ptr, old, new, size) \
257 ({ \
258 __typeof__(ptr) __ptr = (ptr); \
259 __typeof__(*(ptr)) __old = (old); \
260 __typeof__(*(ptr)) __new = (new); \
261 __typeof__(*(ptr)) __ret; \
262 register unsigned int __rc; \
263 switch (size) { \
264 case 4: \
265 __asm__ __volatile__ ( \
266 RISCV_RELEASE_BARRIER \
267 "0: lr.w %0, %2\n" \
268 " bne %0, %z3, 1f\n" \
269 " sc.w %1, %z4, %2\n" \
270 " bnez %1, 0b\n" \
271 "1:\n" \
272 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
273 : "rJ" (__old), "rJ" (__new) \
274 : "memory"); \
275 break; \
276 case 8: \
277 __asm__ __volatile__ ( \
278 RISCV_RELEASE_BARRIER \
279 "0: lr.d %0, %2\n" \
280 " bne %0, %z3, 1f\n" \
281 " sc.d %1, %z4, %2\n" \
282 " bnez %1, 0b\n" \
283 "1:\n" \
284 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
285 : "rJ" (__old), "rJ" (__new) \
286 : "memory"); \
287 break; \
288 default: \
289 BUILD_BUG(); \
290 } \
291 __ret; \
292 })
293
294 #define cmpxchg_release(ptr, o, n) \
295 ({ \
296 __typeof__(*(ptr)) _o_ = (o); \
297 __typeof__(*(ptr)) _n_ = (n); \
298 (__typeof__(*(ptr))) __cmpxchg_release((ptr), \
299 _o_, _n_, sizeof(*(ptr))); \
300 })
301
302 #define __cmpxchg(ptr, old, new, size) \
303 ({ \
304 __typeof__(ptr) __ptr = (ptr); \
305 __typeof__(*(ptr)) __old = (old); \
306 __typeof__(*(ptr)) __new = (new); \
307 __typeof__(*(ptr)) __ret; \
308 register unsigned int __rc; \
309 switch (size) { \
310 case 4: \
311 __asm__ __volatile__ ( \
312 "0: lr.w %0, %2\n" \
313 " bne %0, %z3, 1f\n" \
314 " sc.w.rl %1, %z4, %2\n" \
315 " bnez %1, 0b\n" \
316 " fence rw, rw\n" \
317 "1:\n" \
318 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
319 : "rJ" (__old), "rJ" (__new) \
320 : "memory"); \
321 break; \
322 case 8: \
323 __asm__ __volatile__ ( \
324 "0: lr.d %0, %2\n" \
325 " bne %0, %z3, 1f\n" \
326 " sc.d.rl %1, %z4, %2\n" \
327 " bnez %1, 0b\n" \
328 " fence rw, rw\n" \
329 "1:\n" \
330 : "=&r" (__ret), "=&r" (__rc), "+A" (*__ptr) \
331 : "rJ" (__old), "rJ" (__new) \
332 : "memory"); \
333 break; \
334 default: \
335 BUILD_BUG(); \
336 } \
337 __ret; \
338 })
339
340 #define cmpxchg(ptr, o, n) \
341 ({ \
342 __typeof__(*(ptr)) _o_ = (o); \
343 __typeof__(*(ptr)) _n_ = (n); \
344 (__typeof__(*(ptr))) __cmpxchg((ptr), \
345 _o_, _n_, sizeof(*(ptr))); \
346 })
347
348 #define cmpxchg_local(ptr, o, n) \
349 (__cmpxchg_relaxed((ptr), (o), (n), sizeof(*(ptr))))
350
351 #define cmpxchg32(ptr, o, n) \
352 ({ \
353 BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
354 cmpxchg((ptr), (o), (n)); \
355 })
356
357 #define cmpxchg32_local(ptr, o, n) \
358 ({ \
359 BUILD_BUG_ON(sizeof(*(ptr)) != 4); \
360 cmpxchg_relaxed((ptr), (o), (n)) \
361 })
362
363 #define cmpxchg64(ptr, o, n) \
364 ({ \
365 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
366 cmpxchg((ptr), (o), (n)); \
367 })
368
369 #define cmpxchg64_local(ptr, o, n) \
370 ({ \
371 BUILD_BUG_ON(sizeof(*(ptr)) != 8); \
372 cmpxchg_relaxed((ptr), (o), (n)); \
373 })
374
375 #endif