|
|
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 |
|