On Tue, 2019-09-10 at 16:24 +0800, Xiaoyao Li wrote: > When limit checking is required, it should be executed first, which is > consistent with the CPUID specification. > > Signed-off-by: Xiaoyao Li <xiaoyao.li@xxxxxxxxx> > --- > arch/x86/kvm/cpuid.c | 50 +++++++++++++++++++++++++------------------- > 1 file changed, 28 insertions(+), 22 deletions(-) > > diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c > index 22c2720cd948..866546b4d834 100644 > --- a/arch/x86/kvm/cpuid.c > +++ b/arch/x86/kvm/cpuid.c > @@ -952,23 +952,33 @@ struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct > kvm_vcpu *vcpu, > EXPORT_SYMBOL_GPL(kvm_find_cpuid_entry); > > /* > - * If no match is found, check whether we exceed the vCPU's limit > - * and return the content of the highest valid _standard_ leaf instead. > - * This is to satisfy the CPUID specification. > + * Based on CPUID specification, if leaf number exceeds the vCPU's limit, > + * it should return the content of the highest valid _standard_ leaf instead. > + * Note: *found is set true only means the queried leaf number doesn't exceed > + * the maximum leaf number of basic or extented leaf. > */ > -static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu, > - u32 function, u32 index) > +static struct kvm_cpuid_entry2* cpuid_check_limit(struct kvm_vcpu *vcpu, > + u32 function, u32 index, > + bool *found) > { > struct kvm_cpuid_entry2 *maxlevel; > > maxlevel = kvm_find_cpuid_entry(vcpu, function & 0x80000000, 0); > - if (!maxlevel || maxlevel->eax >= function) > + if (!maxlevel) > return NULL; > - if (function & 0x80000000) { > - maxlevel = kvm_find_cpuid_entry(vcpu, 0, 0); > - if (!maxlevel) > - return NULL; > + > + if (maxlevel->eax >= function) { > + if (found) > + *found = true; > + return kvm_find_cpuid_entry(vcpu, function, index); > } > + > + if (function & 0x80000000) > + maxlevel = kvm_find_cpuid_entry(vcpu, 0, 0); > + > + if (!maxlevel) > + return NULL; > + > return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index); > } > > @@ -977,26 +987,22 @@ bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 > *ebx, > { > u32 function = *eax, index = *ecx; > struct kvm_cpuid_entry2 *best; > - bool entry_found = true; > + bool entry_found = false; > > - best = kvm_find_cpuid_entry(vcpu, function, index); > + if (check_limit) > + best = cpuid_check_limit(vcpu, function, index, &entry_found); > + else > + best = kvm_find_cpuid_entry(vcpu, function, index); > > - if (!best) { > - entry_found = false; > - if (!check_limit) > - goto out; > - > - best = check_cpuid_limit(vcpu, function, index); > - } > - > -out: > if (best) { > *eax = best->eax; > *ebx = best->ebx; > *ecx = best->ecx; > *edx = best->edx; > - } else > + } else { > + entry_found = false; > *eax = *ebx = *ecx = *edx = 0; > + } > trace_kvm_cpuid(function, *eax, *ebx, *ecx, *edx, entry_found); > return entry_found; > } Just realise the entry_found is not set true if found in no limit checking case. Will send v2.