On 1/10/2018 11:35 AM, tip-bot for David Woodhouse wrote: > Commit-ID: d569ded27d11bcb1643b14c54403910d9b3328b1 > Gitweb: https://git.kernel.org/tip/d569ded27d11bcb1643b14c54403910d9b3328b1 > Author: David Woodhouse <dwmw@xxxxxxxxxxxx> > AuthorDate: Tue, 9 Jan 2018 14:43:09 +0000 > Committer: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > CommitDate: Wed, 10 Jan 2018 18:28:22 +0100 > > x86/spectre: Add boot time option to select Spectre v2 mitigation > > Add a spectre_v2= option to select the mitigation used for the indirect > branch speculation vulnerability. > > Currently, the only option available is retpoline, in its various forms. > This will be expanded to cover the new IBRS/IBPB microcode features. > > The RETPOLINE_AMD feature relies on a serializing LFENCE for speculation > control. For AMD hardware, only set RETPOLINE_AMD if LFENCE is a > serializing instruction, which is indicated by the LFENCE_RDTSC feature. > > [ tglx: Folded back the LFENCE/AMD fixes and reworked it so IBRS > integration becomes simple ] > > Signed-off-by: David Woodhouse <dwmw@xxxxxxxxxxxx> > Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx> > Cc: gnomes@xxxxxxxxxxxxxxxxxxx > Cc: Rik van Riel <riel@xxxxxxxxxx> > Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx> > Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> > Cc: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> > Cc: Jiri Kosina <jikos@xxxxxxxxxx> > Cc: Andy Lutomirski <luto@xxxxxxxxxxxxxx> > Cc: Dave Hansen <dave.hansen@xxxxxxxxx> > Cc: Kees Cook <keescook@xxxxxxxxxx> > Cc: Tim Chen <tim.c.chen@xxxxxxxxxxxxxxx> > Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxxx> > Cc: Paul Turner <pjt@xxxxxxxxxx> > Cc: Tom Lendacky <thomas.lendacky@xxxxxxx> > Link: https://lkml.kernel.org/r/1515508997-6154-4-git-send-email-dwmw@xxxxxxxxxxxx > > > --- > Documentation/admin-guide/kernel-parameters.txt | 28 +++++ > arch/x86/include/asm/nospec-branch.h | 10 ++ > arch/x86/kernel/cpu/bugs.c | 158 +++++++++++++++++++++++- > arch/x86/kernel/cpu/common.c | 4 - > 4 files changed, 195 insertions(+), 5 deletions(-) > ... > diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c > index 76ad6cb..5b96fed 100644 > --- a/arch/x86/kernel/cpu/bugs.c > +++ b/arch/x86/kernel/cpu/bugs.c > @@ -11,6 +11,9 @@ > #include <linux/init.h> > #include <linux/utsname.h> > #include <linux/cpu.h> > + > +#include <asm/nospec-branch.h> > +#include <asm/cmdline.h> > #include <asm/bugs.h> > #include <asm/processor.h> > #include <asm/processor-flags.h> > @@ -21,6 +24,8 @@ > #include <asm/pgtable.h> > #include <asm/set_memory.h> > > +static void __init spectre_v2_select_mitigation(void); > + > void __init check_bugs(void) > { > identify_boot_cpu(); > @@ -30,6 +35,9 @@ void __init check_bugs(void) > print_cpu_info(&boot_cpu_data); > } > > + /* Select the proper spectre mitigation before patching alternatives */ > + spectre_v2_select_mitigation(); > + > #ifdef CONFIG_X86_32 > /* > * Check whether we are able to run this kernel safely on SMP. > @@ -62,6 +70,153 @@ void __init check_bugs(void) > #endif > } > > +/* The kernel command line selection */ > +enum spectre_v2_mitigation_cmd { > + SPECTRE_V2_CMD_NONE, > + SPECTRE_V2_CMD_AUTO, > + SPECTRE_V2_CMD_FORCE, > + SPECTRE_V2_CMD_RETPOLINE, > + SPECTRE_V2_CMD_RETPOLINE_GENERIC, > + SPECTRE_V2_CMD_RETPOLINE_AMD, > +}; > + > +static const char *spectre_v2_strings[] = { > + [SPECTRE_V2_NONE] = "Vulnerable", > + [SPECTRE_V2_RETPOLINE_MINIMAL] = "Vulnerable: Minimal generic ASM retpoline", > + [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", > +}; > + > +#undef pr_fmt > +#define pr_fmt(fmt) "Spectre V2 mitigation: " fmt > + > +static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE; > + > +static void __init spec2_print_if_insecure(const char *reason) > +{ > + if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) > + pr_info("%s\n", reason); > +} > + > +static void __init spec2_print_if_secure(const char *reason) > +{ > + if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) > + pr_info("%s\n", reason); > +} > + > +static inline bool retp_compiler(void) > +{ > + return __is_defined(RETPOLINE); > +} > + > +static inline bool match_option(const char *arg, int arglen, const char *opt) > +{ > + int len = strlen(opt); > + > + return len == arglen && !strncmp(arg, opt, len); > +} > + > +static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void) > +{ > + char arg[20]; > + int ret; > + > + ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, > + sizeof(arg)); > + if (ret > 0) { > + if (match_option(arg, ret, "off")) { > + goto disable; > + } else if (match_option(arg, ret, "on")) { > + spec2_print_if_secure("force enabled on command line."); > + return SPECTRE_V2_CMD_FORCE; > + } else if (match_option(arg, ret, "retpoline")) { > + spec2_print_if_insecure("retpoline selected on command line."); > + return SPECTRE_V2_CMD_RETPOLINE; > + } else if (match_option(arg, ret, "retpoline,amd")) { > + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { > + pr_err("retpoline,amd selected but CPU is not AMD. Switching to AUTO select\n"); > + return SPECTRE_V2_CMD_AUTO; > + } > + if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) { > + pr_err("LFENCE not serializing. Switching to generic retpoline\n"); > + return SPECTRE_V2_CMD_RETPOLINE_GENERIC; > + } > + spec2_print_if_insecure("AMD retpoline selected on command line."); > + return SPECTRE_V2_CMD_RETPOLINE_AMD; > + } 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, "auto")) { > + return SPECTRE_V2_CMD_AUTO; > + } > + } > + > + if (!cmdline_find_option_bool(boot_command_line, "nospectre_v2")) > + return SPECTRE_V2_CMD_AUTO; > +disable: > + spec2_print_if_insecure("disabled on command line."); > + return SPECTRE_V2_CMD_NONE; > +} > + > +static void __init spectre_v2_select_mitigation(void) > +{ > + enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); > + enum spectre_v2_mitigation mode = SPECTRE_V2_NONE; > + > + /* > + * If the CPU is not affected and the command line mode is NONE or AUTO > + * then nothing to do. > + */ > + if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2) && > + (cmd == SPECTRE_V2_CMD_NONE || cmd == SPECTRE_V2_CMD_AUTO)) > + return; > + > + switch (cmd) { > + case SPECTRE_V2_CMD_NONE: > + return; > + > + case SPECTRE_V2_CMD_FORCE: > + /* FALLTRHU */ > + case SPECTRE_V2_CMD_AUTO: > + goto retpoline_auto; > + > + case SPECTRE_V2_CMD_RETPOLINE_AMD: > + if (IS_ENABLED(CONFIG_RETPOLINE)) > + goto retpoline_amd; > + break; > + case SPECTRE_V2_CMD_RETPOLINE_GENERIC: > + if (IS_ENABLED(CONFIG_RETPOLINE)) > + goto retpoline_generic; > + break; > + case SPECTRE_V2_CMD_RETPOLINE: > + if (IS_ENABLED(CONFIG_RETPOLINE)) > + goto retpoline_auto; > + break; > + } > + pr_err("kernel not compiled with retpoline; no mitigation available!"); > + return; > + > +retpoline_auto: > + if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) { Not specifying anything on the command line will get SPECTRE_V2_CMD_AUTO, so boot_cpu_has(X86_FEATURE_LFENCE_RDTSC) needs to be checked since it won't have been checked previously. Thanks, Tom > + retpoline_amd: > + mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD : > + SPECTRE_V2_RETPOLINE_MINIMAL_AMD; > + setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD); > + setup_force_cpu_cap(X86_FEATURE_RETPOLINE); > + } else { > + retpoline_generic: > + mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC : > + SPECTRE_V2_RETPOLINE_MINIMAL; > + setup_force_cpu_cap(X86_FEATURE_RETPOLINE); > + } > + > + spectre_v2_enabled = mode; > + pr_info("%s\n", spectre_v2_strings[mode]); > +} > + > +#undef pr_fmt > + > #ifdef CONFIG_SYSFS > ssize_t cpu_show_meltdown(struct device *dev, > struct device_attribute *attr, char *buf) > @@ -86,6 +241,7 @@ ssize_t cpu_show_spectre_v2(struct device *dev, > { > if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2)) > return sprintf(buf, "Not affected\n"); > - return sprintf(buf, "Vulnerable\n"); > + > + return sprintf(buf, "%s\n", spectre_v2_strings[spectre_v2_enabled]); > } > #endif > diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c > index 7a671d1..372ba3f 100644 > --- a/arch/x86/kernel/cpu/common.c > +++ b/arch/x86/kernel/cpu/common.c > @@ -905,10 +905,6 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) > setup_force_cpu_bug(X86_BUG_SPECTRE_V1); > setup_force_cpu_bug(X86_BUG_SPECTRE_V2); > > -#ifdef CONFIG_RETPOLINE > - setup_force_cpu_cap(X86_FEATURE_RETPOLINE); > -#endif > - > fpu__init_system(c); > > #ifdef CONFIG_X86_32 > -- To unsubscribe from this list: send the line "unsubscribe linux-tip-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html
![]() |