]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - arch/x86/kernel/cpu/bugs.c
x86/speculation: Support 'mitigations=' cmdline option
[mirror_ubuntu-bionic-kernel.git] / arch / x86 / kernel / cpu / bugs.c
index 448392c0b8f275959333bc01ed0ab164bb2dd235..415f841ec4c007ea7d84f38ce421bf704a57d19e 100644 (file)
 #include <asm/set_memory.h>
 #include <asm/intel-family.h>
 #include <asm/e820/api.h>
+#include <asm/hypervisor.h>
 
 static void __init spectre_v2_select_mitigation(void);
 static void __init ssb_select_mitigation(void);
 static void __init l1tf_select_mitigation(void);
+static void __init mds_select_mitigation(void);
 
 /* The base value of the SPEC_CTRL MSR that always has to be preserved. */
 u64 x86_spec_ctrl_base;
@@ -53,13 +55,20 @@ static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;
 u64 __ro_after_init x86_amd_ls_cfg_base;
 u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask;
 
-/* Control conditional STIPB in switch_to() */
+/* Control conditional STIBP in switch_to() */
 DEFINE_STATIC_KEY_FALSE(switch_to_cond_stibp);
 /* Control conditional IBPB in switch_mm() */
 DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
 /* Control unconditional IBPB in switch_mm() */
 DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
 
+/* Control MDS CPU buffer clear before returning to user space */
+DEFINE_STATIC_KEY_FALSE(mds_user_clear);
+EXPORT_SYMBOL_GPL(mds_user_clear);
+/* Control MDS CPU buffer clear before idling (halt, mwait) */
+DEFINE_STATIC_KEY_FALSE(mds_idle_clear);
+EXPORT_SYMBOL_GPL(mds_idle_clear);
+
 void __init check_bugs(void)
 {
        identify_boot_cpu();
@@ -98,6 +107,10 @@ void __init check_bugs(void)
 
        l1tf_select_mitigation();
 
+       mds_select_mitigation();
+
+       arch_smt_update();
+
 #ifdef CONFIG_X86_32
        /*
         * Check whether we are able to run this kernel safely on SMP.
@@ -203,6 +216,60 @@ static void x86_amd_ssb_disable(void)
                wrmsrl(MSR_AMD64_LS_CFG, msrval);
 }
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "MDS: " fmt
+
+/* Default mitigation for MDS-affected CPUs */
+static enum mds_mitigations mds_mitigation __ro_after_init = MDS_MITIGATION_FULL;
+static bool mds_nosmt __ro_after_init = false;
+
+static const char * const mds_strings[] = {
+       [MDS_MITIGATION_OFF]    = "Vulnerable",
+       [MDS_MITIGATION_FULL]   = "Mitigation: Clear CPU buffers",
+       [MDS_MITIGATION_VMWERV] = "Vulnerable: Clear CPU buffers attempted, no microcode",
+};
+
+static void mds_select_mitigation(void)
+{
+       if (!boot_cpu_has_bug(X86_BUG_MDS)) {
+               mds_mitigation = MDS_MITIGATION_OFF;
+               return;
+       }
+
+       if (mds_mitigation == MDS_MITIGATION_FULL) {
+               if (!boot_cpu_has(X86_FEATURE_MD_CLEAR))
+                       mds_mitigation = MDS_MITIGATION_VMWERV;
+
+               static_branch_enable(&mds_user_clear);
+
+               if (mds_nosmt && !boot_cpu_has(X86_BUG_MSBDS_ONLY))
+                       cpu_smt_disable(false);
+       }
+
+       pr_info("%s\n", mds_strings[mds_mitigation]);
+}
+
+static int __init mds_cmdline(char *str)
+{
+       if (!boot_cpu_has_bug(X86_BUG_MDS))
+               return 0;
+
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "off"))
+               mds_mitigation = MDS_MITIGATION_OFF;
+       else if (!strcmp(str, "full"))
+               mds_mitigation = MDS_MITIGATION_FULL;
+       else if (!strcmp(str, "full,nosmt")) {
+               mds_mitigation = MDS_MITIGATION_FULL;
+               mds_nosmt = true;
+       }
+
+       return 0;
+}
+early_param("mds", mds_cmdline);
+
 #undef pr_fmt
 #define pr_fmt(fmt)     "Spectre V2 : " fmt
 
@@ -212,7 +279,7 @@ static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
 static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init =
        SPECTRE_V2_USER_NONE;
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 static bool spectre_v2_bad_module;
 
 bool retpoline_module_ok(bool has_retpoline)
@@ -254,11 +321,18 @@ enum spectre_v2_user_cmd {
        SPECTRE_V2_USER_CMD_NONE,
        SPECTRE_V2_USER_CMD_AUTO,
        SPECTRE_V2_USER_CMD_FORCE,
+       SPECTRE_V2_USER_CMD_PRCTL,
+       SPECTRE_V2_USER_CMD_PRCTL_IBPB,
+       SPECTRE_V2_USER_CMD_SECCOMP,
+       SPECTRE_V2_USER_CMD_SECCOMP_IBPB,
 };
 
 static const char * const spectre_v2_user_strings[] = {
-       [SPECTRE_V2_USER_NONE]          = "User space: Vulnerable",
-       [SPECTRE_V2_USER_STRICT]        = "User space: Mitigation: STIBP protection",
+       [SPECTRE_V2_USER_NONE]                  = "User space: Vulnerable",
+       [SPECTRE_V2_USER_STRICT]                = "User space: Mitigation: STIBP protection",
+       [SPECTRE_V2_USER_STRICT_PREFERRED]      = "User space: Mitigation: STIBP always-on protection",
+       [SPECTRE_V2_USER_PRCTL]                 = "User space: Mitigation: STIBP via prctl",
+       [SPECTRE_V2_USER_SECCOMP]               = "User space: Mitigation: STIBP via seccomp and prctl",
 };
 
 static const struct {
@@ -266,9 +340,13 @@ static const struct {
        enum spectre_v2_user_cmd        cmd;
        bool                            secure;
 } v2_user_options[] __initdata = {
-       { "auto",       SPECTRE_V2_USER_CMD_AUTO,       false },
-       { "off",        SPECTRE_V2_USER_CMD_NONE,       false },
-       { "on",         SPECTRE_V2_USER_CMD_FORCE,      true  },
+       { "auto",               SPECTRE_V2_USER_CMD_AUTO,               false },
+       { "off",                SPECTRE_V2_USER_CMD_NONE,               false },
+       { "on",                 SPECTRE_V2_USER_CMD_FORCE,              true  },
+       { "prctl",              SPECTRE_V2_USER_CMD_PRCTL,              false },
+       { "prctl,ibpb",         SPECTRE_V2_USER_CMD_PRCTL_IBPB,         false },
+       { "seccomp",            SPECTRE_V2_USER_CMD_SECCOMP,            false },
+       { "seccomp,ibpb",       SPECTRE_V2_USER_CMD_SECCOMP_IBPB,       false },
 };
 
 static void __init spec_v2_user_print_cond(const char *reason, bool secure)
@@ -314,6 +392,7 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
 {
        enum spectre_v2_user_mitigation mode = SPECTRE_V2_USER_NONE;
        bool smt_possible = IS_ENABLED(CONFIG_SMP);
+       enum spectre_v2_user_cmd cmd;
 
        if (!boot_cpu_has(X86_FEATURE_IBPB) && !boot_cpu_has(X86_FEATURE_STIBP))
                return;
@@ -322,35 +401,70 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
            cpu_smt_control == CPU_SMT_NOT_SUPPORTED)
                smt_possible = false;
 
-       switch (spectre_v2_parse_user_cmdline(v2_cmd)) {
-       case SPECTRE_V2_USER_CMD_AUTO:
+       cmd = spectre_v2_parse_user_cmdline(v2_cmd);
+       switch (cmd) {
        case SPECTRE_V2_USER_CMD_NONE:
                goto set_mode;
        case SPECTRE_V2_USER_CMD_FORCE:
                mode = SPECTRE_V2_USER_STRICT;
                break;
+       case SPECTRE_V2_USER_CMD_PRCTL:
+       case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
+               mode = SPECTRE_V2_USER_PRCTL;
+               break;
+       case SPECTRE_V2_USER_CMD_AUTO:
+       case SPECTRE_V2_USER_CMD_SECCOMP:
+       case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
+               if (IS_ENABLED(CONFIG_SECCOMP))
+                       mode = SPECTRE_V2_USER_SECCOMP;
+               else
+                       mode = SPECTRE_V2_USER_PRCTL;
+               break;
        }
 
+       /*
+        * At this point, an STIBP mode other than "off" has been set.
+        * If STIBP support is not being forced, check if STIBP always-on
+        * is preferred.
+        */
+       if (mode != SPECTRE_V2_USER_STRICT &&
+           boot_cpu_has(X86_FEATURE_AMD_STIBP_ALWAYS_ON))
+               mode = SPECTRE_V2_USER_STRICT_PREFERRED;
+
        /* Initialize Indirect Branch Prediction Barrier */
        if (boot_cpu_has(X86_FEATURE_IBPB)) {
                setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
 
-               switch (mode) {
-               case SPECTRE_V2_USER_STRICT:
+               switch (cmd) {
+               case SPECTRE_V2_USER_CMD_FORCE:
+               case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
+               case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
                        static_branch_enable(&switch_mm_always_ibpb);
                        break;
+               case SPECTRE_V2_USER_CMD_PRCTL:
+               case SPECTRE_V2_USER_CMD_AUTO:
+               case SPECTRE_V2_USER_CMD_SECCOMP:
+                       static_branch_enable(&switch_mm_cond_ibpb);
+                       break;
                default:
                        break;
                }
 
                pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n",
-                       mode == SPECTRE_V2_USER_STRICT ? "always-on" : "conditional");
+                       static_key_enabled(&switch_mm_always_ibpb) ?
+                       "always-on" : "conditional");
        }
 
-       /* If enhanced IBRS is enabled no STIPB required */
+       /* If enhanced IBRS is enabled no STIBP required */
        if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
                return;
 
+       /*
+        * If SMT is not possible or STIBP is not available clear the STIBP
+        * mode.
+        */
+       if (!smt_possible || !boot_cpu_has(X86_FEATURE_STIBP))
+               mode = SPECTRE_V2_USER_NONE;
 set_mode:
        spectre_v2_user = mode;
        /* Only print the STIBP mode when SMT possible */
@@ -390,7 +504,8 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
        char arg[20];
        int ret, i;
 
-       if (cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
+       if (cmdline_find_option_bool(boot_command_line, "nospectre_v2") ||
+           cpu_mitigations_off())
                return SPECTRE_V2_CMD_NONE;
 
        ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
@@ -522,45 +637,94 @@ specv2_set_mode:
 
        /* Set up IBPB and STIBP depending on the general spectre V2 command */
        spectre_v2_user_select_mitigation(cmd);
+}
 
-       /* Enable STIBP if appropriate */
-       arch_smt_update();
+static void update_stibp_msr(void * __unused)
+{
+       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
 }
 
-static bool stibp_needed(void)
+/* Update x86_spec_ctrl_base in case SMT state changed. */
+static void update_stibp_strict(void)
 {
-       /* Enhanced IBRS makes using STIBP unnecessary. */
-       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
-               return false;
+       u64 mask = x86_spec_ctrl_base & ~SPEC_CTRL_STIBP;
+
+       if (sched_smt_active())
+               mask |= SPEC_CTRL_STIBP;
+
+       if (mask == x86_spec_ctrl_base)
+               return;
 
-       /* Check for strict user mitigation mode */
-       return spectre_v2_user == SPECTRE_V2_USER_STRICT;
+       pr_info("Update user space SMT mitigation: STIBP %s\n",
+               mask & SPEC_CTRL_STIBP ? "always-on" : "off");
+       x86_spec_ctrl_base = mask;
+       on_each_cpu(update_stibp_msr, NULL, 1);
 }
 
-static void update_stibp_msr(void *info)
+/* Update the static key controlling the evaluation of TIF_SPEC_IB */
+static void update_indir_branch_cond(void)
 {
-       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+       if (sched_smt_active())
+               static_branch_enable(&switch_to_cond_stibp);
+       else
+               static_branch_disable(&switch_to_cond_stibp);
 }
 
-void arch_smt_update(void)
+#undef pr_fmt
+#define pr_fmt(fmt) fmt
+
+/* Update the static key controlling the MDS CPU buffer clear in idle */
+static void update_mds_branch_idle(void)
 {
-       u64 mask;
+       /*
+        * Enable the idle clearing on CPUs which are affected only by
+        * MDBDS and not any other MDS variant. The other variants cannot
+        * be mitigated when SMT is enabled, so clearing the buffers on
+        * idle would be a window dressing exercise.
+        */
+       if (!boot_cpu_has(X86_BUG_MSBDS_ONLY))
+               return;
+
+       if (sched_smt_active())
+               static_branch_enable(&mds_idle_clear);
+       else
+               static_branch_disable(&mds_idle_clear);
+}
+
+#define MDS_MSG_SMT "MDS CPU bug present and SMT on, data leak possible. See https://www.kernel.org/doc/html/latest/admin-guide/hw-vuln/mds.html for more details.\n"
 
-       if (!stibp_needed())
+void arch_smt_update(void)
+{
+       /* Enhanced IBRS implies STIBP. No update required. */
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
                return;
 
        mutex_lock(&spec_ctrl_mutex);
 
-       mask = x86_spec_ctrl_base & ~SPEC_CTRL_STIBP;
-       if (sched_smt_active())
-               mask |= SPEC_CTRL_STIBP;
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               break;
+       case SPECTRE_V2_USER_STRICT:
+       case SPECTRE_V2_USER_STRICT_PREFERRED:
+               update_stibp_strict();
+               break;
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               update_indir_branch_cond();
+               break;
+       }
 
-       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);
+       switch(mds_mitigation) {
+       case MDS_MITIGATION_FULL:
+       case MDS_MITIGATION_VMWERV:
+               if (sched_smt_active() && !boot_cpu_has(X86_BUG_MSBDS_ONLY))
+                       pr_warn_once(MDS_MSG_SMT);
+               update_mds_branch_idle();
+               break;
+       case MDS_MITIGATION_OFF:
+               break;
        }
+
        mutex_unlock(&spec_ctrl_mutex);
 }
 
@@ -602,7 +766,8 @@ static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
        char arg[20];
        int ret, i;
 
-       if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable")) {
+       if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable") ||
+           cpu_mitigations_off()) {
                return SPEC_STORE_BYPASS_CMD_NONE;
        } else {
                ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable",
@@ -699,14 +864,10 @@ static void ssb_select_mitigation(void)
 #undef pr_fmt
 #define pr_fmt(fmt)     "Speculation prctl: " fmt
 
-static void task_update_spec_tif(struct task_struct *tsk, int tifbit, bool on)
+static void task_update_spec_tif(struct task_struct *tsk)
 {
-       bool update;
-
-       if (on)
-               update = !test_and_set_tsk_thread_flag(tsk, tifbit);
-       else
-               update = test_and_clear_tsk_thread_flag(tsk, tifbit);
+       /* Force the update of the real TIF bits */
+       set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE);
 
        /*
         * Immediately update the speculation control MSRs for the current
@@ -716,7 +877,7 @@ static void task_update_spec_tif(struct task_struct *tsk, int tifbit, bool on)
         * This can only happen for SECCOMP mitigation. For PRCTL it's
         * always the current task.
         */
-       if (tsk == current && update)
+       if (tsk == current)
                speculation_ctrl_update_current();
 }
 
@@ -732,16 +893,54 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
                if (task_spec_ssb_force_disable(task))
                        return -EPERM;
                task_clear_spec_ssb_disable(task);
-               task_update_spec_tif(task, TIF_SSBD, false);
+               task_update_spec_tif(task);
                break;
        case PR_SPEC_DISABLE:
                task_set_spec_ssb_disable(task);
-               task_update_spec_tif(task, TIF_SSBD, true);
+               task_update_spec_tif(task);
                break;
        case PR_SPEC_FORCE_DISABLE:
                task_set_spec_ssb_disable(task);
                task_set_spec_ssb_force_disable(task);
-               task_update_spec_tif(task, TIF_SSBD, true);
+               task_update_spec_tif(task);
+               break;
+       default:
+               return -ERANGE;
+       }
+       return 0;
+}
+
+static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
+{
+       switch (ctrl) {
+       case PR_SPEC_ENABLE:
+               if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+                       return 0;
+               /*
+                * Indirect branch speculation is always disabled in strict
+                * mode.
+                */
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT ||
+                   spectre_v2_user == SPECTRE_V2_USER_STRICT_PREFERRED)
+                       return -EPERM;
+               task_clear_spec_ib_disable(task);
+               task_update_spec_tif(task);
+               break;
+       case PR_SPEC_DISABLE:
+       case PR_SPEC_FORCE_DISABLE:
+               /*
+                * Indirect branch speculation is always allowed when
+                * mitigation is force disabled.
+                */
+               if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+                       return -EPERM;
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT ||
+                   spectre_v2_user == SPECTRE_V2_USER_STRICT_PREFERRED)
+                       return 0;
+               task_set_spec_ib_disable(task);
+               if (ctrl == PR_SPEC_FORCE_DISABLE)
+                       task_set_spec_ib_force_disable(task);
+               task_update_spec_tif(task);
                break;
        default:
                return -ERANGE;
@@ -755,6 +954,8 @@ int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
        switch (which) {
        case PR_SPEC_STORE_BYPASS:
                return ssb_prctl_set(task, ctrl);
+       case PR_SPEC_INDIRECT_BRANCH:
+               return ib_prctl_set(task, ctrl);
        default:
                return -ENODEV;
        }
@@ -765,6 +966,8 @@ void arch_seccomp_spec_mitigate(struct task_struct *task)
 {
        if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP)
                ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE);
+       if (spectre_v2_user == SPECTRE_V2_USER_SECCOMP)
+               ib_prctl_set(task, PR_SPEC_FORCE_DISABLE);
 }
 #endif
 
@@ -787,11 +990,36 @@ static int ssb_prctl_get(struct task_struct *task)
        }
 }
 
+static int ib_prctl_get(struct task_struct *task)
+{
+       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
+               return PR_SPEC_NOT_AFFECTED;
+
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               return PR_SPEC_ENABLE;
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               if (task_spec_ib_force_disable(task))
+                       return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
+               if (task_spec_ib_disable(task))
+                       return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
+               return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
+       case SPECTRE_V2_USER_STRICT:
+       case SPECTRE_V2_USER_STRICT_PREFERRED:
+               return PR_SPEC_DISABLE;
+       default:
+               return PR_SPEC_NOT_AFFECTED;
+       }
+}
+
 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
 {
        switch (which) {
        case PR_SPEC_STORE_BYPASS:
                return ssb_prctl_get(task);
+       case PR_SPEC_INDIRECT_BRANCH:
+               return ib_prctl_get(task);
        default:
                return -ENODEV;
        }
@@ -864,6 +1092,11 @@ static void __init l1tf_select_mitigation(void)
        if (!boot_cpu_has_bug(X86_BUG_L1TF))
                return;
 
+       if (cpu_mitigations_off())
+               l1tf_mitigation = L1TF_MITIGATION_OFF;
+       else if (cpu_mitigations_auto_nosmt())
+               l1tf_mitigation = L1TF_MITIGATION_FLUSH_NOSMT;
+
        override_cache_bits(&boot_cpu_data);
 
        switch (l1tf_mitigation) {
@@ -888,6 +1121,10 @@ static void __init l1tf_select_mitigation(void)
        half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT;
        if (e820__mapped_any(half_pa, ULLONG_MAX - half_pa, E820_TYPE_RAM)) {
                pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n");
+               pr_info("You may make it effective by booting the kernel with mem=%llu parameter.\n",
+                               half_pa);
+               pr_info("However, doing so will make a part of your RAM unusable.\n");
+               pr_info("Reading https://www.kernel.org/doc/html/latest/admin-guide/l1tf.html might help you decide.\n");
                return;
        }
 
@@ -920,6 +1157,7 @@ static int __init l1tf_cmdline(char *str)
 early_param("l1tf", l1tf_cmdline);
 
 #undef pr_fmt
+#define pr_fmt(fmt) fmt
 
 #ifdef CONFIG_SYSFS
 
@@ -958,6 +1196,23 @@ static ssize_t l1tf_show_state(char *buf)
 }
 #endif
 
+static ssize_t mds_show_state(char *buf)
+{
+       if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
+               return sprintf(buf, "%s; SMT Host state unknown\n",
+                              mds_strings[mds_mitigation]);
+       }
+
+       if (boot_cpu_has(X86_BUG_MSBDS_ONLY)) {
+               return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+                              (mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
+                               sched_smt_active() ? "mitigated" : "disabled"));
+       }
+
+       return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+                      sched_smt_active() ? "vulnerable" : "disabled");
+}
+
 static char *stibp_state(void)
 {
        if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
@@ -968,6 +1223,12 @@ static char *stibp_state(void)
                return ", STIBP: disabled";
        case SPECTRE_V2_USER_STRICT:
                return ", STIBP: forced";
+       case SPECTRE_V2_USER_STRICT_PREFERRED:
+               return ", STIBP: always-on";
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               if (static_key_enabled(&switch_to_cond_stibp))
+                       return ", STIBP: conditional";
        }
        return "";
 }
@@ -975,12 +1236,11 @@ static char *stibp_state(void)
 static char *ibpb_state(void)
 {
        if (boot_cpu_has(X86_FEATURE_IBPB)) {
-               switch (spectre_v2_user) {
-               case SPECTRE_V2_USER_NONE:
-                       return ", IBPB: disabled";
-               case SPECTRE_V2_USER_STRICT:
+               if (static_key_enabled(&switch_mm_always_ibpb))
                        return ", IBPB: always-on";
-               }
+               if (static_key_enabled(&switch_mm_cond_ibpb))
+                       return ", IBPB: conditional";
+               return ", IBPB: disabled";
        }
        return "";
 }
@@ -1016,6 +1276,10 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
                        return l1tf_show_state(buf);
                break;
+
+       case X86_BUG_MDS:
+               return mds_show_state(buf);
+
        default:
                break;
        }
@@ -1047,4 +1311,9 @@ ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *b
 {
        return cpu_show_common(dev, attr, buf, X86_BUG_L1TF);
 }
+
+ssize_t cpu_show_mds(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_MDS);
+}
 #endif