Merge tag 'x86-urgent-2022-08-13' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / arch / x86 / kernel / cpu / bugs.c
index d50686c..510d852 100644 (file)
@@ -1336,6 +1336,53 @@ static void __init spec_ctrl_disable_kernel_rrsba(void)
        }
 }
 
+static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode)
+{
+       /*
+        * Similar to context switches, there are two types of RSB attacks
+        * after VM exit:
+        *
+        * 1) RSB underflow
+        *
+        * 2) Poisoned RSB entry
+        *
+        * When retpoline is enabled, both are mitigated by filling/clearing
+        * the RSB.
+        *
+        * When IBRS is enabled, while #1 would be mitigated by the IBRS branch
+        * prediction isolation protections, RSB still needs to be cleared
+        * because of #2.  Note that SMEP provides no protection here, unlike
+        * user-space-poisoned RSB entries.
+        *
+        * eIBRS should protect against RSB poisoning, but if the EIBRS_PBRSB
+        * bug is present then a LITE version of RSB protection is required,
+        * just a single call needs to retire before a RET is executed.
+        */
+       switch (mode) {
+       case SPECTRE_V2_NONE:
+               return;
+
+       case SPECTRE_V2_EIBRS_LFENCE:
+       case SPECTRE_V2_EIBRS:
+               if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
+                       setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT_LITE);
+                       pr_info("Spectre v2 / PBRSB-eIBRS: Retire a single CALL on VMEXIT\n");
+               }
+               return;
+
+       case SPECTRE_V2_EIBRS_RETPOLINE:
+       case SPECTRE_V2_RETPOLINE:
+       case SPECTRE_V2_LFENCE:
+       case SPECTRE_V2_IBRS:
+               setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT);
+               pr_info("Spectre v2 / SpectreRSB : Filling RSB on VMEXIT\n");
+               return;
+       }
+
+       pr_warn_once("Unknown Spectre v2 mode, disabling RSB mitigation at VM exit");
+       dump_stack();
+}
+
 static void __init spectre_v2_select_mitigation(void)
 {
        enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -1486,28 +1533,7 @@ static void __init spectre_v2_select_mitigation(void)
        setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
        pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
 
-       /*
-        * Similar to context switches, there are two types of RSB attacks
-        * after vmexit:
-        *
-        * 1) RSB underflow
-        *
-        * 2) Poisoned RSB entry
-        *
-        * When retpoline is enabled, both are mitigated by filling/clearing
-        * the RSB.
-        *
-        * When IBRS is enabled, while #1 would be mitigated by the IBRS branch
-        * prediction isolation protections, RSB still needs to be cleared
-        * because of #2.  Note that SMEP provides no protection here, unlike
-        * user-space-poisoned RSB entries.
-        *
-        * eIBRS, on the other hand, has RSB-poisoning protections, so it
-        * doesn't need RSB clearing after vmexit.
-        */
-       if (boot_cpu_has(X86_FEATURE_RETPOLINE) ||
-           boot_cpu_has(X86_FEATURE_KERNEL_IBRS))
-               setup_force_cpu_cap(X86_FEATURE_RSB_VMEXIT);
+       spectre_v2_determine_rsb_fill_type_at_vmexit(mode);
 
        /*
         * Retpoline protects the kernel, but doesn't protect firmware.  IBRS
@@ -2293,6 +2319,19 @@ static char *ibpb_state(void)
        return "";
 }
 
+static char *pbrsb_eibrs_state(void)
+{
+       if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) {
+               if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) ||
+                   boot_cpu_has(X86_FEATURE_RSB_VMEXIT))
+                       return ", PBRSB-eIBRS: SW sequence";
+               else
+                       return ", PBRSB-eIBRS: Vulnerable";
+       } else {
+               return ", PBRSB-eIBRS: Not affected";
+       }
+}
+
 static ssize_t spectre_v2_show_state(char *buf)
 {
        if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
@@ -2305,12 +2344,13 @@ static ssize_t spectre_v2_show_state(char *buf)
            spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
                return sprintf(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
 
-       return sprintf(buf, "%s%s%s%s%s%s\n",
+       return sprintf(buf, "%s%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" : "",
                       stibp_state(),
                       boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
+                      pbrsb_eibrs_state(),
                       spectre_v2_module_string());
 }