|
|
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 |
|