From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755743AbeARPBN (ORCPT ); Thu, 18 Jan 2018 10:01:13 -0500 Received: from merlin.infradead.org ([205.233.59.134]:46788 "EHLO merlin.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755189AbeARO6F (ORCPT ); Thu, 18 Jan 2018 09:58:05 -0500 Message-Id: <20180118140152.830682032@infradead.org> User-Agent: quilt/0.63-1 Date: Thu, 18 Jan 2018 14:48:23 +0100 From: Peter Zijlstra From: Peter Zijlstra To: David Woodhouse , Thomas Gleixner , Josh Poimboeuf Cc: linux-kernel@vger.kernel.org, Dave Hansen , Ashok Raj , Tim Chen , Andy Lutomirski , Linus Torvalds , Greg KH , Andrea Arcangeli , Andi Kleen , Arjan Van De Ven , Dan Williams , Paolo Bonzini , Jun Nakajima , Asit Mallick , Jason Baron , Peter Zijlstra Subject: [PATCH 23/35] x86/speculation: Add basic speculation control code References: <20180118134800.711245485@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 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 From: Thomas Gleixner 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. [peterz: fixed Makefile] Signed-off-by: Thomas Gleixner Signed-off-by: Peter Zijlstra (Intel) --- Documentation/admin-guide/kernel-parameters.txt | 1 arch/x86/include/asm/nospec-branch.h | 5 +++ arch/x86/kernel/cpu/Makefile | 1 arch/x86/kernel/cpu/bugs.c | 26 +++++++++++++++++- arch/x86/kernel/cpu/specctrl.c | 33 ++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3932,6 +3932,7 @@ retpoline - replace indirect branches retpoline,generic - google's original retpoline retpoline,amd - AMD-specific minimal thunk + ibrs - Intel: Indirect Branch Restricted Speculation Not specifying this option is equivalent to spectre_v2=auto. --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -214,5 +214,10 @@ static inline void vmexit_fill_RSB(void) : "r" (loops) : "memory" ); #endif } + +bool specctrl_force_enable_ibrs(void); +bool specctrl_cond_enable_ibrs(bool full_retpoline); +bool is_skylake_era(void); + #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.o 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] = "Vulnerable: 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 @@ -144,6 +146,8 @@ static enum spectre_v2_mitigation_cmd __ } else if (match_option(arg, ret, "retpoline,generic")) { spec2_print_if_insecure("generic retpoline selected on command line."); return SPECTRE_V2_CMD_RETPOLINE_GENERIC; + } else if (match_option(arg, ret, "ibrs")) { + return SPECTRE_V2_CMD_IBRS; } else if (match_option(arg, ret, "auto")) { return SPECTRE_V2_CMD_AUTO; } @@ -156,8 +160,8 @@ static enum spectre_v2_mitigation_cmd __ return SPECTRE_V2_CMD_NONE; } -/* Check for Skylake-like CPUs (for RSB handling) */ -static bool __init is_skylake_era(void) +/* Check for Skylake-like CPUs (for RSB and IBRS handling) */ +bool __init is_skylake_era(void) { if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 == 6) { @@ -175,6 +179,7 @@ static bool __init is_skylake_era(void) static void __init spectre_v2_select_mitigation(void) { + bool full_retpoline = IS_ENABLED(CONFIG_RETPOLINE) && retp_compiler(); enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); enum spectre_v2_mitigation mode = SPECTRE_V2_NONE; @@ -190,9 +195,25 @@ static void __init spectre_v2_select_mit 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 or IBRS is + * the only available mitigation. + */ + if (specctrl_cond_enable_ibrs(full_retpoline)) { + mode = SPECTRE_V2_IBRS; + goto set_mode; + } goto retpoline_auto; case SPECTRE_V2_CMD_RETPOLINE_AMD: @@ -229,6 +250,7 @@ static void __init spectre_v2_select_mit setup_force_cpu_cap(X86_FEATURE_RETPOLINE); } +set_mode: spectre_v2_enabled = mode; pr_info("%s\n", spectre_v2_strings[mode]); --- /dev/null +++ b/arch/x86/kernel/cpu/specctrl.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include + +static inline void specctrl_enable_ibrs(void) +{ + setup_force_cpu_cap(X86_FEATURE_IBRS); +} + +bool __init specctrl_force_enable_ibrs(void) +{ + if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + return false; + specctrl_enable_ibrs(); + return true; +} + +bool __init specctrl_cond_enable_ibrs(bool full_retpoline) +{ + if (!boot_cpu_has(X86_FEATURE_SPEC_CTRL)) + return false; + /* + * IBRS is only required by SKL or as fallback if retpoline is not + * fully supported. + */ + if (!is_skylake_era() && full_retpoline) + return false; + + specctrl_enable_ibrs(); + return true; +}