Blame SOURCES/kvm-target-i386-Populate-x86_ext_save_areas-offsets-usin.patch

e2f3ee
From ae580956fc0ed8feb794b6392df59ff5de673565 Mon Sep 17 00:00:00 2001
e2f3ee
From: David Edmondson <david.edmondson@oracle.com>
e2f3ee
Date: Mon, 5 Jul 2021 11:46:31 +0100
e2f3ee
Subject: [PATCH 7/7] target/i386: Populate x86_ext_save_areas offsets using
e2f3ee
 cpuid where possible
e2f3ee
e2f3ee
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
e2f3ee
RH-MergeRequest: 113: non-av 8.5z: Fix XSAVE on newer CPUs
e2f3ee
RH-Commit: [7/7] 145fc1dd5232673e2070423a027cad38fa4c4890
e2f3ee
RH-Bugzilla: 2065239
e2f3ee
RH-Acked-by: Jon Maloy <jmaloy@redhat.com>
e2f3ee
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
e2f3ee
RH-Acked-by: Bandan Das <None>
e2f3ee
e2f3ee
Rather than relying on the X86XSaveArea structure definition,
e2f3ee
determine the offset of XSAVE state areas using CPUID leaf 0xd where
e2f3ee
possible (KVM and HVF).
e2f3ee
e2f3ee
Signed-off-by: David Edmondson <david.edmondson@oracle.com>
e2f3ee
Message-Id: <20210705104632.2902400-8-david.edmondson@oracle.com>
e2f3ee
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
e2f3ee
(cherry picked from commit fea4500841024195ec701713e05b92ebf667f192)
e2f3ee
   dgilbert: Hairy backport, since we've not got Claudio's cpu
e2f3ee
accelerator split
e2f3ee
---
e2f3ee
 target/i386/cpu.c     | 65 +++++++++++++++++++++++++++++++++++--------
e2f3ee
 target/i386/cpu.h     |  2 +-
e2f3ee
 target/i386/hvf/hvf.c | 17 ++++-------
e2f3ee
 target/i386/kvm.c     |  7 +++++
e2f3ee
 4 files changed, 66 insertions(+), 25 deletions(-)
e2f3ee
e2f3ee
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
e2f3ee
index a030030299..c52eae1f0d 100644
e2f3ee
--- a/target/i386/cpu.c
e2f3ee
+++ b/target/i386/cpu.c
e2f3ee
@@ -1504,48 +1504,37 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = {
e2f3ee
 };
e2f3ee
 #undef REGISTER
e2f3ee
 
e2f3ee
-const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
e2f3ee
+ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
e2f3ee
     [XSTATE_FP_BIT] = {
e2f3ee
         /* x87 FP state component is always enabled if XSAVE is supported */
e2f3ee
         .feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE,
e2f3ee
-        /* x87 state is in the legacy region of the XSAVE area */
e2f3ee
-        .offset = 0,
e2f3ee
         .size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader),
e2f3ee
     },
e2f3ee
     [XSTATE_SSE_BIT] = {
e2f3ee
         /* SSE state component is always enabled if XSAVE is supported */
e2f3ee
         .feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE,
e2f3ee
-        /* SSE state is in the legacy region of the XSAVE area */
e2f3ee
-        .offset = 0,
e2f3ee
         .size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader),
e2f3ee
     },
e2f3ee
     [XSTATE_YMM_BIT] =
e2f3ee
           { .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX,
e2f3ee
-            .offset = offsetof(X86XSaveArea, avx_state),
e2f3ee
             .size = sizeof(XSaveAVX) },
e2f3ee
     [XSTATE_BNDREGS_BIT] =
e2f3ee
           { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
e2f3ee
-            .offset = offsetof(X86XSaveArea, bndreg_state),
e2f3ee
             .size = sizeof(XSaveBNDREG)  },
e2f3ee
     [XSTATE_BNDCSR_BIT] =
e2f3ee
           { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
e2f3ee
-            .offset = offsetof(X86XSaveArea, bndcsr_state),
e2f3ee
             .size = sizeof(XSaveBNDCSR)  },
e2f3ee
     [XSTATE_OPMASK_BIT] =
e2f3ee
           { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
e2f3ee
-            .offset = offsetof(X86XSaveArea, opmask_state),
e2f3ee
             .size = sizeof(XSaveOpmask) },
e2f3ee
     [XSTATE_ZMM_Hi256_BIT] =
e2f3ee
           { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
e2f3ee
-            .offset = offsetof(X86XSaveArea, zmm_hi256_state),
e2f3ee
             .size = sizeof(XSaveZMM_Hi256) },
e2f3ee
     [XSTATE_Hi16_ZMM_BIT] =
e2f3ee
           { .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
e2f3ee
-            .offset = offsetof(X86XSaveArea, hi16_zmm_state),
e2f3ee
             .size = sizeof(XSaveHi16_ZMM) },
e2f3ee
     [XSTATE_PKRU_BIT] =
e2f3ee
           { .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU,
e2f3ee
-            .offset = offsetof(X86XSaveArea, pkru_state),
e2f3ee
             .size = sizeof(XSavePKRU) },
e2f3ee
 };
e2f3ee
 
e2f3ee
@@ -5237,6 +5226,52 @@ static void x86_cpu_apply_version_props(X86CPU *cpu, X86CPUModel *model)
e2f3ee
     assert(vdef->version == version);
e2f3ee
 }
e2f3ee
 
e2f3ee
+static void kvm_cpu_xsave_init(void)
e2f3ee
+{
e2f3ee
+    static bool first = true;
e2f3ee
+    KVMState *s = kvm_state;
e2f3ee
+    int i;
e2f3ee
+
e2f3ee
+    if (!first) {
e2f3ee
+        return;
e2f3ee
+    }
e2f3ee
+    first = false;
e2f3ee
+
e2f3ee
+    /* x87 and SSE states are in the legacy region of the XSAVE area. */
e2f3ee
+    x86_ext_save_areas[XSTATE_FP_BIT].offset = 0;
e2f3ee
+    x86_ext_save_areas[XSTATE_SSE_BIT].offset = 0;
e2f3ee
+
e2f3ee
+    for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) {
e2f3ee
+        ExtSaveArea *esa = &x86_ext_save_areas[i];
e2f3ee
+
e2f3ee
+        if (esa->size) {
e2f3ee
+            int sz = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EAX);
e2f3ee
+            if (sz != 0) {
e2f3ee
+                assert(esa->size == sz);
e2f3ee
+                esa->offset = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EBX);
e2f3ee
+            }
e2f3ee
+        }
e2f3ee
+    }
e2f3ee
+}
e2f3ee
+
e2f3ee
+static void tcg_cpu_xsave_init(void)
e2f3ee
+{
e2f3ee
+#define XO(bit, field) \
e2f3ee
+    x86_ext_save_areas[bit].offset = offsetof(X86XSaveArea, field);
e2f3ee
+
e2f3ee
+    XO(XSTATE_FP_BIT, legacy);
e2f3ee
+    XO(XSTATE_SSE_BIT, legacy);
e2f3ee
+    XO(XSTATE_YMM_BIT, avx_state);
e2f3ee
+    XO(XSTATE_BNDREGS_BIT, bndreg_state);
e2f3ee
+    XO(XSTATE_BNDCSR_BIT, bndcsr_state);
e2f3ee
+    XO(XSTATE_OPMASK_BIT, opmask_state);
e2f3ee
+    XO(XSTATE_ZMM_Hi256_BIT, zmm_hi256_state);
e2f3ee
+    XO(XSTATE_Hi16_ZMM_BIT, hi16_zmm_state);
e2f3ee
+    XO(XSTATE_PKRU_BIT, pkru_state);
e2f3ee
+
e2f3ee
+#undef XO
e2f3ee
+}
e2f3ee
+
e2f3ee
 /* Load data from X86CPUDefinition into a X86CPU object
e2f3ee
  */
e2f3ee
 static void x86_cpu_load_model(X86CPU *cpu, X86CPUModel *model, Error **errp)
e2f3ee
@@ -7147,6 +7182,12 @@ static void x86_cpu_initfn(Object *obj)
e2f3ee
     if (xcc->model) {
e2f3ee
         x86_cpu_load_model(cpu, xcc->model, &error_abort);
e2f3ee
     }
e2f3ee
+
e2f3ee
+    if (kvm_enabled()) {
e2f3ee
+        kvm_cpu_xsave_init();
e2f3ee
+    } else if (tcg_enabled()) {
e2f3ee
+        tcg_cpu_xsave_init();
e2f3ee
+    }
e2f3ee
 }
e2f3ee
 
e2f3ee
 static int64_t x86_cpu_get_arch_id(CPUState *cs)
e2f3ee
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
e2f3ee
index cff2914203..53895a97dd 100644
e2f3ee
--- a/target/i386/cpu.h
e2f3ee
+++ b/target/i386/cpu.h
e2f3ee
@@ -1344,7 +1344,7 @@ typedef struct ExtSaveArea {
e2f3ee
 
e2f3ee
 #define XSAVE_STATE_AREA_COUNT (XSTATE_PKRU_BIT + 1)
e2f3ee
 
e2f3ee
-extern const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT];
e2f3ee
+extern ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT];
e2f3ee
 
e2f3ee
 typedef enum TPRAccess {
e2f3ee
     TPR_ACCESS_READ,
e2f3ee
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
e2f3ee
index bbede52fb7..de29137bec 100644
e2f3ee
--- a/target/i386/hvf/hvf.c
e2f3ee
+++ b/target/i386/hvf/hvf.c
e2f3ee
@@ -612,18 +612,11 @@ int hvf_init_vcpu(CPUState *cpu)
e2f3ee
     x86cpu->env.xsave_buf_len = 4096;
e2f3ee
     x86cpu->env.xsave_buf = qemu_memalign(4096, x86cpu->env.xsave_buf_len);
e2f3ee
 
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_STAR, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_LSTAR, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_CSTAR, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_FMASK, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_FSBASE, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_GSBASE, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_KERNELGSBASE, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_TSC_AUX, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_TSC, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_CS, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_EIP, 1);
e2f3ee
-    hv_vcpu_enable_native_msr(cpu->hvf_fd, MSR_IA32_SYSENTER_ESP, 1);
e2f3ee
+    /*
e2f3ee
+     * The allocated storage must be large enough for all of the
e2f3ee
+     * possible XSAVE state components.
e2f3ee
+     */
e2f3ee
+    assert(hvf_get_supported_cpuid(0xd, 0, R_ECX) <= x86cpu->env.xsave_buf_len);
e2f3ee
 
e2f3ee
     return 0;
e2f3ee
 }
e2f3ee
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
e2f3ee
index 8167587445..548c5e94bb 100644
e2f3ee
--- a/target/i386/kvm.c
e2f3ee
+++ b/target/i386/kvm.c
e2f3ee
@@ -1829,6 +1829,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
e2f3ee
         env->xsave_buf_len = sizeof(struct kvm_xsave);
e2f3ee
         env->xsave_buf = qemu_memalign(4096, env->xsave_buf_len);
e2f3ee
         memset(env->xsave_buf, 0, env->xsave_buf_len);
e2f3ee
+
e2f3ee
+        /*
e2f3ee
+         * The allocated storage must be large enough for all of the
e2f3ee
+         * possible XSAVE state components.
e2f3ee
+         */
e2f3ee
+        assert(kvm_arch_get_supported_cpuid(kvm_state, 0xd, 0, R_ECX)
e2f3ee
+               <= env->xsave_buf_len);
e2f3ee
     }
e2f3ee
 
e2f3ee
     max_nested_state_len = kvm_max_nested_state_length();
e2f3ee
-- 
e2f3ee
2.27.0
e2f3ee