From 0867acb1633892f8105e507d81c5fd6e137dde87 Mon Sep 17 00:00:00 2001 Message-Id: <0867acb1633892f8105e507d81c5fd6e137dde87.1337678792.git.minovotn@redhat.com> In-Reply-To: References: From: Eduardo Habkost Date: Mon, 21 May 2012 13:54:41 +0200 Subject: [PATCH 2/2] Expose CPUID leaf 7 only for -cpu host (v2) RH-Author: Eduardo Habkost Message-id: <1337608481-29002-3-git-send-email-ehabkost@redhat.com> Patchwork-id: 39750 O-Subject: [RHEL6.3 qemu-kvm PATCH 2/2] Expose CPUID leaf 7 only for -cpu host (v2) Bugzilla: 819562 RH-Acked-by: Paolo Bonzini RH-Acked-by: Gleb Natapov RH-Acked-by: Marcelo Tosatti Bugzilla: 819562 Upstream status: - v1 submitted at: Message-ID: <20120517162655.GQ16951@otherpad.lan.raisama.net> http://article.gmane.org/gmane.comp.emulators.kvm.devel/91040 - v2 will be submitted in a few minutes Changes v1 -> v2: - Check for kvm_enabled() before setting cpuid_7_0_ebx_features (patch 1/2 is unchanged) Description of the bug: Since QEMU 0.15, the CPUID information on CPUID[EAX=7,ECX=0] is being returned unfiltered to the guest, directly from the GET_SUPPORTED_CPUID return value. The problem is that this makes the resulting CPU feature flags unpredictable and dependent on the host CPU and kernel version. This breaks live-migration badly if migrating from a host CPU that supports some features on that CPUID leaf (running a recent kernel) to a kernel or host CPU that doesn't support it. Migration also is incorrect (the virtual CPU changes under the guest's feet) if you migrate in the opposite direction (from an old CPU/kernel to a new CPU/kernel), but with less serious consequences (guests normally query CPUID information only once on boot). Fortunately, the bug affects only users using cpudefs with level >= 7. The right behavior should be to explicitly enable those features on [cpudef] config sections or on the "-cpu" command-line arguments. Right now there is no predefined CPU model on QEMU that has those features: the latest Intel model we have is Sandy Bridge. This patch changes QEMU to enable those features only if "-cpu host" is being used (as we don't have any pre-defined CPU model that actually have those features). Later we can make those features properly configurable on [cpudef] and -cpu configuration. One problem is: with this patch, users with the following setup: - Running QEMU 1.0; - Using a cpudef having level >= 7; - Running a kernel that supports the features on CPUID leaf 7; and - Running on a CPU that supports some features on CPUID leaf 7 won't be able to live-migrate to QEMU 1.1. But for these users live-migration is already broken (they can't live-migrate to hosts with older CPUs or older kernels, already), I don't see how to avoid this problem. Signed-off-by: Eduardo Habkost --- target-i386/cpu.h | 2 ++ target-i386/cpuid.c | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) Signed-off-by: Michal Novotny --- target-i386/cpu.h | 2 ++ target-i386/cpuid.c | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 09ba354..91e1961 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -701,6 +701,8 @@ typedef struct CPUX86State { uint32_t cpuid_model[12]; uint32_t cpuid_ext2_features; uint32_t cpuid_ext3_features; + /* Flags from CPUID[EAX=7,ECX=0].EBX */ + uint32_t cpuid_7_0_ebx; uint32_t cpuid_apic_id; int cpuid_vendor_override; diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c index a24c228..18a3ea2 100644 --- a/target-i386/cpuid.c +++ b/target-i386/cpuid.c @@ -186,6 +186,8 @@ typedef struct x86_def_t { char model_id[48]; int vendor_override; uint32_t flags; + /* The feature bits on CPUID[EAX=7,ECX=0].EBX */ + uint32_t cpuid_7_0_ebx_features; } x86_def_t; #define I486_FEATURES (CPUID_FP87 | CPUID_VME | CPUID_PSE) @@ -445,6 +447,12 @@ static int cpu_x86_fill_host(x86_def_t *x86_cpu_def) x86_cpu_def->ext_features = ecx; x86_cpu_def->features = edx; + if (kvm_enabled() && x86_cpu_def->level >= 7) { + x86_cpu_def->cpuid_7_0_ebx_features = kvm_arch_get_supported_cpuid(kvm_state, 0x7, 0, R_EBX); + } else { + x86_cpu_def->cpuid_7_0_ebx_features = 0; + } + host_cpuid(0x80000000, 0, &eax, &ebx, &ecx, &edx); x86_cpu_def->xlevel = eax; @@ -786,6 +794,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model) env->cpuid_ext2_features = def->ext2_features; env->cpuid_xlevel = def->xlevel; env->cpuid_ext3_features = def->ext3_features; + env->cpuid_7_0_ebx = def->cpuid_7_0_ebx_features; env->cpuid_kvm_features = def->kvm_features; { const char *model_id = def->model_id; @@ -1073,12 +1082,12 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *edx = 0; break; case 7: - if (kvm_enabled()) { - KVMState *s = env->kvm_state; - *eax = kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EAX); - *ebx = kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EBX); - *ecx = kvm_arch_get_supported_cpuid(s, 0x7, 0, R_ECX); - *edx = kvm_arch_get_supported_cpuid(s, 0x7, 0, R_EDX); + /* Structured Extended Feature Flags Enumeration Leaf */ + if (count == 0) { + *eax = 0; /* Maximum ECX value for sub-leaves */ + *ebx = env->cpuid_7_0_ebx; /* Feature flags */ + *ecx = 0; /* Reserved */ + *edx = 0; /* Reserved */ } else { *eax = 0; *ebx = 0; -- 1.7.7.6