From 1a92e9ba72edd6386d35cf4894b7b83ea3279cff Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 5 Nov 2013 15:10:44 +0100 Subject: [PATCH 53/81] x86: cpuid: reconstruct leaf 0Dh data RH-Author: Paolo Bonzini Message-id: <1383664244-14818-3-git-send-email-pbonzini@redhat.com> Patchwork-id: 55409 O-Subject: [RHEL 7.0 qemu-kvm PATCH 2/2] x86: cpuid: reconstruct leaf 0Dh data Bugzilla: 1005695 RH-Acked-by: Alex Williamson RH-Acked-by: Orit Wasserman RH-Acked-by: Eduardo Habkost The data in leaf 0Dh depends on information from other feature bits. Instead of passing it blindly from the host, compute it based on whether these feature bits are enabled. Signed-off-by: Paolo Bonzini Signed-off-by: Gleb Natapov (cherry picked from commit 2560f19f426aceb4f2e809d860b93e7573cb1c4e) --- target-i386/cpu.c | 65 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 17 deletions(-) Signed-off-by: Miroslav Rezanina --- target-i386/cpu.c | 65 +++++++++++++++++++++++++++++++++++++++-------------- 1 files changed, 48 insertions(+), 17 deletions(-) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index bc077ca..42105aa 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -218,6 +218,15 @@ X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { }; #undef REGISTER +typedef struct ExtSaveArea { + uint32_t feature, bits; + uint32_t offset, size; +} ExtSaveArea; + +static const ExtSaveArea ext_save_areas[] = { + [2] = { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX, + .offset = 0x100, .size = 0x240 }, +}; const char *get_register_name_32(unsigned int reg) { @@ -2061,29 +2070,51 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, *edx = 0; } break; - case 0xD: + case 0xD: { + KVMState *s = cs->kvm_state; + uint64_t kvm_mask; + int i; + /* Processor Extended State */ - if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; + *eax = 0; + *ebx = 0; + *ecx = 0; + *edx = 0; + if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE) || !kvm_enabled()) { break; } - if (kvm_enabled()) { - KVMState *s = cs->kvm_state; + kvm_mask = + kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EAX) | + ((uint64_t)kvm_arch_get_supported_cpuid(s, 0xd, 0, R_EDX) << 32); - *eax = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EAX); - *ebx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EBX); - *ecx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_ECX); - *edx = kvm_arch_get_supported_cpuid(s, 0xd, count, R_EDX); - } else { - *eax = 0; - *ebx = 0; - *ecx = 0; - *edx = 0; + if (count == 0) { + *ecx = 0x240; + for (i = 2; i < ARRAY_SIZE(ext_save_areas); i++) { + const ExtSaveArea *esa = &ext_save_areas[i]; + if ((env->features[esa->feature] & esa->bits) == esa->bits && + (kvm_mask & (1 << i)) != 0) { + if (i < 32) { + *eax |= 1 << i; + } else { + *edx |= 1 << (i - 32); + } + *ecx = MAX(*ecx, esa->offset + esa->size); + } + } + *eax |= kvm_mask & (XSTATE_FP | XSTATE_SSE); + *ebx = *ecx; + } else if (count == 1) { + *eax = kvm_arch_get_supported_cpuid(s, 0xd, 1, R_EAX); + } else if (count < ARRAY_SIZE(ext_save_areas)) { + const ExtSaveArea *esa = &ext_save_areas[count]; + if ((env->features[esa->feature] & esa->bits) == esa->bits && + (kvm_mask & (1 << count)) != 0) { + *eax = esa->offset; + *ebx = esa->size; + } } break; + } case 0x80000000: *eax = env->cpuid_xlevel; *ebx = env->cpuid_vendor1; -- 1.7.1