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