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