xref: /linux/arch/x86/include/asm/barrier.h (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _ASM_X86_BARRIER_H
3 #define _ASM_X86_BARRIER_H
4 
5 #include <asm/alternative.h>
6 #include <asm/nops.h>
7 
8 /*
9  * Force strict CPU ordering.
10  * And yes, this might be required on UP too when we're talking
11  * to devices.
12  */
13 
14 #ifdef CONFIG_X86_32
15 #define mb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "mfence", \
16 				      X86_FEATURE_XMM2) ::: "memory", "cc")
17 #define rmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "lfence", \
18 				       X86_FEATURE_XMM2) ::: "memory", "cc")
19 #define wmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "sfence", \
20 				       X86_FEATURE_XMM2) ::: "memory", "cc")
21 #else
22 #define __mb()	asm volatile("mfence":::"memory")
23 #define __rmb()	asm volatile("lfence":::"memory")
24 #define __wmb()	asm volatile("sfence" ::: "memory")
25 #endif
26 
27 /**
28  * array_index_mask_nospec() - generate a mask that is ~0UL when the
29  * 	bounds check succeeds and 0 otherwise
30  * @index: array element index
31  * @size: number of elements in array
32  *
33  * Returns:
34  *     0 - (index < size)
35  */
36 #define array_index_mask_nospec(idx,sz) ({	\
37 	typeof((idx)+(sz)) __idx = (idx);	\
38 	typeof(__idx) __sz = (sz);		\
39 	unsigned long __mask;			\
40 	asm volatile ("cmp %1,%2; sbb %0,%0"	\
41 			:"=r" (__mask)		\
42 			:ASM_INPUT_G (__sz),	\
43 			 "r" (__idx)		\
44 			:"cc");			\
45 	__mask; })
46 
47 /* Prevent speculative execution past this barrier. */
48 #define barrier_nospec() alternative("", "lfence", X86_FEATURE_LFENCE_RDTSC)
49 
50 #define __dma_rmb()	barrier()
51 #define __dma_wmb()	barrier()
52 
53 #define __smp_mb()	asm volatile("lock; addl $0,-4(%%" _ASM_SP ")" ::: "memory", "cc")
54 
55 #define __smp_rmb()	dma_rmb()
56 #define __smp_wmb()	barrier()
57 #define __smp_store_mb(var, value) do { (void)xchg(&var, value); } while (0)
58 
59 #define __smp_store_release(p, v)					\
60 do {									\
61 	compiletime_assert_atomic_type(*p);				\
62 	barrier();							\
63 	WRITE_ONCE(*p, v);						\
64 } while (0)
65 
66 #define __smp_load_acquire(p)						\
67 ({									\
68 	typeof(*p) ___p1 = READ_ONCE(*p);				\
69 	compiletime_assert_atomic_type(*p);				\
70 	barrier();							\
71 	___p1;								\
72 })
73 
74 /* Atomic operations are already serializing on x86 */
75 #define __smp_mb__before_atomic()	do { } while (0)
76 #define __smp_mb__after_atomic()	do { } while (0)
77 
78 /* Writing to CR3 provides a full memory barrier in switch_mm(). */
79 #define smp_mb__after_switch_mm()	do { } while (0)
80 
81 #include <asm-generic/barrier.h>
82 
83 #endif /* _ASM_X86_BARRIER_H */
84