From 1a6f3d4038c2989cf751f99dce9899cfd83c2cbb Mon Sep 17 00:00:00 2001 Message-Id: <1a6f3d4038c2989cf751f99dce9899cfd83c2cbb.1351793582.git.minovotn@redhat.com> In-Reply-To: References: From: Eduardo Habkost Date: Thu, 25 Oct 2012 19:28:17 +0200 Subject: [PATCH 4/8] i386: kvm: set CPUID_EXT_TSC_DEADLINE_TIMER on kvm_arch_get_supported_cpuid() RH-Author: Eduardo Habkost Message-id: <1351193301-31675-5-git-send-email-ehabkost@redhat.com> Patchwork-id: 43655 O-Subject: [RHEL6.4 qemu-kvm PATCH 4/8] i386: kvm: set CPUID_EXT_TSC_DEADLINE_TIMER on kvm_arch_get_supported_cpuid() Bugzilla: 691638 RH-Acked-by: Marcelo Tosatti RH-Acked-by: Gleb Natapov RH-Acked-by: Laszlo Ersek Bugzilla: 691638 Upstream status: equivalent patch submitted Message-Id: <1349383747-19383-10-git-send-email-ehabkost@redhat.com> This moves the CPUID_EXT_TSC_DEADLINE_TIMER CPUID flag hacking from kvm_arch_init_vcpu() to kvm_arch_get_supported_cpuid(). Full git 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_TSC_DEADLINE_TIMER, so we can simply make kvm_arch_get_supported_cpuid() set it, to let the rest of the code know 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. One thing I was worrying about when doing this is that now kvm_get_supported_cpuid() depends on kvm_irqchip_in_kernel(). But as soon as the kvm_context global variable is set by kvm_init, the kvm_context->irqchip_in_kernel field should be initialized too (by kvm_create_irqchip(), called by kvm_create() by kvm_create_context(), called by kvm_init()). And kvm_get_supported_cpuid() can be called only after kvm_init() was called. Signed-off-by: Eduardo Habkost --- qemu-kvm-x86.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) Signed-off-by: Michal Novotny --- qemu-kvm-x86.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 3516480..f7f8428 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -764,6 +764,14 @@ uint32_t kvm_get_supported_cpuid(kvm_context_t kvm, uint32_t function, * GET_SUPPORTED_CPUID */ ret |= CPUID_EXT_HYPERVISOR; + /* tsc-deadline flag is not returned by GET_SUPPORTED_CPUID, but it + * can be enabled if the kernel has KVM_CAP_TSC_DEADLINE_TIMER, + * and the irqchip is in the kernel. + */ + if (kvm_irqchip_in_kernel() && + kvm_check_extension(kvm_state, KVM_CAP_TSC_DEADLINE_TIMER)) { + ret |= CPUID_EXT_TSC_DEADLINE_TIMER; + } } @@ -1434,14 +1442,8 @@ 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 */ - 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)); - 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; - } - kvm_trim_features(&cenv->cpuid_ext2_features, kvm_arch_get_supported_cpuid(cenv->kvm_state, 0x80000001, 0, R_EDX)); kvm_trim_features(&cenv->cpuid_ext3_features, -- 1.7.11.7