From a7c5501f677041edd955a7f76f2cd695f2238f8e Mon Sep 17 00:00:00 2001 From: Christoph Muellner Date: Tue, 15 May 2018 15:26:10 +0200 Subject: arm64: Use alternative framework for retpoline. This reduces the impact of retpoline on non-affected processors. By default the retpoline will consist of 6 nop instructions. In case an affected processor is detected (by a MIDR match) the nops will be replaced by the retpoline. The processors, which are using this are Applied Micro's X-Gene1, X-Gene2, X-Gene3, and Ampere Computing's eMAG1. Signed-off-by: Christoph Muellner --- arch/arm64/include/asm/cpucaps.h | 3 +- arch/arm64/include/asm/nospec-branch.h | 5 +++ arch/arm64/kernel/cpu_errata.c | 58 ++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) 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 +#include + #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) || \ @@ -425,6 +473,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = { MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), .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 { } -- cgit v1.2.3