On Tue, Aug 14, 2018 at 10:30:48AM -0700, Jim Mattson wrote: > Expose IA32_FLUSH_CMD to the guest if the guest CPUID enumerates > support for this MSR. As with IA32_PRED_CMD, permission for > unintercepted writes to this MSR will be granted to the guest after > the first non-zero write. I can't seem to find the Intel docs (even thought all the pages are all set), but my understanding is that the ARCH_CAPABILITIES Bit(3) would suffice. That is it says that for nested OSes you shouldn't use the IA32_FLUSH_CMD? > > Signed-off-by: Jim Mattson <jmattson@xxxxxxxxxx> > Reviewed-by: Ben Serebrin <serebrin@xxxxxxxxxx> > Reviewed-by: Peter Shier <pshier@xxxxxxxxxx> > --- > arch/x86/kvm/vmx.c | 44 +++++++++++++++++++++++++++++++++++--------- > 1 file changed, 35 insertions(+), 9 deletions(-) > > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index 46b428c0990e0..1b40265376641 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -3996,6 +3996,28 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > > static void vmx_leave_nested(struct kvm_vcpu *vcpu); > > +static bool valid_msr_setting(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > +{ > + bool valid; > + > + switch (msr_info->index) { > + case MSR_IA32_PRED_CMD: > + valid = (msr_info->host_initiated || > + guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) && > + !(msr_info->data & ~PRED_CMD_IBPB); > + break; > + case MSR_IA32_FLUSH_CMD: > + valid = (msr_info->host_initiated || > + guest_cpuid_has(vcpu, X86_FEATURE_FLUSH_L1D)) && > + !(msr_info->data & ~L1D_FLUSH); > + break; > + default: > + valid = false; > + break; > + } > + return valid; > +} > + > /* > * Writes msr value into into the appropriate "register". > * Returns 0 on success, non-0 otherwise. > @@ -4077,17 +4099,14 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > MSR_TYPE_RW); > break; > case MSR_IA32_PRED_CMD: > - if (!msr_info->host_initiated && > - !guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL)) > - return 1; > - > - if (data & ~PRED_CMD_IBPB) > + case MSR_IA32_FLUSH_CMD: > + if (!valid_msr_setting(vcpu, msr_info)) > return 1; > > if (!data) > break; > > - wrmsrl(MSR_IA32_PRED_CMD, PRED_CMD_IBPB); > + wrmsrl(msr_index, data); > > /* > * For non-nested: > @@ -4100,7 +4119,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > * vmcs02.msr_bitmap here since it gets completely overwritten > * in the merging. > */ > - vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD, > + vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, msr_index, > MSR_TYPE_W); > break; > case MSR_IA32_ARCH_CAPABILITIES: > @@ -11089,7 +11108,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, > unsigned long *msr_bitmap_l1; > unsigned long *msr_bitmap_l0 = to_vmx(vcpu)->nested.vmcs02.msr_bitmap; > /* > - * pred_cmd & spec_ctrl are trying to verify two things: > + * pred_cmd, flush_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 > @@ -11102,6 +11121,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, > * the MSR. > */ > bool pred_cmd = !msr_write_intercepted_l01(vcpu, MSR_IA32_PRED_CMD); > + bool flush_cmd = !msr_write_intercepted_l01(vcpu, MSR_IA32_FLUSH_CMD); > bool spec_ctrl = !msr_write_intercepted_l01(vcpu, MSR_IA32_SPEC_CTRL); > > /* Nothing to do if the MSR bitmap is not in use. */ > @@ -11110,7 +11130,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, > return false; > > if (!nested_cpu_has_virt_x2apic_mode(vmcs12) && > - !pred_cmd && !spec_ctrl) > + !pred_cmd && !flush_cmd && !spec_ctrl) > return false; > > page = kvm_vcpu_gpa_to_page(vcpu, vmcs12->msr_bitmap); > @@ -11165,6 +11185,12 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, > MSR_IA32_PRED_CMD, > MSR_TYPE_W); > > + if (flush_cmd) > + nested_vmx_disable_intercept_for_msr( > + msr_bitmap_l1, msr_bitmap_l0, > + MSR_IA32_FLUSH_CMD, > + MSR_TYPE_W); > + > kunmap(page); > kvm_release_page_clean(page); > > -- > 2.18.0.865.gffc8e1a3cd6-goog >