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