diff options
-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 | 58 |
3 files changed, 65 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..d9bc01ef8ed3 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -242,6 +242,54 @@ 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 void +enable_retpoline(const struct arm64_cpu_capabilities *entry) +{ + spectre_v2_enabled = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC : + SPECTRE_V2_RETPOLINE_MINIMAL; +} + +#endif + const struct arm64_cpu_capabilities arm64_errata[] = { #if defined(CONFIG_ARM64_ERRATUM_826319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \ @@ -426,6 +474,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = { .enable = enable_smccc_arch_workaround_1, }, #endif +#ifdef CONFIG_RETPOLINE + { + .desc = "speculative branch prediction using retpoline", + .capability = ARM64_RETPOLINE, + .type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE, + .cpu_enable = enable_retpoline, + .matches = is_affected_midr_range, + .midr_range = MIDR_RANGE(MIDR_APM_POTENZA, 0, 0, 3, 1), + }, +#endif { } }; |