diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm64/include/asm/cpucaps.h | 3 | ||||
-rw-r--r-- | arch/arm64/include/asm/nospec-branch.h | 5 | ||||
-rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 56 |
3 files changed, 63 insertions, 1 deletions
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index bb263820de13..1a4513277802 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -45,7 +45,8 @@ #define ARM64_HARDEN_BRANCH_PREDICTOR 24 #define ARM64_HARDEN_BP_POST_GUEST_EXIT 25 #define ARM64_HAS_RAS_EXTN 26 +#define ARM64_RETPOLINE 27 -#define ARM64_NCAPS 27 +#define ARM64_NCAPS 28 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/nospec-branch.h b/arch/arm64/include/asm/nospec-branch.h index 463ec183f4ec..63db0e2b19a2 100644 --- a/arch/arm64/include/asm/nospec-branch.h +++ b/arch/arm64/include/asm/nospec-branch.h @@ -3,9 +3,13 @@ #ifndef _ASM_ARM64_NOSPEC_BRANCH_H_ #define _ASM_ARM64_NOSPEC_BRANCH_H_ +#include <asm/alternative.h> +#include <asm/cpucaps.h> + #ifdef __ASSEMBLY__ .macro retpoline +alternative_if ARM64_RETPOLINE str x30, [sp, #-16]! bl 101f 100: //speculation trap @@ -16,6 +20,7 @@ ret 102: //non-spec code ldr x30, [sp], #16 +alternative_else_nop_endif .endm .macro br_nospec reg diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index b5a28336c077..c1e2ee0144f6 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -242,6 +242,55 @@ static int qcom_enable_link_stack_sanitization(void *data) .midr_range_min = 0, \ .midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK) +#ifdef CONFIG_RETPOLINE + +static inline bool retp_compiler(void) +{ + return __is_defined(RETPOLINE); +} + +/* The Spectre V2 mitigation variants */ +enum spectre_v2_mitigation { + SPECTRE_V2_NOT_AFFECTED, + SPECTRE_V2_RETPOLINE_MINIMAL, + SPECTRE_V2_RETPOLINE_GENERIC, +}; + +static const char *spectre_v2_strings[] = { + [SPECTRE_V2_NOT_AFFECTED] = "Not affected", + [SPECTRE_V2_RETPOLINE_MINIMAL] = "Vulnerable: Minimal ASM retpoline", + [SPECTRE_V2_RETPOLINE_GENERIC] = "Mitigation: Full retpoline", +}; + +static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NOT_AFFECTED; + +static bool spectre_v2_bad_module; + +bool retpoline_module_ok(bool has_retpoline) +{ + if (has_retpoline) + return true; + + pr_err("System may be vulnerable to spectre v2\n"); + spectre_v2_bad_module = true; + return false; +} + +static inline const char *spectre_v2_module_string(void) +{ + return spectre_v2_bad_module ? " - vulnerable module loaded" : ""; +} + +static int +enable_retpoline(void *data) +{ + spectre_v2_enabled = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC : + SPECTRE_V2_RETPOLINE_MINIMAL; + return 0; +} + +#endif + const struct arm64_cpu_capabilities arm64_errata[] = { #if defined(CONFIG_ARM64_ERRATUM_826319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \ @@ -426,6 +475,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = { .enable = enable_smccc_arch_workaround_1, }, #endif +#ifdef CONFIG_RETPOLINE + { + .capability = ARM64_RETPOLINE, + MIDR_ALL_VERSIONS(MIDR_APM_POTENZA), + .enable = enable_retpoline, + }, +#endif { } }; |