xref: /OK3568_Linux_fs/kernel/arch/arm64/include/asm/barrier.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Based on arch/arm/include/asm/barrier.h
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2012 ARM Ltd.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun #ifndef __ASM_BARRIER_H
8*4882a593Smuzhiyun #define __ASM_BARRIER_H
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #ifndef __ASSEMBLY__
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/kasan-checks.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #define __nops(n)	".rept	" #n "\nnop\n.endr\n"
15*4882a593Smuzhiyun #define nops(n)		asm volatile(__nops(n))
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #define sev()		asm volatile("sev" : : : "memory")
18*4882a593Smuzhiyun #define wfe()		asm volatile("wfe" : : : "memory")
19*4882a593Smuzhiyun #define wfi()		asm volatile("wfi" : : : "memory")
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define isb()		asm volatile("isb" : : : "memory")
22*4882a593Smuzhiyun #define dmb(opt)	asm volatile("dmb " #opt : : : "memory")
23*4882a593Smuzhiyun #define dsb(opt)	asm volatile("dsb " #opt : : : "memory")
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define psb_csync()	asm volatile("hint #17" : : : "memory")
26*4882a593Smuzhiyun #define __tsb_csync()	asm volatile("hint #18" : : : "memory")
27*4882a593Smuzhiyun #define csdb()		asm volatile("hint #20" : : : "memory")
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define spec_bar()	asm volatile(ALTERNATIVE("dsb nsh\nisb\n",		\
30*4882a593Smuzhiyun 						 SB_BARRIER_INSN"nop\n",	\
31*4882a593Smuzhiyun 						 ARM64_HAS_SB))
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #ifdef CONFIG_ARM64_PSEUDO_NMI
34*4882a593Smuzhiyun #define pmr_sync()						\
35*4882a593Smuzhiyun 	do {							\
36*4882a593Smuzhiyun 		extern struct static_key_false gic_pmr_sync;	\
37*4882a593Smuzhiyun 								\
38*4882a593Smuzhiyun 		if (static_branch_unlikely(&gic_pmr_sync))	\
39*4882a593Smuzhiyun 			dsb(sy);				\
40*4882a593Smuzhiyun 	} while(0)
41*4882a593Smuzhiyun #else
42*4882a593Smuzhiyun #define pmr_sync()	do {} while (0)
43*4882a593Smuzhiyun #endif
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #define mb()		dsb(sy)
46*4882a593Smuzhiyun #define rmb()		dsb(ld)
47*4882a593Smuzhiyun #define wmb()		dsb(st)
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #define dma_mb()	dmb(osh)
50*4882a593Smuzhiyun #define dma_rmb()	dmb(oshld)
51*4882a593Smuzhiyun #define dma_wmb()	dmb(oshst)
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #define tsb_csync()								\
55*4882a593Smuzhiyun 	do {									\
56*4882a593Smuzhiyun 		/*								\
57*4882a593Smuzhiyun 		 * CPUs affected by Arm Erratum 2054223 or 2067961 needs	\
58*4882a593Smuzhiyun 		 * another TSB to ensure the trace is flushed. The barriers	\
59*4882a593Smuzhiyun 		 * don't have to be strictly back to back, as long as the	\
60*4882a593Smuzhiyun 		 * CPU is in trace prohibited state.				\
61*4882a593Smuzhiyun 		 */								\
62*4882a593Smuzhiyun 		if (cpus_have_final_cap(ARM64_WORKAROUND_TSB_FLUSH_FAILURE))	\
63*4882a593Smuzhiyun 			__tsb_csync();						\
64*4882a593Smuzhiyun 		__tsb_csync();							\
65*4882a593Smuzhiyun 	} while (0)
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun /*
68*4882a593Smuzhiyun  * Generate a mask for array_index__nospec() that is ~0UL when 0 <= idx < sz
69*4882a593Smuzhiyun  * and 0 otherwise.
70*4882a593Smuzhiyun  */
71*4882a593Smuzhiyun #define array_index_mask_nospec array_index_mask_nospec
array_index_mask_nospec(unsigned long idx,unsigned long sz)72*4882a593Smuzhiyun static inline unsigned long array_index_mask_nospec(unsigned long idx,
73*4882a593Smuzhiyun 						    unsigned long sz)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	unsigned long mask;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	asm volatile(
78*4882a593Smuzhiyun 	"	cmp	%1, %2\n"
79*4882a593Smuzhiyun 	"	sbc	%0, xzr, xzr\n"
80*4882a593Smuzhiyun 	: "=r" (mask)
81*4882a593Smuzhiyun 	: "r" (idx), "Ir" (sz)
82*4882a593Smuzhiyun 	: "cc");
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	csdb();
85*4882a593Smuzhiyun 	return mask;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun /*
89*4882a593Smuzhiyun  * Ensure that reads of the counter are treated the same as memory reads
90*4882a593Smuzhiyun  * for the purposes of ordering by subsequent memory barriers.
91*4882a593Smuzhiyun  *
92*4882a593Smuzhiyun  * This insanity brought to you by speculative system register reads,
93*4882a593Smuzhiyun  * out-of-order memory accesses, sequence locks and Thomas Gleixner.
94*4882a593Smuzhiyun  *
95*4882a593Smuzhiyun  * http://lists.infradead.org/pipermail/linux-arm-kernel/2019-February/631195.html
96*4882a593Smuzhiyun  */
97*4882a593Smuzhiyun #define arch_counter_enforce_ordering(val) do {				\
98*4882a593Smuzhiyun 	u64 tmp, _val = (val);						\
99*4882a593Smuzhiyun 									\
100*4882a593Smuzhiyun 	asm volatile(							\
101*4882a593Smuzhiyun 	"	eor	%0, %1, %1\n"					\
102*4882a593Smuzhiyun 	"	add	%0, sp, %0\n"					\
103*4882a593Smuzhiyun 	"	ldr	xzr, [%0]"					\
104*4882a593Smuzhiyun 	: "=r" (tmp) : "r" (_val));					\
105*4882a593Smuzhiyun } while (0)
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun #define __smp_mb()	dmb(ish)
108*4882a593Smuzhiyun #define __smp_rmb()	dmb(ishld)
109*4882a593Smuzhiyun #define __smp_wmb()	dmb(ishst)
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun #define __smp_store_release(p, v)					\
112*4882a593Smuzhiyun do {									\
113*4882a593Smuzhiyun 	typeof(p) __p = (p);						\
114*4882a593Smuzhiyun 	union { __unqual_scalar_typeof(*p) __val; char __c[1]; } __u =	\
115*4882a593Smuzhiyun 		{ .__val = (__force __unqual_scalar_typeof(*p)) (v) };	\
116*4882a593Smuzhiyun 	compiletime_assert_atomic_type(*p);				\
117*4882a593Smuzhiyun 	kasan_check_write(__p, sizeof(*p));				\
118*4882a593Smuzhiyun 	switch (sizeof(*p)) {						\
119*4882a593Smuzhiyun 	case 1:								\
120*4882a593Smuzhiyun 		asm volatile ("stlrb %w1, %0"				\
121*4882a593Smuzhiyun 				: "=Q" (*__p)				\
122*4882a593Smuzhiyun 				: "r" (*(__u8 *)__u.__c)		\
123*4882a593Smuzhiyun 				: "memory");				\
124*4882a593Smuzhiyun 		break;							\
125*4882a593Smuzhiyun 	case 2:								\
126*4882a593Smuzhiyun 		asm volatile ("stlrh %w1, %0"				\
127*4882a593Smuzhiyun 				: "=Q" (*__p)				\
128*4882a593Smuzhiyun 				: "r" (*(__u16 *)__u.__c)		\
129*4882a593Smuzhiyun 				: "memory");				\
130*4882a593Smuzhiyun 		break;							\
131*4882a593Smuzhiyun 	case 4:								\
132*4882a593Smuzhiyun 		asm volatile ("stlr %w1, %0"				\
133*4882a593Smuzhiyun 				: "=Q" (*__p)				\
134*4882a593Smuzhiyun 				: "r" (*(__u32 *)__u.__c)		\
135*4882a593Smuzhiyun 				: "memory");				\
136*4882a593Smuzhiyun 		break;							\
137*4882a593Smuzhiyun 	case 8:								\
138*4882a593Smuzhiyun 		asm volatile ("stlr %1, %0"				\
139*4882a593Smuzhiyun 				: "=Q" (*__p)				\
140*4882a593Smuzhiyun 				: "r" (*(__u64 *)__u.__c)		\
141*4882a593Smuzhiyun 				: "memory");				\
142*4882a593Smuzhiyun 		break;							\
143*4882a593Smuzhiyun 	}								\
144*4882a593Smuzhiyun } while (0)
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun #define __smp_load_acquire(p)						\
147*4882a593Smuzhiyun ({									\
148*4882a593Smuzhiyun 	union { __unqual_scalar_typeof(*p) __val; char __c[1]; } __u;	\
149*4882a593Smuzhiyun 	typeof(p) __p = (p);						\
150*4882a593Smuzhiyun 	compiletime_assert_atomic_type(*p);				\
151*4882a593Smuzhiyun 	kasan_check_read(__p, sizeof(*p));				\
152*4882a593Smuzhiyun 	switch (sizeof(*p)) {						\
153*4882a593Smuzhiyun 	case 1:								\
154*4882a593Smuzhiyun 		asm volatile ("ldarb %w0, %1"				\
155*4882a593Smuzhiyun 			: "=r" (*(__u8 *)__u.__c)			\
156*4882a593Smuzhiyun 			: "Q" (*__p) : "memory");			\
157*4882a593Smuzhiyun 		break;							\
158*4882a593Smuzhiyun 	case 2:								\
159*4882a593Smuzhiyun 		asm volatile ("ldarh %w0, %1"				\
160*4882a593Smuzhiyun 			: "=r" (*(__u16 *)__u.__c)			\
161*4882a593Smuzhiyun 			: "Q" (*__p) : "memory");			\
162*4882a593Smuzhiyun 		break;							\
163*4882a593Smuzhiyun 	case 4:								\
164*4882a593Smuzhiyun 		asm volatile ("ldar %w0, %1"				\
165*4882a593Smuzhiyun 			: "=r" (*(__u32 *)__u.__c)			\
166*4882a593Smuzhiyun 			: "Q" (*__p) : "memory");			\
167*4882a593Smuzhiyun 		break;							\
168*4882a593Smuzhiyun 	case 8:								\
169*4882a593Smuzhiyun 		asm volatile ("ldar %0, %1"				\
170*4882a593Smuzhiyun 			: "=r" (*(__u64 *)__u.__c)			\
171*4882a593Smuzhiyun 			: "Q" (*__p) : "memory");			\
172*4882a593Smuzhiyun 		break;							\
173*4882a593Smuzhiyun 	}								\
174*4882a593Smuzhiyun 	(typeof(*p))__u.__val;						\
175*4882a593Smuzhiyun })
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun #define smp_cond_load_relaxed(ptr, cond_expr)				\
178*4882a593Smuzhiyun ({									\
179*4882a593Smuzhiyun 	typeof(ptr) __PTR = (ptr);					\
180*4882a593Smuzhiyun 	__unqual_scalar_typeof(*ptr) VAL;				\
181*4882a593Smuzhiyun 	for (;;) {							\
182*4882a593Smuzhiyun 		VAL = READ_ONCE(*__PTR);				\
183*4882a593Smuzhiyun 		if (cond_expr)						\
184*4882a593Smuzhiyun 			break;						\
185*4882a593Smuzhiyun 		__cmpwait_relaxed(__PTR, VAL);				\
186*4882a593Smuzhiyun 	}								\
187*4882a593Smuzhiyun 	(typeof(*ptr))VAL;						\
188*4882a593Smuzhiyun })
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun #define smp_cond_load_acquire(ptr, cond_expr)				\
191*4882a593Smuzhiyun ({									\
192*4882a593Smuzhiyun 	typeof(ptr) __PTR = (ptr);					\
193*4882a593Smuzhiyun 	__unqual_scalar_typeof(*ptr) VAL;				\
194*4882a593Smuzhiyun 	for (;;) {							\
195*4882a593Smuzhiyun 		VAL = smp_load_acquire(__PTR);				\
196*4882a593Smuzhiyun 		if (cond_expr)						\
197*4882a593Smuzhiyun 			break;						\
198*4882a593Smuzhiyun 		__cmpwait_relaxed(__PTR, VAL);				\
199*4882a593Smuzhiyun 	}								\
200*4882a593Smuzhiyun 	(typeof(*ptr))VAL;						\
201*4882a593Smuzhiyun })
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun #include <asm-generic/barrier.h>
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun #endif	/* __ASSEMBLY__ */
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun #endif	/* __ASM_BARRIER_H */
208