From: Mihai Carabas Date: Fri, 7 Dec 2018 13:09:51 +0000 (+0200) Subject: KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL - reloaded X-Git-Tag: v4.1.12-124.31.3~338 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=eaaa119c0f931596b7da2bb70e33d8cd1fcea576;p=users%2Fjedix%2Flinux-maple.git KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL - reloaded 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 Reviewed-by: Darren Kenny Reviewed-by: Boris Ostrovsky Signed-off-by: Brian Maly --- diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index feda28e6f539f..4833ceaf780e3 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -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(); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 97f1c35eb7611..24a166ad0a983 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -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 diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index e5a13224b919e..bec5cac5b51a5 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -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);