diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 12:23:57 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-22 12:23:57 -0400 |
| commit | 1b674bf106f59e04e24b3825c2f08dcd9a5b7264 (patch) | |
| tree | b90b52b692111f0be66eaf7efb040e35a6e763e3 | |
| parent | e17fdf5c6778ff77d93dd769910992e4073b9348 (diff) | |
| parent | cb8095bba6d24118135a5683a956f4f4fb5f17bb (diff) | |
Merge branch 'x86-atomic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/atomic changes from Ingo Molnar.
* 'x86-atomic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86: atomic64 assembly improvements
x86: Adjust asm constraints in atomic64 wrappers
| -rw-r--r-- | arch/x86/include/asm/alternative.h | 6 | ||||
| -rw-r--r-- | arch/x86/include/asm/atomic64_32.h | 146 | ||||
| -rw-r--r-- | arch/x86/lib/atomic64_32.c | 59 | ||||
| -rw-r--r-- | arch/x86/lib/atomic64_386_32.S | 6 | ||||
| -rw-r--r-- | arch/x86/lib/atomic64_cx8_32.S | 29 |
5 files changed, 101 insertions, 145 deletions
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index 37ad100a2210..49331bedc158 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h | |||
| @@ -145,6 +145,12 @@ static inline int alternatives_text_reserved(void *start, void *end) | |||
| 145 | */ | 145 | */ |
| 146 | #define ASM_OUTPUT2(a...) a | 146 | #define ASM_OUTPUT2(a...) a |
| 147 | 147 | ||
| 148 | /* | ||
| 149 | * use this macro if you need clobbers but no inputs in | ||
| 150 | * alternative_{input,io,call}() | ||
| 151 | */ | ||
| 152 | #define ASM_NO_INPUT_CLOBBER(clbr...) "i" (0) : clbr | ||
| 153 | |||
| 148 | struct paravirt_patch_site; | 154 | struct paravirt_patch_site; |
| 149 | #ifdef CONFIG_PARAVIRT | 155 | #ifdef CONFIG_PARAVIRT |
| 150 | void apply_paravirt(struct paravirt_patch_site *start, | 156 | void apply_paravirt(struct paravirt_patch_site *start, |
diff --git a/arch/x86/include/asm/atomic64_32.h b/arch/x86/include/asm/atomic64_32.h index fa13f0ec2874..198119910da5 100644 --- a/arch/x86/include/asm/atomic64_32.h +++ b/arch/x86/include/asm/atomic64_32.h | |||
| @@ -14,13 +14,52 @@ typedef struct { | |||
| 14 | 14 | ||
| 15 | #define ATOMIC64_INIT(val) { (val) } | 15 | #define ATOMIC64_INIT(val) { (val) } |
| 16 | 16 | ||
| 17 | #define __ATOMIC64_DECL(sym) void atomic64_##sym(atomic64_t *, ...) | ||
| 18 | #ifndef ATOMIC64_EXPORT | ||
| 19 | #define ATOMIC64_DECL_ONE __ATOMIC64_DECL | ||
| 20 | #else | ||
| 21 | #define ATOMIC64_DECL_ONE(sym) __ATOMIC64_DECL(sym); \ | ||
| 22 | ATOMIC64_EXPORT(atomic64_##sym) | ||
| 23 | #endif | ||
| 24 | |||
| 17 | #ifdef CONFIG_X86_CMPXCHG64 | 25 | #ifdef CONFIG_X86_CMPXCHG64 |
| 18 | #define ATOMIC64_ALTERNATIVE_(f, g) "call atomic64_" #g "_cx8" | 26 | #define __alternative_atomic64(f, g, out, in...) \ |
| 27 | asm volatile("call %P[func]" \ | ||
| 28 | : out : [func] "i" (atomic64_##g##_cx8), ## in) | ||
| 29 | |||
| 30 | #define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8) | ||
| 19 | #else | 31 | #else |
| 20 | #define ATOMIC64_ALTERNATIVE_(f, g) ALTERNATIVE("call atomic64_" #f "_386", "call atomic64_" #g "_cx8", X86_FEATURE_CX8) | 32 | #define __alternative_atomic64(f, g, out, in...) \ |
| 33 | alternative_call(atomic64_##f##_386, atomic64_##g##_cx8, \ | ||
| 34 | X86_FEATURE_CX8, ASM_OUTPUT2(out), ## in) | ||
| 35 | |||
| 36 | #define ATOMIC64_DECL(sym) ATOMIC64_DECL_ONE(sym##_cx8); \ | ||
| 37 | ATOMIC64_DECL_ONE(sym##_386) | ||
| 38 | |||
| 39 | ATOMIC64_DECL_ONE(add_386); | ||
| 40 | ATOMIC64_DECL_ONE(sub_386); | ||
| 41 | ATOMIC64_DECL_ONE(inc_386); | ||
| 42 | ATOMIC64_DECL_ONE(dec_386); | ||
| 21 | #endif | 43 | #endif |
| 22 | 44 | ||
| 23 | #define ATOMIC64_ALTERNATIVE(f) ATOMIC64_ALTERNATIVE_(f, f) | 45 | #define alternative_atomic64(f, out, in...) \ |
| 46 | __alternative_atomic64(f, f, ASM_OUTPUT2(out), ## in) | ||
| 47 | |||
| 48 | ATOMIC64_DECL(read); | ||
| 49 | ATOMIC64_DECL(set); | ||
| 50 | ATOMIC64_DECL(xchg); | ||
| 51 | ATOMIC64_DECL(add_return); | ||
| 52 | ATOMIC64_DECL(sub_return); | ||
| 53 | ATOMIC64_DECL(inc_return); | ||
| 54 | ATOMIC64_DECL(dec_return); | ||
| 55 | ATOMIC64_DECL(dec_if_positive); | ||
| 56 | ATOMIC64_DECL(inc_not_zero); | ||
| 57 | ATOMIC64_DECL(add_unless); | ||
| 58 | |||
| 59 | #undef ATOMIC64_DECL | ||
| 60 | #undef ATOMIC64_DECL_ONE | ||
| 61 | #undef __ATOMIC64_DECL | ||
| 62 | #undef ATOMIC64_EXPORT | ||
| 24 | 63 | ||
| 25 | /** | 64 | /** |
| 26 | * atomic64_cmpxchg - cmpxchg atomic64 variable | 65 | * atomic64_cmpxchg - cmpxchg atomic64 variable |
| @@ -50,11 +89,9 @@ static inline long long atomic64_xchg(atomic64_t *v, long long n) | |||
| 50 | long long o; | 89 | long long o; |
| 51 | unsigned high = (unsigned)(n >> 32); | 90 | unsigned high = (unsigned)(n >> 32); |
| 52 | unsigned low = (unsigned)n; | 91 | unsigned low = (unsigned)n; |
| 53 | asm volatile(ATOMIC64_ALTERNATIVE(xchg) | 92 | alternative_atomic64(xchg, "=&A" (o), |
| 54 | : "=A" (o), "+b" (low), "+c" (high) | 93 | "S" (v), "b" (low), "c" (high) |
| 55 | : "S" (v) | 94 | : "memory"); |
| 56 | : "memory" | ||
| 57 | ); | ||
| 58 | return o; | 95 | return o; |
| 59 | } | 96 | } |
| 60 | 97 | ||
| @@ -69,11 +106,9 @@ static inline void atomic64_set(atomic64_t *v, long long i) | |||
| 69 | { | 106 | { |
| 70 | unsigned high = (unsigned)(i >> 32); | 107 | unsigned high = (unsigned)(i >> 32); |
| 71 | unsigned low = (unsigned)i; | 108 | unsigned low = (unsigned)i; |
| 72 | asm volatile(ATOMIC64_ALTERNATIVE(set) | 109 | alternative_atomic64(set, /* no output */, |
| 73 | : "+b" (low), "+c" (high) | 110 | "S" (v), "b" (low), "c" (high) |
| 74 | : "S" (v) | 111 | : "eax", "edx", "memory"); |
| 75 | : "eax", "edx", "memory" | ||
| 76 | ); | ||
| 77 | } | 112 | } |
| 78 | 113 | ||
| 79 | /** | 114 | /** |
| @@ -85,10 +120,7 @@ static inline void atomic64_set(atomic64_t *v, long long i) | |||
| 85 | static inline long long atomic64_read(const atomic64_t *v) | 120 | static inline long long atomic64_read(const atomic64_t *v) |
| 86 | { | 121 | { |
| 87 | long long r; | 122 | long long r; |
| 88 | asm volatile(ATOMIC64_ALTERNATIVE(read) | 123 | alternative_atomic64(read, "=&A" (r), "c" (v) : "memory"); |
| 89 | : "=A" (r), "+c" (v) | ||
| 90 | : : "memory" | ||
| 91 | ); | ||
| 92 | return r; | 124 | return r; |
| 93 | } | 125 | } |
| 94 | 126 | ||
| @@ -101,10 +133,9 @@ static inline long long atomic64_read(const atomic64_t *v) | |||
| 101 | */ | 133 | */ |
| 102 | static inline long long atomic64_add_return(long long i, atomic64_t *v) | 134 | static inline long long atomic64_add_return(long long i, atomic64_t *v) |
| 103 | { | 135 | { |
| 104 | asm volatile(ATOMIC64_ALTERNATIVE(add_return) | 136 | alternative_atomic64(add_return, |
| 105 | : "+A" (i), "+c" (v) | 137 | ASM_OUTPUT2("+A" (i), "+c" (v)), |
| 106 | : : "memory" | 138 | ASM_NO_INPUT_CLOBBER("memory")); |
| 107 | ); | ||
| 108 | return i; | 139 | return i; |
| 109 | } | 140 | } |
| 110 | 141 | ||
| @@ -113,32 +144,25 @@ static inline long long atomic64_add_return(long long i, atomic64_t *v) | |||
| 113 | */ | 144 | */ |
| 114 | static inline long long atomic64_sub_return(long long i, atomic64_t *v) | 145 | static inline long long atomic64_sub_return(long long i, atomic64_t *v) |
| 115 | { | 146 | { |
| 116 | asm volatile(ATOMIC64_ALTERNATIVE(sub_return) | 147 | alternative_atomic64(sub_return, |
| 117 | : "+A" (i), "+c" (v) | 148 | ASM_OUTPUT2("+A" (i), "+c" (v)), |
| 118 | : : "memory" | 149 | ASM_NO_INPUT_CLOBBER("memory")); |
| 119 | ); | ||
| 120 | return i; | 150 | return i; |
| 121 | } | 151 | } |
| 122 | 152 | ||
| 123 | static inline long long atomic64_inc_return(atomic64_t *v) | 153 | static inline long long atomic64_inc_return(atomic64_t *v) |
| 124 | { | 154 | { |
| 125 | long long a; | 155 | long long a; |
| 126 | asm volatile(ATOMIC64_ALTERNATIVE(inc_return) | 156 | alternative_atomic64(inc_return, "=&A" (a), |
| 127 | : "=A" (a) | 157 | "S" (v) : "memory", "ecx"); |
| 128 | : "S" (v) | ||
| 129 | : "memory", "ecx" | ||
| 130 | ); | ||
| 131 | return a; | 158 | return a; |
| 132 | } | 159 | } |
| 133 | 160 | ||
| 134 | static inline long long atomic64_dec_return(atomic64_t *v) | 161 | static inline long long atomic64_dec_return(atomic64_t *v) |
| 135 | { | 162 | { |
| 136 | long long a; | 163 | long long a; |
| 137 | asm volatile(ATOMIC64_ALTERNATIVE(dec_return) | 164 | alternative_atomic64(dec_return, "=&A" (a), |
| 138 | : "=A" (a) | 165 | "S" (v) : "memory", "ecx"); |
| 139 | : "S" (v) | ||
| 140 | : "memory", "ecx" | ||
| 141 | ); | ||
| 142 | return a; | 166 | return a; |
| 143 | } | ||
