summaryrefslogtreecommitdiffstats
path: root/target-i386
diff options
context:
space:
mode:
authorPaolo Bonzini2014-01-23 19:27:24 +0100
committerPaolo Bonzini2014-02-03 17:33:55 +0100
commit234cc64796557eea829544e4ff72ee99b6149187 (patch)
tree47f69a505738738bc070902ebc036e9bad241a58 /target-i386
parentkvm: print suberror on all internal errors (diff)
downloadqemu-234cc64796557eea829544e4ff72ee99b6149187.tar.gz
qemu-234cc64796557eea829544e4ff72ee99b6149187.tar.xz
qemu-234cc64796557eea829544e4ff72ee99b6149187.zip
KVM: fix coexistence of KVM and Hyper-V leaves
kvm_arch_init_vcpu's initialization of the KVM leaves at 0x40000100 is broken, because KVM_CPUID_FEATURES is left at 0x40000001. Move it to 0x40000101 if Hyper-V is enabled. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/kvm.c47
1 files changed, 25 insertions, 22 deletions
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0a21c3085d..57389114f6 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -455,6 +455,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
uint32_t unused;
struct kvm_cpuid_entry2 *c;
uint32_t signature[3];
+ int kvm_base = KVM_CPUID_SIGNATURE;
int r;
memset(&cpuid_data, 0, sizeof(cpuid_data));
@@ -462,26 +463,22 @@ int kvm_arch_init_vcpu(CPUState *cs)
cpuid_i = 0;
/* Paravirtualization CPUIDs */
- c = &cpuid_data.entries[cpuid_i++];
- c->function = KVM_CPUID_SIGNATURE;
- if (!hyperv_enabled(cpu)) {
- memcpy(signature, "KVMKVMKVM\0\0\0", 12);
- c->eax = 0;
- } else {
+ if (hyperv_enabled(cpu)) {
+ c = &cpuid_data.entries[cpuid_i++];
+ c->function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
memcpy(signature, "Microsoft Hv", 12);
c->eax = HYPERV_CPUID_MIN;
- }
- c->ebx = signature[0];
- c->ecx = signature[1];
- c->edx = signature[2];
-
- c = &cpuid_data.entries[cpuid_i++];
- c->function = KVM_CPUID_FEATURES;
- c->eax = env->features[FEAT_KVM];
+ c->ebx = signature[0];
+ c->ecx = signature[1];
+ c->edx = signature[2];
- if (hyperv_enabled(cpu)) {
+ c = &cpuid_data.entries[cpuid_i++];
+ c->function = HYPERV_CPUID_INTERFACE;
memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
c->eax = signature[0];
+ c->ebx = 0;
+ c->ecx = 0;
+ c->edx = 0;
c = &cpuid_data.entries[cpuid_i++];
c->function = HYPERV_CPUID_VERSION;
@@ -513,15 +510,21 @@ int kvm_arch_init_vcpu(CPUState *cs)
c->eax = 0x40;
c->ebx = 0x40;
- c = &cpuid_data.entries[cpuid_i++];
- c->function = KVM_CPUID_SIGNATURE_NEXT;
- memcpy(signature, "KVMKVMKVM\0\0\0", 12);
- c->eax = 0;
- c->ebx = signature[0];
- c->ecx = signature[1];
- c->edx = signature[2];
+ kvm_base = KVM_CPUID_SIGNATURE_NEXT;
}
+ memcpy(signature, "KVMKVMKVM\0\0\0", 12);
+ c = &cpuid_data.entries[cpuid_i++];
+ c->function = KVM_CPUID_SIGNATURE | kvm_base;
+ c->eax = 0;
+ c->ebx = signature[0];
+ c->ecx = signature[1];
+ c->edx = signature[2];
+
+ c = &cpuid_data.entries[cpuid_i++];
+ c->function = KVM_CPUID_FEATURES | kvm_base;
+ c->eax = env->features[FEAT_KVM];
+
has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
has_msr_pv_eoi_en = c->eax & (1 << KVM_FEATURE_PV_EOI);