@@ -463,9 +463,10 @@ void kvm_arch_save_regs(CPUState *env)
}
static void do_cpuid_ent(struct kvm_cpuid_entry *e, uint32_t function,
- CPUState *env)
+ uint32_t count, CPUState *env)
{
env->regs[R_EAX] = function;
+ env->regs[R_ECX] = count;
qemu_kvm_cpuid_on_env(env);
e->function = function;
e->eax = env->regs[R_EAX];
@@ -514,7 +515,7 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
#endif
int cpuid_nent = 0;
CPUState copy;
- uint32_t i, limit;
+ uint32_t i, j, limit;
copy = *cenv;
@@ -539,15 +540,28 @@ int kvm_arch_qemu_init_env(CPUState *cenv)
qemu_kvm_cpuid_on_env(©);
limit = copy.regs[R_EAX];
- for (i = 0; i <= limit; ++i)
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, ©);
+ for (i = 0; i <= limit; ++i) {
+ if (i == 4 || i == 0xb || i == 0xd) {
+ for (j = 0; ; ++j) {
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, j, ©);
+
+ if (i == 4 && copy.regs[R_EAX] == 0)
+ break;
+ if (i == 0xb && !(copy.regs[R_ECX] & 0xff00))
+ break;
+ if (i == 0xd && copy.regs[R_EAX] == 0)
+ break;
+ }
+ } else
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
+ }
copy.regs[R_EAX] = 0x80000000;
qemu_kvm_cpuid_on_env(©);
limit = copy.regs[R_EAX];
for (i = 0x80000000; i <= limit; ++i)
- do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, ©);
+ do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©);
kvm_setup_cpuid(kvm_context, cenv->cpu_index, cpuid_nent, cpuid_ent);
return 0;
CPUID functions 4, 0xb and 0xd have sub-leaf values which depend on the input value of ECX. Fetch these cpuid values and pass them on to the kernel. Signed-off-by: Amit Shah <amit.shah@redhat.com> --- qemu/qemu-kvm-x86.c | 24 +++++++++++++++++++----- 1 files changed, 19 insertions(+), 5 deletions(-)