]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
KVM: VMX: Allow direct access to MSR_IA32_SPEC_CTRL
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Thu, 1 Feb 2018 20:47:19 +0000 (15:47 -0500)
committerJack Vogel <jack.vogel@oracle.com>
Thu, 8 Feb 2018 18:15:22 +0000 (10:15 -0800)
This is an adopation of what is being posted upstream.

The issue here is that guest kernels such as Windows
needs IBRS to solve their spectre_v2 mitigation.

And since our kernel can do either IBRS or retpoline
we need to be aware of both.

(We are ignoring for right now the situation in which
the microcode is not loaded and we want to emulate IBRS)

In short:
 1) If the CPU has microcode, and host uses IBRS we need
    to save the MSR during VMEXIT and write our IBRS value.
    Also before VMENTER we need to write the guest MSR value.

 2) If the host kernel uses retpoline we need to WRMSR the
    guest MSR value on VMENTER, but we are optimizing by only
    doing it if it a non-zero value.

    On VMEXIT we read the guest MSR value.

Orabug: 27477743
CVE: CVE-2017-5715

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: Pavel Tatashin <pasha.tatashin@oracle.com>
arch/x86/kvm/cpuid.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c

index c58f32463dda7b913d748e5cc04bd90944614c47..d2392f8affbaecf598fd2dc01b784ed7b1d26807 100644 (file)
@@ -442,6 +442,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                        // TSC_ADJUST is emulated
                        entry->ebx |= F(TSC_ADJUST);
                        entry->edx &= kvm_cpuid_7_0_edx_x86_features;
+                       /* Aka !ibrs_supported and !ibpb_supported */
                        if ( !boot_cpu_has(X86_FEATURE_SPEC_CTRL) )
                                entry->edx &= !(1u << KVM_CPUID_BIT_SPEC_CTRL);
                        if ( !boot_cpu_has(X86_FEATURE_STIPB) )
index e8eff903bd4366cd126ba6dc6ca6a8d9fec10230..4bbde986125997510767e59afe16a4242f5929ab 100644 (file)
@@ -3932,10 +3932,10 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 
        local_irq_enable();
 
-       if (ibrs_inuse &&
-           svm->spec_ctrl != SPEC_CTRL_FEATURE_ENABLE_IBRS)
-               wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
-
+       if (ibrs_supported) {
+               if (ibrs_inuse || svm->spec_ctrl)
+                       wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
+       }
        asm volatile (
                "push %%" _ASM_BP "; \n\t"
                "mov %c[rbx](%[svm]), %%" _ASM_BX " \n\t"
@@ -4028,9 +4028,9 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
 #endif
                );
 
-       if (ibrs_inuse) {
+       if (ibrs_supported) {
                rdmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
-               if (svm->spec_ctrl != SPEC_CTRL_FEATURE_ENABLE_IBRS)
+               if (ibrs_inuse)
                        wrmsrl(MSR_IA32_SPEC_CTRL, SPEC_CTRL_FEATURE_ENABLE_IBRS);
        }
 
index 1373b8e2003a34cbbe1330e72517e5d8c5ecdac9..b8465bb9e54c7c33a7107205e9d470e5f9890a90 100644 (file)
@@ -8193,8 +8193,10 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 
        vmx->__launched = vmx->loaded_vmcs->launched;
 
-       if (ibrs_inuse)
-               wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
+       if (ibrs_supported) {
+               if (ibrs_inuse || vmx->spec_ctrl)
+                       wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
+       }
 
        asm(
                /* Store host registers */
@@ -8318,14 +8320,15 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 #endif
              );
 
-       if (ibrs_inuse) {
-               rdmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
-               wrmsrl(MSR_IA32_SPEC_CTRL, SPEC_CTRL_FEATURE_ENABLE_IBRS);
-       }
-
        /* Eliminate branch target predictions from guest mode */
        vmexit_fill_RSB();
 
+       if (ibrs_supported) {
+               rdmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
+               if (ibrs_inuse)
+                       wrmsrl(MSR_IA32_SPEC_CTRL, SPEC_CTRL_FEATURE_ENABLE_IBRS);
+       }
+
        /* MSR_IA32_DEBUGCTLMSR is zeroed on vmexit. Restore it if needed */
        if (debugctlmsr)
                update_debugctlmsr(debugctlmsr);