On 1/10/2018 12:14 PM, tip-bot for David Woodhouse wrote:
> Commit-ID:  fe1678d070e36070c43005c71ce783df57852252
> Gitweb:     
> https://git.kernel.org/tip/fe1678d070e36070c43005c71ce783df57852252
> Author:     David Woodhouse <d...@amazon.co.uk>
> AuthorDate: Tue, 9 Jan 2018 14:43:09 +0000
> Committer:  Thomas Gleixner <t...@linutronix.de>
> CommitDate: Wed, 10 Jan 2018 19:09:09 +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 <d...@amazon.co.uk>
> Signed-off-by: Thomas Gleixner <t...@linutronix.de>
> Cc: gno...@lxorguk.ukuu.org.uk
> Cc: Rik van Riel <r...@redhat.com>
> Cc: Andi Kleen <a...@linux.intel.com>
> Cc: Peter Zijlstra <pet...@infradead.org>
> Cc: Linus Torvalds <torva...@linux-foundation.org>
> Cc: Jiri Kosina <ji...@kernel.org>
> Cc: Andy Lutomirski <l...@amacapital.net>
> Cc: Dave Hansen <dave.han...@intel.com>
> Cc: Kees Cook <keesc...@google.com>
> Cc: Tim Chen <tim.c.c...@linux.intel.com>
> Cc: Greg Kroah-Hartman <gre...@linux-foundation.org>
> Cc: Paul Turner <p...@google.com>
> Cc: Tom Lendacky <thomas.lenda...@amd.com>
> Link: 
> https://lkml.kernel.org/r/1515508997-6154-4-git-send-email-d...@amazon.co.uk
> 
> 
> ---
>  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..4f7a2a0 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) {

I missed this in the first review, but this should be != X86_VENDOR_AMD.
Sorry about that.

Thanks,
Tom

> +                             pr_err("retpoline,amd selected but CPU is not 
> AMD. Switching to AUTO select\n");
> +                             return SPECTRE_V2_CMD_AUTO;
> +                     }
> +                     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) {
> +     retpoline_amd:
> +             if (!boot_cpu_has(X86_FEATURE_LFENCE_RDTSC)) {
> +                     pr_err("LFENCE not serializing. Switching to generic 
> retpoline\n");
> +                     goto retpoline_generic;
> +             }
> +             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
> 

Reply via email to