From 7000eca2b2e3a59d4d0c7b7dea94e8fdde34daa3 Mon Sep 17 00:00:00 2001
Message-Id: <7000eca2b2e3a59d4d0c7b7dea94e8fdde34daa3.1351793582.git.minovotn@redhat.com>
In-Reply-To: <e74f21f4030b33aaac45cab138ecabe18aac615b.1351793582.git.minovotn@redhat.com>
References: <e74f21f4030b33aaac45cab138ecabe18aac615b.1351793582.git.minovotn@redhat.com>
From: Eduardo Habkost <ehabkost@redhat.com>
Date: Thu, 25 Oct 2012 19:28:16 +0200
Subject: [PATCH 3/8] i386: kvm: set CPUID_EXT_HYPERVISOR on
 kvm_arch_get_supported_cpuid()

RH-Author: Eduardo Habkost <ehabkost@redhat.com>
Message-id: <1351193301-31675-4-git-send-email-ehabkost@redhat.com>
Patchwork-id: 43652
O-Subject: [RHEL6.4 qemu-kvm PATCH 3/8] i386: kvm: set CPUID_EXT_HYPERVISOR on kvm_arch_get_supported_cpuid()
Bugzilla: 691638
RH-Acked-by: Marcelo Tosatti <mtosatti@redhat.com>
RH-Acked-by: Gleb Natapov <gleb@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

Bugzilla: 691638
Upstream status: equivalent patch submitted
 Message-Id: <1349383747-19383-9-git-send-email-ehabkost@redhat.com>

Full grep for get_supported_cpuid:

   kvm/libkvm/libkvm-x86.c:uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function,
   kvm/libkvm/libkvm-x86.c:                                        cpuid_1_edx = kvm_get_supported_cpuid(kvm, 1, 0, R_EDX);
   kvm/libkvm/libkvm-x86.c:uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function,
   kvm/libkvm/libkvm.h:uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function,
   qemu-kvm-x86.c:static struct kvm_cpuid2 *get_supported_cpuid(kvm_context_t kvm)
   qemu-kvm-x86.c:uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function,
   qemu-kvm-x86.c: cpuid = get_supported_cpuid(kvm);
   qemu-kvm-x86.c:         cpuid_1_edx = kvm_get_supported_cpuid(kvm, 1, 0, R_EDX);
   qemu-kvm-x86.c:    pv_ent->eax = cenv->cpuid_kvm_features & kvm_arch_get_supported_cpuid(cenv->kvm_state,
   qemu-kvm-x86.c:                      kvm_arch_get_supported_cpuid(cenv->kvm_state, 1, 0, R_EDX));
 * qemu-kvm-x86.c:                      kvm_arch_get_supported_cpuid(cenv->kvm_state, 1, 0, R_ECX));
   qemu-kvm-x86.c:                      kvm_arch_get_supported_cpuid(cenv->kvm_state, 0x80000001, 0, R_EDX));
   qemu-kvm-x86.c:                      kvm_arch_get_supported_cpuid(cenv->kvm_state, 0x80000001, 0, R_ECX));
   qemu-kvm-x86.c:uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function,
   qemu-kvm-x86.c:    return kvm_get_supported_cpuid(kvm_context, function, index, reg);
   qemu-kvm.h:uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function,
   qemu-kvm.h:uint32_t kvm_arch_get_supported_cpuid(struct KVMState *env, uint32_t function,
   target-i386/cpuid.c:        x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX);
** target-i386/cpuid.c:                    kvm_arch_get_supported_cpuid(env->kvm_state, p->cmd, 0, p->reg);
   target-i386/cpuid.c:            *eax = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EAX);
   target-i386/cpuid.c:            *ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
   target-i386/cpuid.c:            *ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
   target-i386/cpuid.c:            *edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
   target-i386/cpuid.c:            *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX);
   target-i386/cpuid.c:            *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX);
   target-i386/cpuid.c:            *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX);
   target-i386/cpuid.c:            *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX);

Note that there is only one call for CPUID[1].ECX above (*), and it is the one
that gets hacked to include CPUID_EXT_HYPERVISOR, so we can simply make
kvm_arch_get_supported_cpuid() set it, to let the rest of the code
automatically know that the flag can be safely set by QEMU.

Also, the -cpu check/enforce checks on summary_cpuid_features() &
check_features_against_host() (**) will see the new bit set, but they
won't be affected because summary_cpuid_features() is using
kvm_arch_get_supported_cpuid() only for the CPUID_EXT_X2APIC bit and
nothing else.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 qemu-kvm-x86.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 qemu-kvm-x86.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c
index 70d0885..3516480 100644
--- a/qemu-kvm-x86.c
+++ b/qemu-kvm-x86.c
@@ -759,8 +759,14 @@ uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function,
 		 */
 		cpuid_1_edx = kvm_get_supported_cpuid(kvm, 1, 0, R_EDX);
 		ret |= cpuid_1_edx & 0x183f7ff;
+	} else if (function == 1 && reg == R_ECX) {
+		/* We can set the hypervisor flag, even if KVM does not return it on
+		 * GET_SUPPORTED_CPUID
+		 */
+		ret |= CPUID_EXT_HYPERVISOR;
 	}
 
+
 	free(cpuid);
 #endif
 	/* fallback for older kernels */
@@ -1428,11 +1434,9 @@ int kvm_arch_init_vcpu(CPUState *cenv)
                       kvm_arch_get_supported_cpuid(cenv->kvm_state, 1, 0, R_EDX));
 
     /* prevent the hypervisor bit from being cleared by the kernel */
-    i = cenv->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
     j = cenv->cpuid_ext_features & CPUID_EXT_TSC_DEADLINE_TIMER;
     kvm_trim_features(&cenv->cpuid_ext_features,
                       kvm_arch_get_supported_cpuid(cenv->kvm_state, 1, 0, R_ECX));
-    cenv->cpuid_ext_features |= i;
     if (j && kvm_irqchip_in_kernel() &&
         kvm_check_extension(cenv->kvm_state, KVM_CAP_TSC_DEADLINE_TIMER)) {
         cenv->cpuid_ext_features |= CPUID_EXT_TSC_DEADLINE_TIMER;
-- 
1.7.11.7

