On Wed, 3 Apr 2019, Fenghua Yu wrote: > @@ -1663,6 +1663,12 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > u32 index; > > switch (msr_info->index) { > + case MSR_TEST_CTL: > + if (!msr_info->host_initiated && > + !(vcpu->arch.core_capability & CORE_CAP_SPLIT_LOCK_DETECT)) Errm? If the MSR_TEST_CTL is exposed to the guest via CPUID then the rdmsr() in the guest is not supposed to fail just because CORE_CAP_SPLIT_LOCK_DETECT is not set. vmx->msr_test_ctl holds the proper value, which is either 0 or CORE_CAP_SPLIT_LOCK_DETECT until more bits are supported. So the chek needs to be guest_cpuid_has(X86_FEATURE_CORE_CAPABILITY). > + return 1; > + msr_info->data = vmx->msr_test_ctl; > + break; > #ifdef CONFIG_X86_64 > case MSR_FS_BASE: > msr_info->data = vmcs_readl(GUEST_FS_BASE); > @@ -1797,6 +1803,14 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > u32 index; > > switch (msr_index) { > + case MSR_TEST_CTL: > + if (!(vcpu->arch.core_capability & CORE_CAP_SPLIT_LOCK_DETECT)) > + return 1; Again, this wants to be a check for the availability of the MSR in the guest cpuid and not to the CORE_CAP_SPLIT_LOCK_DETECT magic bit. > + > + if (data & ~TEST_CTL_ENABLE_SPLIT_LOCK_DETECT) > + return 1; and this one wants to be: if (data & vmx->msr_test_ctl_mask) so additional bits can be enabled later on at exactly one point in the code, i.e. during vm init. > + vmx->msr_test_ctl = data; > + break; > > +static void atomic_switch_msr_test_ctl(struct vcpu_vmx *vmx) > +{ > + u64 host_msr_test_ctl; > + > + /* if TEST_CTL MSR doesn't exist on the hardware, do nothing */ > + if (rdmsrl_safe(MSR_TEST_CTL, &host_msr_test_ctl)) > + return; Yikes. So on hosts which do not have MSR_TEST_CTL this takes a fault on every VM enter. The host knows whether it has this MSR or not. Even if it exists there is no point to do the rdmsr on every vmenter. The value should be cached per cpu. It only changes when: 1) #AC triggers in kernel space 2) The sysfs knob is flipped #1 It happens either _BEFORE_ or _AFTER_ atomic_switch_msr_test_ctl(). In both cases the cached value is correct in atomic_switch_msr_test_ctl(). If it happens _AFTER_ atomic_switch_msr_test_ctl() then the VMEXIT will restore the enabled bit, but there is nothing you can do about that. #2 CANNOT happen in the context of vcpu_run(). So this wants to be: host_msr_test_ctl = this_cpu_read(msr_test_ctl_cache); > + if (host_msr_test_ctl == vmx->msr_test_ctl) > + clear_atomic_switch_msr(vmx, MSR_TEST_CTL); > + else > + add_atomic_switch_msr(vmx, MSR_TEST_CTL, vmx->msr_test_ctl, > + host_msr_test_ctl, false); > +} > + > u64 kvm_get_core_capability(void) > { > - return 0; > + u64 data; > + > + rdmsrl_safe(MSR_IA32_CORE_CAPABILITY, &data); if (!boot_cpu_has(X86_FEATURE_CORE_CAPABILITY)) return 0; > + /* mask non-virtualizable functions */ > + data &= CORE_CAP_SPLIT_LOCK_DETECT; Why? > + /* > + * There will be a list of FMS values that have split lock detection > + * but lack the CORE CAPABILITY MSR. In this case, set > + * CORE_CAP_SPLIT_LOCK_DETECT since we emulate MSR CORE_CAPABILITY. That's completely wrong. X86_FEATURE_SPLIT_LOCK_DETECT is set when the capability is enumerated in CPUID or it's set via the FMS quirk. So: data = 0; > + if (boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) > + data |= CORE_CAP_SPLIT_LOCK_DETECT; > + > + return data; is absolutely sufficient. Thanks, tglx