diff --git a/kernel/x86.c b/kernel/x86.c index b55c177..73312e9 100644 --- a/kernel/x86.c +++ b/kernel/x86.c @@ -783,7 +783,7 @@ static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid *cpuid, struct kvm_cpuid_entry __user *entries) { - int r, i; + int r, i, n = 0; struct kvm_cpuid_entry *cpuid_entries; r = -E2BIG; @@ -803,8 +803,17 @@ static int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu, vcpu->arch.cpuid_entries[i].ebx = cpuid_entries[i].ebx; vcpu->arch.cpuid_entries[i].ecx = cpuid_entries[i].ecx; vcpu->arch.cpuid_entries[i].edx = cpuid_entries[i].edx; - vcpu->arch.cpuid_entries[i].index = 0; - vcpu->arch.cpuid_entries[i].flags = 0; + switch(vcpu->arch.cpuid_entries[i].function) { + case 4: + vcpu->arch.cpuid_entries[i].index = n; + vcpu->arch.cpuid_entries[i].flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX; + n++; + break; + default: + vcpu->arch.cpuid_entries[i].index = 0; + vcpu->arch.cpuid_entries[i].flags = 0; + break; + } vcpu->arch.cpuid_entries[i].padding[0] = 0; vcpu->arch.cpuid_entries[i].padding[1] = 0; vcpu->arch.cpuid_entries[i].padding[2] = 0; diff --git a/qemu/qemu-kvm-x86.c b/qemu/qemu-kvm-x86.c index d86fec3..8e5d754 100644 --- a/qemu/qemu-kvm-x86.c +++ b/qemu/qemu-kvm-x86.c @@ -461,10 +461,11 @@ static void host_cpuid(uint32_t function, uint32_t *eax, uint32_t *ebx, } -static void do_cpuid_ent(struct kvm_cpuid_entry *e, uint32_t function, +static void do_cpuid_ent(struct kvm_cpuid_entry *e, uint32_t function, uint32_t index, CPUState *env) { env->regs[R_EAX] = function; + env->regs[R_ECX] = index; qemu_kvm_cpuid_on_env(env); e->function = function; e->eax = env->regs[R_EAX]; @@ -515,7 +516,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; @@ -540,16 +541,27 @@ 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) { + switch(i) { + case 4: + for(j = 0; ; j++) { + do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, j, ©); + if(!copy.regs[R_EAX]) break; + } + break; + default: + do_cpuid_ent(&cpuid_ent[cpuid_nent++], i, 0, ©); + break; + } + } 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; }