Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932585AbeAJBWo (ORCPT + 1 other); Tue, 9 Jan 2018 20:22:44 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:53930 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752977AbeAJBVs (ORCPT ); Tue, 9 Jan 2018 20:21:48 -0500 Message-Id: <20180110011350.855878109@linutronix.de> User-Agent: quilt/0.63-1 Date: Wed, 10 Jan 2018 02:06:57 +0100 From: Thomas Gleixner To: LKML Cc: Linus Torvalds , x86@kernel.org, Peter Zijlstra , Borislav Petkov , David Woodhouse , Tim Chen , Andrea Arcangeli , Andi Kleen , Greg KH , Dave Hansen , Andy Lutomirski , Arjan Van De Ven Subject: [patch RFC 5/5] x86/speculation: Add basic speculation control code References: <20180110010652.404145126@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-15 Content-Disposition: inline; filename=x86-speculation--Add-basic-speculation-control-code.patch Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: Add the minimal infrastructure to control the speculation control feature. - Integrate it into the spectre_v2 coammand line parser and the mitigation selector function. The conditional selector function is a placeholder right now, which needs to be expanded with CPU specific decision functions. - Provide a static key for the actual code control. - Provide a init function which is called after jump label patching is functional. - Provide an interface for the late micro code loader to allow late discovery of the IBRS support. Not yet functional. Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/nospec-branch.h | 9 +++++ arch/x86/kernel/cpu/Makefile | 1 arch/x86/kernel/cpu/bugs.c | 17 +++++++++ arch/x86/kernel/cpu/specctrl.c | 62 +++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+) --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -3,6 +3,8 @@ #ifndef __NOSPEC_BRANCH_H__ #define __NOSPEC_BRANCH_H__ +#include + #include #include #include @@ -165,5 +167,12 @@ enum spectre_v2_mitigation { enum spectre_v2_mitigation spectre_v2_enabled; void spectre_v2_select_mitigation(void); +DECLARE_STATIC_KEY_FALSE(specctrl_ibrs); + +void specctrl_init_features(void); +void specctrl_update_features(void); +bool specctrl_force_enable_ibrs(void); +bool specctrl_cond_enable_ibrs(bool full_retpoline); + #endif /* __ASSEMBLY__ */ #endif /* __NOSPEC_BRANCH_H__ */ --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -24,6 +24,7 @@ obj-y += match.o obj-y += bugs.o obj-$(CONFIG_CPU_FREQ) += aperfmperf.o obj-y += cpuid-deps.o +obj-y += specctrl.c obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -79,6 +79,7 @@ enum spectre_v2_mitigation_cmd { SPECTRE_V2_CMD_RETPOLINE, SPECTRE_V2_CMD_RETPOLINE_GENERIC, SPECTRE_V2_CMD_RETPOLINE_AMD, + SPECTRE_V2_CMD_IBRS, }; static const char *spectre_v2_strings[] = { @@ -87,6 +88,7 @@ static const char *spectre_v2_strings[] [SPECTRE_V2_RETPOLINE_MINIMAL_AMD] = "Mitigation: Minimal AMD ASM retpoline", [SPECTRE_V2_RETPOLINE_GENERIC] = "Mitigation: Full generic retpoline", [SPECTRE_V2_RETPOLINE_AMD] = "Mitigation: Full AMD retpoline", + [SPECTRE_V2_IBRS] = "Mitigation: Indirect Branch Restricted Speculation", }; #undef pr_fmt @@ -163,6 +165,7 @@ static void __init spectre_v2_check_boot void spectre_v2_select_mitigation(void) { + bool full_retpoline = IS_ENABLED(CONFIG_RETPOLINE) && retp_compiler(); enum spectre_v2_mitigation mode = SPECTRE_V2_NONE; /* @@ -178,9 +181,22 @@ void spectre_v2_select_mitigation(void) case SPECTRE_V2_CMD_NONE: return; + case SPECTRE_V2_CMD_IBRS: + /* Command line requested IBRS. Try to enable it */ + if (specctrl_force_enable_ibrs()) { + mode = SPECTRE_V2_IBRS; + goto set_mode; + } + /* FALLTRHU */ + case SPECTRE_V2_CMD_FORCE: /* FALLTRHU */ case SPECTRE_V2_CMD_AUTO: + /* Check whether the CPU prefers to have IBRS */ + if (specctrl_cond_enable_ibrs(full_retpoline)) { + mode = SPECTRE_V2_IBRS; + goto set_mode; + } goto retpoline_auto; case SPECTRE_V2_CMD_RETPOLINE_AMD: @@ -223,6 +239,7 @@ void spectre_v2_select_mitigation(void) setup_force_cpu_cap(X86_FEATURE_RETPOLINE); } +set_mode: if (spectre_v2_enabled == mode) return; spectre_v2_enabled = mode; --- /dev/null +++ b/arch/x86/kernel/cpu/specctrl.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +/* Static key to control enablement of IBRS */ +DEFINE_STATIC_KEY_FALSE(specctrl_ibrs); + +/** + * specctrl_init_features - Init speculation control features + * + * Called after static key patching is functional. The decision which + * mitigation to use has been made already in check_bugs() before patching + * the alternatives. + */ +void __init specctrl_init_features(void) +{ + if (spectre_v2_enabled != SPECTRE_V2_IBRS) + return; + + static_branch_enable(&specctrl_ibrs); +} + +/** + * specctrl_update_features - Update the speculation control features + * + * Called after a late microcode load changed CPU feature bits. + * + * Note: This is called with CPU hotplug lock and microcode mutex held. + */ +void specctrl_update_features(void) +{ + if (static_key_enabled(&specctrl_ibrs)) + return; + + /* + * FIXME: Either the CPU bits need to be reevaluated here or its + * done in the late microcode loader. Borislav ? + */ + spectre_v2_select_mitigation(); + if (spectre_v2_enabled != SPECTRE_V2_IBRS) + return; + static_branch_enable_cpuslocked(&specctrl_ibrs); +} + +bool specctrl_force_enable_ibrs(void) +{ + if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + return false; + return true; +} + +bool specctrl_cond_enable_ibrs(bool full_retpoline) +{ + if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + return false; + /* + * FIXME: Add logic here to decide what the best option is for a + * particular CPU. + */ + return true; +}