From patchwork Wed Oct 31 09:39:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marcelo Tosatti X-Patchwork-Id: 195791 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 446EC2C0180 for ; Wed, 31 Oct 2012 20:41:04 +1100 (EST) Received: from localhost ([::1]:35827 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTUnG-0008BR-7g for incoming@patchwork.ozlabs.org; Wed, 31 Oct 2012 05:41:02 -0400 Received: from eggs.gnu.org ([208.118.235.92]:49806) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTUml-0007pP-GS for qemu-devel@nongnu.org; Wed, 31 Oct 2012 05:40:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TTUmh-00034G-OU for qemu-devel@nongnu.org; Wed, 31 Oct 2012 05:40:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:34741) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TTUmh-00033h-F2 for qemu-devel@nongnu.org; Wed, 31 Oct 2012 05:40:27 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q9V9eQ31006582 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 31 Oct 2012 05:40:26 -0400 Received: from amt.cnet (vpn1-4-142.gru2.redhat.com [10.97.4.142]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q9V9ePq3020672; Wed, 31 Oct 2012 05:40:25 -0400 Received: from amt.cnet (amt.cnet [127.0.0.1]) by amt.cnet (Postfix) with ESMTP id B0EAE652299; Wed, 31 Oct 2012 07:40:13 -0200 (BRST) Received: (from marcelo@localhost) by amt.cnet (8.14.5/8.14.5/Submit) id q9V9eDHZ025086; Wed, 31 Oct 2012 07:40:13 -0200 From: Marcelo Tosatti To: Anthony Liguori Date: Wed, 31 Oct 2012 07:39:51 -0200 Message-Id: In-Reply-To: References: X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: Marcelo Tosatti , qemu-devel@nongnu.org, kvm@vger.kernel.org, Eduardo Habkost Subject: [Qemu-devel] [PATCH 13/28] i386: kvm: filter CPUID feature words earlier, on cpu.c X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Eduardo Habkost cpu.c contains the code that will check if all requested CPU features are available, so the filtering of KVM features must be there, so we can implement "check" and "enforce" properly. The only point where kvm_arch_init_vcpu() is called on i386 is: - cpu_x86_init() - x86_cpu_realize() (after cpu_x86_register() is called) - qemu_init_vcpu() - qemu_kvm_start_vcpu() - qemu_kvm_thread_fn() (on a new thread) - kvm_init_vcpu() - kvm_arch_init_vcpu() With this patch, the filtering will be done earlier, at: - cpu_x86_init() - cpu_x86_register() (before x86_cpu_realize() is called) Also, the KVM CPUID filtering will now be done at the same place where the TCG CPUID feature filtering is done. Later, the code can be changed to use the same filtering code for the "check" and "enforce" modes, as now the cpu.c code knows exactly which CPU features are going to be exposed to the guest (and much earlier). One thing I was worrying about when doing this is that kvm_arch_get_supported_cpuid() depends on kvm_irqchip_in_kernel(), and maybe the 'kvm_kernel_irqchip' global variable wasn't initialized yet at CPU creation time. But kvm_kernel_irqchip is initialized during kvm_init(), that is called very early (much earlier than the machine init function), and kvm_init() is already a requirement to run the GET_SUPPORTED_CPUID ioctl() (as kvm_init() initializes the kvm_state global variable). Side note: it would be nice to keep KVM-specific code inside kvm.c. The problem is that properly implementing -cpu check/enforce code (that's inside cpu.c) depends directly on the feature bit filtering done using kvm_arch_get_supported_cpuid(). Currently -cpu check/enforce is broken because it simply uses the host CPU feature bits instead of GET_SUPPORTED_CPUID, and we need to fix that. Signed-off-by: Eduardo Habkost Signed-off-by: Marcelo Tosatti --- kvm.h | 1 + target-i386/cpu.c | 30 ++++++++++++++++++++++++++++++ target-i386/kvm.c | 18 ------------------ 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/kvm.h b/kvm.h index 2b26dcb..1e7f244 100644 --- a/kvm.h +++ b/kvm.h @@ -20,6 +20,7 @@ #ifdef CONFIG_KVM #include +#include #endif extern int kvm_allowed; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index d4f2e65..78876f6 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -1368,6 +1368,32 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) return cpu_list; } +#ifdef CONFIG_KVM +static void filter_features_for_kvm(X86CPU *cpu) +{ + CPUX86State *env = &cpu->env; + KVMState *s = kvm_state; + + env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); + + env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); + + env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, + 0, R_EDX); + env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, + 0, R_ECX); + env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, + 0, R_EDX); + + env->cpuid_kvm_features &= + kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); + + env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, + 0, R_EDX); + +} +#endif + int cpu_x86_register(X86CPU *cpu, const char *cpu_model) { CPUX86State *env = &cpu->env; @@ -1425,6 +1451,10 @@ int cpu_x86_register(X86CPU *cpu, const char *cpu_model) ); env->cpuid_ext3_features &= TCG_EXT3_FEATURES; env->cpuid_svm_features &= TCG_SVM_FEATURES; + } else { +#ifdef CONFIG_KVM + filter_features_for_kvm(cpu); +#endif } object_property_set_str(OBJECT(cpu), def->model_id, "model-id", &error); if (error_is_set(&error)) { diff --git a/target-i386/kvm.c b/target-i386/kvm.c index be37a1f..593e9d3 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -410,30 +410,12 @@ int kvm_arch_init_vcpu(CPUX86State *env) struct kvm_cpuid2 cpuid; struct kvm_cpuid_entry2 entries[100]; } QEMU_PACKED cpuid_data; - KVMState *s = env->kvm_state; uint32_t limit, i, j, cpuid_i; uint32_t unused; struct kvm_cpuid_entry2 *c; uint32_t signature[3]; int r; - env->cpuid_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_EDX); - - env->cpuid_ext_features &= kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX); - - env->cpuid_ext2_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_EDX); - env->cpuid_ext3_features &= kvm_arch_get_supported_cpuid(s, 0x80000001, - 0, R_ECX); - env->cpuid_svm_features &= kvm_arch_get_supported_cpuid(s, 0x8000000A, - 0, R_EDX); - - env->cpuid_kvm_features &= - kvm_arch_get_supported_cpuid(s, KVM_CPUID_FEATURES, 0, R_EAX); - - env->cpuid_ext4_features &= kvm_arch_get_supported_cpuid(s, 0xC0000001, - 0, R_EDX); - cpuid_i = 0; /* Paravirtualization CPUIDs */