]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - arch/x86/kernel/cpu/bugs.c
x86/bugs, KVM: Support the combination of guest and host IBRS
[mirror_ubuntu-artful-kernel.git] / arch / x86 / kernel / cpu / bugs.c
index d5bafcdb4891098cff0c596cb2389149e43b878b..934ed77137a02725dd062f51910a4d0481f60df2 100644 (file)
 
 static void __init spectre_v2_select_mitigation(void);
 
+/*
+ * Our boot-time value of the SPEC_CTRL MSR. We read it once so that any
+ * writes to SPEC_CTRL contain whatever reserved bits have been set.
+ */
+static u64 __ro_after_init x86_spec_ctrl_base;
+
 void __init check_bugs(void)
 {
        identify_boot_cpu();
@@ -36,6 +42,13 @@ void __init check_bugs(void)
                print_cpu_info(&boot_cpu_data);
        }
 
+       /*
+        * Read the SPEC_CTRL MSR to account for reserved bits which may
+        * have unknown values.
+        */
+       if (ibrs_inuse)
+               rdmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+
        /* Select the proper spectre mitigation before patching alternatives */
        spectre_v2_select_mitigation();
 
@@ -94,6 +107,39 @@ static const char *spectre_v2_strings[] = {
 
 static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
 
+void x86_spec_ctrl_set(u64 val)
+{
+       if (val & ~SPEC_CTRL_IBRS)
+               WARN_ONCE(1, "SPEC_CTRL MSR value 0x%16llx is unknown.\n", val);
+       else
+               wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base | val);
+}
+EXPORT_SYMBOL_GPL(x86_spec_ctrl_set);
+
+u64 x86_spec_ctrl_get_default(void)
+{
+       return x86_spec_ctrl_base;
+}
+EXPORT_SYMBOL_GPL(x86_spec_ctrl_get_default);
+
+void x86_spec_ctrl_set_guest(u64 guest_spec_ctrl)
+{
+       if (!ibrs_inuse)
+               return;
+       if (x86_spec_ctrl_base != guest_spec_ctrl)
+               wrmsrl(MSR_IA32_SPEC_CTRL, guest_spec_ctrl);
+}
+EXPORT_SYMBOL_GPL(x86_spec_ctrl_set_guest);
+
+void x86_spec_ctrl_restore_host(u64 guest_spec_ctrl)
+{
+       if (!ibrs_inuse)
+               return;
+       if (x86_spec_ctrl_base != guest_spec_ctrl)
+               wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+}
+EXPORT_SYMBOL_GPL(x86_spec_ctrl_restore_host);
+
 static void __init spec2_print_if_insecure(const char *reason)
 {
        if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
@@ -273,33 +319,47 @@ retpoline_auto:
 #undef pr_fmt
 
 #ifdef CONFIG_SYSFS
-ssize_t cpu_show_meltdown(struct device *dev,
-                         struct device_attribute *attr, char *buf)
+ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
+                       char *buf, unsigned int bug)
 {
-       if (!boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN))
+       if (!boot_cpu_has_bug(bug))
                return sprintf(buf, "Not affected\n");
-       if (boot_cpu_has(X86_FEATURE_PTI))
-               return sprintf(buf, "Mitigation: PTI\n");
+
+       switch (bug) {
+       case X86_BUG_CPU_MELTDOWN:
+               if (boot_cpu_has(X86_FEATURE_PTI))
+                       return sprintf(buf, "Mitigation: PTI\n");
+               break;
+
+       case X86_BUG_SPECTRE_V1:
+               if (osb_is_enabled)
+                       return sprintf(buf, "Mitigation: OSB (observable speculation barrier, Intel v6)\n");
+
+       case X86_BUG_SPECTRE_V2:
+               return sprintf(buf, "%s%s\n", spectre_v2_strings[spectre_v2_enabled], ibpb_inuse ? ", IBPB (Intel v4)" : "");
+
+       default:
+               break;
+       }
+
        return sprintf(buf, "Vulnerable\n");
 }
 
-ssize_t cpu_show_spectre_v1(struct device *dev,
-                           struct device_attribute *attr, char *buf)
+ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr,
+                         char *buf)
 {
-       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1))
-               return sprintf(buf, "Not affected\n");
-       if (osb_is_enabled)
-               return sprintf(buf, "Mitigation: OSB (observable speculation barrier, Intel v6)\n");
-       return sprintf(buf, "Vulnerable\n");
+       return cpu_show_common(dev, attr, buf, X86_BUG_CPU_MELTDOWN);
 }
 
-ssize_t cpu_show_spectre_v2(struct device *dev,
-                           struct device_attribute *attr, char *buf)
+ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr,
+                           char *buf)
 {
-       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
-               return sprintf(buf, "Not affected\n");
+       return cpu_show_common(dev, attr, buf, X86_BUG_SPECTRE_V1);
+}
 
-       return sprintf(buf, "%s%s\n", spectre_v2_strings[spectre_v2_enabled],
-                      ibpb_inuse ? ", IBPB (Intel v4)" : "");
+ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_SPECTRE_V2);
 }
 #endif