]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL - reloaded
authorMihai Carabas <mihai.carabas@oracle.com>
Fri, 7 Dec 2018 13:09:51 +0000 (15:09 +0200)
committerBrian Maly <brian.maly@oracle.com>
Tue, 8 Jan 2019 16:12:32 +0000 (11:12 -0500)
This commit is filling out the blanks that were missed in the backport
26a0cd21bb76 ("KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL") due to lack
of different interfaces. 26a0cd21bb76 ("KVM/VMX: Allow direct access to
MSR_IA32_SPEC_CTRL") is basically an incomplet cherry-pick from
d28b387fb74da95d69d2615732f50cceb38e9a4d.

Also added the interception of MSR_IA32_SPEC_CTRL and
MSR_IA32_PRED_CMD in order for the get/set MSR handling to have a sense.

Orabug: 28069548

Signed-off-by: Mihai Carabas <mihai.carabas@oracle.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: Brian Maly <brian.maly@oracle.com>
arch/x86/kvm/cpuid.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/vmx.c

index feda28e6f539f62bff0d6a70a1b1127dad8d0188..4833ceaf780e3d11d1dcd09f80abbb28ca475c71 100644 (file)
@@ -358,7 +358,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
 
        /* cpuid 0x80000008.ebx */
        const u32 kvm_cpuid_80000008_ebx_x86_features =
-               KF(IBPB) | KF(VIRT_SSBD);
+               KF(IBPB) | KF(IBRS) | KF(VIRT_SSBD);
 
        /* all calls to cpuid_count() should be made on the same cpu */
        get_cpu();
index 97f1c35eb7611101484f28172cb851d66fec1b52..24a166ad0a983705cea98b70df2686e15aeacb74 100644 (file)
@@ -152,4 +152,12 @@ static inline bool guest_cpuid_has_ibrs(struct kvm_vcpu *vcpu)
        best = kvm_find_cpuid_entry(vcpu, 7, 0);
        return best && (best->edx & KF(IBRS));
 }
+
+static inline bool guest_cpuid_has_ssbd(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, 7, 0);
+       return best && (best->edx & KF(SSBD));
+}
 #endif
index e5a13224b919e6daa4294c4c3b50997bb18dc4bc..bec5cac5b51a57f92f9b972240b5174b2fe063c7 100644 (file)
@@ -2856,6 +2856,11 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = guest_read_tsc();
                break;
        case MSR_IA32_SPEC_CTRL:
+               if (!msr_info->host_initiated &&
+                   !guest_cpuid_has_ibrs(vcpu) &&
+                   !guest_cpuid_has_ssbd(vcpu))
+                       return 1;
+
                msr_info->data = to_vmx(vcpu)->spec_ctrl;
                break;
        case MSR_IA32_ARCH_CAPABILITIES:
@@ -2956,7 +2961,35 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                kvm_write_tsc(vcpu, msr_info);
                break;
        case MSR_IA32_SPEC_CTRL:
-               to_vmx(vcpu)->spec_ctrl = data;
+               if (!msr_info->host_initiated &&
+                   !guest_cpuid_has_ibrs(vcpu) &&
+                   !guest_cpuid_has_ssbd(vcpu))
+                       return 1;
+
+               /* The STIBP bit doesn't fault even if it's not advertised */
+               if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP))
+                       return 1;
+
+               vmx->spec_ctrl = data;
+
+               if (!data)
+                       break;
+
+               /*
+                * For non-nested:
+                * When it's written (to non-zero) for the first time, pass
+                * it through.
+                *
+                * For nested:
+                * The handling of the MSR bitmap for L2 guests is done in
+                * nested_vmx_merge_msr_bitmap. We should not touch the
+                * vmcs02.msr_bitmap here since it gets completely overwritten
+                * in the merging. We update the vmcs01 here for L1 as well
+                * since it will end up touching the MSR anyway now.
+                */
+               vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap,
+                                             MSR_IA32_SPEC_CTRL,
+                                             MSR_TYPE_RW);
                break;
        case MSR_IA32_PRED_CMD:
                if (!msr_info->host_initiated &&
@@ -8718,8 +8751,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
        vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_CS, MSR_TYPE_RW);
        vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_ESP, MSR_TYPE_RW);
        vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SYSENTER_EIP, MSR_TYPE_RW);
-       vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_SPEC_CTRL, MSR_TYPE_RW);
-       vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_PRED_CMD, MSR_TYPE_RW);
        vmx_disable_intercept_for_msr(msr_bitmap, MSR_IA32_BNDCFGS, MSR_TYPE_RW);
        vmx->msr_bitmap_mode = 0;
 
@@ -9118,7 +9149,7 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
        unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap;
 
        /*
-        * pred_cmd is trying to verify two things:
+        * pred_cmd & spec_ctrl are trying to verify two things:
         *
         * 1. L0 gave a permission to L1 to actually passthrough the MSR. This
         *    ensures that we do not accidentally generate an L02 MSR bitmap
@@ -9131,9 +9162,10 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
         *    the MSR.
         */
        bool pred_cmd = msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD);
+       bool spec_ctrl = msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL);
 
        if (!nested_cpu_has_virt_x2apic_mode(vmcs12) &&
-           !pred_cmd)
+           !pred_cmd && !spec_ctrl)
                return false;
 
        page = nested_get_page(vcpu, vmcs12->msr_bitmap);
@@ -9180,6 +9212,12 @@ static inline bool nested_vmx_merge_msr_bitmap(struct kvm_vcpu *vcpu,
                                        MSR_IA32_PRED_CMD,
                                        MSR_TYPE_W);
 
+       if (spec_ctrl)
+               nested_vmx_disable_intercept_for_msr(
+                                       msr_bitmap_l1, msr_bitmap_l0,
+                                       MSR_IA32_SPEC_CTRL,
+                                       MSR_TYPE_R | MSR_TYPE_W);
+
        kunmap(page);
        nested_release_page_clean(page);