x86/srso: Add IBPB on VMEXIT
authorBorislav Petkov (AMD) <bp@alien8.de>
Fri, 7 Jul 2023 11:53:41 +0000 (13:53 +0200)
committerBorislav Petkov (AMD) <bp@alien8.de>
Thu, 27 Jul 2023 09:07:19 +0000 (11:07 +0200)
Add the option to flush IBPB only on VMEXIT in order to protect from
malicious guests but one otherwise trusts the software that runs on the
hypervisor.

Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
arch/x86/include/asm/cpufeatures.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/svm/vmenter.S

index 93070aa..7600a8a 100644 (file)
 
 #define X86_FEATURE_SRSO               (11*32+24) /* "" AMD BTB untrain RETs */
 #define X86_FEATURE_SRSO_ALIAS         (11*32+25) /* "" AMD BTB untrain RETs through aliasing */
+#define X86_FEATURE_IBPB_ON_VMEXIT     (11*32+26) /* "" Issue an IBPB only on VMEXIT */
 
 /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
 #define X86_FEATURE_AVX_VNNI           (12*32+ 4) /* AVX VNNI instructions */
index f3cc432..d4109eb 100644 (file)
@@ -2198,6 +2198,7 @@ enum srso_mitigation {
        SRSO_MITIGATION_MICROCODE,
        SRSO_MITIGATION_SAFE_RET,
        SRSO_MITIGATION_IBPB,
+       SRSO_MITIGATION_IBPB_ON_VMEXIT,
 };
 
 enum srso_mitigation_cmd {
@@ -2205,6 +2206,7 @@ enum srso_mitigation_cmd {
        SRSO_CMD_MICROCODE,
        SRSO_CMD_SAFE_RET,
        SRSO_CMD_IBPB,
+       SRSO_CMD_IBPB_ON_VMEXIT,
 };
 
 static const char * const srso_strings[] = {
@@ -2212,6 +2214,7 @@ static const char * const srso_strings[] = {
        [SRSO_MITIGATION_MICROCODE]      = "Mitigation: microcode",
        [SRSO_MITIGATION_SAFE_RET]       = "Mitigation: safe RET",
        [SRSO_MITIGATION_IBPB]           = "Mitigation: IBPB",
+       [SRSO_MITIGATION_IBPB_ON_VMEXIT] = "Mitigation: IBPB on VMEXIT only"
 };
 
 static enum srso_mitigation srso_mitigation __ro_after_init = SRSO_MITIGATION_NONE;
@@ -2230,6 +2233,8 @@ static int __init srso_parse_cmdline(char *str)
                srso_cmd = SRSO_CMD_SAFE_RET;
        else if (!strcmp(str, "ibpb"))
                srso_cmd = SRSO_CMD_IBPB;
+       else if (!strcmp(str, "ibpb-vmexit"))
+               srso_cmd = SRSO_CMD_IBPB_ON_VMEXIT;
        else
                pr_err("Ignoring unknown SRSO option (%s).", str);
 
@@ -2313,6 +2318,20 @@ static void __init srso_select_mitigation(void)
                        pr_err("WARNING: kernel not compiled with CPU_IBPB_ENTRY.\n");
                        goto pred_cmd;
                }
+               break;
+
+       case SRSO_CMD_IBPB_ON_VMEXIT:
+               if (IS_ENABLED(CONFIG_CPU_SRSO)) {
+                       if (!boot_cpu_has(X86_FEATURE_ENTRY_IBPB) && has_microcode) {
+                               setup_force_cpu_cap(X86_FEATURE_IBPB_ON_VMEXIT);
+                               srso_mitigation = SRSO_MITIGATION_IBPB_ON_VMEXIT;
+                       }
+               } else {
+                       pr_err("WARNING: kernel not compiled with CPU_SRSO.\n");
+                       goto pred_cmd;
+                }
+               break;
+
        default:
                break;
        }
index d381ad4..0a51fd5 100644 (file)
@@ -1498,7 +1498,9 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 
        if (sd->current_vmcb != svm->vmcb) {
                sd->current_vmcb = svm->vmcb;
-               indirect_branch_prediction_barrier();
+
+               if (!cpu_feature_enabled(X86_FEATURE_IBPB_ON_VMEXIT))
+                       indirect_branch_prediction_barrier();
        }
        if (kvm_vcpu_apicv_active(vcpu))
                avic_vcpu_load(vcpu, cpu);
index 8e8295e..265452f 100644 (file)
@@ -224,6 +224,9 @@ SYM_FUNC_START(__svm_vcpu_run)
         */
        UNTRAIN_RET
 
+       /* SRSO */
+       ALTERNATIVE "", "call entry_ibpb", X86_FEATURE_IBPB_ON_VMEXIT
+
        /*
         * Clear all general purpose registers except RSP and RAX to prevent
         * speculative use of the guest's values, even those that are reloaded