Skip to content

Commit 4736d85

Browse files
vittyvksean-jc
authored andcommitted
KVM: x86: Use actual kvm_cpuid.base for clearing KVM_FEATURE_PV_UNHALT
Commit ee3a5f9 ("KVM: x86: Do runtime CPUID update before updating vcpu->arch.cpuid_entries") moved tweaking of the supplied CPUID data earlier in kvm_set_cpuid() but __kvm_update_cpuid_runtime() actually uses 'vcpu->arch.kvm_cpuid' (though __kvm_find_kvm_cpuid_features()) which gets set later in kvm_set_cpuid(). In some cases, e.g. when kvm_set_cpuid() is called for the first time and 'vcpu->arch.kvm_cpuid' is clear, __kvm_find_kvm_cpuid_features() fails to find KVM PV feature entry and the logic which clears KVM_FEATURE_PV_UNHALT after enabling KVM_X86_DISABLE_EXITS_HLT does not work. The logic, introduced by the commit ee3a5f9 ("KVM: x86: Do runtime CPUID update before updating vcpu->arch.cpuid_entries") must stay: the supplied CPUID data is tweaked by KVM first (__kvm_update_cpuid_runtime()) and checked later (kvm_check_cpuid()) and the actual data (vcpu->arch.cpuid_*, vcpu->arch.kvm_cpuid, vcpu->arch.xen.cpuid,..) is only updated on success. Switch to searching for KVM_SIGNATURE in the supplied CPUID data to discover KVM PV feature entry instead of using stale 'vcpu->arch.kvm_cpuid'. While on it, drop pointless "&& (best->eax & (1 << KVM_FEATURE_PV_UNHALT)" check when clearing KVM_FEATURE_PV_UNHALT bit. Fixes: ee3a5f9 ("KVM: x86: Do runtime CPUID update before updating vcpu->arch.cpuid_entries") Reported-and-tested-by: Li RongQing <lirongqing@baidu.com> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Link: https://lore.kernel.org/r/20240228101837.93642-3-vkuznets@redhat.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 92e82cf commit 4736d85

File tree

1 file changed

+17
-14
lines changed

1 file changed

+17
-14
lines changed

arch/x86/kvm/cpuid.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -224,22 +224,22 @@ static struct kvm_hypervisor_cpuid kvm_get_hypervisor_cpuid(struct kvm_vcpu *vcp
224224
vcpu->arch.cpuid_nent, sig);
225225
}
226226

227-
static struct kvm_cpuid_entry2 *__kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu,
228-
struct kvm_cpuid_entry2 *entries, int nent)
227+
static struct kvm_cpuid_entry2 *__kvm_find_kvm_cpuid_features(struct kvm_cpuid_entry2 *entries,
228+
int nent, u32 kvm_cpuid_base)
229229
{
230-
u32 base = vcpu->arch.kvm_cpuid.base;
231-
232-
if (!base)
233-
return NULL;
234-
235-
return cpuid_entry2_find(entries, nent, base | KVM_CPUID_FEATURES,
230+
return cpuid_entry2_find(entries, nent, kvm_cpuid_base | KVM_CPUID_FEATURES,
236231
KVM_CPUID_INDEX_NOT_SIGNIFICANT);
237232
}
238233

239234
static struct kvm_cpuid_entry2 *kvm_find_kvm_cpuid_features(struct kvm_vcpu *vcpu)
240235
{
241-
return __kvm_find_kvm_cpuid_features(vcpu, vcpu->arch.cpuid_entries,
242-
vcpu->arch.cpuid_nent);
236+
u32 base = vcpu->arch.kvm_cpuid.base;
237+
238+
if (!base)
239+
return NULL;
240+
241+
return __kvm_find_kvm_cpuid_features(vcpu->arch.cpuid_entries,
242+
vcpu->arch.cpuid_nent, base);
243243
}
244244

245245
void kvm_update_pv_runtime(struct kvm_vcpu *vcpu)
@@ -273,6 +273,7 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e
273273
int nent)
274274
{
275275
struct kvm_cpuid_entry2 *best;
276+
struct kvm_hypervisor_cpuid kvm_cpuid;
276277

277278
best = cpuid_entry2_find(entries, nent, 1, KVM_CPUID_INDEX_NOT_SIGNIFICANT);
278279
if (best) {
@@ -299,10 +300,12 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e
299300
cpuid_entry_has(best, X86_FEATURE_XSAVEC)))
300301
best->ebx = xstate_required_size(vcpu->arch.xcr0, true);
301302

302-
best = __kvm_find_kvm_cpuid_features(vcpu, entries, nent);
303-
if (kvm_hlt_in_guest(vcpu->kvm) && best &&
304-
(best->eax & (1 << KVM_FEATURE_PV_UNHALT)))
305-
best->eax &= ~(1 << KVM_FEATURE_PV_UNHALT);
303+
kvm_cpuid = __kvm_get_hypervisor_cpuid(entries, nent, KVM_SIGNATURE);
304+
if (kvm_cpuid.base) {
305+
best = __kvm_find_kvm_cpuid_features(entries, nent, kvm_cpuid.base);
306+
if (kvm_hlt_in_guest(vcpu->kvm) && best)
307+
best->eax &= ~(1 << KVM_FEATURE_PV_UNHALT);
308+
}
306309

307310
if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT)) {
308311
best = cpuid_entry2_find(entries, nent, 0x1, KVM_CPUID_INDEX_NOT_SIGNIFICANT);

0 commit comments

Comments
 (0)