diff options
-rw-r--r-- | arch/arm/include/asm/spinlock.h | 4 | ||||
-rw-r--r-- | arch/arm64/include/asm/spinlock.h | 4 | ||||
-rw-r--r-- | arch/mips/mm/gup.c | 2 | ||||
-rw-r--r-- | arch/s390/kvm/gaccess.c | 18 | ||||
-rw-r--r-- | arch/x86/include/asm/spinlock.h | 8 | ||||
-rw-r--r-- | arch/x86/mm/gup.c | 2 | ||||
-rw-r--r-- | include/linux/compiler.h | 74 | ||||
-rw-r--r-- | mm/gup.c | 2 | ||||
-rw-r--r-- | mm/memory.c | 11 | ||||
-rw-r--r-- | mm/rmap.c | 3 |
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 | ||
121 | static inline int arch_spin_is_locked(arch_spinlock_t *lock) | 121 | static 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 | ||
126 | static inline int arch_spin_is_contended(arch_spinlock_t *lock) | 126 | static 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 | ||
100 | static inline int arch_spin_is_locked(arch_spinlock_t *lock) | 100 | static 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 | ||
105 | static inline int arch_spin_is_contended(arch_spinlock_t *lock) | 105 | static 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 | ||
163 | static inline int arch_spin_is_locked(arch_spinlock_t *lock) | 163 | static 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 | ||
170 | static inline int arch_spin_is_contended(arch_spinlock_t *lock) | 170 | static 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 @@ | |||
15 | static inline pte_t gup_get_pte(pte_t *ptep) | 15 | static 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 | |||
191 | static __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 | |||
197 | static __always_inline void data_access_exceeds_word_size(void) | ||
198 | { | ||
199 | } | ||
200 | |||
201 | static __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 | |||
218 | static __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__ */ |
@@ -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) { |
@@ -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; |
589 | out: | 590 | out: |