9ae3a8
From 5fcaf5176d7545518c76f3aa8ea7ce6fb063c62d Mon Sep 17 00:00:00 2001
9ae3a8
From: Eduardo Habkost <ehabkost@redhat.com>
9ae3a8
Date: Wed, 6 Jul 2016 20:47:52 +0200
9ae3a8
Subject: [PATCH 1/2] target-i386: add feature flags for CPUID[EAX=0xd, ECX=1]
9ae3a8
9ae3a8
RH-Author: Eduardo Habkost <ehabkost@redhat.com>
9ae3a8
Message-id: <1467838073-23873-2-git-send-email-ehabkost@redhat.com>
9ae3a8
Patchwork-id: 71051
9ae3a8
O-Subject: [RHEL-7.3 qemu-kvm PATCH 1/2] target-i386: add feature flags for CPUID[EAX=0xd, ECX=1]
9ae3a8
Bugzilla: 1327599
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
9ae3a8
RH-Acked-by: Bandan Das <bsd@redhat.com>
9ae3a8
9ae3a8
From: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
9ae3a8
These represent xsave-related capabilities of the processor, and KVM may
9ae3a8
or may not support them.
9ae3a8
9ae3a8
Add feature bits so that they are considered by "-cpu ...,enforce", and use
9ae3a8
the new feature work instead of calling kvm_arch_get_supported_cpuid.
9ae3a8
9ae3a8
Bit 3 (XSAVES) is not migratables because it requires saving MSR_IA32_XSS.
9ae3a8
Neither KVM nor any commonly available hardware supports it anyway.
9ae3a8
9ae3a8
RHEL backport notes:
9ae3a8
* In addition to allowing xsave flags to be configured, this
9ae3a8
  patch is a bug fix because we shouldn't use
9ae3a8
  kvm_arch_supported_cpuid() directly when configuring CPUID for
9ae3a8
  the guest
9ae3a8
* tcg_features didn't exist, handle it inside x86_cpu_realizefn()
9ae3a8
  directly in the !kvm_enabled() check
9ae3a8
* As the unmigratable_flags mechanism is not present yet,
9ae3a8
  remove the "xsaves" flag name so it can't be enabled manually
9ae3a8
  (otherwise we would need to backport upstream commit
9ae3a8
  18cd2c17b5370369a886155c001da0a7f54bbcca too)
9ae3a8
9ae3a8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
(cherry picked from commit 0bb0b2d2fe7f645ddaf1f0ff40ac669c9feb4aa1)
9ae3a8
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 target-i386/cpu.c | 28 +++++++++++++++++++++++++++-
9ae3a8
 target-i386/cpu.h |  6 ++++++
9ae3a8
 2 files changed, 33 insertions(+), 1 deletion(-)
9ae3a8
9ae3a8
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
9ae3a8
index 06efe17..6650c72 100644
9ae3a8
--- a/target-i386/cpu.c
9ae3a8
+++ b/target-i386/cpu.c
9ae3a8
@@ -150,6 +150,17 @@ static const char *cpuid_7_0_ebx_feature_name[] = {
9ae3a8
     NULL, NULL, "avx512pf", "avx512er", "avx512cd", NULL, NULL, NULL,
9ae3a8
 };
9ae3a8
 
9ae3a8
+static const char *cpuid_xsave_feature_name[] = {
9ae3a8
+    "xsaveopt", "xsavec", "xgetbv1", NULL,
9ae3a8
+    NULL, NULL, NULL, NULL,
9ae3a8
+    NULL, NULL, NULL, NULL,
9ae3a8
+    NULL, NULL, NULL, NULL,
9ae3a8
+    NULL, NULL, NULL, NULL,
9ae3a8
+    NULL, NULL, NULL, NULL,
9ae3a8
+    NULL, NULL, NULL, NULL,
9ae3a8
+    NULL, NULL, NULL, NULL,
9ae3a8
+};
9ae3a8
+
9ae3a8
 typedef struct FeatureWordInfo {
9ae3a8
     const char **feat_names;
9ae3a8
     uint32_t cpuid_eax;   /* Input EAX for CPUID */
9ae3a8
@@ -193,6 +204,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
9ae3a8
         .cpuid_needs_ecx = true, .cpuid_ecx = 0,
9ae3a8
         .cpuid_reg = R_EBX,
9ae3a8
     },
9ae3a8
+    [FEAT_XSAVE] = {
9ae3a8
+        .feat_names = cpuid_xsave_feature_name,
9ae3a8
+        .cpuid_eax = 0xd,
9ae3a8
+        .cpuid_needs_ecx = true, .cpuid_ecx = 1,
9ae3a8
+        .cpuid_reg = R_EAX,
9ae3a8
+    },
9ae3a8
 };
9ae3a8
 
9ae3a8
 typedef struct X86RegisterInfo32 {
9ae3a8
@@ -833,6 +850,8 @@ static x86_def_t builtin_x86_defs[] = {
9ae3a8
              CPUID_EXT2_SYSCALL,
9ae3a8
         .features[FEAT_8000_0001_ECX] =
9ae3a8
             CPUID_EXT3_LAHF_LM,
9ae3a8
+        .features[FEAT_XSAVE] =
9ae3a8
+            CPUID_XSAVE_XSAVEOPT,
9ae3a8
         .xlevel = 0x8000000A,
9ae3a8
         .model_id = "Intel Xeon E312xx (Sandy Bridge)",
9ae3a8
     },
9ae3a8
@@ -866,6 +885,8 @@ static x86_def_t builtin_x86_defs[] = {
9ae3a8
             CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP |
9ae3a8
             CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
9ae3a8
             CPUID_7_0_EBX_RTM,
9ae3a8
+        .features[FEAT_XSAVE] =
9ae3a8
+            CPUID_XSAVE_XSAVEOPT,
9ae3a8
         .xlevel = 0x8000000A,
9ae3a8
         .model_id = "Intel Core Processor (Haswell)",
9ae3a8
     },
9ae3a8
@@ -900,6 +921,8 @@ static x86_def_t builtin_x86_defs[] = {
9ae3a8
             CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID |
9ae3a8
             CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
9ae3a8
             CPUID_7_0_EBX_SMAP,
9ae3a8
+        .features[FEAT_XSAVE] =
9ae3a8
+            CPUID_XSAVE_XSAVEOPT,
9ae3a8
         .xlevel = 0x8000000A,
9ae3a8
         .model_id = "Intel Core Processor (Broadwell)",
9ae3a8
     },
9ae3a8
@@ -1017,6 +1040,7 @@ static x86_def_t builtin_x86_defs[] = {
9ae3a8
              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
9ae3a8
              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
9ae3a8
              CPUID_EXT3_LAHF_LM,
9ae3a8
+        /* no xsaveopt! */
9ae3a8
         .xlevel = 0x8000001A,
9ae3a8
         .model_id = "AMD Opteron 62xx class CPU",
9ae3a8
     },
9ae3a8
@@ -1051,6 +1075,7 @@ static x86_def_t builtin_x86_defs[] = {
9ae3a8
              CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_MISALIGNSSE |
9ae3a8
              CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | CPUID_EXT3_SVM |
9ae3a8
              CPUID_EXT3_LAHF_LM,
9ae3a8
+        /* no xsaveopt! */
9ae3a8
         .xlevel = 0x8000001A,
9ae3a8
         .model_id = "AMD Opteron 63xx class CPU",
9ae3a8
     },
9ae3a8
@@ -2196,7 +2221,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
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
+            *eax = env->features[FEAT_XSAVE];
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
@@ -2540,6 +2565,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
9ae3a8
             );
9ae3a8
         env->features[FEAT_8000_0001_ECX] &= TCG_EXT3_FEATURES;
9ae3a8
         env->features[FEAT_SVM] &= TCG_SVM_FEATURES;
9ae3a8
+        env->features[FEAT_XSAVE] = 0;
9ae3a8
     } else {
9ae3a8
         if ((cpu->check_cpuid || cpu->enforce_cpuid)
9ae3a8
             && kvm_check_features_against_host(cpu) && cpu->enforce_cpuid) {
9ae3a8
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
9ae3a8
index 61e9b86..da7e060 100644
9ae3a8
--- a/target-i386/cpu.h
9ae3a8
+++ b/target-i386/cpu.h
9ae3a8
@@ -405,6 +405,7 @@ typedef enum FeatureWord {
9ae3a8
     FEAT_C000_0001_EDX, /* CPUID[C000_0001].EDX */
9ae3a8
     FEAT_KVM,           /* CPUID[4000_0001].EAX (KVM_CPUID_FEATURES) */
9ae3a8
     FEAT_SVM,           /* CPUID[8000_000A].EDX */
9ae3a8
+    FEAT_XSAVE,         /* CPUID[EAX=0xd,ECX=1].EAX */
9ae3a8
     FEATURE_WORDS,
9ae3a8
 } FeatureWord;
9ae3a8
 
9ae3a8
@@ -565,6 +566,11 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
9ae3a8
 #define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and Reciprocal */
9ae3a8
 #define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */
9ae3a8
 
9ae3a8
+#define CPUID_XSAVE_XSAVEOPT   (1U << 0)
9ae3a8
+#define CPUID_XSAVE_XSAVEC     (1U << 1)
9ae3a8
+#define CPUID_XSAVE_XGETBV1    (1U << 2)
9ae3a8
+#define CPUID_XSAVE_XSAVES     (1U << 3)
9ae3a8
+
9ae3a8
 #define CPUID_VENDOR_SZ      12
9ae3a8
 
9ae3a8
 #define CPUID_VENDOR_INTEL_1 0x756e6547 /* "Genu" */
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8