diff options
Diffstat (limited to 'target/i386/kvm.c')
-rw-r--r-- | target/i386/kvm.c | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 8e130ccf9c..27fd0505df 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -982,12 +982,6 @@ int kvm_arch_init_vcpu(CPUState *cs) } } - cpuid_data.cpuid.padding = 0; - r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data); - if (r) { - goto fail; - } - r = kvm_arch_set_tsc_khz(cs); if (r < 0) { goto fail; @@ -1007,6 +1001,36 @@ int kvm_arch_init_vcpu(CPUState *cs) } } + if (cpu->vmware_cpuid_freq + /* Guests depend on 0x40000000 to detect this feature, so only expose + * it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V) */ + && cpu->expose_kvm + && kvm_base == KVM_CPUID_SIGNATURE + /* TSC clock must be stable and known for this feature. */ + && ((env->features[FEAT_8000_0007_EDX] & CPUID_APM_INVTSC) + || env->user_tsc_khz != 0) + && env->tsc_khz != 0) { + + c = &cpuid_data.entries[cpuid_i++]; + c->function = KVM_CPUID_SIGNATURE | 0x10; + c->eax = env->tsc_khz; + /* LAPIC resolution of 1ns (freq: 1GHz) is hardcoded in KVM's + * APIC_BUS_CYCLE_NS */ + c->ebx = 1000000; + c->ecx = c->edx = 0; + + c = cpuid_find_entry(&cpuid_data.cpuid, kvm_base, 0); + c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10); + } + + cpuid_data.cpuid.nent = cpuid_i; + + cpuid_data.cpuid.padding = 0; + r = kvm_vcpu_ioctl(cs, KVM_SET_CPUID2, &cpuid_data); + if (r) { + goto fail; + } + if (has_xsave) { env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); } |