aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-20 19:48:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-20 19:48:59 -0500
commit60815cf2e05057db5b78e398d9734c493560b11e (patch)
tree23d7f55df13cc5a0c072cc8a6f361f8e7050b825
parentbfc7249cc293deac8f2678b7ec3d2407b68c0a33 (diff)
parent5de72a2247ac05bde7c89039631b3d0c6186fafb (diff)
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux
Pull ACCESS_ONCE cleanup preparation from Christian Borntraeger: "kernel: Provide READ_ONCE and ASSIGN_ONCE As discussed on LKML http://marc.info/?i=54611D86.4040306%40de.ibm.com ACCESS_ONCE might fail with specific compilers for non-scalar accesses. Here is a set of patches to tackle that problem. The first patch introduce READ_ONCE and ASSIGN_ONCE. If the data structure is larger than the machine word size memcpy is used and a warning is emitted. The next patches fix up several in-tree users of ACCESS_ONCE on non-scalar types. This does not yet contain a patch that forces ACCESS_ONCE to work only on scalar types. This is targetted for the next merge window as Linux next already contains new offenders regarding ACCESS_ONCE vs. non-scalar types" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/borntraeger/linux: s390/kvm: REPLACE barrier fixup with READ_ONCE arm/spinlock: Replace ACCESS_ONCE with READ_ONCE arm64/spinlock: Replace ACCESS_ONCE READ_ONCE mips/gup: Replace ACCESS_ONCE with READ_ONCE x86/gup: Replace ACCESS_ONCE with READ_ONCE x86/spinlock: Replace ACCESS_ONCE with READ_ONCE mm: replace ACCESS_ONCE with READ_ONCE or barriers kernel: Provide READ_ONCE and ASSIGN_ONCE
-rw-r--r--arch/arm/include/asm/spinlock.h4
-rw-r--r--arch/arm64/include/asm/spinlock.h4
-rw-r--r--arch/mips/mm/gup.c2
-rw-r--r--arch/s390/kvm/gaccess.c18
-rw-r--r--arch/x86/include/asm/spinlock.h8
-rw-r--r--arch/x86/mm/gup.c2
-rw-r--r--include/linux/compiler.h74
-rw-r--r--mm/gup.c2
-rw-r--r--mm/memory.c11
-rw-r--r--mm/rmap.c3
10 files changed, 103 insertions, 25 deletions
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index ac4bfae26702..0fa418463f49 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -120,12 +120,12 @@ static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
120 120
121static inline int arch_spin_is_locked(arch_spinlock_t *lock) 121static inline int arch_spin_is_locked(arch_spinlock_t *lock)
122{ 122{
123 return !arch_spin_value_unlocked(ACCESS_ONCE(*lock)); 123 return !arch_spin_value_unlocked(READ_ONCE(*lock));
124} 124}
125 125
126static inline int arch_spin_is_contended(arch_spinlock_t *lock) 126static inline int arch_spin_is_contended(arch_spinlock_t *lock)
127{ 127{
128 struct __raw_tickets tickets = ACCESS_ONCE(lock->tickets); 128 struct __raw_tickets tickets = READ_ONCE(lock->tickets);
129 return (tickets.next - tickets.owner) > 1; 129 return (tickets.next - tickets.owner) > 1;
130} 130}
131#define arch_spin_is_contended arch_spin_is_contended 131#define arch_spin_is_contended arch_spin_is_contended
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
index c45b7b1b7197..cee128732435 100644
--- a/arch/arm64/include/asm/spinlock.h
+++ b/arch/arm64/include/asm/spinlock.h
@@ -99,12 +99,12 @@ static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
99 99
100static inline int arch_spin_is_locked(arch_spinlock_t *lock) 100static inline int arch_spin_is_locked(arch_spinlock_t *lock)
101{ 101{
102 return !arch_spin_value_unlocked(ACCESS_ONCE(*lock)); 102 return !arch_spin_value_unlocked(READ_ONCE(*lock));
103} 103}
104 104
105static inline int arch_spin_is_contended(arch_spinlock_t *lock) 105static inline int arch_spin_is_contended(arch_spinlock_t *lock)
106{ 106{
107 arch_spinlock_t lockval = ACCESS_ONCE(*lock); 107 arch_spinlock_t lockval = READ_ONCE(*lock);
108 return (lockval.next - lockval.owner) > 1; 108 return (lockval.next - lockval.owner) > 1;
109} 109}
110#define arch_spin_is_contended arch_spin_is_contended 110#define arch_spin_is_contended arch_spin_is_contended
diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c
index 7cba480568c8..70795a67a276 100644
--- a/arch/mips/mm/gup.c
+++ b/arch/mips/mm/gup.c
@@ -30,7 +30,7 @@ retry:
30 30
31 return pte; 31 return pte;
32#else 32#else
33 return ACCESS_ONCE(*ptep); 33 return READ_ONCE(*ptep);
34#endif 34#endif
35} 35}
36 36
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index 8b9ccf02a2c5..8a1be9017730 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -227,12 +227,10 @@ static void ipte_lock_simple(struct kvm_vcpu *vcpu)
227 goto out; 227 goto out;
228 ic = &vcpu->kvm->arch.sca->ipte_control; 228 ic = &vcpu->kvm->arch.sca->ipte_control;
229 do { 229 do {
230 old = *ic; 230 old = READ_ONCE(*ic);
231 barrier();
232 while (old.k) { 231 while (old.k) {
233 cond_resched(); 232 cond_resched();
234 old = *ic; 233 old = READ_ONCE(*ic);
235 barrier();
236 } 234 }
237 new = old; 235 new = old;
238 new.k = 1; 236 new.k = 1;
@@ -251,8 +249,7 @@ static void ipte_unlock_simple(struct kvm_vcpu *vcpu)
251 goto out; 249 goto out;
252 ic = &vcpu->kvm->arch.sca->ipte_control; 250 ic = &vcpu->kvm->arch.sca->ipte_control;
253 do { 251 do {
254 old = *ic; 252 old = READ_ONCE(*ic);
255 barrier();
256 new = old; 253 new = old;
257 new.k = 0; 254 new.k = 0;
258 } while (cmpxchg(&ic->val, old.val, new.val) != old.val); 255 } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
@@ -267,12 +264,10 @@ static void ipte_lock_siif(struct kvm_vcpu *vcpu)
267 264
268 ic = &vcpu->kvm->arch.sca->ipte_control; 265 ic = &vcpu->kvm->arch.sca->ipte_control;
269 do { 266 do {
270 old = *ic; 267 old = READ_ONCE(*ic);
271 barrier();
272 while (old.kg) { 268 while (old.kg) {
273 cond_resched(); 269 cond_resched();
274 old = *ic; 270 old = READ_ONCE(*ic);
275 barrier();
276 } 271 }
277 new = old; 272 new = old;
278 new.k = 1; 273 new.k = 1;
@@ -286,8 +281,7 @@ static void ipte_unlock_siif(struct kvm_vcpu *vcpu)
286 281
287 ic = &vcpu->kvm->arch.sca->ipte_control; 282 ic = &vcpu->kvm->arch.sca->ipte_control;
288 do { 283 do {
289 old = *ic; 284 old = READ_ONCE(*ic);
290 barrier();
291 new = old; 285 new = old;
292 new.kh--; 286 new.kh--;
293 if (!new.kh) 287 if (!new.kh)
diff --git a/arch/x86/include/asm/spinlock.h b/arch/x86/include/asm/spinlock.h
index a4efe477ceab..625660f8a2fc 100644
--- a/arch/x86/include/asm/spinlock.h
+++ b/arch/x86/include/asm/spinlock.h
@@ -92,7 +92,7 @@ static __always_inline void arch_spin_lock(arch_spinlock_t *lock)
92 unsigned count = SPIN_THRESHOLD; 92 unsigned count = SPIN_THRESHOLD;
93 93
94 do { 94 do {
95 if (ACCESS_ONCE(lock->tickets.head) == inc.tail) 95 if (READ_ONCE(lock->tickets.head) == inc.tail)
96 goto out; 96 goto out;
97 cpu_relax(); 97 cpu_relax();
98 } while (--count); 98 } while (--count);
@@ -105,7 +105,7 @@ static __always_inline int arch_spin_trylock(arch_spinlock_t *lock)
105{ 105{
106 arch_spinlock_t old, new; 106 arch_spinlock_t old, new;
107 107
108 old.tickets = ACCESS_ONCE(lock->tickets); 108 old.tickets = READ_ONCE(lock->tickets);
109 if (old.tickets.head != (old.tickets.tail & ~TICKET_SLOWPATH_FLAG)) 109 if (old.tickets.head != (old.tickets.tail & ~TICKET_SLOWPATH_FLAG))
110 return 0; 110 return 0;
111 111
@@ -162,14 +162,14 @@ static __always_inline void arch_spin_unlock(arch_spinlock_t *lock)
162 162
163static inline int arch_spin_is_locked(arch_spinlock_t *lock) 163static inline int arch_spin_is_locked(arch_spinlock_t *lock)
164{ 164{
165 struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets); 165 struct __raw_tickets tmp = READ_ONCE(lock->tickets);
166 166
167 return tmp.tail != tmp.head; 167 return tmp.tail != tmp.head;
168} 168}
169 169
170static inline int arch_spin_is_contended(arch_spinlock_t *lock) 170static inline int arch_spin_is_contended(arch_spinlock_t *lock)
171{ 171{
172 struct __raw_tickets tmp = ACCESS_ONCE(lock->tickets); 172 struct __raw_tickets tmp = READ_ONCE(lock->tickets);
173 173
174 return (__ticket_t)(tmp.tail - tmp.head) > TICKET_LOCK_INC; 174 return (__ticket_t)(tmp.tail - tmp.head) > TICKET_LOCK_INC;
175} 175}
diff --git a/arch/x86/mm/gup.c b/arch/x86/mm/gup.c
index 207d9aef662d..d7547824e763 100644
--- a/arch/x86/mm/gup.c
+++ b/arch/x86/mm/gup.c
@@ -15,7 +15,7 @@
15static inline pte_t gup_get_pte(pte_t *ptep) 15static inline pte_t gup_get_pte(pte_t *ptep)
16{ 16{
17#ifndef CONFIG_X86_PAE 17#ifndef CONFIG_X86_PAE
18 return ACCESS_ONCE(*ptep); 18 return READ_ONCE(*ptep);
19#else 19#else
20 /* 20 /*
21 * With get_user_pages_fast, we walk down the pagetables without taking 21 * With get_user_pages_fast, we walk down the pagetables without taking
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index d5ad7b1118fc..a1c81f80978e 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -186,6 +186,80 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
186# define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__) 186# define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __LINE__)
187#endif 187#endif
188 188
189#include <uapi/linux/types.h>
190
191static __always_inline void data_access_exceeds_word_size(void)
192#ifdef __compiletime_warning
193__compiletime_warning("data access exceeds word size and won't be atomic")
194#endif
195;
196
197static __always_inline void data_access_exceeds_word_size(void)
198{
199}
200
201static __always_inline void __read_once_size(volatile void *p, void *res, int size)
202{
203 switch (size) {
204 case 1: *(__u8 *)res = *(volatile __u8 *)p; break;
205 case 2: *(__u16 *)res = *(volatile __u16 *)p; break;
206 case 4: *(__u32 *)res = *(volatile __u32 *)p; break;
207#ifdef CONFIG_64BIT
208 case 8: *(__u64 *)res = *(volatile __u64 *)p; break;
209#endif
210 default:
211 barrier();
212 __builtin_memcpy((void *)res, (const void *)p, size);
213 data_access_exceeds_word_size();
214 barrier();
215 }
216}
217
218static __always_inline void __assign_once_size(volatile void *p, void *res, int size)
219{
220 switch (size) {
221 case 1: *(volatile __u8 *)p = *(__u8 *)res; break;
222 case 2: *(volatile __u16 *)p = *(__u16 *)res; break;
223 case 4: *(volatile __u32 *)p = *(__u32 *)res; break;
224#ifdef CONFIG_64BIT
225 case 8: *(volatile __u64 *)p = *(__u64 *)res; break;
226#endif
227 default:
228 barrier();
229 __builtin_memcpy((void *)p, (const void *)res, size);
230 data_access_exceeds_word_size();
231 barrier();
232 }
233}
234
235/*
236 * Prevent the compiler from merging or refetching reads or writes. The
237 * compiler is also forbidden from reordering successive instances of
238 * READ_ONCE, ASSIGN_ONCE and ACCESS_ONCE (see below), but only when the
239 * compiler is aware of some particular ordering. One way to make the
240 * compiler aware of ordering is to put the two invocations of READ_ONCE,
241 * ASSIGN_ONCE or ACCESS_ONCE() in different C statements.
242 *
243 * In contrast to ACCESS_ONCE these two macros will also work on aggregate
244 * data types like structs or unions. If the size of the accessed data
245 * type exceeds the word size of the machine (e.g., 32 bits or 64 bits)
246 * READ_ONCE() and ASSIGN_ONCE() will fall back to memcpy and print a
247 * compile-time warning.
248 *
249 * Their two major use cases are: (1) Mediating communication between
250 * process-level code and irq/NMI handlers, all running on the same CPU,
251 * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
252 * mutilate accesses that either do not require ordering or that interact
253 * with an explicit memory barrier or atomic instruction that provides the
254 * required ordering.
255 */
256
257#define READ_ONCE(x) \
258 ({ typeof(x) __val; __read_once_size(&x, &__val, sizeof(__val)); __val; })
259
260#define ASSIGN_ONCE(val, x) \
261 ({ typeof(x) __val; __val = val; __assign_once_size(&x, &__val, sizeof(__val)); __val; })
262
189#endif /* __KERNEL__ */ 263#endif /* __KERNEL__ */
190 264
191#endif /* __ASSEMBLY__ */ 265#endif /* __ASSEMBLY__ */
diff --git a/mm/gup.c b/mm/gup.c
index 0ca1df9075ab..a900759cc807 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -968,7 +968,7 @@ static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end,
968 968
969 pudp = pud_offset(&pgd, addr); 969 pudp = pud_offset(&pgd, addr);
970 do { 970 do {
971 pud_t pud = ACCESS_ONCE(*pudp); 971 pud_t pud = READ_ONCE(*pudp);
972 972
973 next = pud_addr_end(addr, end); 973 next = pud_addr_end(addr, end);
974 if (pud_none(pud)) 974 if (pud_none(pud))
diff --git a/mm/memory.c b/mm/memory.c
index d8aebc52265f..649e7d440bd7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3195,7 +3195,16 @@ static int handle_pte_fault(struct mm_struct *mm,
3195 pte_t entry; 3195 pte_t entry;
3196 spinlock_t *ptl; 3196 spinlock_t *ptl;
3197 3197
3198 entry = ACCESS_ONCE(*pte); 3198 /*
3199 * some architectures can have larger ptes than wordsize,
3200 * e.g.ppc44x-defconfig has CONFIG_PTE_64BIT=y and CONFIG_32BIT=y,
3201 * so READ_ONCE or ACCESS_ONCE cannot guarantee atomic accesses.
3202 * The code below just needs a consistent view for the ifs and
3203 * we later double check anyway with the ptl lock held. So here
3204 * a barrier will do.
3205 */
3206 entry = *pte;
3207 barrier();
3199 if (!pte_present(entry)) { 3208 if (!pte_present(entry)) {
3200 if (pte_none(entry)) { 3209 if (pte_none(entry)) {
3201 if (vma->vm_ops) { 3210 if (vma->vm_ops) {
diff --git a/mm/rmap.c b/mm/rmap.c
index 45ba250babd8..c5bc241127b2 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -583,7 +583,8 @@ pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address)
583 * without holding anon_vma lock for write. So when looking for a 583 * without holding anon_vma lock for write. So when looking for a
584 * genuine pmde (in which to find pte), test present and !THP together. 584 * genuine pmde (in which to find pte), test present and !THP together.
585 */ 585 */
586 pmde = ACCESS_ONCE(*pmd); 586 pmde = *pmd;
587 barrier();
587 if (!pmd_present(pmde) || pmd_trans_huge(pmde)) 588 if (!pmd_present(pmde) || pmd_trans_huge(pmde))
588 pmd = NULL; 589 pmd = NULL;
589out: 590out: