OSDN Git Service

x86/speculation: Unify conditional spectre v2 print functions
[uclinux-h8/linux.git] / arch / x86 / kernel / cpu / bugs.c
index c37e66e..4f5a631 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/nospec.h>
 #include <linux/prctl.h>
+#include <linux/sched/smt.h>
 
 #include <asm/spec-ctrl.h>
 #include <asm/cmdline.h>
@@ -123,31 +124,6 @@ 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",
-       [SPECTRE_V2_IBRS_ENHANCED]              = "Mitigation: Enhanced IBRS",
-};
-
-#undef pr_fmt
-#define pr_fmt(fmt)     "Spectre V2 : " fmt
-
-static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
-       SPECTRE_V2_NONE;
-
 void
 x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
 {
@@ -202,7 +178,7 @@ x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
                tif = setguest ? ssbd_spec_ctrl_to_tif(guestval) :
                                 ssbd_spec_ctrl_to_tif(hostval);
 
-               speculative_store_bypass_update(tif);
+               speculation_ctrl_update(tif);
        }
 }
 EXPORT_SYMBOL_GPL(x86_virt_spec_ctrl);
@@ -217,6 +193,12 @@ static void x86_amd_ssb_disable(void)
                wrmsrl(MSR_AMD64_LS_CFG, msrval);
 }
 
+#undef pr_fmt
+#define pr_fmt(fmt)     "Spectre V2 : " fmt
+
+static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
+       SPECTRE_V2_NONE;
+
 #ifdef RETPOLINE
 static bool spectre_v2_bad_module;
 
@@ -238,23 +220,6 @@ static inline const char *spectre_v2_module_string(void)
 static inline const char *spectre_v2_module_string(void) { return ""; }
 #endif
 
-static void __init spec2_print_if_insecure(const char *reason)
-{
-       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
-               pr_info("%s selected on command line.\n", reason);
-}
-
-static void __init spec2_print_if_secure(const char *reason)
-{
-       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
-               pr_info("%s selected on command line.\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);
@@ -262,43 +227,65 @@ static inline bool match_option(const char *arg, int arglen, const char *opt)
        return len == arglen && !strncmp(arg, opt, len);
 }
 
+/* The kernel command line selection for spectre v2 */
+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 * const spectre_v2_strings[] = {
+       [SPECTRE_V2_NONE]                       = "Vulnerable",
+       [SPECTRE_V2_RETPOLINE_GENERIC]          = "Mitigation: Full generic retpoline",
+       [SPECTRE_V2_RETPOLINE_AMD]              = "Mitigation: Full AMD retpoline",
+       [SPECTRE_V2_IBRS_ENHANCED]              = "Mitigation: Enhanced IBRS",
+};
+
 static const struct {
        const char *option;
        enum spectre_v2_mitigation_cmd cmd;
        bool secure;
-} mitigation_options[] = {
-       { "off",               SPECTRE_V2_CMD_NONE,              false },
-       { "on",                SPECTRE_V2_CMD_FORCE,             true },
-       { "retpoline",         SPECTRE_V2_CMD_RETPOLINE,         false },
-       { "retpoline,amd",     SPECTRE_V2_CMD_RETPOLINE_AMD,     false },
-       { "retpoline,generic", SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
-       { "auto",              SPECTRE_V2_CMD_AUTO,              false },
+} mitigation_options[] __initdata = {
+       { "off",                SPECTRE_V2_CMD_NONE,              false },
+       { "on",                 SPECTRE_V2_CMD_FORCE,             true  },
+       { "retpoline",          SPECTRE_V2_CMD_RETPOLINE,         false },
+       { "retpoline,amd",      SPECTRE_V2_CMD_RETPOLINE_AMD,     false },
+       { "retpoline,generic",  SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
+       { "auto",               SPECTRE_V2_CMD_AUTO,              false },
 };
 
+static void __init spec_v2_print_cond(const char *reason, bool secure)
+{
+       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2) != secure)
+               pr_info("%s selected on command line.\n", reason);
+}
+
 static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
 {
+       enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
        char arg[20];
        int ret, i;
-       enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
 
        if (cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
                return SPECTRE_V2_CMD_NONE;
-       else {
-               ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
-               if (ret < 0)
-                       return SPECTRE_V2_CMD_AUTO;
 
-               for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
-                       if (!match_option(arg, ret, mitigation_options[i].option))
-                               continue;
-                       cmd = mitigation_options[i].cmd;
-                       break;
-               }
+       ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
+       if (ret < 0)
+               return SPECTRE_V2_CMD_AUTO;
 
-               if (i >= ARRAY_SIZE(mitigation_options)) {
-                       pr_err("unknown option (%s). Switching to AUTO select\n", arg);
-                       return SPECTRE_V2_CMD_AUTO;
-               }
+       for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
+               if (!match_option(arg, ret, mitigation_options[i].option))
+                       continue;
+               cmd = mitigation_options[i].cmd;
+               break;
+       }
+
+       if (i >= ARRAY_SIZE(mitigation_options)) {
+               pr_err("unknown option (%s). Switching to AUTO select\n", arg);
+               return SPECTRE_V2_CMD_AUTO;
        }
 
        if ((cmd == SPECTRE_V2_CMD_RETPOLINE ||
@@ -316,54 +303,11 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
                return SPECTRE_V2_CMD_AUTO;
        }
 
-       if (mitigation_options[i].secure)
-               spec2_print_if_secure(mitigation_options[i].option);
-       else
-               spec2_print_if_insecure(mitigation_options[i].option);
-
+       spec_v2_print_cond(mitigation_options[i].option,
+                          mitigation_options[i].secure);
        return cmd;
 }
 
-static bool stibp_needed(void)
-{
-       if (spectre_v2_enabled == SPECTRE_V2_NONE)
-               return false;
-
-       if (!boot_cpu_has(X86_FEATURE_STIBP))
-               return false;
-
-       return true;
-}
-
-static void update_stibp_msr(void *info)
-{
-       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
-}
-
-void arch_smt_update(void)
-{
-       u64 mask;
-
-       if (!stibp_needed())
-               return;
-
-       mutex_lock(&spec_ctrl_mutex);
-       mask = x86_spec_ctrl_base;
-       if (cpu_smt_control == CPU_SMT_ENABLED)
-               mask |= SPEC_CTRL_STIBP;
-       else
-               mask &= ~SPEC_CTRL_STIBP;
-
-       if (mask != x86_spec_ctrl_base) {
-               pr_info("Spectre v2 cross-process SMT mitigation: %s STIBP\n",
-                               cpu_smt_control == CPU_SMT_ENABLED ?
-                               "Enabling" : "Disabling");
-               x86_spec_ctrl_base = mask;
-               on_each_cpu(update_stibp_msr, NULL, 1);
-       }
-       mutex_unlock(&spec_ctrl_mutex);
-}
-
 static void __init spectre_v2_select_mitigation(void)
 {
        enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -417,14 +361,12 @@ retpoline_auto:
                        pr_err("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n");
                        goto retpoline_generic;
                }
-               mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD :
-                                        SPECTRE_V2_RETPOLINE_MINIMAL_AMD;
+               mode = SPECTRE_V2_RETPOLINE_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;
+               mode = SPECTRE_V2_RETPOLINE_GENERIC;
                setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
        }
 
@@ -469,6 +411,48 @@ specv2_set_mode:
        arch_smt_update();
 }
 
+static bool stibp_needed(void)
+{
+       if (spectre_v2_enabled == SPECTRE_V2_NONE)
+               return false;
+
+       /* Enhanced IBRS makes using STIBP unnecessary. */
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return false;
+
+       if (!boot_cpu_has(X86_FEATURE_STIBP))
+               return false;
+
+       return true;
+}
+
+static void update_stibp_msr(void *info)
+{
+       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+}
+
+void arch_smt_update(void)
+{
+       u64 mask;
+
+       if (!stibp_needed())
+               return;
+
+       mutex_lock(&spec_ctrl_mutex);
+
+       mask = x86_spec_ctrl_base & ~SPEC_CTRL_STIBP;
+       if (sched_smt_active())
+               mask |= SPEC_CTRL_STIBP;
+
+       if (mask != x86_spec_ctrl_base) {
+               pr_info("Spectre v2 cross-process SMT mitigation: %s STIBP\n",
+                       mask & SPEC_CTRL_STIBP ? "Enabling" : "Disabling");
+               x86_spec_ctrl_base = mask;
+               on_each_cpu(update_stibp_msr, NULL, 1);
+       }
+       mutex_unlock(&spec_ctrl_mutex);
+}
+
 #undef pr_fmt
 #define pr_fmt(fmt)    "Speculative Store Bypass: " fmt
 
@@ -483,7 +467,7 @@ enum ssb_mitigation_cmd {
        SPEC_STORE_BYPASS_CMD_SECCOMP,
 };
 
-static const char *ssb_strings[] = {
+static const char * const ssb_strings[] = {
        [SPEC_STORE_BYPASS_NONE]        = "Vulnerable",
        [SPEC_STORE_BYPASS_DISABLE]     = "Mitigation: Speculative Store Bypass disabled",
        [SPEC_STORE_BYPASS_PRCTL]       = "Mitigation: Speculative Store Bypass disabled via prctl",
@@ -493,7 +477,7 @@ static const char *ssb_strings[] = {
 static const struct {
        const char *option;
        enum ssb_mitigation_cmd cmd;
-} ssb_mitigation_options[] = {
+} ssb_mitigation_options[]  __initdata = {
        { "auto",       SPEC_STORE_BYPASS_CMD_AUTO },    /* Platform decides */
        { "on",         SPEC_STORE_BYPASS_CMD_ON },      /* Disable Speculative Store Bypass */
        { "off",        SPEC_STORE_BYPASS_CMD_NONE },    /* Don't touch Speculative Store Bypass */
@@ -638,7 +622,7 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
         * mitigation until it is next scheduled.
         */
        if (task == current && update)
-               speculative_store_bypass_update_current();
+               speculation_ctrl_update_current();
 
        return 0;
 }
@@ -823,7 +807,7 @@ early_param("l1tf", l1tf_cmdline);
 #define L1TF_DEFAULT_MSG "Mitigation: PTE Inversion"
 
 #if IS_ENABLED(CONFIG_KVM_INTEL)
-static const char *l1tf_vmx_states[] = {
+static const char * const l1tf_vmx_states[] = {
        [VMENTER_L1D_FLUSH_AUTO]                = "auto",
        [VMENTER_L1D_FLUSH_NEVER]               = "vulnerable",
        [VMENTER_L1D_FLUSH_COND]                = "conditional cache flushes",
@@ -839,13 +823,14 @@ static ssize_t l1tf_show_state(char *buf)
 
        if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED ||
            (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER &&
-            cpu_smt_control == CPU_SMT_ENABLED))
+            sched_smt_active())) {
                return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
                               l1tf_vmx_states[l1tf_vmx_mitigation]);
+       }
 
        return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
                       l1tf_vmx_states[l1tf_vmx_mitigation],
-                      cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled");
+                      sched_smt_active() ? "vulnerable" : "disabled");
 }
 #else
 static ssize_t l1tf_show_state(char *buf)
@@ -854,11 +839,28 @@ static ssize_t l1tf_show_state(char *buf)
 }
 #endif
 
+static char *stibp_state(void)
+{
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return "";
+
+       if (x86_spec_ctrl_base & SPEC_CTRL_STIBP)
+               return ", STIBP";
+       else
+               return "";
+}
+
+static char *ibpb_state(void)
+{
+       if (boot_cpu_has(X86_FEATURE_USE_IBPB))
+               return ", IBPB";
+       else
+               return "";
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
                               char *buf, unsigned int bug)
 {
-       int ret;
-
        if (!boot_cpu_has_bug(bug))
                return sprintf(buf, "Not affected\n");
 
@@ -876,13 +878,12 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                return sprintf(buf, "Mitigation: __user pointer sanitization\n");
 
        case X86_BUG_SPECTRE_V2:
-               ret = sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
-                              boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
+               return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
+                              ibpb_state(),
                               boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
-                              (x86_spec_ctrl_base & SPEC_CTRL_STIBP) ? ", STIBP" : "",
+                              stibp_state(),
                               boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
                               spectre_v2_module_string());
-               return ret;
 
        case X86_BUG_SPEC_STORE_BYPASS:
                return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);