diff options
Diffstat (limited to 'arch/x86/um/asm/barrier.h')
-rw-r--r-- | arch/x86/um/asm/barrier.h | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/arch/x86/um/asm/barrier.h b/arch/x86/um/asm/barrier.h new file mode 100644 index 000000000000..7d01b8c56c00 --- /dev/null +++ b/arch/x86/um/asm/barrier.h | |||
@@ -0,0 +1,75 @@ | |||
1 | #ifndef _ASM_UM_BARRIER_H_ | ||
2 | #define _ASM_UM_BARRIER_H_ | ||
3 | |||
4 | #include <asm/asm.h> | ||
5 | #include <asm/segment.h> | ||
6 | #include <asm/cpufeature.h> | ||
7 | #include <asm/cmpxchg.h> | ||
8 | #include <asm/nops.h> | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/irqflags.h> | ||
12 | |||
13 | /* | ||
14 | * Force strict CPU ordering. | ||
15 | * And yes, this is required on UP too when we're talking | ||
16 | * to devices. | ||
17 | */ | ||
18 | #ifdef CONFIG_X86_32 | ||
19 | |||
20 | #define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2) | ||
21 | #define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2) | ||
22 | #define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM) | ||
23 | |||
24 | #else /* CONFIG_X86_32 */ | ||
25 | |||
26 | #define mb() asm volatile("mfence" : : : "memory") | ||
27 | #define rmb() asm volatile("lfence" : : : "memory") | ||
28 | #define wmb() asm volatile("sfence" : : : "memory") | ||
29 | |||
30 | #endif /* CONFIG_X86_32 */ | ||
31 | |||
32 | #define read_barrier_depends() do { } while (0) | ||
33 | |||
34 | #ifdef CONFIG_SMP | ||
35 | |||
36 | #define smp_mb() mb() | ||
37 | #ifdef CONFIG_X86_PPRO_FENCE | ||
38 | #define smp_rmb() rmb() | ||
39 | #else /* CONFIG_X86_PPRO_FENCE */ | ||
40 | #define smp_rmb() barrier() | ||
41 | #endif /* CONFIG_X86_PPRO_FENCE */ | ||
42 | |||
43 | #ifdef CONFIG_X86_OOSTORE | ||
44 | #define smp_wmb() wmb() | ||
45 | #else /* CONFIG_X86_OOSTORE */ | ||
46 | #define smp_wmb() barrier() | ||
47 | #endif /* CONFIG_X86_OOSTORE */ | ||
48 | |||
49 | #define smp_read_barrier_depends() read_barrier_depends() | ||
50 | #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) | ||
51 | |||
52 | #else /* CONFIG_SMP */ | ||
53 | |||
54 | #define smp_mb() barrier() | ||
55 | #define smp_rmb() barrier() | ||
56 | #define smp_wmb() barrier() | ||
57 | #define smp_read_barrier_depends() do { } while (0) | ||
58 | #define set_mb(var, value) do { var = value; barrier(); } while (0) | ||
59 | |||
60 | #endif /* CONFIG_SMP */ | ||
61 | |||
62 | /* | ||
63 | * Stop RDTSC speculation. This is needed when you need to use RDTSC | ||
64 | * (or get_cycles or vread that possibly accesses the TSC) in a defined | ||
65 | * code region. | ||
66 | * | ||
67 | * (Could use an alternative three way for this if there was one.) | ||
68 | */ | ||
69 | static inline void rdtsc_barrier(void) | ||
70 | { | ||
71 | alternative(ASM_NOP3, "mfence", X86_FEATURE_MFENCE_RDTSC); | ||
72 | alternative(ASM_NOP3, "lfence", X86_FEATURE_LFENCE_RDTSC); | ||
73 | } | ||
74 | |||
75 | #endif | ||