From patchwork Wed May 14 19:30:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eduardo Habkost X-Patchwork-Id: 348943 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 6923C1400DA for ; Thu, 15 May 2014 05:34:01 +1000 (EST) Received: from localhost ([::1]:53976 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WkewB-0004Ng-7n for incoming@patchwork.ozlabs.org; Wed, 14 May 2014 15:33:59 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35556) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wketn-0000gN-TO for qemu-devel@nongnu.org; Wed, 14 May 2014 15:31:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Wketg-0001Gz-0z for qemu-devel@nongnu.org; Wed, 14 May 2014 15:31:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48123) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Wketf-0001Ga-Qv for qemu-devel@nongnu.org; Wed, 14 May 2014 15:31:23 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s4EJVNcD031593 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 14 May 2014 15:31:23 -0400 Received: from localhost (ovpn-113-115.phx2.redhat.com [10.3.113.115]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s4EJVMsa013715; Wed, 14 May 2014 15:31:22 -0400 From: Eduardo Habkost To: qemu-devel@nongnu.org, =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Wed, 14 May 2014 16:30:06 -0300 Message-Id: <1400095810-27684-15-git-send-email-ehabkost@redhat.com> In-Reply-To: <1400095810-27684-1-git-send-email-ehabkost@redhat.com> References: <1400095810-27684-1-git-send-email-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PATCH RESEND v4 14/18] target-i386: Add "migratable" property to "host" CPU model 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 This flag will allow the user to choose between two modes: * All flags that can be enabled on the host, even if unmigratable (migratable=no); * All flags that can be enabled on the host, known to QEMU, and migratable (migratable=yes). The default is still migratable=false, to keep current behavior, but this will be changed to migratable=true by another patch. My plan was to support the "migratable" flag on all CPU classes, but have the default to "false" on all CPU models except "host". However, DeviceClass has no mechanism to allow a child class to have a different property default from the parent class yet, so by now only the "host" CPU model will support the "migratable" flag. Signed-off-by: Eduardo Habkost --- target-i386/cpu-qom.h | 5 +++++ target-i386/cpu.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index e9b3d57..016f90d 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -87,6 +87,11 @@ typedef struct X86CPU { bool hyperv_time; bool check_cpuid; bool enforce_cpuid; + /* If set, only migratable flags will be accepted when "enforce" mode is + * used, and only migratable flags will be included in the "host" + * CPU model. + */ + bool migratable; /* if true the CPUID code directly forward host cache leaves to the guest */ bool cache_info_passthrough; diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 77d6d3c..105006b 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -338,6 +338,7 @@ typedef struct FeatureWordInfo { uint32_t cpuid_ecx; /* Input ECX value for CPUID */ int cpuid_reg; /* output register (R_* constant) */ uint32_t tcg_features; /* Feature flags supported by TCG */ + uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */ } FeatureWordInfo; static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { @@ -461,6 +462,30 @@ void x86_cpu_compat_disable_kvm_features(FeatureWord w, uint32_t features) kvm_default_features[w] &= ~features; } +/* Returns the set of feature flags that are supported and migratable by + * QEMU, for a given FeatureWord + */ +static uint32_t x86_cpu_get_migratable_flags(FeatureWord w) +{ + uint32_t r = 0; + int i; + + FeatureWordInfo *wi = &feature_word_info[w]; + for (i = 0; i < 32; i++) { + uint32_t f = 1U << i; + /* If the feature name is unknown, it is not supported by QEMU yet */ + if (!wi->feat_names[i]) { + continue; + } + /* Skip features known to QEMU, but explicitly marked as unmigratable */ + if (wi->unmigratable_flags & f) { + continue; + } + r |= f; + } + return r; +} + void host_cpuid(uint32_t function, uint32_t count, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) { @@ -1206,6 +1231,11 @@ static int cpu_x86_fill_model_id(char *str) static X86CPUDefinition host_cpudef; +static Property x86_host_cpu_properties[] = { + DEFINE_PROP_BOOL("migratable", X86CPU, migratable, false), + DEFINE_PROP_END_OF_LIST() +}; + /* class_init for the "host" CPU model * * This function may be called before KVM is initialized. @@ -1213,6 +1243,7 @@ static X86CPUDefinition host_cpudef; static void host_x86_cpu_class_init(ObjectClass *oc, void *data) { X86CPUClass *xcc = X86_CPU_CLASS(oc); + DeviceClass *dc = DEVICE_CLASS(oc); uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0; host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx); @@ -1228,12 +1259,14 @@ static void host_x86_cpu_class_init(ObjectClass *oc, void *data) xcc->cpu_def = &host_cpudef; host_cpudef.cache_info_passthrough = true; + dc->props = x86_host_cpu_properties; /* level, xlevel, xlevel2, and the feature words are initialized on * instance_init, because they require KVM to be initialized. */ } -static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w); +static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, + bool migratable_only); static void host_x86_cpu_initfn(Object *obj) { @@ -1257,7 +1290,7 @@ static void host_x86_cpu_initfn(Object *obj) for (w = 0; w < FEATURE_WORDS; w++) { env->features[w] = - x86_cpu_get_supported_feature_word(w); + x86_cpu_get_supported_feature_word(w, cpu->migratable); } object_property_set_bool(OBJECT(cpu), true, "pmu", &error_abort); } @@ -1847,16 +1880,22 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) return cpu_list; } -static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w) +static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, + bool migratable_only) { FeatureWordInfo *wi = &feature_word_info[w]; + uint32_t r; if (kvm_enabled()) { - return kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax, + r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax, wi->cpuid_ecx, wi->cpuid_reg); } else { - return wi->tcg_features; + r = wi->tcg_features; + } + if (migratable_only) { + r &= x86_cpu_get_migratable_flags(w); } + return r; } /* Filters CPU feature words based on host availability of each feature @@ -1870,7 +1909,8 @@ static int x86_cpu_filter_features(X86CPU *cpu) int rv = 0; for (w = 0; w < FEATURE_WORDS; w++) { - uint32_t host_feat = x86_cpu_get_supported_feature_word(w); + uint32_t host_feat = + x86_cpu_get_supported_feature_word(w, cpu->migratable); uint32_t requested_features = env->features[w]; env->features[w] &= host_feat; cpu->filtered_features[w] = requested_features & ~env->features[w];