1be5c7
From ea5299b5dde7d0b6b2f93cb646e6a24c9f105466 Mon Sep 17 00:00:00 2001
1be5c7
From: Paolo Bonzini <pbonzini@redhat.com>
1be5c7
Date: Wed, 23 Mar 2022 12:33:25 +0100
1be5c7
Subject: [PATCH 13/24] KVM: x86: workaround invalid CPUID[0xD,9] info on some
1be5c7
 AMD processors
1be5c7
MIME-Version: 1.0
1be5c7
Content-Type: text/plain; charset=UTF-8
1be5c7
Content-Transfer-Encoding: 8bit
1be5c7
1be5c7
RH-Author: Paul Lai <plai@redhat.com>
1be5c7
RH-MergeRequest: 176: Enable KVM AMX support
1be5c7
RH-Commit: [13/13] 38f147c911258e84e01336271ebd23a1c24371fc
1be5c7
RH-Bugzilla: 1916415
1be5c7
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
1be5c7
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
1be5c7
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
1be5c7
1be5c7
Some AMD processors expose the PKRU extended save state even if they do not have
1be5c7
the related PKU feature in CPUID.  Worse, when they do they report a size of
1be5c7
64, whereas the expected size of the PKRU extended save state is 8, therefore
1be5c7
the esa->size == eax assertion does not hold.
1be5c7
1be5c7
The state is already ignored by KVM_GET_SUPPORTED_CPUID because it
1be5c7
was not enabled in the host XCR0.  However, QEMU kvm_cpu_xsave_init()
1be5c7
runs before QEMU invokes arch_prctl() to enable dynamically-enabled
1be5c7
save states such as XTILEDATA, and KVM_GET_SUPPORTED_CPUID hides save
1be5c7
states that have yet to be enabled.  Therefore, kvm_cpu_xsave_init()
1be5c7
needs to consult the host CPUID instead of KVM_GET_SUPPORTED_CPUID,
1be5c7
and dies with an assertion failure.
1be5c7
1be5c7
When setting up the ExtSaveArea array to match the host, ignore features that
1be5c7
KVM does not report as supported.  This will cause QEMU to skip the incorrect
1be5c7
CPUID leaf instead of tripping the assertion.
1be5c7
1be5c7
Closes: https://gitlab.com/qemu-project/qemu/-/issues/916
1be5c7
Reported-by: Daniel P. Berrangé <berrange@redhat.com>
1be5c7
Analyzed-by: Yang Zhong <yang.zhong@intel.com>
1be5c7
Reported-by: Peter Krempa <pkrempa@redhat.com>
1be5c7
Tested-by: Daniel P. Berrangé <berrange@redhat.com>
1be5c7
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1be5c7
(cherry picked from commit 58f7db26f21c690cf9a669c314cfd7371506084a)
1be5c7
Signed-off-by: Paul Lai <plai@redhat.com>
1be5c7
---
1be5c7
 target/i386/cpu.c         |  4 ++--
1be5c7
 target/i386/cpu.h         |  2 ++
1be5c7
 target/i386/kvm/kvm-cpu.c | 19 ++++++++++++-------
1be5c7
 3 files changed, 16 insertions(+), 9 deletions(-)
1be5c7
1be5c7
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
1be5c7
index 09e08f7f38..0543b846ff 100644
1be5c7
--- a/target/i386/cpu.c
1be5c7
+++ b/target/i386/cpu.c
1be5c7
@@ -4980,8 +4980,8 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
1be5c7
     return cpu_list;
1be5c7
 }
1be5c7
 
1be5c7
-static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
1be5c7
-                                                   bool migratable_only)
1be5c7
+uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
1be5c7
+                                            bool migratable_only)
1be5c7
 {
1be5c7
     FeatureWordInfo *wi = &feature_word_info[w];
1be5c7
     uint64_t r = 0;
1be5c7
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
1be5c7
index 8ab2a4042a..006b735fe4 100644
1be5c7
--- a/target/i386/cpu.h
1be5c7
+++ b/target/i386/cpu.h
1be5c7
@@ -604,6 +604,8 @@ typedef enum FeatureWord {
1be5c7
 } FeatureWord;
1be5c7
 
1be5c7
 typedef uint64_t FeatureWordArray[FEATURE_WORDS];
1be5c7
+uint64_t x86_cpu_get_supported_feature_word(FeatureWord w,
1be5c7
+                                            bool migratable_only);
1be5c7
 
1be5c7
 /* cpuid_features bits */
1be5c7
 #define CPUID_FP87 (1U << 0)
1be5c7
diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c
1be5c7
index bdc967c484..74c1396a93 100644
1be5c7
--- a/target/i386/kvm/kvm-cpu.c
1be5c7
+++ b/target/i386/kvm/kvm-cpu.c
1be5c7
@@ -99,13 +99,18 @@ static void kvm_cpu_xsave_init(void)
1be5c7
     for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) {
1be5c7
         ExtSaveArea *esa = &x86_ext_save_areas[i];
1be5c7
 
1be5c7
-        if (esa->size) {
1be5c7
-            host_cpuid(0xd, i, &eax, &ebx, &ecx, &edx;;
1be5c7
-            if (eax != 0) {
1be5c7
-                assert(esa->size == eax);
1be5c7
-                esa->offset = ebx;
1be5c7
-                esa->ecx = ecx;
1be5c7
-            }
1be5c7
+        if (!esa->size) {
1be5c7
+            continue;
1be5c7
+        }
1be5c7
+        if ((x86_cpu_get_supported_feature_word(esa->feature, false) & esa->bits)
1be5c7
+            != esa->bits) {
1be5c7
+            continue;
1be5c7
+        }
1be5c7
+        host_cpuid(0xd, i, &eax, &ebx, &ecx, &edx;;
1be5c7
+        if (eax != 0) {
1be5c7
+            assert(esa->size == eax);
1be5c7
+            esa->offset = ebx;
1be5c7
+            esa->ecx = ecx;
1be5c7
         }
1be5c7
     }
1be5c7
 }
1be5c7
-- 
1be5c7
2.35.3
1be5c7