aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2019-05-01 10:34:56 -0400
committerWill Deacon <will.deacon@arm.com>2019-05-01 10:34:56 -0400
commit50abbe19623e08e2aa34e0e526bd6115569f3dc3 (patch)
treeecaddb898d671847f70c40fcab5fd115dacc1a1e
parent9431ac2bf6b742d87cdac051adc1976308070110 (diff)
parent4ad499c94264a2ee05aacc518b9bde658318e510 (diff)
Merge branch 'for-next/mitigations' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux into for-next/core
-rw-r--r--Documentation/admin-guide/kernel-parameters.rst1
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt42
-rw-r--r--arch/arm64/Kconfig1
-rw-r--r--arch/arm64/include/asm/cpufeature.h4
-rw-r--r--arch/arm64/kernel/cpu_errata.c243
-rw-r--r--arch/arm64/kernel/cpufeature.c66
-rw-r--r--arch/powerpc/kernel/security.c6
-rw-r--r--arch/powerpc/kernel/setup_64.c2
-rw-r--r--arch/s390/kernel/nospec-branch.c3
-rw-r--r--arch/x86/kernel/cpu/bugs.c11
-rw-r--r--arch/x86/mm/pti.c4
-rw-r--r--include/linux/cpu.h24
-rw-r--r--kernel/cpu.c15
13 files changed, 325 insertions, 97 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst
index b8d0bc07ed0a..0124980dca2d 100644
--- a/Documentation/admin-guide/kernel-parameters.rst
+++ b/Documentation/admin-guide/kernel-parameters.rst
@@ -88,6 +88,7 @@ parameter is applicable::
88 APIC APIC support is enabled. 88 APIC APIC support is enabled.
89 APM Advanced Power Management support is enabled. 89 APM Advanced Power Management support is enabled.
90 ARM ARM architecture is enabled. 90 ARM ARM architecture is enabled.
91 ARM64 ARM64 architecture is enabled.
91 AX25 Appropriate AX.25 support is enabled. 92 AX25 Appropriate AX.25 support is enabled.
92 CLK Common clock infrastructure is enabled. 93 CLK Common clock infrastructure is enabled.
93 CMA Contiguous Memory Area support is enabled. 94 CMA Contiguous Memory Area support is enabled.
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 2b8ee90bb644..ce226f7ee566 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2544,6 +2544,40 @@
2544 in the "bleeding edge" mini2440 support kernel at 2544 in the "bleeding edge" mini2440 support kernel at
2545 http://repo.or.cz/w/linux-2.6/mini2440.git 2545 http://repo.or.cz/w/linux-2.6/mini2440.git
2546 2546
2547 mitigations=
2548 [X86,PPC,S390,ARM64] Control optional mitigations for
2549 CPU vulnerabilities. This is a set of curated,
2550 arch-independent options, each of which is an
2551 aggregation of existing arch-specific options.
2552
2553 off
2554 Disable all optional CPU mitigations. This
2555 improves system performance, but it may also
2556 expose users to several CPU vulnerabilities.
2557 Equivalent to: nopti [X86,PPC]
2558 kpti=0 [ARM64]
2559 nospectre_v1 [PPC]
2560 nobp=0 [S390]
2561 nospectre_v2 [X86,PPC,S390,ARM64]
2562 spectre_v2_user=off [X86]
2563 spec_store_bypass_disable=off [X86,PPC]
2564 ssbd=force-off [ARM64]
2565 l1tf=off [X86]
2566
2567 auto (default)
2568 Mitigate all CPU vulnerabilities, but leave SMT
2569 enabled, even if it's vulnerable. This is for
2570 users who don't want to be surprised by SMT
2571 getting disabled across kernel upgrades, or who
2572 have other ways of avoiding SMT-based attacks.
2573 Equivalent to: (default behavior)
2574
2575 auto,nosmt
2576 Mitigate all CPU vulnerabilities, disabling SMT
2577 if needed. This is for users who always want to
2578 be fully mitigated, even if it means losing SMT.
2579 Equivalent to: l1tf=flush,nosmt [X86]
2580
2547 mminit_loglevel= 2581 mminit_loglevel=
2548 [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this 2582 [KNL] When CONFIG_DEBUG_MEMORY_INIT is set, this
2549 parameter allows control of the logging verbosity for 2583 parameter allows control of the logging verbosity for
@@ -2873,10 +2907,10 @@
2873 check bypass). With this option data leaks are possible 2907 check bypass). With this option data leaks are possible
2874 in the system. 2908 in the system.
2875 2909
2876 nospectre_v2 [X86,PPC_FSL_BOOK3E] Disable all mitigations for the Spectre variant 2 2910 nospectre_v2 [X86,PPC_FSL_BOOK3E,ARM64] Disable all mitigations for
2877 (indirect branch prediction) vulnerability. System may 2911 the Spectre variant 2 (indirect branch prediction)
2878 allow data leaks with this option, which is equivalent 2912 vulnerability. System may allow data leaks with this
2879 to spectre_v2=off. 2913 option.
2880 2914
2881 nospec_store_bypass_disable 2915 nospec_store_bypass_disable
2882 [HW] Disable all mitigations for the Speculative Store Bypass vulnerability 2916 [HW] Disable all mitigations for the Speculative Store Bypass vulnerability
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index d28f12e9c160..b5c6943225ce 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -90,6 +90,7 @@ config ARM64
90 select GENERIC_CLOCKEVENTS 90 select GENERIC_CLOCKEVENTS
91 select GENERIC_CLOCKEVENTS_BROADCAST 91 select GENERIC_CLOCKEVENTS_BROADCAST
92 select GENERIC_CPU_AUTOPROBE 92 select GENERIC_CPU_AUTOPROBE
93 select GENERIC_CPU_VULNERABILITIES
93 select GENERIC_EARLY_IOREMAP 94 select GENERIC_EARLY_IOREMAP
94 select GENERIC_IDLE_POLL_SETUP 95 select GENERIC_IDLE_POLL_SETUP
95 select GENERIC_IRQ_MULTI_HANDLER 96 select GENERIC_IRQ_MULTI_HANDLER
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index a3f028f82def..f210bcf096f7 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -633,11 +633,7 @@ static inline int arm64_get_ssbd_state(void)
633#endif 633#endif
634} 634}
635 635
636#ifdef CONFIG_ARM64_SSBD
637void arm64_set_ssbd_mitigation(bool state); 636void arm64_set_ssbd_mitigation(bool state);
638#else
639static inline void arm64_set_ssbd_mitigation(bool state) {}
640#endif
641 637
642extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt); 638extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
643 639
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 9950bb0cbd52..1b9ce0fdd81d 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -19,6 +19,7 @@
19#include <linux/arm-smccc.h> 19#include <linux/arm-smccc.h>
20#include <linux/psci.h> 20#include <linux/psci.h>
21#include <linux/types.h> 21#include <linux/types.h>
22#include <linux/cpu.h>
22#include <asm/cpu.h> 23#include <asm/cpu.h>
23#include <asm/cputype.h> 24#include <asm/cputype.h>
24#include <asm/cpufeature.h> 25#include <asm/cpufeature.h>
@@ -109,7 +110,6 @@ cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *__unused)
109 110
110atomic_t arm64_el2_vector_last_slot = ATOMIC_INIT(-1); 111atomic_t arm64_el2_vector_last_slot = ATOMIC_INIT(-1);
111 112
112#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
113#include <asm/mmu_context.h> 113#include <asm/mmu_context.h>
114#include <asm/cacheflush.h> 114#include <asm/cacheflush.h>
115 115
@@ -131,9 +131,9 @@ static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start,
131 __flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K); 131 __flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K);
132} 132}
133 133
134static void __install_bp_hardening_cb(bp_hardening_cb_t fn, 134static void install_bp_hardening_cb(bp_hardening_cb_t fn,
135 const char *hyp_vecs_start, 135 const char *hyp_vecs_start,
136 const char *hyp_vecs_end) 136 const char *hyp_vecs_end)
137{ 137{
138 static DEFINE_RAW_SPINLOCK(bp_lock); 138 static DEFINE_RAW_SPINLOCK(bp_lock);
139 int cpu, slot = -1; 139 int cpu, slot = -1;
@@ -169,7 +169,7 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
169#define __smccc_workaround_1_smc_start NULL 169#define __smccc_workaround_1_smc_start NULL
170#define __smccc_workaround_1_smc_end NULL 170#define __smccc_workaround_1_smc_end NULL
171 171
172static void __install_bp_hardening_cb(bp_hardening_cb_t fn, 172static void install_bp_hardening_cb(bp_hardening_cb_t fn,
173 const char *hyp_vecs_start, 173 const char *hyp_vecs_start,
174 const char *hyp_vecs_end) 174 const char *hyp_vecs_end)
175{ 175{
@@ -177,23 +177,6 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
177} 177}
178#endif /* CONFIG_KVM_INDIRECT_VECTORS */ 178#endif /* CONFIG_KVM_INDIRECT_VECTORS */
179 179
180static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry,
181 bp_hardening_cb_t fn,
182 const char *hyp_vecs_start,
183 const char *hyp_vecs_end)
184{
185 u64 pfr0;
186
187 if (!entry->matches(entry, SCOPE_LOCAL_CPU))
188 return;
189
190 pfr0 = read_cpuid(ID_AA64PFR0_EL1);
191 if (cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_CSV2_SHIFT))
192 return;
193
194 __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end);
195}
196
197#include <uapi/linux/psci.h> 180#include <uapi/linux/psci.h>
198#include <linux/arm-smccc.h> 181#include <linux/arm-smccc.h>
199#include <linux/psci.h> 182#include <linux/psci.h>
@@ -220,60 +203,83 @@ static void qcom_link_stack_sanitization(void)
220 : "=&r" (tmp)); 203 : "=&r" (tmp));
221} 204}
222 205
223static void 206static bool __nospectre_v2;
224enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) 207static int __init parse_nospectre_v2(char *str)
208{
209 __nospectre_v2 = true;
210 return 0;
211}
212early_param("nospectre_v2", parse_nospectre_v2);
213
214/*
215 * -1: No workaround
216 * 0: No workaround required
217 * 1: Workaround installed
218 */
219static int detect_harden_bp_fw(void)
225{ 220{
226 bp_hardening_cb_t cb; 221 bp_hardening_cb_t cb;
227 void *smccc_start, *smccc_end; 222 void *smccc_start, *smccc_end;
228 struct arm_smccc_res res; 223 struct arm_smccc_res res;
229 u32 midr = read_cpuid_id(); 224 u32 midr = read_cpuid_id();
230 225
231 if (!entry->matches(entry, SCOPE_LOCAL_CPU))
232 return;
233
234 if (psci_ops.smccc_version == SMCCC_VERSION_1_0) 226 if (psci_ops.smccc_version == SMCCC_VERSION_1_0)
235 return; 227 return -1;
236 228
237 switch (psci_ops.conduit) { 229 switch (psci_ops.conduit) {
238 case PSCI_CONDUIT_HVC: 230 case PSCI_CONDUIT_HVC:
239 arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, 231 arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
240 ARM_SMCCC_ARCH_WORKAROUND_1, &res); 232 ARM_SMCCC_ARCH_WORKAROUND_1, &res);
241 if ((int)res.a0 < 0) 233 switch ((int)res.a0) {
242 return; 234 case 1:
243 cb = call_hvc_arch_workaround_1; 235 /* Firmware says we're just fine */
244 /* This is a guest, no need to patch KVM vectors */ 236 return 0;
245 smccc_start = NULL; 237 case 0:
246 smccc_end = NULL; 238 cb = call_hvc_arch_workaround_1;
239 /* This is a guest, no need to patch KVM vectors */
240 smccc_start = NULL;
241 smccc_end = NULL;
242 break;
243 default:
244 return -1;
245 }
247 break; 246 break;
248 247
249 case PSCI_CONDUIT_SMC: 248 case PSCI_CONDUIT_SMC:
250 arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, 249 arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
251 ARM_SMCCC_ARCH_WORKAROUND_1, &res); 250 ARM_SMCCC_ARCH_WORKAROUND_1, &res);
252 if ((int)res.a0 < 0) 251 switch ((int)res.a0) {
253 return; 252 case 1:
254 cb = call_smc_arch_workaround_1; 253 /* Firmware says we're just fine */
255 smccc_start = __smccc_workaround_1_smc_start; 254 return 0;
256 smccc_end = __smccc_workaround_1_smc_end; 255 case 0:
256 cb = call_smc_arch_workaround_1;
257 smccc_start = __smccc_workaround_1_smc_start;
258 smccc_end = __smccc_workaround_1_smc_end;
259 break;
260 default:
261 return -1;
262 }
257 break; 263 break;
258 264
259 default: 265 default:
260 return; 266 return -1;
261 } 267 }
262 268
263 if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) || 269 if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) ||
264 ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1)) 270 ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1))
265 cb = qcom_link_stack_sanitization; 271 cb = qcom_link_stack_sanitization;
266 272
267 install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); 273 if (IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR))
274 install_bp_hardening_cb(cb, smccc_start, smccc_end);
268 275
269 return; 276 return 1;
270} 277}
271#endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */
272 278
273#ifdef CONFIG_ARM64_SSBD
274DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); 279DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required);
275 280
276int ssbd_state __read_mostly = ARM64_SSBD_KERNEL; 281int ssbd_state __read_mostly = ARM64_SSBD_KERNEL;
282static bool __ssb_safe = true;
277 283
278static const struct ssbd_options { 284static const struct ssbd_options {
279 const char *str; 285 const char *str;
@@ -343,6 +349,11 @@ void __init arm64_enable_wa2_handling(struct alt_instr *alt,
343 349
344void arm64_set_ssbd_mitigation(bool state) 350void arm64_set_ssbd_mitigation(bool state)
345{ 351{
352 if (!IS_ENABLED(CONFIG_ARM64_SSBD)) {
353 pr_info_once("SSBD disabled by kernel configuration\n");
354 return;
355 }
356
346 if (this_cpu_has_cap(ARM64_SSBS)) { 357 if (this_cpu_has_cap(ARM64_SSBS)) {
347 if (state) 358 if (state)
348 asm volatile(SET_PSTATE_SSBS(0)); 359 asm volatile(SET_PSTATE_SSBS(0));
@@ -372,16 +383,28 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
372 struct arm_smccc_res res; 383 struct arm_smccc_res res;
373 bool required = true; 384 bool required = true;
374 s32 val; 385 s32 val;
386 bool this_cpu_safe = false;
375 387
376 WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); 388 WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
377 389
390 if (cpu_mitigations_off())
391 ssbd_state = ARM64_SSBD_FORCE_DISABLE;
392
393 /* delay setting __ssb_safe until we get a firmware response */
394 if (is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list))
395 this_cpu_safe = true;
396
378 if (this_cpu_has_cap(ARM64_SSBS)) { 397 if (this_cpu_has_cap(ARM64_SSBS)) {
398 if (!this_cpu_safe)
399 __ssb_safe = false;
379 required = false; 400 required = false;
380 goto out_printmsg; 401 goto out_printmsg;
381 } 402 }
382 403
383 if (psci_ops.smccc_version == SMCCC_VERSION_1_0) { 404 if (psci_ops.smccc_version == SMCCC_VERSION_1_0) {
384 ssbd_state = ARM64_SSBD_UNKNOWN; 405 ssbd_state = ARM64_SSBD_UNKNOWN;
406 if (!this_cpu_safe)
407 __ssb_safe = false;
385 return false; 408 return false;
386 } 409 }
387 410
@@ -398,6 +421,8 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
398 421
399 default: 422 default:
400 ssbd_state = ARM64_SSBD_UNKNOWN; 423 ssbd_state = ARM64_SSBD_UNKNOWN;
424 if (!this_cpu_safe)
425 __ssb_safe = false;
401 return false; 426 return false;
402 } 427 }
403 428
@@ -406,14 +431,18 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
406 switch (val) { 431 switch (val) {
407 case SMCCC_RET_NOT_SUPPORTED: 432 case SMCCC_RET_NOT_SUPPORTED:
408 ssbd_state = ARM64_SSBD_UNKNOWN; 433 ssbd_state = ARM64_SSBD_UNKNOWN;
434 if (!this_cpu_safe)
435 __ssb_safe = false;
409 return false; 436 return false;
410 437
438 /* machines with mixed mitigation requirements must not return this */
411 case SMCCC_RET_NOT_REQUIRED: 439 case SMCCC_RET_NOT_REQUIRED:
412 pr_info_once("%s mitigation not required\n", entry->desc); 440 pr_info_once("%s mitigation not required\n", entry->desc);
413 ssbd_state = ARM64_SSBD_MITIGATED; 441 ssbd_state = ARM64_SSBD_MITIGATED;
414 return false; 442 return false;
415 443
416 case SMCCC_RET_SUCCESS: 444 case SMCCC_RET_SUCCESS:
445 __ssb_safe = false;
417 required = true; 446 required = true;
418 break; 447 break;
419 448
@@ -423,6 +452,8 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
423 452
424 default: 453 default:
425 WARN_ON(1); 454 WARN_ON(1);
455 if (!this_cpu_safe)
456 __ssb_safe = false;
426 return false; 457 return false;
427 } 458 }
428 459
@@ -462,7 +493,14 @@ out_printmsg:
462 493
463 return required; 494 return required;
464} 495}
465#endif /* CONFIG_ARM64_SSBD */ 496
497/* known invulnerable cores */
498static const struct midr_range arm64_ssb_cpus[] = {
499 MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
500 MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
501 MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
502 {},
503};
466 504
467static void __maybe_unused 505static void __maybe_unused
468cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused) 506cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
@@ -507,26 +545,67 @@ cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
507 .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \ 545 .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, \
508 CAP_MIDR_RANGE_LIST(midr_list) 546 CAP_MIDR_RANGE_LIST(midr_list)
509 547
510#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR 548/* Track overall mitigation state. We are only mitigated if all cores are ok */
549static bool __hardenbp_enab = true;
550static bool __spectrev2_safe = true;
511 551
512/* 552/*
513 * List of CPUs where we need to issue a psci call to 553 * List of CPUs that do not need any Spectre-v2 mitigation at all.
514 * harden the branch predictor.
515 */ 554 */
516static const struct midr_range arm64_bp_harden_smccc_cpus[] = { 555static const struct midr_range spectre_v2_safe_list[] = {
517 MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), 556 MIDR_ALL_VERSIONS(MIDR_CORTEX_A35),
518 MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), 557 MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
519 MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), 558 MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
520 MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), 559 { /* sentinel */ }
521 MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
522 MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
523 MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
524 MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
525 MIDR_ALL_VERSIONS(MIDR_NVIDIA_DENVER),
526 {},
527}; 560};
528 561
529#endif 562/*
563 * Track overall bp hardening for all heterogeneous cores in the machine.
564 * We are only considered "safe" if all booted cores are known safe.
565 */
566static bool __maybe_unused
567check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope)
568{
569 int need_wa;
570
571 WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
572
573 /* If the CPU has CSV2 set, we're safe */
574 if (cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64PFR0_EL1),
575 ID_AA64PFR0_CSV2_SHIFT))
576 return false;
577
578 /* Alternatively, we have a list of unaffected CPUs */
579 if (is_midr_in_range_list(read_cpuid_id(), spectre_v2_safe_list))
580 return false;
581
582 /* Fallback to firmware detection */
583 need_wa = detect_harden_bp_fw();
584 if (!need_wa)
585 return false;
586
587 __spectrev2_safe = false;
588
589 if (!IS_ENABLED(CONFIG_HARDEN_BRANCH_PREDICTOR)) {
590 pr_warn_once("spectrev2 mitigation disabled by kernel configuration\n");
591 __hardenbp_enab = false;
592 return false;
593 }
594
595 /* forced off */
596 if (__nospectre_v2 || cpu_mitigations_off()) {
597 pr_info_once("spectrev2 mitigation disabled by command line option\n");
598 __hardenbp_enab = false;
599 return false;
600 }
601
602 if (need_wa < 0) {
603 pr_warn_once("ARM_SMCCC_ARCH_WORKAROUND_1 missing from firmware\n");
604 __hardenbp_enab = false;
605 }
606
607 return (need_wa > 0);
608}
530 609
531#ifdef CONFIG_HARDEN_EL2_VECTORS 610#ifdef CONFIG_HARDEN_EL2_VECTORS
532 611
@@ -701,13 +780,11 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
701 ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), 780 ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
702 }, 781 },
703#endif 782#endif
704#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
705 { 783 {
706 .capability = ARM64_HARDEN_BRANCH_PREDICTOR, 784 .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
707 .cpu_enable = enable_smccc_arch_workaround_1, 785 .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
708 ERRATA_MIDR_RANGE_LIST(arm64_bp_harden_smccc_cpus), 786 .matches = check_branch_predictor,
709 }, 787 },
710#endif
711#ifdef CONFIG_HARDEN_EL2_VECTORS 788#ifdef CONFIG_HARDEN_EL2_VECTORS
712 { 789 {
713 .desc = "EL2 vector hardening", 790 .desc = "EL2 vector hardening",
@@ -715,14 +792,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
715 ERRATA_MIDR_RANGE_LIST(arm64_harden_el2_vectors), 792 ERRATA_MIDR_RANGE_LIST(arm64_harden_el2_vectors),
716 }, 793 },
717#endif 794#endif
718#ifdef CONFIG_ARM64_SSBD
719 { 795 {
720 .desc = "Speculative Store Bypass Disable", 796 .desc = "Speculative Store Bypass Disable",
721 .capability = ARM64_SSBD, 797 .capability = ARM64_SSBD,
722 .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, 798 .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
723 .matches = has_ssbd_mitigation, 799 .matches = has_ssbd_mitigation,
800 .midr_range_list = arm64_ssb_cpus,
724 }, 801 },
725#endif
726#ifdef CONFIG_ARM64_ERRATUM_1188873 802#ifdef CONFIG_ARM64_ERRATUM_1188873
727 { 803 {
728 /* Cortex-A76 r0p0 to r2p0 */ 804 /* Cortex-A76 r0p0 to r2p0 */
@@ -742,3 +818,38 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
742 { 818 {
743 } 819 }
744}; 820};
821
822ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr,
823 char *buf)
824{
825 return sprintf(buf, "Mitigation: __user pointer sanitization\n");
826}
827
828ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr,
829 char *buf)
830{
831 if (__spectrev2_safe)
832 return sprintf(buf, "Not affected\n");
833
834 if (__hardenbp_enab)
835 return sprintf(buf, "Mitigation: Branch predictor hardening\n");
836
837 return sprintf(buf, "Vulnerable\n");
838}
839
840ssize_t cpu_show_spec_store_bypass(struct device *dev,
841 struct device_attribute *attr, char *buf)
842{
843 if (__ssb_safe)
844 return sprintf(buf, "Not affected\n");
845
846 switch (ssbd_state) {
847 case ARM64_SSBD_KERNEL:
848 case ARM64_SSBD_FORCE_ENABLE:
849 if (IS_ENABLED(CONFIG_ARM64_SSBD))
850 return sprintf(buf,
851 "Mitigation: Speculative Store Bypass disabled via prctl\n");
852 }
853
854 return sprintf(buf, "Vulnerable\n");
855}
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d856c55445a2..2b807f129e60 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -25,6 +25,7 @@
25#include <linux/stop_machine.h> 25#include <linux/stop_machine.h>
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/mm.h> 27#include <linux/mm.h>
28#include <linux/cpu.h>
28#include <asm/cpu.h> 29#include <asm/cpu.h>
29#include <asm/cpufeature.h> 30#include <asm/cpufeature.h>
30#include <asm/cpu_ops.h> 31#include <asm/cpu_ops.h>
@@ -956,7 +957,7 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope)
956 return has_cpuid_feature(entry, scope); 957 return has_cpuid_feature(entry, scope);
957} 958}
958 959
959#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 960static bool __meltdown_safe = true;
960static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */ 961static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
961 962
962static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, 963static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
@@ -975,7 +976,17 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
975 MIDR_ALL_VERSIONS(MIDR_HISI_TSV110), 976 MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
976 { /* sentinel */ } 977 { /* sentinel */ }
977 }; 978 };
978 char const *str = "command line option"; 979 char const *str = "kpti command line option";
980 bool meltdown_safe;
981
982 meltdown_safe = is_midr_in_range_list(read_cpuid_id(), kpti_safe_list);
983
984 /* Defer to CPU feature registers */
985 if (has_cpuid_feature(entry, scope))
986 meltdown_safe = true;
987
988 if (!meltdown_safe)
989 __meltdown_safe = false;
979 990
980 /* 991 /*
981 * For reasons that aren't entirely clear, enabling KPTI on Cavium 992 * For reasons that aren't entirely clear, enabling KPTI on Cavium
@@ -987,6 +998,24 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
987 __kpti_forced = -1; 998 __kpti_forced = -1;
988 } 999 }
989 1000
1001 /* Useful for KASLR robustness */
1002 if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset() > 0) {
1003 if (!__kpti_forced) {
1004 str = "KASLR";
1005 __kpti_forced = 1;
1006 }
1007 }
1008
1009 if (cpu_mitigations_off() && !__kpti_forced) {
1010 str = "mitigations=off";
1011 __kpti_forced = -1;
1012 }
1013
1014 if (!IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0)) {
1015 pr_info_once("kernel page table isolation disabled by kernel configuration\n");
1016 return false;
1017 }
1018
990 /* Forced? */ 1019 /* Forced? */
991 if (__kpti_forced) { 1020 if (__kpti_forced) {
992 pr_info_once("kernel page table isolation forced %s by %s\n", 1021 pr_info_once("kernel page table isolation forced %s by %s\n",
@@ -994,18 +1023,10 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
994 return __kpti_forced > 0; 1023 return __kpti_forced > 0;
995 } 1024 }
996 1025
997 /* Useful for KASLR robustness */ 1026 return !meltdown_safe;
998 if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
999 return kaslr_offset() > 0;
1000
1001 /* Don't force KPTI for CPUs that are not vulnerable */
1002 if (is_midr_in_range_list(read_cpuid_id(), kpti_safe_list))
1003 return false;
1004
1005 /* Defer to CPU feature registers */
1006 return !has_cpuid_feature(entry, scope);
1007} 1027}
1008 1028
1029#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
1009static void 1030static void
1010kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused) 1031kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
1011{ 1032{
@@ -1035,6 +1056,12 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
1035 1056
1036 return; 1057 return;
1037} 1058}
1059#else
1060static void
1061kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
1062{
1063}
1064#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
1038 1065
1039static int __init parse_kpti(char *str) 1066static int __init parse_kpti(char *str)
1040{ 1067{
@@ -1048,7 +1075,6 @@ static int __init parse_kpti(char *str)
1048 return 0; 1075 return 0;
1049} 1076}
1050early_param("kpti", parse_kpti); 1077early_param("kpti", parse_kpti);
1051#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
1052 1078
1053#ifdef CONFIG_ARM64_HW_AFDBM 1079#ifdef CONFIG_ARM64_HW_AFDBM
1054static inline void __cpu_enable_hw_dbm(void) 1080static inline void __cpu_enable_hw_dbm(void)
@@ -1315,7 +1341,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
1315 .field_pos = ID_AA64PFR0_EL0_SHIFT, 1341 .field_pos = ID_AA64PFR0_EL0_SHIFT,
1316 .min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT, 1342 .min_field_value = ID_AA64PFR0_EL0_32BIT_64BIT,
1317 }, 1343 },
1318#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
1319 { 1344 {
1320 .desc = "Kernel page table isolation (KPTI)", 1345 .desc = "Kernel page table isolation (KPTI)",
1321 .capability = ARM64_UNMAP_KERNEL_AT_EL0, 1346 .capability = ARM64_UNMAP_KERNEL_AT_EL0,
@@ -1331,7 +1356,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
1331 .matches = unmap_kernel_at_el0, 1356 .matches = unmap_kernel_at_el0,
1332 .cpu_enable = kpti_install_ng_mappings, 1357 .cpu_enable = kpti_install_ng_mappings,
1333 }, 1358 },
1334#endif
1335 { 1359 {
1336 /* FP/SIMD is not implemented */ 1360 /* FP/SIMD is not implemented */
1337 .capability = ARM64_HAS_NO_FPSIMD, 1361 .capability = ARM64_HAS_NO_FPSIMD,
@@ -2156,3 +2180,15 @@ static int __init enable_mrs_emulation(void)
2156} 2180}
2157 2181
2158core_initcall(enable_mrs_emulation); 2182core_initcall(enable_mrs_emulation);
2183
2184ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr,
2185 char *buf)
2186{
2187 if (__meltdown_safe)
2188 return sprintf(buf, "Not affected\n");
2189
2190 if (arm64_kernel_unmapped_at_el0())
2191 return sprintf(buf, "Mitigation: PTI\n");
2192
2193 return sprintf(buf, "Vulnerable\n");
2194}
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
index b33bafb8fcea..70568ccbd9fd 100644
--- a/arch/powerpc/kernel/security.c
+++ b/arch/powerpc/kernel/security.c
@@ -57,7 +57,7 @@ void setup_barrier_nospec(void)
57 enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && 57 enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) &&
58 security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); 58 security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR);
59 59
60 if (!no_nospec) 60 if (!no_nospec && !cpu_mitigations_off())
61 enable_barrier_nospec(enable); 61 enable_barrier_nospec(enable);
62} 62}
63 63
@@ -116,7 +116,7 @@ static int __init handle_nospectre_v2(char *p)
116early_param("nospectre_v2", handle_nospectre_v2); 116early_param("nospectre_v2", handle_nospectre_v2);
117void setup_spectre_v2(void) 117void setup_spectre_v2(void)
118{ 118{
119 if (no_spectrev2) 119 if (no_spectrev2 || cpu_mitigations_off())
120 do_btb_flush_fixups(); 120 do_btb_flush_fixups();
121 else 121 else
122 btb_flush_enabled = true; 122 btb_flush_enabled = true;
@@ -300,7 +300,7 @@ void setup_stf_barrier(void)
300 300
301 stf_enabled_flush_types = type; 301 stf_enabled_flush_types = type;
302 302
303 if (!no_stf_barrier) 303 if (!no_stf_barrier && !cpu_mitigations_off())
304 stf_barrier_enable(enable); 304 stf_barrier_enable(enable);
305} 305}
306 306
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index ba404dd9ce1d..4f49e1a3594c 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -932,7 +932,7 @@ void setup_rfi_flush(enum l1d_flush_type types, bool enable)
932 932
933 enabled_flush_types = types; 933 enabled_flush_types = types;
934 934
935 if (!no_rfi_flush) 935 if (!no_rfi_flush && !cpu_mitigations_off())
936 rfi_flush_enable(enable); 936 rfi_flush_enable(enable);
937} 937}
938 938
diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c
index bdddaae96559..649135cbedd5 100644
--- a/arch/s390/kernel/nospec-branch.c
+++ b/arch/s390/kernel/nospec-branch.c
@@ -1,6 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 1// SPDX-License-Identifier: GPL-2.0
2#include <linux/module.h> 2#include <linux/module.h>
3#include <linux/device.h> 3#include <linux/device.h>
4#include <linux/cpu.h>
4#include <asm/nospec-branch.h> 5#include <asm/nospec-branch.h>
5 6
6static int __init nobp_setup_early(char *str) 7static int __init nobp_setup_early(char *str)
@@ -58,7 +59,7 @@ early_param("nospectre_v2", nospectre_v2_setup_early);
58 59
59void __init nospec_auto_detect(void) 60void __init nospec_auto_detect(void)
60{ 61{
61 if (test_facility(156)) { 62 if (test_facility(156) || cpu_mitigations_off()) {
62 /* 63 /*
63 * The machine supports etokens. 64 * The machine supports etokens.
64 * Disable expolines and disable nobp. 65 * Disable expolines and disable nobp.
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 2da82eff0eb4..8043a21f36be 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -440,7 +440,8 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
440 char arg[20]; 440 char arg[20];
441 int ret, i; 441 int ret, i;
442 442
443 if (cmdline_find_option_bool(boot_command_line, "nospectre_v2")) 443 if (cmdline_find_option_bool(boot_command_line, "nospectre_v2") ||
444 cpu_mitigations_off())
444 return SPECTRE_V2_CMD_NONE; 445 return SPECTRE_V2_CMD_NONE;
445 446
446 ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg)); 447 ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
@@ -672,7 +673,8 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
672 char arg[20]; 673 char arg[20];
673 int ret, i; 674 int ret, i;
674 675
675 if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable")) { 676 if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable") ||
677 cpu_mitigations_off()) {
676 return SPEC_STORE_BYPASS_CMD_NONE; 678 return SPEC_STORE_BYPASS_CMD_NONE;
677 } else { 679 } else {
678 ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable", 680 ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable",
@@ -1008,6 +1010,11 @@ static void __init l1tf_select_mitigation(void)
1008 if (!boot_cpu_has_bug(X86_BUG_L1TF)) 1010 if (!boot_cpu_has_bug(X86_BUG_L1TF))
1009 return; 1011 return;
1010 1012
1013 if (cpu_mitigations_off())
1014 l1tf_mitigation = L1TF_MITIGATION_OFF;
1015 else if (cpu_mitigations_auto_nosmt())
1016 l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT;
1017
1011 override_cache_bits(&boot_cpu_data); 1018 override_cache_bits(&boot_cpu_data);
1012 1019
1013 switch (l1tf_mitigation) { 1020 switch (l1tf_mitigation) {
diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index 139b28a01ce4..d0255d64edce 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -35,6 +35,7 @@
35#include <linux/spinlock.h> 35#include <linux/spinlock.h>
36#include <linux/mm.h> 36#include <linux/mm.h>
37#include <linux/uaccess.h> 37#include <linux/uaccess.h>
38#include <linux/cpu.h>
38 39
39#include <asm/cpufeature.h> 40#include <asm/cpufeature.h>
40#include <asm/hypervisor.h> 41#include <asm/hypervisor.h>
@@ -115,7 +116,8 @@ void __init pti_check_boottime_disable(void)
115 } 116 }
116 } 117 }
117 118
118 if (cmdline_find_option_bool(boot_command_line, "nopti")) { 119 if (cmdline_find_option_bool(boot_command_line, "nopti") ||
120 cpu_mitigations_off()) {
119 pti_mode = PTI_FORCE_OFF; 121 pti_mode = PTI_FORCE_OFF;
120 pti_print_if_insecure("disabled on command line."); 122 pti_print_if_insecure("disabled on command line.");
121 return; 123 return;
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 5041357d0297..2d9c6f4b78f5 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -187,4 +187,28 @@ static inline void cpu_smt_disable(bool force) { }
187static inline void cpu_smt_check_topology(void) { } 187static inline void cpu_smt_check_topology(void) { }
188#endif 188#endif
189 189
190/*
191 * These are used for a global "mitigations=" cmdline option for toggling
192 * optional CPU mitigations.
193 */
194enum cpu_mitigations {
195 CPU_MITIGATIONS_OFF,
196 CPU_MITIGATIONS_AUTO,
197 CPU_MITIGATIONS_AUTO_NOSMT,
198};
199
200extern enum cpu_mitigations cpu_mitigations;
201
202/* mitigations=off */
203static inline bool cpu_mitigations_off(void)
204{
205 return cpu_mitigations == CPU_MITIGATIONS_OFF;
206}
207
208/* mitigations=auto,nosmt */
209static inline bool cpu_mitigations_auto_nosmt(void)
210{
211 return cpu_mitigations == CPU_MITIGATIONS_AUTO_NOSMT;
212}
213
190#endif /* _LINUX_CPU_H_ */ 214#endif /* _LINUX_CPU_H_ */
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 6754f3ecfd94..43e741e88691 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -2304,3 +2304,18 @@ void __init boot_cpu_hotplug_init(void)
2304#endif 2304#endif
2305 this_cpu_write(cpuhp_state.state, CPUHP_ONLINE); 2305 this_cpu_write(cpuhp_state.state, CPUHP_ONLINE);
2306} 2306}
2307
2308enum cpu_mitigations cpu_mitigations __ro_after_init = CPU_MITIGATIONS_AUTO;
2309
2310static int __init mitigations_parse_cmdline(char *arg)
2311{
2312 if (!strcmp(arg, "off"))
2313 cpu_mitigations = CPU_MITIGATIONS_OFF;
2314 else if (!strcmp(arg, "auto"))
2315 cpu_mitigations = CPU_MITIGATIONS_AUTO;
2316 else if (!strcmp(arg, "auto,nosmt"))
2317 cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT;
2318
2319 return 0;
2320}
2321early_param("mitigations", mitigations_parse_cmdline);