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