Contents of /trunk/kernel-alx-legacy/patches-4.9/0344-4.9.245-all-fixes.patch
Parent Directory | Revision Log
Revision 3646 -
(show annotations)
(download)
Mon Oct 24 14:07:26 2022 UTC (23 months ago) by niro
File size: 48286 byte(s)
Mon Oct 24 14:07:26 2022 UTC (23 months ago) by niro
File size: 48286 byte(s)
-linux-4.9.245
1 | diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt |
2 | index e51e42d9f6460..713765521c451 100644 |
3 | --- a/Documentation/kernel-parameters.txt |
4 | +++ b/Documentation/kernel-parameters.txt |
5 | @@ -2527,6 +2527,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. |
6 | mds=off [X86] |
7 | tsx_async_abort=off [X86] |
8 | kvm.nx_huge_pages=off [X86] |
9 | + no_entry_flush [PPC] |
10 | + no_uaccess_flush [PPC] |
11 | |
12 | Exceptions: |
13 | This does not have any effect on |
14 | @@ -2833,6 +2835,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. |
15 | |
16 | noefi Disable EFI runtime services support. |
17 | |
18 | + no_entry_flush [PPC] Don't flush the L1-D cache when entering the kernel. |
19 | + |
20 | noexec [IA-64] |
21 | |
22 | noexec [X86] |
23 | @@ -2882,6 +2886,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted. |
24 | nospec_store_bypass_disable |
25 | [HW] Disable all mitigations for the Speculative Store Bypass vulnerability |
26 | |
27 | + no_uaccess_flush |
28 | + [PPC] Don't flush the L1-D cache after accessing user data. |
29 | + |
30 | noxsave [BUGS=X86] Disables x86 extended register state save |
31 | and restore using xsave. The kernel will fallback to |
32 | enabling legacy floating-point and sse state. |
33 | diff --git a/Makefile b/Makefile |
34 | index 27314b9f0fe67..b72f286d3bcdd 100644 |
35 | --- a/Makefile |
36 | +++ b/Makefile |
37 | @@ -1,6 +1,6 @@ |
38 | VERSION = 4 |
39 | PATCHLEVEL = 9 |
40 | -SUBLEVEL = 244 |
41 | +SUBLEVEL = 245 |
42 | EXTRAVERSION = |
43 | NAME = Roaring Lionus |
44 | |
45 | diff --git a/arch/powerpc/include/asm/book3s/64/kup-radix.h b/arch/powerpc/include/asm/book3s/64/kup-radix.h |
46 | new file mode 100644 |
47 | index 0000000000000..aa54ac2e5659e |
48 | --- /dev/null |
49 | +++ b/arch/powerpc/include/asm/book3s/64/kup-radix.h |
50 | @@ -0,0 +1,22 @@ |
51 | +/* SPDX-License-Identifier: GPL-2.0 */ |
52 | +#ifndef _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H |
53 | +#define _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H |
54 | + |
55 | +DECLARE_STATIC_KEY_FALSE(uaccess_flush_key); |
56 | + |
57 | +/* Prototype for function defined in exceptions-64s.S */ |
58 | +void do_uaccess_flush(void); |
59 | + |
60 | +static __always_inline void allow_user_access(void __user *to, const void __user *from, |
61 | + unsigned long size) |
62 | +{ |
63 | +} |
64 | + |
65 | +static inline void prevent_user_access(void __user *to, const void __user *from, |
66 | + unsigned long size) |
67 | +{ |
68 | + if (static_branch_unlikely(&uaccess_flush_key)) |
69 | + do_uaccess_flush(); |
70 | +} |
71 | + |
72 | +#endif /* _ASM_POWERPC_BOOK3S_64_KUP_RADIX_H */ |
73 | diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h |
74 | index e2200100828d4..6ffec5b18a6dc 100644 |
75 | --- a/arch/powerpc/include/asm/exception-64s.h |
76 | +++ b/arch/powerpc/include/asm/exception-64s.h |
77 | @@ -66,11 +66,18 @@ |
78 | nop; \ |
79 | nop |
80 | |
81 | +#define ENTRY_FLUSH_SLOT \ |
82 | + ENTRY_FLUSH_FIXUP_SECTION; \ |
83 | + nop; \ |
84 | + nop; \ |
85 | + nop; |
86 | + |
87 | /* |
88 | * r10 must be free to use, r13 must be paca |
89 | */ |
90 | #define INTERRUPT_TO_KERNEL \ |
91 | - STF_ENTRY_BARRIER_SLOT |
92 | + STF_ENTRY_BARRIER_SLOT; \ |
93 | + ENTRY_FLUSH_SLOT |
94 | |
95 | /* |
96 | * Macros for annotating the expected destination of (h)rfid |
97 | @@ -563,6 +570,10 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) |
98 | EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_HV, vec); \ |
99 | EXCEPTION_PROLOG_PSERIES_1(label, EXC_HV) |
100 | |
101 | +#define MASKABLE_RELON_EXCEPTION_PSERIES_OOL(vec, label) \ |
102 | + EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_PR, vec); \ |
103 | + EXCEPTION_PROLOG_PSERIES_1(label, EXC_STD) |
104 | + |
105 | /* |
106 | * Our exception common code can be passed various "additions" |
107 | * to specify the behaviour of interrupts, whether to kick the |
108 | diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h |
109 | index 175128e19025b..a8e7ca27fb54c 100644 |
110 | --- a/arch/powerpc/include/asm/feature-fixups.h |
111 | +++ b/arch/powerpc/include/asm/feature-fixups.h |
112 | @@ -205,6 +205,22 @@ void setup_feature_keys(void); |
113 | FTR_ENTRY_OFFSET 955b-956b; \ |
114 | .popsection; |
115 | |
116 | +#define UACCESS_FLUSH_FIXUP_SECTION \ |
117 | +959: \ |
118 | + .pushsection __uaccess_flush_fixup,"a"; \ |
119 | + .align 2; \ |
120 | +960: \ |
121 | + FTR_ENTRY_OFFSET 959b-960b; \ |
122 | + .popsection; |
123 | + |
124 | +#define ENTRY_FLUSH_FIXUP_SECTION \ |
125 | +957: \ |
126 | + .pushsection __entry_flush_fixup,"a"; \ |
127 | + .align 2; \ |
128 | +958: \ |
129 | + FTR_ENTRY_OFFSET 957b-958b; \ |
130 | + .popsection; |
131 | + |
132 | #define RFI_FLUSH_FIXUP_SECTION \ |
133 | 951: \ |
134 | .pushsection __rfi_flush_fixup,"a"; \ |
135 | @@ -236,8 +252,11 @@ void setup_feature_keys(void); |
136 | #ifndef __ASSEMBLY__ |
137 | |
138 | extern long stf_barrier_fallback; |
139 | +extern long entry_flush_fallback; |
140 | extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; |
141 | extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; |
142 | +extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup; |
143 | +extern long __start___entry_flush_fixup, __stop___entry_flush_fixup; |
144 | extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; |
145 | extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup; |
146 | extern long __start__btb_flush_fixup, __stop__btb_flush_fixup; |
147 | diff --git a/arch/powerpc/include/asm/futex.h b/arch/powerpc/include/asm/futex.h |
148 | index b73ab8a7ebc3f..10746519b351b 100644 |
149 | --- a/arch/powerpc/include/asm/futex.h |
150 | +++ b/arch/powerpc/include/asm/futex.h |
151 | @@ -36,6 +36,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, |
152 | { |
153 | int oldval = 0, ret; |
154 | |
155 | + allow_write_to_user(uaddr, sizeof(*uaddr)); |
156 | pagefault_disable(); |
157 | |
158 | switch (op) { |
159 | @@ -62,6 +63,7 @@ static inline int arch_futex_atomic_op_inuser(int op, int oparg, int *oval, |
160 | |
161 | *oval = oldval; |
162 | |
163 | + prevent_write_to_user(uaddr, sizeof(*uaddr)); |
164 | return ret; |
165 | } |
166 | |
167 | @@ -75,6 +77,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
168 | if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) |
169 | return -EFAULT; |
170 | |
171 | + allow_write_to_user(uaddr, sizeof(*uaddr)); |
172 | __asm__ __volatile__ ( |
173 | PPC_ATOMIC_ENTRY_BARRIER |
174 | "1: lwarx %1,0,%3 # futex_atomic_cmpxchg_inatomic\n\ |
175 | @@ -97,6 +100,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, |
176 | : "cc", "memory"); |
177 | |
178 | *uval = prev; |
179 | + prevent_write_to_user(uaddr, sizeof(*uaddr)); |
180 | return ret; |
181 | } |
182 | |
183 | diff --git a/arch/powerpc/include/asm/kup.h b/arch/powerpc/include/asm/kup.h |
184 | new file mode 100644 |
185 | index 0000000000000..f0f8e36ad71f5 |
186 | --- /dev/null |
187 | +++ b/arch/powerpc/include/asm/kup.h |
188 | @@ -0,0 +1,40 @@ |
189 | +/* SPDX-License-Identifier: GPL-2.0 */ |
190 | +#ifndef _ASM_POWERPC_KUP_H_ |
191 | +#define _ASM_POWERPC_KUP_H_ |
192 | + |
193 | +#ifndef __ASSEMBLY__ |
194 | + |
195 | +#include <asm/pgtable.h> |
196 | + |
197 | +#ifdef CONFIG_PPC_BOOK3S_64 |
198 | +#include <asm/book3s/64/kup-radix.h> |
199 | +#else |
200 | +static inline void allow_user_access(void __user *to, const void __user *from, |
201 | + unsigned long size) { } |
202 | +static inline void prevent_user_access(void __user *to, const void __user *from, |
203 | + unsigned long size) { } |
204 | +#endif /* CONFIG_PPC_BOOK3S_64 */ |
205 | + |
206 | +static inline void allow_read_from_user(const void __user *from, unsigned long size) |
207 | +{ |
208 | + allow_user_access(NULL, from, size); |
209 | +} |
210 | + |
211 | +static inline void allow_write_to_user(void __user *to, unsigned long size) |
212 | +{ |
213 | + allow_user_access(to, NULL, size); |
214 | +} |
215 | + |
216 | +static inline void prevent_read_from_user(const void __user *from, unsigned long size) |
217 | +{ |
218 | + prevent_user_access(NULL, from, size); |
219 | +} |
220 | + |
221 | +static inline void prevent_write_to_user(void __user *to, unsigned long size) |
222 | +{ |
223 | + prevent_user_access(to, NULL, size); |
224 | +} |
225 | + |
226 | +#endif /* !__ASSEMBLY__ */ |
227 | + |
228 | +#endif /* _ASM_POWERPC_KUP_H_ */ |
229 | diff --git a/arch/powerpc/include/asm/security_features.h b/arch/powerpc/include/asm/security_features.h |
230 | index ccf44c135389a..3b45a64e491e5 100644 |
231 | --- a/arch/powerpc/include/asm/security_features.h |
232 | +++ b/arch/powerpc/include/asm/security_features.h |
233 | @@ -84,12 +84,19 @@ static inline bool security_ftr_enabled(unsigned long feature) |
234 | // Software required to flush link stack on context switch |
235 | #define SEC_FTR_FLUSH_LINK_STACK 0x0000000000001000ull |
236 | |
237 | +// The L1-D cache should be flushed when entering the kernel |
238 | +#define SEC_FTR_L1D_FLUSH_ENTRY 0x0000000000004000ull |
239 | + |
240 | +// The L1-D cache should be flushed after user accesses from the kernel |
241 | +#define SEC_FTR_L1D_FLUSH_UACCESS 0x0000000000008000ull |
242 | |
243 | // Features enabled by default |
244 | #define SEC_FTR_DEFAULT \ |
245 | (SEC_FTR_L1D_FLUSH_HV | \ |
246 | SEC_FTR_L1D_FLUSH_PR | \ |
247 | SEC_FTR_BNDS_CHK_SPEC_BAR | \ |
248 | + SEC_FTR_L1D_FLUSH_ENTRY | \ |
249 | + SEC_FTR_L1D_FLUSH_UACCESS | \ |
250 | SEC_FTR_FAVOUR_SECURITY) |
251 | |
252 | #endif /* _ASM_POWERPC_SECURITY_FEATURES_H */ |
253 | diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h |
254 | index 862ebce3ae544..944c9eb0cdaf2 100644 |
255 | --- a/arch/powerpc/include/asm/setup.h |
256 | +++ b/arch/powerpc/include/asm/setup.h |
257 | @@ -50,12 +50,16 @@ enum l1d_flush_type { |
258 | }; |
259 | |
260 | void setup_rfi_flush(enum l1d_flush_type, bool enable); |
261 | +void setup_entry_flush(bool enable); |
262 | +void setup_uaccess_flush(bool enable); |
263 | void do_rfi_flush_fixups(enum l1d_flush_type types); |
264 | #ifdef CONFIG_PPC_BARRIER_NOSPEC |
265 | void setup_barrier_nospec(void); |
266 | #else |
267 | static inline void setup_barrier_nospec(void) { }; |
268 | #endif |
269 | +void do_uaccess_flush_fixups(enum l1d_flush_type types); |
270 | +void do_entry_flush_fixups(enum l1d_flush_type types); |
271 | void do_barrier_nospec_fixups(bool enable); |
272 | extern bool barrier_nospec_enabled; |
273 | |
274 | diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h |
275 | index da852153c1f8a..fde865a4e2cb1 100644 |
276 | --- a/arch/powerpc/include/asm/uaccess.h |
277 | +++ b/arch/powerpc/include/asm/uaccess.h |
278 | @@ -9,6 +9,7 @@ |
279 | #include <asm/asm-compat.h> |
280 | #include <asm/processor.h> |
281 | #include <asm/page.h> |
282 | +#include <asm/kup.h> |
283 | |
284 | #define VERIFY_READ 0 |
285 | #define VERIFY_WRITE 1 |
286 | @@ -105,9 +106,14 @@ struct exception_table_entry { |
287 | __put_user_check((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) |
288 | |
289 | #define __get_user(x, ptr) \ |
290 | - __get_user_nocheck((x), (ptr), sizeof(*(ptr))) |
291 | + __get_user_nocheck((x), (ptr), sizeof(*(ptr)), true) |
292 | #define __put_user(x, ptr) \ |
293 | - __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr))) |
294 | + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), true) |
295 | + |
296 | +#define __get_user_allowed(x, ptr) \ |
297 | + __get_user_nocheck((x), (ptr), sizeof(*(ptr)), false) |
298 | +#define __put_user_allowed(x, ptr) \ |
299 | + __put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), false) |
300 | |
301 | #define __get_user_inatomic(x, ptr) \ |
302 | __get_user_nosleep((x), (ptr), sizeof(*(ptr))) |
303 | @@ -161,7 +167,7 @@ extern long __put_user_bad(void); |
304 | : "r" (x), "b" (addr), "i" (-EFAULT), "0" (err)) |
305 | #endif /* __powerpc64__ */ |
306 | |
307 | -#define __put_user_size(x, ptr, size, retval) \ |
308 | +#define __put_user_size_allowed(x, ptr, size, retval) \ |
309 | do { \ |
310 | retval = 0; \ |
311 | switch (size) { \ |
312 | @@ -173,14 +179,28 @@ do { \ |
313 | } \ |
314 | } while (0) |
315 | |
316 | -#define __put_user_nocheck(x, ptr, size) \ |
317 | +#define __put_user_size(x, ptr, size, retval) \ |
318 | +do { \ |
319 | + allow_write_to_user(ptr, size); \ |
320 | + __put_user_size_allowed(x, ptr, size, retval); \ |
321 | + prevent_write_to_user(ptr, size); \ |
322 | +} while (0) |
323 | + |
324 | +#define __put_user_nocheck(x, ptr, size, do_allow) \ |
325 | ({ \ |
326 | long __pu_err; \ |
327 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ |
328 | + __typeof__(*(ptr)) __pu_val = (x); \ |
329 | + __typeof__(size) __pu_size = (size); \ |
330 | + \ |
331 | if (!is_kernel_addr((unsigned long)__pu_addr)) \ |
332 | might_fault(); \ |
333 | - __chk_user_ptr(ptr); \ |
334 | - __put_user_size((x), __pu_addr, (size), __pu_err); \ |
335 | + __chk_user_ptr(__pu_addr); \ |
336 | + if (do_allow) \ |
337 | + __put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \ |
338 | + else \ |
339 | + __put_user_size_allowed(__pu_val, __pu_addr, __pu_size, __pu_err); \ |
340 | + \ |
341 | __pu_err; \ |
342 | }) |
343 | |
344 | @@ -188,9 +208,13 @@ do { \ |
345 | ({ \ |
346 | long __pu_err = -EFAULT; \ |
347 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ |
348 | + __typeof__(*(ptr)) __pu_val = (x); \ |
349 | + __typeof__(size) __pu_size = (size); \ |
350 | + \ |
351 | might_fault(); \ |
352 | - if (access_ok(VERIFY_WRITE, __pu_addr, size)) \ |
353 | - __put_user_size((x), __pu_addr, (size), __pu_err); \ |
354 | + if (access_ok(VERIFY_WRITE, __pu_addr, __pu_size)) \ |
355 | + __put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \ |
356 | + \ |
357 | __pu_err; \ |
358 | }) |
359 | |
360 | @@ -198,8 +222,12 @@ do { \ |
361 | ({ \ |
362 | long __pu_err; \ |
363 | __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ |
364 | - __chk_user_ptr(ptr); \ |
365 | - __put_user_size((x), __pu_addr, (size), __pu_err); \ |
366 | + __typeof__(*(ptr)) __pu_val = (x); \ |
367 | + __typeof__(size) __pu_size = (size); \ |
368 | + \ |
369 | + __chk_user_ptr(__pu_addr); \ |
370 | + __put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \ |
371 | + \ |
372 | __pu_err; \ |
373 | }) |
374 | |
375 | @@ -246,7 +274,7 @@ extern long __get_user_bad(void); |
376 | : "b" (addr), "i" (-EFAULT), "0" (err)) |
377 | #endif /* __powerpc64__ */ |
378 | |
379 | -#define __get_user_size(x, ptr, size, retval) \ |
380 | +#define __get_user_size_allowed(x, ptr, size, retval) \ |
381 | do { \ |
382 | retval = 0; \ |
383 | __chk_user_ptr(ptr); \ |
384 | @@ -261,17 +289,30 @@ do { \ |
385 | } \ |
386 | } while (0) |
387 | |
388 | -#define __get_user_nocheck(x, ptr, size) \ |
389 | +#define __get_user_size(x, ptr, size, retval) \ |
390 | +do { \ |
391 | + allow_read_from_user(ptr, size); \ |
392 | + __get_user_size_allowed(x, ptr, size, retval); \ |
393 | + prevent_read_from_user(ptr, size); \ |
394 | +} while (0) |
395 | + |
396 | +#define __get_user_nocheck(x, ptr, size, do_allow) \ |
397 | ({ \ |
398 | long __gu_err; \ |
399 | unsigned long __gu_val; \ |
400 | __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
401 | - __chk_user_ptr(ptr); \ |
402 | + __typeof__(size) __gu_size = (size); \ |
403 | + \ |
404 | + __chk_user_ptr(__gu_addr); \ |
405 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ |
406 | might_fault(); \ |
407 | barrier_nospec(); \ |
408 | - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
409 | + if (do_allow) \ |
410 | + __get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \ |
411 | + else \ |
412 | + __get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \ |
413 | (x) = (__typeof__(*(ptr)))__gu_val; \ |
414 | + \ |
415 | __gu_err; \ |
416 | }) |
417 | |
418 | @@ -280,12 +321,15 @@ do { \ |
419 | long __gu_err = -EFAULT; \ |
420 | unsigned long __gu_val = 0; \ |
421 | __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
422 | + __typeof__(size) __gu_size = (size); \ |
423 | + \ |
424 | might_fault(); \ |
425 | - if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ |
426 | + if (access_ok(VERIFY_READ, __gu_addr, __gu_size)) { \ |
427 | barrier_nospec(); \ |
428 | - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
429 | + __get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \ |
430 | } \ |
431 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
432 | + \ |
433 | __gu_err; \ |
434 | }) |
435 | |
436 | @@ -294,10 +338,13 @@ do { \ |
437 | long __gu_err; \ |
438 | unsigned long __gu_val; \ |
439 | __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
440 | - __chk_user_ptr(ptr); \ |
441 | + __typeof__(size) __gu_size = (size); \ |
442 | + \ |
443 | + __chk_user_ptr(__gu_addr); \ |
444 | barrier_nospec(); \ |
445 | - __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
446 | + __get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \ |
447 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
448 | + \ |
449 | __gu_err; \ |
450 | }) |
451 | |
452 | @@ -312,9 +359,14 @@ extern unsigned long __copy_tofrom_user(void __user *to, |
453 | static inline unsigned long copy_from_user(void *to, |
454 | const void __user *from, unsigned long n) |
455 | { |
456 | + unsigned long ret; |
457 | + |
458 | if (likely(access_ok(VERIFY_READ, from, n))) { |
459 | check_object_size(to, n, false); |
460 | - return __copy_tofrom_user((__force void __user *)to, from, n); |
461 | + allow_user_access(to, from, n); |
462 | + ret = __copy_tofrom_user((__force void __user *)to, from, n); |
463 | + prevent_user_access(to, from, n); |
464 | + return ret; |
465 | } |
466 | memset(to, 0, n); |
467 | return n; |
468 | @@ -347,8 +399,9 @@ extern unsigned long copy_in_user(void __user *to, const void __user *from, |
469 | static inline unsigned long __copy_from_user_inatomic(void *to, |
470 | const void __user *from, unsigned long n) |
471 | { |
472 | + unsigned long ret; |
473 | if (__builtin_constant_p(n) && (n <= 8)) { |
474 | - unsigned long ret = 1; |
475 | + ret = 1; |
476 | |
477 | switch (n) { |
478 | case 1: |
479 | @@ -375,27 +428,32 @@ static inline unsigned long __copy_from_user_inatomic(void *to, |
480 | check_object_size(to, n, false); |
481 | |
482 | barrier_nospec(); |
483 | - return __copy_tofrom_user((__force void __user *)to, from, n); |
484 | + allow_read_from_user(from, n); |
485 | + ret = __copy_tofrom_user((__force void __user *)to, from, n); |
486 | + prevent_read_from_user(from, n); |
487 | + return ret; |
488 | } |
489 | |
490 | static inline unsigned long __copy_to_user_inatomic(void __user *to, |
491 | const void *from, unsigned long n) |
492 | { |
493 | + unsigned long ret; |
494 | + |
495 | if (__builtin_constant_p(n) && (n <= 8)) { |
496 | - unsigned long ret = 1; |
497 | + ret = 1; |
498 | |
499 | switch (n) { |
500 | case 1: |
501 | - __put_user_size(*(u8 *)from, (u8 __user *)to, 1, ret); |
502 | + __put_user_size_allowed(*(u8 *)from, (u8 __user *)to, 1, ret); |
503 | break; |
504 | case 2: |
505 | - __put_user_size(*(u16 *)from, (u16 __user *)to, 2, ret); |
506 | + __put_user_size_allowed(*(u16 *)from, (u16 __user *)to, 2, ret); |
507 | break; |
508 | case 4: |
509 | - __put_user_size(*(u32 *)from, (u32 __user *)to, 4, ret); |
510 | + __put_user_size_allowed(*(u32 *)from, (u32 __user *)to, 4, ret); |
511 | break; |
512 | case 8: |
513 | - __put_user_size(*(u64 *)from, (u64 __user *)to, 8, ret); |
514 | + __put_user_size_allowed(*(u64 *)from, (u64 __user *)to, 8, ret); |
515 | break; |
516 | } |
517 | if (ret == 0) |
518 | @@ -403,8 +461,10 @@ static inline unsigned long __copy_to_user_inatomic(void __user *to, |
519 | } |
520 | |
521 | check_object_size(from, n, true); |
522 | - |
523 | - return __copy_tofrom_user(to, (__force const void __user *)from, n); |
524 | + allow_write_to_user(to, n); |
525 | + ret = __copy_tofrom_user(to, (__force const void __user *)from, n); |
526 | + prevent_write_to_user(to, n); |
527 | + return ret; |
528 | } |
529 | |
530 | static inline unsigned long __copy_from_user(void *to, |
531 | @@ -421,20 +481,39 @@ static inline unsigned long __copy_to_user(void __user *to, |
532 | return __copy_to_user_inatomic(to, from, size); |
533 | } |
534 | |
535 | -extern unsigned long __clear_user(void __user *addr, unsigned long size); |
536 | +unsigned long __arch_clear_user(void __user *addr, unsigned long size); |
537 | |
538 | static inline unsigned long clear_user(void __user *addr, unsigned long size) |
539 | { |
540 | + unsigned long ret = size; |
541 | might_fault(); |
542 | - if (likely(access_ok(VERIFY_WRITE, addr, size))) |
543 | - return __clear_user(addr, size); |
544 | - return size; |
545 | + if (likely(access_ok(VERIFY_WRITE, addr, size))) { |
546 | + allow_write_to_user(addr, size); |
547 | + ret = __arch_clear_user(addr, size); |
548 | + prevent_write_to_user(addr, size); |
549 | + } |
550 | + return ret; |
551 | +} |
552 | + |
553 | +static inline unsigned long __clear_user(void __user *addr, unsigned long size) |
554 | +{ |
555 | + return clear_user(addr, size); |
556 | } |
557 | |
558 | extern long strncpy_from_user(char *dst, const char __user *src, long count); |
559 | extern __must_check long strlen_user(const char __user *str); |
560 | extern __must_check long strnlen_user(const char __user *str, long n); |
561 | |
562 | + |
563 | +#define user_access_begin() do { } while (0) |
564 | +#define user_access_end() prevent_user_access(NULL, NULL, ~0ul) |
565 | + |
566 | +#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0) |
567 | +#define unsafe_get_user(x, p, e) unsafe_op_wrap(__get_user_allowed(x, p), e) |
568 | +#define unsafe_put_user(x, p, e) unsafe_op_wrap(__put_user_allowed(x, p), e) |
569 | +#define unsafe_copy_to_user(d, s, l, e) \ |
570 | + unsafe_op_wrap(__copy_to_user_inatomic(d, s, l), e) |
571 | + |
572 | #endif /* __ASSEMBLY__ */ |
573 | #endif /* __KERNEL__ */ |
574 | |
575 | diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S |
576 | index 0c8b966e80702..a1c22989a2f24 100644 |
577 | --- a/arch/powerpc/kernel/exceptions-64s.S |
578 | +++ b/arch/powerpc/kernel/exceptions-64s.S |
579 | @@ -487,7 +487,7 @@ EXC_COMMON_BEGIN(unrecover_mce) |
580 | b 1b |
581 | |
582 | |
583 | -EXC_REAL(data_access, 0x300, 0x380) |
584 | +EXC_REAL_OOL(data_access, 0x300, 0x380) |
585 | EXC_VIRT(data_access, 0x4300, 0x4380, 0x300) |
586 | TRAMP_KVM_SKIP(PACA_EXGEN, 0x300) |
587 | |
588 | @@ -519,6 +519,10 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) |
589 | EXC_REAL_BEGIN(data_access_slb, 0x380, 0x400) |
590 | SET_SCRATCH0(r13) |
591 | EXCEPTION_PROLOG_0(PACA_EXSLB) |
592 | + b tramp_data_access_slb |
593 | +EXC_REAL_END(data_access_slb, 0x380, 0x400) |
594 | + |
595 | +TRAMP_REAL_BEGIN(tramp_data_access_slb) |
596 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x380) |
597 | std r3,PACA_EXSLB+EX_R3(r13) |
598 | mfspr r3,SPRN_DAR |
599 | @@ -537,7 +541,6 @@ EXC_REAL_BEGIN(data_access_slb, 0x380, 0x400) |
600 | mtctr r10 |
601 | bctr |
602 | #endif |
603 | -EXC_REAL_END(data_access_slb, 0x380, 0x400) |
604 | |
605 | EXC_VIRT_BEGIN(data_access_slb, 0x4380, 0x4400) |
606 | SET_SCRATCH0(r13) |
607 | @@ -564,7 +567,7 @@ EXC_VIRT_END(data_access_slb, 0x4380, 0x4400) |
608 | TRAMP_KVM_SKIP(PACA_EXSLB, 0x380) |
609 | |
610 | |
611 | -EXC_REAL(instruction_access, 0x400, 0x480) |
612 | +EXC_REAL_OOL(instruction_access, 0x400, 0x480) |
613 | EXC_VIRT(instruction_access, 0x4400, 0x4480, 0x400) |
614 | TRAMP_KVM(PACA_EXGEN, 0x400) |
615 | |
616 | @@ -587,6 +590,10 @@ ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_TYPE_RADIX) |
617 | EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x500) |
618 | SET_SCRATCH0(r13) |
619 | EXCEPTION_PROLOG_0(PACA_EXSLB) |
620 | + b tramp_instruction_access_slb |
621 | +EXC_REAL_END(instruction_access_slb, 0x480, 0x500) |
622 | + |
623 | +TRAMP_REAL_BEGIN(tramp_instruction_access_slb) |
624 | EXCEPTION_PROLOG_1(PACA_EXSLB, KVMTEST_PR, 0x480) |
625 | std r3,PACA_EXSLB+EX_R3(r13) |
626 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ |
627 | @@ -600,7 +607,6 @@ EXC_REAL_BEGIN(instruction_access_slb, 0x480, 0x500) |
628 | mtctr r10 |
629 | bctr |
630 | #endif |
631 | -EXC_REAL_END(instruction_access_slb, 0x480, 0x500) |
632 | |
633 | EXC_VIRT_BEGIN(instruction_access_slb, 0x4480, 0x4500) |
634 | SET_SCRATCH0(r13) |
635 | @@ -851,13 +857,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) |
636 | |
637 | |
638 | EXC_REAL_OOL_MASKABLE(decrementer, 0x900, 0x980) |
639 | -EXC_VIRT_MASKABLE(decrementer, 0x4900, 0x4980, 0x900) |
640 | +EXC_VIRT_OOL_MASKABLE(decrementer, 0x4900, 0x4980, 0x900) |
641 | TRAMP_KVM(PACA_EXGEN, 0x900) |
642 | EXC_COMMON_ASYNC(decrementer_common, 0x900, timer_interrupt) |
643 | |
644 | |
645 | -EXC_REAL_HV(hdecrementer, 0x980, 0xa00) |
646 | -EXC_VIRT_HV(hdecrementer, 0x4980, 0x4a00, 0x980) |
647 | +EXC_REAL_OOL_HV(hdecrementer, 0x980, 0xa00) |
648 | +EXC_VIRT_OOL_HV(hdecrementer, 0x4980, 0x4a00, 0x980) |
649 | TRAMP_KVM_HV(PACA_EXGEN, 0x980) |
650 | EXC_COMMON(hdecrementer_common, 0x980, hdec_interrupt) |
651 | |
652 | @@ -1371,6 +1377,48 @@ TRAMP_REAL_BEGIN(stf_barrier_fallback) |
653 | .endr |
654 | blr |
655 | |
656 | +/* Clobbers r10, r11, ctr */ |
657 | +.macro L1D_DISPLACEMENT_FLUSH |
658 | + ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) |
659 | + ld r11,PACA_L1D_FLUSH_SIZE(r13) |
660 | + srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ |
661 | + mtctr r11 |
662 | + DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ |
663 | + |
664 | + /* order ld/st prior to dcbt stop all streams with flushing */ |
665 | + sync |
666 | + |
667 | + /* |
668 | + * The load adresses are at staggered offsets within cachelines, |
669 | + * which suits some pipelines better (on others it should not |
670 | + * hurt). |
671 | + */ |
672 | +1: |
673 | + ld r11,(0x80 + 8)*0(r10) |
674 | + ld r11,(0x80 + 8)*1(r10) |
675 | + ld r11,(0x80 + 8)*2(r10) |
676 | + ld r11,(0x80 + 8)*3(r10) |
677 | + ld r11,(0x80 + 8)*4(r10) |
678 | + ld r11,(0x80 + 8)*5(r10) |
679 | + ld r11,(0x80 + 8)*6(r10) |
680 | + ld r11,(0x80 + 8)*7(r10) |
681 | + addi r10,r10,0x80*8 |
682 | + bdnz 1b |
683 | +.endm |
684 | + |
685 | +USE_TEXT_SECTION() |
686 | + |
687 | +_GLOBAL(do_uaccess_flush) |
688 | + UACCESS_FLUSH_FIXUP_SECTION |
689 | + nop |
690 | + nop |
691 | + nop |
692 | + blr |
693 | + L1D_DISPLACEMENT_FLUSH |
694 | + blr |
695 | +_ASM_NOKPROBE_SYMBOL(do_uaccess_flush) |
696 | +EXPORT_SYMBOL(do_uaccess_flush) |
697 | + |
698 | /* |
699 | * Real mode exceptions actually use this too, but alternate |
700 | * instruction code patches (which end up in the common .text area) |
701 | @@ -1626,32 +1674,7 @@ rfi_flush_fallback: |
702 | std r10,PACA_EXRFI+EX_R10(r13) |
703 | std r11,PACA_EXRFI+EX_R11(r13) |
704 | mfctr r9 |
705 | - ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) |
706 | - ld r11,PACA_L1D_FLUSH_SIZE(r13) |
707 | - srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ |
708 | - mtctr r11 |
709 | - DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ |
710 | - |
711 | - /* order ld/st prior to dcbt stop all streams with flushing */ |
712 | - sync |
713 | - |
714 | - /* |
715 | - * The load adresses are at staggered offsets within cachelines, |
716 | - * which suits some pipelines better (on others it should not |
717 | - * hurt). |
718 | - */ |
719 | -1: |
720 | - ld r11,(0x80 + 8)*0(r10) |
721 | - ld r11,(0x80 + 8)*1(r10) |
722 | - ld r11,(0x80 + 8)*2(r10) |
723 | - ld r11,(0x80 + 8)*3(r10) |
724 | - ld r11,(0x80 + 8)*4(r10) |
725 | - ld r11,(0x80 + 8)*5(r10) |
726 | - ld r11,(0x80 + 8)*6(r10) |
727 | - ld r11,(0x80 + 8)*7(r10) |
728 | - addi r10,r10,0x80*8 |
729 | - bdnz 1b |
730 | - |
731 | + L1D_DISPLACEMENT_FLUSH |
732 | mtctr r9 |
733 | ld r9,PACA_EXRFI+EX_R9(r13) |
734 | ld r10,PACA_EXRFI+EX_R10(r13) |
735 | @@ -1667,32 +1690,7 @@ hrfi_flush_fallback: |
736 | std r10,PACA_EXRFI+EX_R10(r13) |
737 | std r11,PACA_EXRFI+EX_R11(r13) |
738 | mfctr r9 |
739 | - ld r10,PACA_RFI_FLUSH_FALLBACK_AREA(r13) |
740 | - ld r11,PACA_L1D_FLUSH_SIZE(r13) |
741 | - srdi r11,r11,(7 + 3) /* 128 byte lines, unrolled 8x */ |
742 | - mtctr r11 |
743 | - DCBT_STOP_ALL_STREAM_IDS(r11) /* Stop prefetch streams */ |
744 | - |
745 | - /* order ld/st prior to dcbt stop all streams with flushing */ |
746 | - sync |
747 | - |
748 | - /* |
749 | - * The load adresses are at staggered offsets within cachelines, |
750 | - * which suits some pipelines better (on others it should not |
751 | - * hurt). |
752 | - */ |
753 | -1: |
754 | - ld r11,(0x80 + 8)*0(r10) |
755 | - ld r11,(0x80 + 8)*1(r10) |
756 | - ld r11,(0x80 + 8)*2(r10) |
757 | - ld r11,(0x80 + 8)*3(r10) |
758 | - ld r11,(0x80 + 8)*4(r10) |
759 | - ld r11,(0x80 + 8)*5(r10) |
760 | - ld r11,(0x80 + 8)*6(r10) |
761 | - ld r11,(0x80 + 8)*7(r10) |
762 | - addi r10,r10,0x80*8 |
763 | - bdnz 1b |
764 | - |
765 | + L1D_DISPLACEMENT_FLUSH |
766 | mtctr r9 |
767 | ld r9,PACA_EXRFI+EX_R9(r13) |
768 | ld r10,PACA_EXRFI+EX_R10(r13) |
769 | @@ -1700,6 +1698,20 @@ hrfi_flush_fallback: |
770 | GET_SCRATCH0(r13); |
771 | hrfid |
772 | |
773 | + .globl entry_flush_fallback |
774 | +entry_flush_fallback: |
775 | + std r9,PACA_EXRFI+EX_R9(r13) |
776 | + std r10,PACA_EXRFI+EX_R10(r13) |
777 | + std r11,PACA_EXRFI+EX_R11(r13) |
778 | + mfctr r9 |
779 | + L1D_DISPLACEMENT_FLUSH |
780 | + mtctr r9 |
781 | + ld r9,PACA_EXRFI+EX_R9(r13) |
782 | + ld r10,PACA_EXRFI+EX_R10(r13) |
783 | + ld r11,PACA_EXRFI+EX_R11(r13) |
784 | + blr |
785 | + |
786 | + |
787 | /* |
788 | * Called from arch_local_irq_enable when an interrupt needs |
789 | * to be resent. r3 contains 0x500, 0x900, 0xa00 or 0xe80 to indicate |
790 | diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S |
791 | index 2274be535ddaf..3801b32b1642d 100644 |
792 | --- a/arch/powerpc/kernel/head_8xx.S |
793 | +++ b/arch/powerpc/kernel/head_8xx.S |
794 | @@ -359,11 +359,9 @@ InstructionTLBMiss: |
795 | /* Load the MI_TWC with the attributes for this "segment." */ |
796 | MTSPR_CPU6(SPRN_MI_TWC, r11, r3) /* Set segment attributes */ |
797 | |
798 | -#ifdef CONFIG_SWAP |
799 | - rlwinm r11, r10, 32-5, _PAGE_PRESENT |
800 | + rlwinm r11, r10, 32-11, _PAGE_PRESENT |
801 | and r11, r11, r10 |
802 | rlwimi r10, r11, 0, _PAGE_PRESENT |
803 | -#endif |
804 | li r11, RPN_PATTERN |
805 | /* The Linux PTE won't go exactly into the MMU TLB. |
806 | * Software indicator bits 20-23 and 28 must be clear. |
807 | @@ -443,11 +441,9 @@ _ENTRY(DTLBMiss_jmp) |
808 | * r11 = ((r10 & PRESENT) & ((r10 & ACCESSED) >> 5)); |
809 | * r10 = (r10 & ~PRESENT) | r11; |
810 | */ |
811 | -#ifdef CONFIG_SWAP |
812 | - rlwinm r11, r10, 32-5, _PAGE_PRESENT |
813 | + rlwinm r11, r10, 32-11, _PAGE_PRESENT |
814 | and r11, r11, r10 |
815 | rlwimi r10, r11, 0, _PAGE_PRESENT |
816 | -#endif |
817 | /* The Linux PTE won't go exactly into the MMU TLB. |
818 | * Software indicator bits 22 and 28 must be clear. |
819 | * Software indicator bits 24, 25, 26, and 27 must be |
820 | diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c |
821 | index fdba10695208f..56089034d401c 100644 |
822 | --- a/arch/powerpc/kernel/setup_64.c |
823 | +++ b/arch/powerpc/kernel/setup_64.c |
824 | @@ -685,7 +685,13 @@ early_initcall(disable_hardlockup_detector); |
825 | static enum l1d_flush_type enabled_flush_types; |
826 | static void *l1d_flush_fallback_area; |
827 | static bool no_rfi_flush; |
828 | +static bool no_entry_flush; |
829 | +static bool no_uaccess_flush; |
830 | bool rfi_flush; |
831 | +bool entry_flush; |
832 | +bool uaccess_flush; |
833 | +DEFINE_STATIC_KEY_FALSE(uaccess_flush_key); |
834 | +EXPORT_SYMBOL(uaccess_flush_key); |
835 | |
836 | static int __init handle_no_rfi_flush(char *p) |
837 | { |
838 | @@ -695,6 +701,22 @@ static int __init handle_no_rfi_flush(char *p) |
839 | } |
840 | early_param("no_rfi_flush", handle_no_rfi_flush); |
841 | |
842 | +static int __init handle_no_entry_flush(char *p) |
843 | +{ |
844 | + pr_info("entry-flush: disabled on command line."); |
845 | + no_entry_flush = true; |
846 | + return 0; |
847 | +} |
848 | +early_param("no_entry_flush", handle_no_entry_flush); |
849 | + |
850 | +static int __init handle_no_uaccess_flush(char *p) |
851 | +{ |
852 | + pr_info("uaccess-flush: disabled on command line."); |
853 | + no_uaccess_flush = true; |
854 | + return 0; |
855 | +} |
856 | +early_param("no_uaccess_flush", handle_no_uaccess_flush); |
857 | + |
858 | /* |
859 | * The RFI flush is not KPTI, but because users will see doco that says to use |
860 | * nopti we hijack that option here to also disable the RFI flush. |
861 | @@ -726,6 +748,32 @@ void rfi_flush_enable(bool enable) |
862 | rfi_flush = enable; |
863 | } |
864 | |
865 | +void entry_flush_enable(bool enable) |
866 | +{ |
867 | + if (enable) { |
868 | + do_entry_flush_fixups(enabled_flush_types); |
869 | + on_each_cpu(do_nothing, NULL, 1); |
870 | + } else { |
871 | + do_entry_flush_fixups(L1D_FLUSH_NONE); |
872 | + } |
873 | + |
874 | + entry_flush = enable; |
875 | +} |
876 | + |
877 | +void uaccess_flush_enable(bool enable) |
878 | +{ |
879 | + if (enable) { |
880 | + do_uaccess_flush_fixups(enabled_flush_types); |
881 | + static_branch_enable(&uaccess_flush_key); |
882 | + on_each_cpu(do_nothing, NULL, 1); |
883 | + } else { |
884 | + static_branch_disable(&uaccess_flush_key); |
885 | + do_uaccess_flush_fixups(L1D_FLUSH_NONE); |
886 | + } |
887 | + |
888 | + uaccess_flush = enable; |
889 | +} |
890 | + |
891 | static void __ref init_fallback_flush(void) |
892 | { |
893 | u64 l1d_size, limit; |
894 | @@ -771,6 +819,24 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable) |
895 | rfi_flush_enable(enable); |
896 | } |
897 | |
898 | +void setup_entry_flush(bool enable) |
899 | +{ |
900 | + if (cpu_mitigations_off()) |
901 | + return; |
902 | + |
903 | + if (!no_entry_flush) |
904 | + entry_flush_enable(enable); |
905 | +} |
906 | + |
907 | +void setup_uaccess_flush(bool enable) |
908 | +{ |
909 | + if (cpu_mitigations_off()) |
910 | + return; |
911 | + |
912 | + if (!no_uaccess_flush) |
913 | + uaccess_flush_enable(enable); |
914 | +} |
915 | + |
916 | #ifdef CONFIG_DEBUG_FS |
917 | static int rfi_flush_set(void *data, u64 val) |
918 | { |
919 | @@ -798,9 +864,63 @@ static int rfi_flush_get(void *data, u64 *val) |
920 | |
921 | DEFINE_SIMPLE_ATTRIBUTE(fops_rfi_flush, rfi_flush_get, rfi_flush_set, "%llu\n"); |
922 | |
923 | +static int entry_flush_set(void *data, u64 val) |
924 | +{ |
925 | + bool enable; |
926 | + |
927 | + if (val == 1) |
928 | + enable = true; |
929 | + else if (val == 0) |
930 | + enable = false; |
931 | + else |
932 | + return -EINVAL; |
933 | + |
934 | + /* Only do anything if we're changing state */ |
935 | + if (enable != entry_flush) |
936 | + entry_flush_enable(enable); |
937 | + |
938 | + return 0; |
939 | +} |
940 | + |
941 | +static int entry_flush_get(void *data, u64 *val) |
942 | +{ |
943 | + *val = entry_flush ? 1 : 0; |
944 | + return 0; |
945 | +} |
946 | + |
947 | +DEFINE_SIMPLE_ATTRIBUTE(fops_entry_flush, entry_flush_get, entry_flush_set, "%llu\n"); |
948 | + |
949 | +static int uaccess_flush_set(void *data, u64 val) |
950 | +{ |
951 | + bool enable; |
952 | + |
953 | + if (val == 1) |
954 | + enable = true; |
955 | + else if (val == 0) |
956 | + enable = false; |
957 | + else |
958 | + return -EINVAL; |
959 | + |
960 | + /* Only do anything if we're changing state */ |
961 | + if (enable != uaccess_flush) |
962 | + uaccess_flush_enable(enable); |
963 | + |
964 | + return 0; |
965 | +} |
966 | + |
967 | +static int uaccess_flush_get(void *data, u64 *val) |
968 | +{ |
969 | + *val = uaccess_flush ? 1 : 0; |
970 | + return 0; |
971 | +} |
972 | + |
973 | +DEFINE_SIMPLE_ATTRIBUTE(fops_uaccess_flush, uaccess_flush_get, uaccess_flush_set, "%llu\n"); |
974 | + |
975 | static __init int rfi_flush_debugfs_init(void) |
976 | { |
977 | debugfs_create_file("rfi_flush", 0600, powerpc_debugfs_root, NULL, &fops_rfi_flush); |
978 | + debugfs_create_file("entry_flush", 0600, powerpc_debugfs_root, NULL, &fops_entry_flush); |
979 | + debugfs_create_file("uaccess_flush", 0600, powerpc_debugfs_root, NULL, &fops_uaccess_flush); |
980 | return 0; |
981 | } |
982 | device_initcall(rfi_flush_debugfs_init); |
983 | diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S |
984 | index c20510497c49d..5d450c74f6f6b 100644 |
985 | --- a/arch/powerpc/kernel/vmlinux.lds.S |
986 | +++ b/arch/powerpc/kernel/vmlinux.lds.S |
987 | @@ -140,6 +140,20 @@ SECTIONS |
988 | __stop___stf_entry_barrier_fixup = .; |
989 | } |
990 | |
991 | + . = ALIGN(8); |
992 | + __uaccess_flush_fixup : AT(ADDR(__uaccess_flush_fixup) - LOAD_OFFSET) { |
993 | + __start___uaccess_flush_fixup = .; |
994 | + *(__uaccess_flush_fixup) |
995 | + __stop___uaccess_flush_fixup = .; |
996 | + } |
997 | + |
998 | + . = ALIGN(8); |
999 | + __entry_flush_fixup : AT(ADDR(__entry_flush_fixup) - LOAD_OFFSET) { |
1000 | + __start___entry_flush_fixup = .; |
1001 | + *(__entry_flush_fixup) |
1002 | + __stop___entry_flush_fixup = .; |
1003 | + } |
1004 | + |
1005 | . = ALIGN(8); |
1006 | __stf_exit_barrier_fixup : AT(ADDR(__stf_exit_barrier_fixup) - LOAD_OFFSET) { |
1007 | __start___stf_exit_barrier_fixup = .; |
1008 | diff --git a/arch/powerpc/lib/checksum_wrappers.c b/arch/powerpc/lib/checksum_wrappers.c |
1009 | index 08e3a3356c402..11b58949eb628 100644 |
1010 | --- a/arch/powerpc/lib/checksum_wrappers.c |
1011 | +++ b/arch/powerpc/lib/checksum_wrappers.c |
1012 | @@ -29,6 +29,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst, |
1013 | unsigned int csum; |
1014 | |
1015 | might_sleep(); |
1016 | + allow_read_from_user(src, len); |
1017 | |
1018 | *err_ptr = 0; |
1019 | |
1020 | @@ -60,6 +61,7 @@ __wsum csum_and_copy_from_user(const void __user *src, void *dst, |
1021 | } |
1022 | |
1023 | out: |
1024 | + prevent_read_from_user(src, len); |
1025 | return (__force __wsum)csum; |
1026 | } |
1027 | EXPORT_SYMBOL(csum_and_copy_from_user); |
1028 | @@ -70,6 +72,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, |
1029 | unsigned int csum; |
1030 | |
1031 | might_sleep(); |
1032 | + allow_write_to_user(dst, len); |
1033 | |
1034 | *err_ptr = 0; |
1035 | |
1036 | @@ -97,6 +100,7 @@ __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, |
1037 | } |
1038 | |
1039 | out: |
1040 | + prevent_write_to_user(dst, len); |
1041 | return (__force __wsum)csum; |
1042 | } |
1043 | EXPORT_SYMBOL(csum_and_copy_to_user); |
1044 | diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c |
1045 | index e6ed0ec94bc8c..446810e37b0cc 100644 |
1046 | --- a/arch/powerpc/lib/feature-fixups.c |
1047 | +++ b/arch/powerpc/lib/feature-fixups.c |
1048 | @@ -232,6 +232,110 @@ void do_stf_barrier_fixups(enum stf_barrier_type types) |
1049 | do_stf_exit_barrier_fixups(types); |
1050 | } |
1051 | |
1052 | +void do_uaccess_flush_fixups(enum l1d_flush_type types) |
1053 | +{ |
1054 | + unsigned int instrs[4], *dest; |
1055 | + long *start, *end; |
1056 | + int i; |
1057 | + |
1058 | + start = PTRRELOC(&__start___uaccess_flush_fixup); |
1059 | + end = PTRRELOC(&__stop___uaccess_flush_fixup); |
1060 | + |
1061 | + instrs[0] = 0x60000000; /* nop */ |
1062 | + instrs[1] = 0x60000000; /* nop */ |
1063 | + instrs[2] = 0x60000000; /* nop */ |
1064 | + instrs[3] = 0x4e800020; /* blr */ |
1065 | + |
1066 | + i = 0; |
1067 | + if (types == L1D_FLUSH_FALLBACK) { |
1068 | + instrs[3] = 0x60000000; /* nop */ |
1069 | + /* fallthrough to fallback flush */ |
1070 | + } |
1071 | + |
1072 | + if (types & L1D_FLUSH_ORI) { |
1073 | + instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ |
1074 | + instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/ |
1075 | + } |
1076 | + |
1077 | + if (types & L1D_FLUSH_MTTRIG) |
1078 | + instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */ |
1079 | + |
1080 | + for (i = 0; start < end; start++, i++) { |
1081 | + dest = (void *)start + *start; |
1082 | + |
1083 | + pr_devel("patching dest %lx\n", (unsigned long)dest); |
1084 | + |
1085 | + patch_instruction(dest, instrs[0]); |
1086 | + |
1087 | + patch_instruction((dest + 1), instrs[1]); |
1088 | + patch_instruction((dest + 2), instrs[2]); |
1089 | + patch_instruction((dest + 3), instrs[3]); |
1090 | + } |
1091 | + |
1092 | + printk(KERN_DEBUG "uaccess-flush: patched %d locations (%s flush)\n", i, |
1093 | + (types == L1D_FLUSH_NONE) ? "no" : |
1094 | + (types == L1D_FLUSH_FALLBACK) ? "fallback displacement" : |
1095 | + (types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG) |
1096 | + ? "ori+mttrig type" |
1097 | + : "ori type" : |
1098 | + (types & L1D_FLUSH_MTTRIG) ? "mttrig type" |
1099 | + : "unknown"); |
1100 | +} |
1101 | + |
1102 | +void do_entry_flush_fixups(enum l1d_flush_type types) |
1103 | +{ |
1104 | + unsigned int instrs[3], *dest; |
1105 | + long *start, *end; |
1106 | + int i; |
1107 | + |
1108 | + start = PTRRELOC(&__start___entry_flush_fixup); |
1109 | + end = PTRRELOC(&__stop___entry_flush_fixup); |
1110 | + |
1111 | + instrs[0] = 0x60000000; /* nop */ |
1112 | + instrs[1] = 0x60000000; /* nop */ |
1113 | + instrs[2] = 0x60000000; /* nop */ |
1114 | + |
1115 | + i = 0; |
1116 | + if (types == L1D_FLUSH_FALLBACK) { |
1117 | + instrs[i++] = 0x7d4802a6; /* mflr r10 */ |
1118 | + instrs[i++] = 0x60000000; /* branch patched below */ |
1119 | + instrs[i++] = 0x7d4803a6; /* mtlr r10 */ |
1120 | + } |
1121 | + |
1122 | + if (types & L1D_FLUSH_ORI) { |
1123 | + instrs[i++] = 0x63ff0000; /* ori 31,31,0 speculation barrier */ |
1124 | + instrs[i++] = 0x63de0000; /* ori 30,30,0 L1d flush*/ |
1125 | + } |
1126 | + |
1127 | + if (types & L1D_FLUSH_MTTRIG) |
1128 | + instrs[i++] = 0x7c12dba6; /* mtspr TRIG2,r0 (SPR #882) */ |
1129 | + |
1130 | + for (i = 0; start < end; start++, i++) { |
1131 | + dest = (void *)start + *start; |
1132 | + |
1133 | + pr_devel("patching dest %lx\n", (unsigned long)dest); |
1134 | + |
1135 | + patch_instruction(dest, instrs[0]); |
1136 | + |
1137 | + if (types == L1D_FLUSH_FALLBACK) |
1138 | + patch_branch((dest + 1), (unsigned long)&entry_flush_fallback, |
1139 | + BRANCH_SET_LINK); |
1140 | + else |
1141 | + patch_instruction((dest + 1), instrs[1]); |
1142 | + |
1143 | + patch_instruction((dest + 2), instrs[2]); |
1144 | + } |
1145 | + |
1146 | + printk(KERN_DEBUG "entry-flush: patched %d locations (%s flush)\n", i, |
1147 | + (types == L1D_FLUSH_NONE) ? "no" : |
1148 | + (types == L1D_FLUSH_FALLBACK) ? "fallback displacement" : |
1149 | + (types & L1D_FLUSH_ORI) ? (types & L1D_FLUSH_MTTRIG) |
1150 | + ? "ori+mttrig type" |
1151 | + : "ori type" : |
1152 | + (types & L1D_FLUSH_MTTRIG) ? "mttrig type" |
1153 | + : "unknown"); |
1154 | +} |
1155 | + |
1156 | void do_rfi_flush_fixups(enum l1d_flush_type types) |
1157 | { |
1158 | unsigned int instrs[3], *dest; |
1159 | diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S |
1160 | index d13e076035195..4e85411d4a7e8 100644 |
1161 | --- a/arch/powerpc/lib/string.S |
1162 | +++ b/arch/powerpc/lib/string.S |
1163 | @@ -89,7 +89,7 @@ _GLOBAL(memchr) |
1164 | EXPORT_SYMBOL(memchr) |
1165 | |
1166 | #ifdef CONFIG_PPC32 |
1167 | -_GLOBAL(__clear_user) |
1168 | +_GLOBAL(__arch_clear_user) |
1169 | addi r6,r3,-4 |
1170 | li r3,0 |
1171 | li r5,0 |
1172 | @@ -130,5 +130,5 @@ _GLOBAL(__clear_user) |
1173 | PPC_LONG 1b,91b |
1174 | PPC_LONG 8b,92b |
1175 | .text |
1176 | -EXPORT_SYMBOL(__clear_user) |
1177 | +EXPORT_SYMBOL(__arch_clear_user) |
1178 | #endif |
1179 | diff --git a/arch/powerpc/lib/string_64.S b/arch/powerpc/lib/string_64.S |
1180 | index 11e6372537fd4..347029f65edb7 100644 |
1181 | --- a/arch/powerpc/lib/string_64.S |
1182 | +++ b/arch/powerpc/lib/string_64.S |
1183 | @@ -28,7 +28,7 @@ PPC64_CACHES: |
1184 | .section ".text" |
1185 | |
1186 | /** |
1187 | - * __clear_user: - Zero a block of memory in user space, with less checking. |
1188 | + * __arch_clear_user: - Zero a block of memory in user space, with less checking. |
1189 | * @to: Destination address, in user space. |
1190 | * @n: Number of bytes to zero. |
1191 | * |
1192 | @@ -78,7 +78,7 @@ err3; stb r0,0(r3) |
1193 | mr r3,r4 |
1194 | blr |
1195 | |
1196 | -_GLOBAL_TOC(__clear_user) |
1197 | +_GLOBAL_TOC(__arch_clear_user) |
1198 | cmpdi r4,32 |
1199 | neg r6,r3 |
1200 | li r0,0 |
1201 | @@ -201,4 +201,4 @@ err1; dcbz 0,r3 |
1202 | cmpdi r4,32 |
1203 | blt .Lshort_clear |
1204 | b .Lmedium_clear |
1205 | -EXPORT_SYMBOL(__clear_user) |
1206 | +EXPORT_SYMBOL(__arch_clear_user) |
1207 | diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c |
1208 | index 365e2b6202012..b77d5eed95205 100644 |
1209 | --- a/arch/powerpc/platforms/powernv/setup.c |
1210 | +++ b/arch/powerpc/platforms/powernv/setup.c |
1211 | @@ -124,12 +124,27 @@ static void pnv_setup_rfi_flush(void) |
1212 | type = L1D_FLUSH_ORI; |
1213 | } |
1214 | |
1215 | + /* |
1216 | + * 4.9 doesn't support Power9 bare metal, so we don't need to flush |
1217 | + * here - the flushes fix a P9 specific vulnerability. |
1218 | + */ |
1219 | + security_ftr_clear(SEC_FTR_L1D_FLUSH_ENTRY); |
1220 | + security_ftr_clear(SEC_FTR_L1D_FLUSH_UACCESS); |
1221 | + |
1222 | enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && \ |
1223 | (security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR) || \ |
1224 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); |
1225 | |
1226 | setup_rfi_flush(type, enable); |
1227 | setup_count_cache_flush(); |
1228 | + |
1229 | + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && |
1230 | + security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY); |
1231 | + setup_entry_flush(enable); |
1232 | + |
1233 | + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && |
1234 | + security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS); |
1235 | + setup_uaccess_flush(enable); |
1236 | } |
1237 | |
1238 | static void __init pnv_setup_arch(void) |
1239 | diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c |
1240 | index 30782859d8980..bb74711388621 100644 |
1241 | --- a/arch/powerpc/platforms/pseries/setup.c |
1242 | +++ b/arch/powerpc/platforms/pseries/setup.c |
1243 | @@ -535,6 +535,14 @@ void pseries_setup_rfi_flush(void) |
1244 | |
1245 | setup_rfi_flush(types, enable); |
1246 | setup_count_cache_flush(); |
1247 | + |
1248 | + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && |
1249 | + security_ftr_enabled(SEC_FTR_L1D_FLUSH_ENTRY); |
1250 | + setup_entry_flush(enable); |
1251 | + |
1252 | + enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && |
1253 | + security_ftr_enabled(SEC_FTR_L1D_FLUSH_UACCESS); |
1254 | + setup_uaccess_flush(enable); |
1255 | } |
1256 | |
1257 | static void __init pSeries_setup_arch(void) |
1258 | diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c |
1259 | index d455221d958fc..2e5553091f902 100644 |
1260 | --- a/arch/x86/kvm/emulate.c |
1261 | +++ b/arch/x86/kvm/emulate.c |
1262 | @@ -3934,6 +3934,12 @@ static int em_clflush(struct x86_emulate_ctxt *ctxt) |
1263 | return X86EMUL_CONTINUE; |
1264 | } |
1265 | |
1266 | +static int em_clflushopt(struct x86_emulate_ctxt *ctxt) |
1267 | +{ |
1268 | + /* emulating clflushopt regardless of cpuid */ |
1269 | + return X86EMUL_CONTINUE; |
1270 | +} |
1271 | + |
1272 | static int em_movsxd(struct x86_emulate_ctxt *ctxt) |
1273 | { |
1274 | ctxt->dst.val = (s32) ctxt->src.val; |
1275 | @@ -4423,7 +4429,7 @@ static const struct opcode group11[] = { |
1276 | }; |
1277 | |
1278 | static const struct gprefix pfx_0f_ae_7 = { |
1279 | - I(SrcMem | ByteOp, em_clflush), N, N, N, |
1280 | + I(SrcMem | ByteOp, em_clflush), I(SrcMem | ByteOp, em_clflushopt), N, N, |
1281 | }; |
1282 | |
1283 | static const struct group_dual group15 = { { |
1284 | diff --git a/drivers/acpi/evged.c b/drivers/acpi/evged.c |
1285 | index 339e6d3dba7c3..73116acd391d1 100644 |
1286 | --- a/drivers/acpi/evged.c |
1287 | +++ b/drivers/acpi/evged.c |
1288 | @@ -104,7 +104,7 @@ static acpi_status acpi_ged_request_interrupt(struct acpi_resource *ares, |
1289 | |
1290 | switch (gsi) { |
1291 | case 0 ... 255: |
1292 | - sprintf(ev_name, "_%c%02hhX", |
1293 | + sprintf(ev_name, "_%c%02X", |
1294 | trigger == ACPI_EDGE_SENSITIVE ? 'E' : 'L', gsi); |
1295 | |
1296 | if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle))) |
1297 | diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c |
1298 | index 9c1be9378dfde..5a148b515f3df 100644 |
1299 | --- a/drivers/i2c/busses/i2c-imx.c |
1300 | +++ b/drivers/i2c/busses/i2c-imx.c |
1301 | @@ -194,6 +194,7 @@ struct imx_i2c_dma { |
1302 | struct imx_i2c_struct { |
1303 | struct i2c_adapter adapter; |
1304 | struct clk *clk; |
1305 | + struct notifier_block clk_change_nb; |
1306 | void __iomem *base; |
1307 | wait_queue_head_t queue; |
1308 | unsigned long i2csr; |
1309 | @@ -468,15 +469,14 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) |
1310 | return 0; |
1311 | } |
1312 | |
1313 | -static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) |
1314 | +static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, |
1315 | + unsigned int i2c_clk_rate) |
1316 | { |
1317 | struct imx_i2c_clk_pair *i2c_clk_div = i2c_imx->hwdata->clk_div; |
1318 | - unsigned int i2c_clk_rate; |
1319 | unsigned int div; |
1320 | int i; |
1321 | |
1322 | /* Divider value calculation */ |
1323 | - i2c_clk_rate = clk_get_rate(i2c_imx->clk); |
1324 | if (i2c_imx->cur_clk == i2c_clk_rate) |
1325 | return; |
1326 | |
1327 | @@ -511,6 +511,20 @@ static void i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx) |
1328 | #endif |
1329 | } |
1330 | |
1331 | +static int i2c_imx_clk_notifier_call(struct notifier_block *nb, |
1332 | + unsigned long action, void *data) |
1333 | +{ |
1334 | + struct clk_notifier_data *ndata = data; |
1335 | + struct imx_i2c_struct *i2c_imx = container_of(&ndata->clk, |
1336 | + struct imx_i2c_struct, |
1337 | + clk); |
1338 | + |
1339 | + if (action & POST_RATE_CHANGE) |
1340 | + i2c_imx_set_clk(i2c_imx, ndata->new_rate); |
1341 | + |
1342 | + return NOTIFY_OK; |
1343 | +} |
1344 | + |
1345 | static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) |
1346 | { |
1347 | unsigned int temp = 0; |
1348 | @@ -518,8 +532,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) |
1349 | |
1350 | dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); |
1351 | |
1352 | - i2c_imx_set_clk(i2c_imx); |
1353 | - |
1354 | imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR); |
1355 | /* Enable I2C controller */ |
1356 | imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR); |
1357 | @@ -1099,14 +1111,6 @@ static int i2c_imx_probe(struct platform_device *pdev) |
1358 | return ret; |
1359 | } |
1360 | |
1361 | - /* Request IRQ */ |
1362 | - ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, |
1363 | - pdev->name, i2c_imx); |
1364 | - if (ret) { |
1365 | - dev_err(&pdev->dev, "can't claim irq %d\n", irq); |
1366 | - goto clk_disable; |
1367 | - } |
1368 | - |
1369 | /* Init queue */ |
1370 | init_waitqueue_head(&i2c_imx->queue); |
1371 | |
1372 | @@ -1125,12 +1129,23 @@ static int i2c_imx_probe(struct platform_device *pdev) |
1373 | if (ret < 0) |
1374 | goto rpm_disable; |
1375 | |
1376 | + /* Request IRQ */ |
1377 | + ret = request_threaded_irq(irq, i2c_imx_isr, NULL, IRQF_SHARED, |
1378 | + pdev->name, i2c_imx); |
1379 | + if (ret) { |
1380 | + dev_err(&pdev->dev, "can't claim irq %d\n", irq); |
1381 | + goto rpm_disable; |
1382 | + } |
1383 | + |
1384 | /* Set up clock divider */ |
1385 | i2c_imx->bitrate = IMX_I2C_BIT_RATE; |
1386 | ret = of_property_read_u32(pdev->dev.of_node, |
1387 | "clock-frequency", &i2c_imx->bitrate); |
1388 | if (ret < 0 && pdata && pdata->bitrate) |
1389 | i2c_imx->bitrate = pdata->bitrate; |
1390 | + i2c_imx->clk_change_nb.notifier_call = i2c_imx_clk_notifier_call; |
1391 | + clk_notifier_register(i2c_imx->clk, &i2c_imx->clk_change_nb); |
1392 | + i2c_imx_set_clk(i2c_imx, clk_get_rate(i2c_imx->clk)); |
1393 | |
1394 | /* Set up chip registers to defaults */ |
1395 | imx_i2c_write_reg(i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN, |
1396 | @@ -1141,12 +1156,12 @@ static int i2c_imx_probe(struct platform_device *pdev) |
1397 | ret = i2c_imx_init_recovery_info(i2c_imx, pdev); |
1398 | /* Give it another chance if pinctrl used is not ready yet */ |
1399 | if (ret == -EPROBE_DEFER) |
1400 | - goto rpm_disable; |
1401 | + goto clk_notifier_unregister; |
1402 | |
1403 | /* Add I2C adapter */ |
1404 | ret = i2c_add_numbered_adapter(&i2c_imx->adapter); |
1405 | if (ret < 0) |
1406 | - goto rpm_disable; |
1407 | + goto clk_notifier_unregister; |
1408 | |
1409 | pm_runtime_mark_last_busy(&pdev->dev); |
1410 | pm_runtime_put_autosuspend(&pdev->dev); |
1411 | @@ -1162,13 +1177,14 @@ static int i2c_imx_probe(struct platform_device *pdev) |
1412 | |
1413 | return 0; /* Return OK */ |
1414 | |
1415 | +clk_notifier_unregister: |
1416 | + clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb); |
1417 | + free_irq(irq, i2c_imx); |
1418 | rpm_disable: |
1419 | pm_runtime_put_noidle(&pdev->dev); |
1420 | pm_runtime_disable(&pdev->dev); |
1421 | pm_runtime_set_suspended(&pdev->dev); |
1422 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
1423 | - |
1424 | -clk_disable: |
1425 | clk_disable_unprepare(i2c_imx->clk); |
1426 | return ret; |
1427 | } |
1428 | @@ -1176,7 +1192,7 @@ clk_disable: |
1429 | static int i2c_imx_remove(struct platform_device *pdev) |
1430 | { |
1431 | struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); |
1432 | - int ret; |
1433 | + int irq, ret; |
1434 | |
1435 | ret = pm_runtime_get_sync(&pdev->dev); |
1436 | if (ret < 0) |
1437 | @@ -1195,6 +1211,10 @@ static int i2c_imx_remove(struct platform_device *pdev) |
1438 | imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2CR); |
1439 | imx_i2c_write_reg(0, i2c_imx, IMX_I2C_I2SR); |
1440 | |
1441 | + clk_notifier_unregister(i2c_imx->clk, &i2c_imx->clk_change_nb); |
1442 | + irq = platform_get_irq(pdev, 0); |
1443 | + if (irq >= 0) |
1444 | + free_irq(irq, i2c_imx); |
1445 | clk_disable_unprepare(i2c_imx->clk); |
1446 | |
1447 | pm_runtime_put_noidle(&pdev->dev); |
1448 | diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c |
1449 | index 9c4ac26c014e1..6f673b0cc8030 100644 |
1450 | --- a/drivers/i2c/muxes/i2c-mux-pca954x.c |
1451 | +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c |
1452 | @@ -96,6 +96,10 @@ static const struct chip_desc chips[] = { |
1453 | .nchans = 4, |
1454 | .muxtype = pca954x_isswi, |
1455 | }, |
1456 | + [pca_9546] = { |
1457 | + .nchans = 4, |
1458 | + .muxtype = pca954x_isswi, |
1459 | + }, |
1460 | [pca_9547] = { |
1461 | .nchans = 8, |
1462 | .enable = 0x8, |
1463 | @@ -113,7 +117,7 @@ static const struct i2c_device_id pca954x_id[] = { |
1464 | { "pca9543", pca_9543 }, |
1465 | { "pca9544", pca_9544 }, |
1466 | { "pca9545", pca_9545 }, |
1467 | - { "pca9546", pca_9545 }, |
1468 | + { "pca9546", pca_9546 }, |
1469 | { "pca9547", pca_9547 }, |
1470 | { "pca9548", pca_9548 }, |
1471 | { } |
1472 | diff --git a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c |
1473 | index dc6bb9d5b4f02..191c27dda3860 100644 |
1474 | --- a/drivers/input/keyboard/sunkbd.c |
1475 | +++ b/drivers/input/keyboard/sunkbd.c |
1476 | @@ -115,7 +115,8 @@ static irqreturn_t sunkbd_interrupt(struct serio *serio, |
1477 | switch (data) { |
1478 | |
1479 | case SUNKBD_RET_RESET: |
1480 | - schedule_work(&sunkbd->tq); |
1481 | + if (sunkbd->enabled) |
1482 | + schedule_work(&sunkbd->tq); |
1483 | sunkbd->reset = -1; |
1484 | break; |
1485 | |
1486 | @@ -216,16 +217,12 @@ static int sunkbd_initialize(struct sunkbd *sunkbd) |
1487 | } |
1488 | |
1489 | /* |
1490 | - * sunkbd_reinit() sets leds and beeps to a state the computer remembers they |
1491 | - * were in. |
1492 | + * sunkbd_set_leds_beeps() sets leds and beeps to a state the computer remembers |
1493 | + * they were in. |
1494 | */ |
1495 | |
1496 | -static void sunkbd_reinit(struct work_struct *work) |
1497 | +static void sunkbd_set_leds_beeps(struct sunkbd *sunkbd) |
1498 | { |
1499 | - struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); |
1500 | - |
1501 | - wait_event_interruptible_timeout(sunkbd->wait, sunkbd->reset >= 0, HZ); |
1502 | - |
1503 | serio_write(sunkbd->serio, SUNKBD_CMD_SETLED); |
1504 | serio_write(sunkbd->serio, |
1505 | (!!test_bit(LED_CAPSL, sunkbd->dev->led) << 3) | |
1506 | @@ -238,11 +235,39 @@ static void sunkbd_reinit(struct work_struct *work) |
1507 | SUNKBD_CMD_BELLOFF - !!test_bit(SND_BELL, sunkbd->dev->snd)); |
1508 | } |
1509 | |
1510 | + |
1511 | +/* |
1512 | + * sunkbd_reinit() wait for the keyboard reset to complete and restores state |
1513 | + * of leds and beeps. |
1514 | + */ |
1515 | + |
1516 | +static void sunkbd_reinit(struct work_struct *work) |
1517 | +{ |
1518 | + struct sunkbd *sunkbd = container_of(work, struct sunkbd, tq); |
1519 | + |
1520 | + /* |
1521 | + * It is OK that we check sunkbd->enabled without pausing serio, |
1522 | + * as we only want to catch true->false transition that will |
1523 | + * happen once and we will be woken up for it. |
1524 | + */ |
1525 | + wait_event_interruptible_timeout(sunkbd->wait, |
1526 | + sunkbd->reset >= 0 || !sunkbd->enabled, |
1527 | + HZ); |
1528 | + |
1529 | + if (sunkbd->reset >= 0 && sunkbd->enabled) |
1530 | + sunkbd_set_leds_beeps(sunkbd); |
1531 | +} |
1532 | + |
1533 | static void sunkbd_enable(struct sunkbd *sunkbd, bool enable) |
1534 | { |
1535 | serio_pause_rx(sunkbd->serio); |
1536 | sunkbd->enabled = enable; |
1537 | serio_continue_rx(sunkbd->serio); |
1538 | + |
1539 | + if (!enable) { |
1540 | + wake_up_interruptible(&sunkbd->wait); |
1541 | + cancel_work_sync(&sunkbd->tq); |
1542 | + } |
1543 | } |
1544 | |
1545 | /* |
1546 | diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c |
1547 | index fef8d7758dae9..8a9bbcfefbca6 100644 |
1548 | --- a/net/mac80211/sta_info.c |
1549 | +++ b/net/mac80211/sta_info.c |
1550 | @@ -243,6 +243,24 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, |
1551 | */ |
1552 | void sta_info_free(struct ieee80211_local *local, struct sta_info *sta) |
1553 | { |
1554 | + /* |
1555 | + * If we had used sta_info_pre_move_state() then we might not |
1556 | + * have gone through the state transitions down again, so do |
1557 | + * it here now (and warn if it's inserted). |
1558 | + * |
1559 | + * This will clear state such as fast TX/RX that may have been |
1560 | + * allocated during state transitions. |
1561 | + */ |
1562 | + while (sta->sta_state > IEEE80211_STA_NONE) { |
1563 | + int ret; |
1564 | + |
1565 | + WARN_ON_ONCE(test_sta_flag(sta, WLAN_STA_INSERTED)); |
1566 | + |
1567 | + ret = sta_info_move_state(sta, sta->sta_state - 1); |
1568 | + if (WARN_ONCE(ret, "sta_info_move_state() returned %d\n", ret)) |
1569 | + break; |
1570 | + } |
1571 | + |
1572 | if (sta->rate_ctrl) |
1573 | rate_control_free_sta(sta); |
1574 |