xref: /freebsd/sys/arm64/include/atomic.h (revision c1fced68)
1412042e2SAndrew Turner /*-
2412042e2SAndrew Turner  * Copyright (c) 2013 Andrew Turner <andrew@freebsd.org>
3412042e2SAndrew Turner  * All rights reserved.
4412042e2SAndrew Turner  *
5412042e2SAndrew Turner  * Redistribution and use in source and binary forms, with or without
6412042e2SAndrew Turner  * modification, are permitted provided that the following conditions
7412042e2SAndrew Turner  * are met:
8412042e2SAndrew Turner  * 1. Redistributions of source code must retain the above copyright
9412042e2SAndrew Turner  *    notice, this list of conditions and the following disclaimer.
10412042e2SAndrew Turner  * 2. Redistributions in binary form must reproduce the above copyright
11412042e2SAndrew Turner  *    notice, this list of conditions and the following disclaimer in the
12412042e2SAndrew Turner  *    documentation and/or other materials provided with the distribution.
13412042e2SAndrew Turner  *
14412042e2SAndrew Turner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15412042e2SAndrew Turner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16412042e2SAndrew Turner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17412042e2SAndrew Turner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18412042e2SAndrew Turner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19412042e2SAndrew Turner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20412042e2SAndrew Turner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21412042e2SAndrew Turner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22412042e2SAndrew Turner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23412042e2SAndrew Turner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24412042e2SAndrew Turner  * SUCH DAMAGE.
25412042e2SAndrew Turner  *
26412042e2SAndrew Turner  * $FreeBSD$
27412042e2SAndrew Turner  */
28412042e2SAndrew Turner 
29412042e2SAndrew Turner #ifndef	_MACHINE_ATOMIC_H_
30412042e2SAndrew Turner #define	_MACHINE_ATOMIC_H_
31412042e2SAndrew Turner 
32412042e2SAndrew Turner #define	isb()		__asm __volatile("isb" : : : "memory")
33412042e2SAndrew Turner 
34458f2175SZbigniew Bodek /*
35458f2175SZbigniew Bodek  * Options for DMB and DSB:
36458f2175SZbigniew Bodek  *	oshld	Outer Shareable, load
37458f2175SZbigniew Bodek  *	oshst	Outer Shareable, store
38458f2175SZbigniew Bodek  *	osh	Outer Shareable, all
39458f2175SZbigniew Bodek  *	nshld	Non-shareable, load
40458f2175SZbigniew Bodek  *	nshst	Non-shareable, store
41458f2175SZbigniew Bodek  *	nsh	Non-shareable, all
42458f2175SZbigniew Bodek  *	ishld	Inner Shareable, load
43458f2175SZbigniew Bodek  *	ishst	Inner Shareable, store
44458f2175SZbigniew Bodek  *	ish	Inner Shareable, all
45458f2175SZbigniew Bodek  *	ld	Full system, load
46458f2175SZbigniew Bodek  *	st	Full system, store
47458f2175SZbigniew Bodek  *	sy	Full system, all
48458f2175SZbigniew Bodek  */
49458f2175SZbigniew Bodek #define	dsb(opt)	__asm __volatile("dsb " __STRING(opt) : : : "memory")
50458f2175SZbigniew Bodek #define	dmb(opt)	__asm __volatile("dmb " __STRING(opt) : : : "memory")
51458f2175SZbigniew Bodek 
52458f2175SZbigniew Bodek #define	mb()	dmb(sy)	/* Full system memory barrier all */
53458f2175SZbigniew Bodek #define	wmb()	dmb(st)	/* Full system memory barrier store */
54458f2175SZbigniew Bodek #define	rmb()	dmb(ld)	/* Full system memory barrier load */
55412042e2SAndrew Turner 
56849aef49SAndrew Turner #if defined(KCSAN) && !defined(KCSAN_RUNTIME)
57849aef49SAndrew Turner #include <sys/_cscan_atomic.h>
58849aef49SAndrew Turner #else
59849aef49SAndrew Turner 
60849aef49SAndrew Turner #include <sys/atomic_common.h>
61849aef49SAndrew Turner 
62c1fced68SMark Johnston #define	_ATOMIC_OP_PROTO(t, op, bar, flav)				\
63119a353eSAndrew Turner static __inline void							\
64c1fced68SMark Johnston atomic_##op##_##bar##t##flav(volatile uint##t##_t *p, uint##t##_t val)
65c1fced68SMark Johnston 
66c1fced68SMark Johnston #define	_ATOMIC_OP_IMPL(t, w, s, op, asm_op, bar, a, l)			\
67c1fced68SMark Johnston _ATOMIC_OP_PROTO(t, op, bar, _llsc)					\
684ffa494eSAndrew Turner {									\
693ad6c736SMark Johnston 	uint##t##_t tmp;						\
704ffa494eSAndrew Turner 	int res;							\
714ffa494eSAndrew Turner 									\
724ffa494eSAndrew Turner 	__asm __volatile(						\
733ad6c736SMark Johnston 	    "1: ld"#a"xr"#s"	%"#w"0, [%2]\n"				\
743ad6c736SMark Johnston 	    "   "#asm_op"	%"#w"0, %"#w"0, %"#w"3\n"		\
753ad6c736SMark Johnston 	    "   st"#l"xr"#s"	%w1, %"#w"0, [%2]\n"			\
76119a353eSAndrew Turner 	    "   cbnz		%w1, 1b\n"				\
77119a353eSAndrew Turner 	    : "=&r"(tmp), "=&r"(res)					\
78119a353eSAndrew Turner 	    : "r" (p), "r" (val)					\
79119a353eSAndrew Turner 	    : "memory"							\
80119a353eSAndrew Turner 	);								\
81c1fced68SMark Johnston }									\
82c1fced68SMark Johnston 									\
83c1fced68SMark Johnston _ATOMIC_OP_PROTO(t, op, bar, )						\
84c1fced68SMark Johnston {									\
85c1fced68SMark Johnston 	atomic_##op##_##bar##t##_llsc(p, val);				\
86412042e2SAndrew Turner }
87412042e2SAndrew Turner 
883ad6c736SMark Johnston #define	__ATOMIC_OP(op, asm_op, bar, a, l)				\
893ad6c736SMark Johnston 	_ATOMIC_OP_IMPL(8,  w, b, op, asm_op, bar, a, l)		\
903ad6c736SMark Johnston 	_ATOMIC_OP_IMPL(16, w, h, op, asm_op, bar, a, l)		\
913ad6c736SMark Johnston 	_ATOMIC_OP_IMPL(32, w,  , op, asm_op, bar, a, l)		\
923ad6c736SMark Johnston 	_ATOMIC_OP_IMPL(64,  ,  , op, asm_op, bar, a, l)
93412042e2SAndrew Turner 
943ad6c736SMark Johnston #define	_ATOMIC_OP(op, asm_op)						\
953ad6c736SMark Johnston 	__ATOMIC_OP(op, asm_op,     ,  ,  )				\
963ad6c736SMark Johnston 	__ATOMIC_OP(op, asm_op, acq_, a,  )				\
973ad6c736SMark Johnston 	__ATOMIC_OP(op, asm_op, rel_,  , l)
98119a353eSAndrew Turner 
993ad6c736SMark Johnston _ATOMIC_OP(add,      add)
1003ad6c736SMark Johnston _ATOMIC_OP(clear,    bic)
1013ad6c736SMark Johnston _ATOMIC_OP(set,      orr)
1023ad6c736SMark Johnston _ATOMIC_OP(subtract, sub)
1033ad6c736SMark Johnston 
104c1fced68SMark Johnston #define	_ATOMIC_CMPSET_PROTO(t, bar, flav)				\
105dc5f9fcdSOlivier Houchard static __inline int							\
106c1fced68SMark Johnston atomic_cmpset_##bar##t##flav(volatile uint##t##_t *p,			\
107c1fced68SMark Johnston     uint##t##_t cmpval, uint##t##_t newval)
108c1fced68SMark Johnston 
109c1fced68SMark Johnston #define	_ATOMIC_FCMPSET_PROTO(t, bar, flav)				\
110c1fced68SMark Johnston static __inline int							\
111c1fced68SMark Johnston atomic_fcmpset_##bar##t##flav(volatile uint##t##_t *p,			\
112c1fced68SMark Johnston     uint##t##_t *cmpval, uint##t##_t newval)
113c1fced68SMark Johnston 
114c1fced68SMark Johnston #define	_ATOMIC_CMPSET_IMPL(t, w, s, bar, a, l)				\
115c1fced68SMark Johnston _ATOMIC_CMPSET_PROTO(t, bar, _llsc)					\
116e39ce4caSEmmanuel Vadot {									\
1173ad6c736SMark Johnston 	uint##t##_t tmp;						\
118e39ce4caSEmmanuel Vadot 	int res;							\
119e39ce4caSEmmanuel Vadot 									\
120e39ce4caSEmmanuel Vadot 	__asm __volatile(						\
121e39ce4caSEmmanuel Vadot 	    "1: mov		%w1, #1\n"				\
1223ad6c736SMark Johnston 	    "   ld"#a"xr"#s"	%"#w"0, [%2]\n"				\
1233ad6c736SMark Johnston 	    "   cmp		%"#w"0, %"#w"3\n"			\
124e39ce4caSEmmanuel Vadot 	    "   b.ne		2f\n"					\
1253ad6c736SMark Johnston 	    "   st"#l"xr"#s"	%w1, %"#w"4, [%2]\n"			\
1264ffa494eSAndrew Turner 	    "   cbnz		%w1, 1b\n"				\
1274ffa494eSAndrew Turner 	    "2:"							\
1284ffa494eSAndrew Turner 	    : "=&r"(tmp), "=&r"(res)					\
1294ffa494eSAndrew Turner 	    : "r" (p), "r" (cmpval), "r" (newval)			\
1304ffa494eSAndrew Turner 	    : "cc", "memory"						\
1314ffa494eSAndrew Turner 	);								\
1324ffa494eSAndrew Turner 									\
1334ffa494eSAndrew Turner 	return (!res);							\
1344ffa494eSAndrew Turner }									\
1354ffa494eSAndrew Turner 									\
136c1fced68SMark Johnston _ATOMIC_CMPSET_PROTO(t, bar, )						\
137c1fced68SMark Johnston {									\
138c1fced68SMark Johnston 	return (atomic_cmpset_##bar##t##_llsc(p, cmpval, newval));	\
139c1fced68SMark Johnston }									\
140c1fced68SMark Johnston 									\
141c1fced68SMark Johnston _ATOMIC_FCMPSET_PROTO(t, bar, _llsc)					\
1424ffa494eSAndrew Turner {									\
1433ad6c736SMark Johnston 	uint##t##_t _cmpval, tmp;					\
1443ad6c736SMark Johnston 	int res;							\
1453ad6c736SMark Johnston 									\
1463ad6c736SMark Johnston 	_cmpval = *cmpval;						\
1473ad6c736SMark Johnston 	__asm __volatile(						\
1483ad6c736SMark Johnston 	    "   mov		%w1, #1\n"				\
1493ad6c736SMark Johnston 	    "   ld"#a"xr"#s"	%"#w"0, [%2]\n"				\
1503ad6c736SMark Johnston 	    "   cmp		%"#w"0, %"#w"3\n"			\
1513ad6c736SMark Johnston 	    "   b.ne		1f\n"					\
1523ad6c736SMark Johnston 	    "   st"#l"xr"#s"	%w1, %"#w"4, [%2]\n"			\
1533ad6c736SMark Johnston 	    "1:"							\
1543ad6c736SMark Johnston 	    : "=&r"(tmp), "=&r"(res)					\
1553ad6c736SMark Johnston 	    : "r" (p), "r" (_cmpval), "r" (newval)			\
1563ad6c736SMark Johnston 	    : "cc", "memory"						\
1573ad6c736SMark Johnston 	);								\
1583ad6c736SMark Johnston 	*cmpval = tmp;							\
1593ad6c736SMark Johnston 									\
1603ad6c736SMark Johnston 	return (!res);							\
161c1fced68SMark Johnston }									\
162c1fced68SMark Johnston 									\
163c1fced68SMark Johnston _ATOMIC_FCMPSET_PROTO(t, bar, )						\
164c1fced68SMark Johnston {									\
165c1fced68SMark Johnston 	return (atomic_fcmpset_##bar##t##_llsc(p, cmpval, newval));	\
1663ad6c736SMark Johnston }
1673ad6c736SMark Johnston 
1683ad6c736SMark Johnston #define	_ATOMIC_CMPSET(bar, a, l)					\
1693ad6c736SMark Johnston 	_ATOMIC_CMPSET_IMPL(8,  w, b, bar, a, l)			\
1703ad6c736SMark Johnston 	_ATOMIC_CMPSET_IMPL(16, w, h, bar, a, l)			\
1713ad6c736SMark Johnston 	_ATOMIC_CMPSET_IMPL(32, w,  , bar, a, l)			\
1723ad6c736SMark Johnston 	_ATOMIC_CMPSET_IMPL(64,  ,  , bar, a, l)
1733ad6c736SMark Johnston 
1743ad6c736SMark Johnston _ATOMIC_CMPSET(    ,  , )
1753ad6c736SMark Johnston _ATOMIC_CMPSET(acq_, a, )
1763ad6c736SMark Johnston _ATOMIC_CMPSET(rel_,  ,l)
1773ad6c736SMark Johnston 
178c1fced68SMark Johnston #define	_ATOMIC_FETCHADD_PROTO(t, flav)					\
1793ad6c736SMark Johnston static __inline uint##t##_t						\
180c1fced68SMark Johnston atomic_fetchadd_##t##flav(volatile uint##t##_t *p, uint##t##_t val)
181c1fced68SMark Johnston 
182c1fced68SMark Johnston #define	_ATOMIC_FETCHADD_IMPL(t, w)					\
183c1fced68SMark Johnston _ATOMIC_FETCHADD_PROTO(t, _llsc)					\
1843ad6c736SMark Johnston {									\
1853ad6c736SMark Johnston 	uint##t##_t tmp, ret;						\
1864ffa494eSAndrew Turner 	int res;							\
1874ffa494eSAndrew Turner 									\
1884ffa494eSAndrew Turner 	__asm __volatile(						\
1893ad6c736SMark Johnston 	    "1: ldxr	%"#w"2, [%3]\n"					\
1903ad6c736SMark Johnston 	    "   add	%"#w"0, %"#w"2, %"#w"4\n"			\
1913ad6c736SMark Johnston 	    "   stxr	%w1, %"#w"0, [%3]\n"				\
1924ffa494eSAndrew Turner             "   cbnz	%w1, 1b\n"					\
1933ad6c736SMark Johnston 	    : "=&r" (tmp), "=&r" (res), "=&r" (ret)			\
1943ad6c736SMark Johnston 	    : "r" (p), "r" (val)					\
1953ad6c736SMark Johnston 	    : "memory"							\
1964ffa494eSAndrew Turner 	);								\
1974ffa494eSAndrew Turner 									\
1983ad6c736SMark Johnston 	return (ret);							\
199c1fced68SMark Johnston }									\
200c1fced68SMark Johnston 									\
201c1fced68SMark Johnston _ATOMIC_FETCHADD_PROTO(t, )						\
202c1fced68SMark Johnston {									\
203c1fced68SMark Johnston 	return (atomic_fetchadd_##t##_llsc(p, val));			\
2043ad6c736SMark Johnston }
2053ad6c736SMark Johnston 
2063ad6c736SMark Johnston _ATOMIC_FETCHADD_IMPL(32, w)
2073ad6c736SMark Johnston _ATOMIC_FETCHADD_IMPL(64,  )
2083ad6c736SMark Johnston 
209c1fced68SMark Johnston #define	_ATOMIC_SWAP_PROTO(t, flav)					\
2103ad6c736SMark Johnston static __inline uint##t##_t						\
211c1fced68SMark Johnston atomic_swap_##t##flav(volatile uint##t##_t *p, uint##t##_t val)
212c1fced68SMark Johnston 
213c1fced68SMark Johnston #define	_ATOMIC_READANDCLEAR_PROTO(t, flav)				\
214c1fced68SMark Johnston static __inline uint##t##_t						\
215c1fced68SMark Johnston atomic_readandclear_##t##flav(volatile uint##t##_t *p)
216c1fced68SMark Johnston 
217c1fced68SMark Johnston #define	_ATOMIC_SWAP_IMPL(t, w, zreg)					\
218c1fced68SMark Johnston _ATOMIC_SWAP_PROTO(t, _llsc)						\
2193ad6c736SMark Johnston {									\
2203ad6c736SMark Johnston 	uint##t##_t ret;						\
2213ad6c736SMark Johnston 	int res;							\
2223ad6c736SMark Johnston 									\
2233ad6c736SMark Johnston 	__asm __volatile(						\
2243ad6c736SMark Johnston 	    "1: ldxr	%"#w"1, [%2]\n"					\
2253ad6c736SMark Johnston 	    "   stxr	%w0, %"#w"3, [%2]\n"				\
2263ad6c736SMark Johnston             "   cbnz	%w0, 1b\n"					\
2273ad6c736SMark Johnston 	    : "=&r" (res), "=&r" (ret)					\
2283ad6c736SMark Johnston 	    : "r" (p), "r" (val)					\
2293ad6c736SMark Johnston 	    : "memory"							\
2303ad6c736SMark Johnston 	);								\
2313ad6c736SMark Johnston 									\
2323ad6c736SMark Johnston 	return (ret);							\
2334ffa494eSAndrew Turner }									\
2344ffa494eSAndrew Turner 									\
235c1fced68SMark Johnston _ATOMIC_SWAP_PROTO(t, )							\
236c1fced68SMark Johnston {									\
237c1fced68SMark Johnston 	return (atomic_swap_##t##_llsc(p, val));			\
238c1fced68SMark Johnston }									\
239c1fced68SMark Johnston 									\
240c1fced68SMark Johnston _ATOMIC_READANDCLEAR_PROTO(t, _llsc)					\
241119a353eSAndrew Turner {									\
2423ad6c736SMark Johnston 	uint##t##_t ret;						\
243119a353eSAndrew Turner 	int res;							\
244119a353eSAndrew Turner 									\
245119a353eSAndrew Turner 	__asm __volatile(						\
2463ad6c736SMark Johnston 	    "1: ldxr	%"#w"1, [%2]\n"					\
2473ad6c736SMark Johnston 	    "   stxr	%w0, "#zreg", [%2]\n"				\
2483ad6c736SMark Johnston 	    "   cbnz	%w0, 1b\n"					\
2493ad6c736SMark Johnston 	    : "=&r" (res), "=&r" (ret)					\
2503ad6c736SMark Johnston 	    : "r" (p)							\
2513ad6c736SMark Johnston 	    : "memory"							\
252119a353eSAndrew Turner 	);								\
253119a353eSAndrew Turner 									\
2543ad6c736SMark Johnston 	return (ret);							\
255c1fced68SMark Johnston }									\
256c1fced68SMark Johnston 									\
257c1fced68SMark Johnston _ATOMIC_READANDCLEAR_PROTO(t, )						\
258c1fced68SMark Johnston {									\
259c1fced68SMark Johnston 	return (atomic_readandclear_##t##_llsc(p));			\
2603ad6c736SMark Johnston }
2613ad6c736SMark Johnston 
2623ad6c736SMark Johnston _ATOMIC_SWAP_IMPL(32, w, wzr)
2633ad6c736SMark Johnston _ATOMIC_SWAP_IMPL(64,  , xzr)
2643ad6c736SMark Johnston 
265c1fced68SMark Johnston #define	_ATOMIC_TEST_OP_PROTO(t, op, flav)				\
266119a353eSAndrew Turner static __inline int							\
267c1fced68SMark Johnston atomic_testand##op##_##t##flav(volatile uint##t##_t *p, u_int val)
268c1fced68SMark Johnston 
269c1fced68SMark Johnston #define	_ATOMIC_TEST_OP_IMPL(t, w, op, asm_op)				\
270c1fced68SMark Johnston _ATOMIC_TEST_OP_PROTO(t, op, _llsc)					\
271119a353eSAndrew Turner {									\
2723ad6c736SMark Johnston 	uint##t##_t mask, old, tmp;					\
273119a353eSAndrew Turner 	int res;							\
274119a353eSAndrew Turner 									\
2753ad6c736SMark Johnston 	mask = 1u << (val & 0x1f);					\
276119a353eSAndrew Turner 	__asm __volatile(						\
2773ad6c736SMark Johnston 	    "1: ldxr		%"#w"2, [%3]\n"				\
2783ad6c736SMark Johnston 	    "  "#asm_op"	%"#w"0, %"#w"2, %"#w"4\n"		\
2793ad6c736SMark Johnston 	    "   stxr		%w1, %"#w"0, [%3]\n"			\
280119a353eSAndrew Turner 	    "   cbnz		%w1, 1b\n"				\
2813ad6c736SMark Johnston 	    : "=&r" (tmp), "=&r" (res), "=&r" (old)			\
2823ad6c736SMark Johnston 	    : "r" (p), "r" (mask)					\
2833ad6c736SMark Johnston 	    : "memory"							\
284119a353eSAndrew Turner 	);								\
285119a353eSAndrew Turner 									\
2863ad6c736SMark Johnston 	return ((old & mask) != 0);					\
287c1fced68SMark Johnston }									\
288c1fced68SMark Johnston 									\
289c1fced68SMark Johnston _ATOMIC_TEST_OP_PROTO(t, op, )						\
290c1fced68SMark Johnston {									\
291c1fced68SMark Johnston 	return (atomic_testand##op##_##t##_llsc(p, val));		\
292412042e2SAndrew Turner }
293412042e2SAndrew Turner 
2943ad6c736SMark Johnston #define	_ATOMIC_TEST_OP(op, asm_op)					\
2953ad6c736SMark Johnston 	_ATOMIC_TEST_OP_IMPL(32, w, op, asm_op)				\
2963ad6c736SMark Johnston 	_ATOMIC_TEST_OP_IMPL(64,  , op, asm_op)
297412042e2SAndrew Turner 
2983ad6c736SMark Johnston _ATOMIC_TEST_OP(clear, bic)
2993ad6c736SMark Johnston _ATOMIC_TEST_OP(set,   orr)
300412042e2SAndrew Turner 
3013ad6c736SMark Johnston #define	_ATOMIC_LOAD_ACQ_IMPL(t, w, s)					\
3023ad6c736SMark Johnston static __inline uint##t##_t						\
3033ad6c736SMark Johnston atomic_load_acq_##t(volatile uint##t##_t *p)				\
3043ad6c736SMark Johnston {									\
3053ad6c736SMark Johnston 	uint##t##_t ret;						\
3063ad6c736SMark Johnston 									\
3073ad6c736SMark Johnston 	__asm __volatile(						\
3083ad6c736SMark Johnston 	    "ldar"#s"	%"#w"0, [%1]\n"					\
3093ad6c736SMark Johnston 	    : "=&r" (ret)						\
3103ad6c736SMark Johnston 	    : "r" (p)							\
3113ad6c736SMark Johnston 	    : "memory");						\
3123ad6c736SMark Johnston 									\
3133ad6c736SMark Johnston 	return (ret);							\
314119a353eSAndrew Turner }
315119a353eSAndrew Turner 
3163ad6c736SMark Johnston _ATOMIC_LOAD_ACQ_IMPL(8,  w, b)
3173ad6c736SMark Johnston _ATOMIC_LOAD_ACQ_IMPL(16, w, h)
3183ad6c736SMark Johnston _ATOMIC_LOAD_ACQ_IMPL(32, w,  )
3193ad6c736SMark Johnston _ATOMIC_LOAD_ACQ_IMPL(64,  ,  )
320119a353eSAndrew Turner 
3213ad6c736SMark Johnston #define	_ATOMIC_STORE_REL_IMPL(t, w, s)					\
3223ad6c736SMark Johnston static __inline void							\
3233ad6c736SMark Johnston atomic_store_rel_##t(volatile uint##t##_t *p, uint##t##_t val)		\
3243ad6c736SMark Johnston {									\
3253ad6c736SMark Johnston 	__asm __volatile(						\
3263ad6c736SMark Johnston 	    "stlr"#s"	%"#w"0, [%1]\n"					\
3273ad6c736SMark Johnston 	    :								\
3283ad6c736SMark Johnston 	    : "r" (val), "r" (p)					\
3293ad6c736SMark Johnston 	    : "memory");						\
330412042e2SAndrew Turner }
331412042e2SAndrew Turner 
3323ad6c736SMark Johnston _ATOMIC_STORE_REL_IMPL(8,  w, b)
3333ad6c736SMark Johnston _ATOMIC_STORE_REL_IMPL(16, w, h)
3343ad6c736SMark Johnston _ATOMIC_STORE_REL_IMPL(32, w,  )
3353ad6c736SMark Johnston _ATOMIC_STORE_REL_IMPL(64,  ,  )
336119a353eSAndrew Turner 
337412042e2SAndrew Turner #define	atomic_add_int			atomic_add_32
338dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_int		atomic_fcmpset_32
339412042e2SAndrew Turner #define	atomic_clear_int		atomic_clear_32
340412042e2SAndrew Turner #define	atomic_cmpset_int		atomic_cmpset_32
341412042e2SAndrew Turner #define	atomic_fetchadd_int		atomic_fetchadd_32
342412042e2SAndrew Turner #define	atomic_readandclear_int		atomic_readandclear_32
343412042e2SAndrew Turner #define	atomic_set_int			atomic_set_32
3449b8c3c4fSAndrew Turner #define	atomic_swap_int			atomic_swap_32
345412042e2SAndrew Turner #define	atomic_subtract_int		atomic_subtract_32
346f2792e5eSAndrew Turner #define	atomic_testandclear_int		atomic_testandclear_32
347f2792e5eSAndrew Turner #define	atomic_testandset_int		atomic_testandset_32
348412042e2SAndrew Turner 
34946f52b02SAndrew Turner #define	atomic_add_acq_int		atomic_add_acq_32
350dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_acq_int		atomic_fcmpset_acq_32
35146f52b02SAndrew Turner #define	atomic_clear_acq_int		atomic_clear_acq_32
35246f52b02SAndrew Turner #define	atomic_cmpset_acq_int		atomic_cmpset_acq_32
35346f52b02SAndrew Turner #define	atomic_load_acq_int		atomic_load_acq_32
35446f52b02SAndrew Turner #define	atomic_set_acq_int		atomic_set_acq_32
35546f52b02SAndrew Turner #define	atomic_subtract_acq_int		atomic_subtract_acq_32
35646f52b02SAndrew Turner 
357412042e2SAndrew Turner #define	atomic_add_rel_int		atomic_add_rel_32
358dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_rel_int		atomic_fcmpset_rel_32
359c90baf68SAndrew Turner #define	atomic_clear_rel_int		atomic_clear_rel_32
360412042e2SAndrew Turner #define	atomic_cmpset_rel_int		atomic_cmpset_rel_32
361412042e2SAndrew Turner #define	atomic_set_rel_int		atomic_set_rel_32
362412042e2SAndrew Turner #define	atomic_subtract_rel_int		atomic_subtract_rel_32
363412042e2SAndrew Turner #define	atomic_store_rel_int		atomic_store_rel_32
364412042e2SAndrew Turner 
365412042e2SAndrew Turner #define	atomic_add_long			atomic_add_64
366dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_long		atomic_fcmpset_64
367412042e2SAndrew Turner #define	atomic_clear_long		atomic_clear_64
368412042e2SAndrew Turner #define	atomic_cmpset_long		atomic_cmpset_64
369412042e2SAndrew Turner #define	atomic_fetchadd_long		atomic_fetchadd_64
370412042e2SAndrew Turner #define	atomic_readandclear_long	atomic_readandclear_64
371412042e2SAndrew Turner #define	atomic_set_long			atomic_set_64
3729b8c3c4fSAndrew Turner #define	atomic_swap_long		atomic_swap_64
373412042e2SAndrew Turner #define	atomic_subtract_long		atomic_subtract_64
374f2792e5eSAndrew Turner #define	atomic_testandclear_long	atomic_testandclear_64
375f2792e5eSAndrew Turner #define	atomic_testandset_long		atomic_testandset_64
376412042e2SAndrew Turner 
377412042e2SAndrew Turner #define	atomic_add_ptr			atomic_add_64
378dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_ptr		atomic_fcmpset_64
379412042e2SAndrew Turner #define	atomic_clear_ptr		atomic_clear_64
380412042e2SAndrew Turner #define	atomic_cmpset_ptr		atomic_cmpset_64
381412042e2SAndrew Turner #define	atomic_fetchadd_ptr		atomic_fetchadd_64
382412042e2SAndrew Turner #define	atomic_readandclear_ptr		atomic_readandclear_64
383412042e2SAndrew Turner #define	atomic_set_ptr			atomic_set_64
3849b8c3c4fSAndrew Turner #define	atomic_swap_ptr			atomic_swap_64
385412042e2SAndrew Turner #define	atomic_subtract_ptr		atomic_subtract_64
386412042e2SAndrew Turner 
387412042e2SAndrew Turner #define	atomic_add_acq_long		atomic_add_acq_64
388dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_acq_long		atomic_fcmpset_acq_64
389c90baf68SAndrew Turner #define	atomic_clear_acq_long		atomic_clear_acq_64
390412042e2SAndrew Turner #define	atomic_cmpset_acq_long		atomic_cmpset_acq_64
391412042e2SAndrew Turner #define	atomic_load_acq_long		atomic_load_acq_64
392412042e2SAndrew Turner #define	atomic_set_acq_long		atomic_set_acq_64
393412042e2SAndrew Turner #define	atomic_subtract_acq_long	atomic_subtract_acq_64
394412042e2SAndrew Turner 
395412042e2SAndrew Turner #define	atomic_add_acq_ptr		atomic_add_acq_64
396dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_acq_ptr		atomic_fcmpset_acq_64
397c90baf68SAndrew Turner #define	atomic_clear_acq_ptr		atomic_clear_acq_64
398412042e2SAndrew Turner #define	atomic_cmpset_acq_ptr		atomic_cmpset_acq_64
399412042e2SAndrew Turner #define	atomic_load_acq_ptr		atomic_load_acq_64
400412042e2SAndrew Turner #define	atomic_set_acq_ptr		atomic_set_acq_64
401412042e2SAndrew Turner #define	atomic_subtract_acq_ptr		atomic_subtract_acq_64
402412042e2SAndrew Turner 
403119a353eSAndrew Turner #define	atomic_add_rel_long		atomic_add_rel_64
404dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_rel_long		atomic_fcmpset_rel_64
405119a353eSAndrew Turner #define	atomic_clear_rel_long		atomic_clear_rel_64
406119a353eSAndrew Turner #define	atomic_cmpset_rel_long		atomic_cmpset_rel_64
407119a353eSAndrew Turner #define	atomic_set_rel_long		atomic_set_rel_64
408119a353eSAndrew Turner #define	atomic_subtract_rel_long	atomic_subtract_rel_64
409119a353eSAndrew Turner #define	atomic_store_rel_long		atomic_store_rel_64
41046f52b02SAndrew Turner 
411119a353eSAndrew Turner #define	atomic_add_rel_ptr		atomic_add_rel_64
412dc5f9fcdSOlivier Houchard #define	atomic_fcmpset_rel_ptr		atomic_fcmpset_rel_64
413119a353eSAndrew Turner #define	atomic_clear_rel_ptr		atomic_clear_rel_64
414119a353eSAndrew Turner #define	atomic_cmpset_rel_ptr		atomic_cmpset_rel_64
415119a353eSAndrew Turner #define	atomic_set_rel_ptr		atomic_set_rel_64
416119a353eSAndrew Turner #define	atomic_subtract_rel_ptr		atomic_subtract_rel_64
417119a353eSAndrew Turner #define	atomic_store_rel_ptr		atomic_store_rel_64
418412042e2SAndrew Turner 
4198954a9a4SKonstantin Belousov static __inline void
4208954a9a4SKonstantin Belousov atomic_thread_fence_acq(void)
4218954a9a4SKonstantin Belousov {
4228954a9a4SKonstantin Belousov 
4238954a9a4SKonstantin Belousov 	dmb(ld);
4248954a9a4SKonstantin Belousov }
4258954a9a4SKonstantin Belousov 
4268954a9a4SKonstantin Belousov static __inline void
4278954a9a4SKonstantin Belousov atomic_thread_fence_rel(void)
4288954a9a4SKonstantin Belousov {
4298954a9a4SKonstantin Belousov 
4308954a9a4SKonstantin Belousov 	dmb(sy);
4318954a9a4SKonstantin Belousov }
4328954a9a4SKonstantin Belousov 
4338954a9a4SKonstantin Belousov static __inline void
4348954a9a4SKonstantin Belousov atomic_thread_fence_acq_rel(void)
4358954a9a4SKonstantin Belousov {
4368954a9a4SKonstantin Belousov 
4378954a9a4SKonstantin Belousov 	dmb(sy);
4388954a9a4SKonstantin Belousov }
4398954a9a4SKonstantin Belousov 
4408954a9a4SKonstantin Belousov static __inline void
4418954a9a4SKonstantin Belousov atomic_thread_fence_seq_cst(void)
4428954a9a4SKonstantin Belousov {
4438954a9a4SKonstantin Belousov 
4448954a9a4SKonstantin Belousov 	dmb(sy);
4458954a9a4SKonstantin Belousov }
4468954a9a4SKonstantin Belousov 
447849aef49SAndrew Turner #endif /* KCSAN && !KCSAN_RUNTIME */
448412042e2SAndrew Turner #endif /* _MACHINE_ATOMIC_H_ */
449