diff options
author | Eduardo Habkost <ehabkost@redhat.com> | 2019-08-22 19:52:10 -0300 |
---|---|---|
committer | Eduardo Habkost <ehabkost@redhat.com> | 2019-10-15 18:34:44 -0300 |
commit | af95cafb877f563ed39ce8a5b2abe227dd5312fa (patch) | |
tree | 23d4d1acf889757203fb8a8d7defe555f08ea58c /target/i386 | |
parent | 76ecd7a514aa74b92dca807c60ca1e427e178fda (diff) | |
download | qemu-af95cafb877f563ed39ce8a5b2abe227dd5312fa.zip qemu-af95cafb877f563ed39ce8a5b2abe227dd5312fa.tar.gz qemu-af95cafb877f563ed39ce8a5b2abe227dd5312fa.tar.bz2 |
i386: Omit all-zeroes entries from KVM CPUID table
KVM has a 80-entry limit at KVM_SET_CPUID2. With the
introduction of CPUID[0x1F], it is now possible to hit this limit
with unusual CPU configurations, e.g.:
$ ./x86_64-softmmu/qemu-system-x86_64 \
-smp 1,dies=2,maxcpus=2 \
-cpu EPYC,check=off,enforce=off \
-machine accel=kvm
qemu-system-x86_64: kvm_init_vcpu failed: Argument list too long
This happens because QEMU adds a lot of all-zeroes CPUID entries
for unused CPUID leaves. In the example above, we end up
creating 48 all-zeroes CPUID entries.
KVM already returns all-zeroes when emulating the CPUID
instruction if an entry is missing, so the all-zeroes entries are
redundant. Skip those entries. This reduces the CPUID table
size by half while keeping CPUID output unchanged.
Reported-by: Yumei Huang <yuhuang@redhat.com>
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1741508
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Message-Id: <20190822225210.32541-1-ehabkost@redhat.com>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'target/i386')
-rw-r--r-- | target/i386/kvm.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 11b9c85..8c73438 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -1567,6 +1567,13 @@ int kvm_arch_init_vcpu(CPUState *cs) c->function = i; c->flags = 0; cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx); + if (!c->eax && !c->ebx && !c->ecx && !c->edx) { + /* + * KVM already returns all zeroes if a CPUID entry is missing, + * so we can omit it and avoid hitting KVM's 80-entry limit. + */ + cpuid_i--; + } break; } } @@ -1631,6 +1638,13 @@ int kvm_arch_init_vcpu(CPUState *cs) c->function = i; c->flags = 0; cpu_x86_cpuid(env, i, 0, &c->eax, &c->ebx, &c->ecx, &c->edx); + if (!c->eax && !c->ebx && !c->ecx && !c->edx) { + /* + * KVM already returns all zeroes if a CPUID entry is missing, + * so we can omit it and avoid hitting KVM's 80-entry limit. + */ + cpuid_i--; + } break; } } |