hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_BARRIER_H
#define _ASM_X86_BARRIER_H
 
#include <asm/alternative.h>
#include <asm/nops.h>
 
/*
 * Force strict CPU ordering.
 * And yes, this might be required on UP too when we're talking
 * to devices.
 */
 
#ifdef CONFIG_X86_32
#define mb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "mfence", \
                     X86_FEATURE_XMM2) ::: "memory", "cc")
#define rmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "lfence", \
                      X86_FEATURE_XMM2) ::: "memory", "cc")
#define wmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "sfence", \
                      X86_FEATURE_XMM2) ::: "memory", "cc")
#else
#define mb()     asm volatile("mfence":::"memory")
#define rmb()    asm volatile("lfence":::"memory")
#define wmb()    asm volatile("sfence" ::: "memory")
#endif
 
/**
 * array_index_mask_nospec() - generate a mask that is ~0UL when the
 *     bounds check succeeds and 0 otherwise
 * @index: array element index
 * @size: number of elements in array
 *
 * Returns:
 *     0 - (index < size)
 */
static inline unsigned long array_index_mask_nospec(unsigned long index,
       unsigned long size)
{
   unsigned long mask;
 
   asm volatile ("cmp %1,%2; sbb %0,%0;"
           :"=r" (mask)
           :"g"(size),"r" (index)
           :"cc");
   return mask;
}
 
/* Override the default implementation from linux/nospec.h. */
#define array_index_mask_nospec array_index_mask_nospec
 
/* Prevent speculative execution past this barrier. */
#define barrier_nospec() alternative("", "lfence", X86_FEATURE_LFENCE_RDTSC)
 
#define dma_rmb()    barrier()
#define dma_wmb()    barrier()
 
#ifdef CONFIG_X86_32
#define __smp_mb()    asm volatile("lock; addl $0,-4(%%esp)" ::: "memory", "cc")
#else
#define __smp_mb()    asm volatile("lock; addl $0,-4(%%rsp)" ::: "memory", "cc")
#endif
#define __smp_rmb()    dma_rmb()
#define __smp_wmb()    barrier()
#define __smp_store_mb(var, value) do { (void)xchg(&var, value); } while (0)
 
#define __smp_store_release(p, v)                    \
do {                                    \
   compiletime_assert_atomic_type(*p);                \
   barrier();                            \
   WRITE_ONCE(*p, v);                        \
} while (0)
 
#define __smp_load_acquire(p)                        \
({                                    \
   typeof(*p) ___p1 = READ_ONCE(*p);                \
   compiletime_assert_atomic_type(*p);                \
   barrier();                            \
   ___p1;                                \
})
 
/* Atomic operations are already serializing on x86 */
#define __smp_mb__before_atomic()    do { } while (0)
#define __smp_mb__after_atomic()    do { } while (0)
 
#include <asm-generic/barrier.h>
 
/*
 * Make previous memory operations globally visible before
 * a WRMSR.
 *
 * MFENCE makes writes visible, but only affects load/store
 * instructions.  WRMSR is unfortunately not a load/store
 * instruction and is unaffected by MFENCE.  The LFENCE ensures
 * that the WRMSR is not reordered.
 *
 * Most WRMSRs are full serializing instructions themselves and
 * do not require this barrier.  This is only required for the
 * IA32_TSC_DEADLINE and X2APIC MSRs.
 */
static inline void weak_wrmsr_fence(void)
{
   asm volatile("mfence; lfence" : : : "memory");
}
 
#endif /* _ASM_X86_BARRIER_H */