From patchwork Fri Oct 12 19:56:17 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [v7, 12/17] target-i386: Use Hypervisor features in -machine pc, accel=kvm. From: Don Slutz X-Patchwork-Id: 191193 Message-Id: <1350071782-23078-13-git-send-email-Don@CloudSwitch.com> To: , , , , , , , , Cc: Don Slutz Date: Fri, 12 Oct 2012 15:56:17 -0400 Part of "target-i386: Add way to expose VMWare CPUID" QEMU knows this as KVM_CPUID_FEATURES (0x40000001) in some builds. If hypervisor features are set, then pass adjusted cpuid_kvm_features as EAX in 0x40000101. This is based on: Microsoft Hypervisor CPUID Leaves: http://msdn.microsoft.com/en-us/library/windows/hardware/ff542428%28v=vs.85%29.aspx Linux kernel change starts with: http://fixunix.com/kernel/538707-use-cpuid-communicate-hypervisor.html Also: http://lkml.indiana.edu/hypermail/linux/kernel/1205.0/00100.html Signed-off-by: Don Slutz --- target-i386/kvm.c | 27 +++++++++++++++++++++------ 1 files changed, 21 insertions(+), 6 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 513356d..b61027f 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -409,13 +409,14 @@ int kvm_arch_init_vcpu(CPUX86State *env) c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_FEATURES; - c->eax = env->cpuid_kvm_features & - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + if (!env->cpuid_hv_features_set) { + c->eax = env->cpuid_kvm_features & + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + } else { + c->eax = env->cpuid_hv_features; + } if (hyperv_enabled()) { - memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12); - c->eax = signature[0]; - c = &cpuid_data.entries[cpuid_i++]; memset(c, 0, sizeof(*c)); c->function = HYPERV_CPUID_VERSION; @@ -455,10 +456,24 @@ int kvm_arch_init_vcpu(CPUX86State *env) memset(c, 0, sizeof(*c)); c->function = KVM_CPUID_SIGNATURE_NEXT; memcpy(signature, "KVMKVMKVM\0\0\0", 12); - c->eax = 0; + if (env->cpuid_hv_features_set) { + c->eax = KVM_CPUID_SIGNATURE_NEXT - + KVM_CPUID_SIGNATURE + KVM_CPUID_FEATURES; + } else { + c->eax = 0; + } c->ebx = signature[0]; c->ecx = signature[1]; c->edx = signature[2]; + + if (env->cpuid_hv_features_set) { + c = &cpuid_data.entries[cpuid_i++]; + memset(c, 0, sizeof(*c)); + c->function = KVM_CPUID_SIGNATURE_NEXT - + KVM_CPUID_SIGNATURE + KVM_CPUID_FEATURES; + c->eax = env->cpuid_kvm_features & + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + } } has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);