@@ -1304,48 +1304,37 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = {
};
#undef REGISTER
-const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
+ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = {
[XSTATE_FP_BIT] = {
/* x87 FP state component is always enabled if XSAVE is supported */
.feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE,
- /* x87 state is in the legacy region of the XSAVE area */
- .offset = 0,
.size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader),
},
[XSTATE_SSE_BIT] = {
/* SSE state component is always enabled if XSAVE is supported */
.feature = FEAT_1_ECX, .bits = CPUID_EXT_XSAVE,
- /* SSE state is in the legacy region of the XSAVE area */
- .offset = 0,
.size = sizeof(X86LegacyXSaveArea) + sizeof(X86XSaveHeader),
},
[XSTATE_YMM_BIT] =
{ .feature = FEAT_1_ECX, .bits = CPUID_EXT_AVX,
- .offset = offsetof(X86XSaveArea, avx_state),
.size = sizeof(XSaveAVX) },
[XSTATE_BNDREGS_BIT] =
{ .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
- .offset = offsetof(X86XSaveArea, bndreg_state),
.size = sizeof(XSaveBNDREG) },
[XSTATE_BNDCSR_BIT] =
{ .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_MPX,
- .offset = offsetof(X86XSaveArea, bndcsr_state),
.size = sizeof(XSaveBNDCSR) },
[XSTATE_OPMASK_BIT] =
{ .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
- .offset = offsetof(X86XSaveArea, opmask_state),
.size = sizeof(XSaveOpmask) },
[XSTATE_ZMM_Hi256_BIT] =
{ .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
- .offset = offsetof(X86XSaveArea, zmm_hi256_state),
.size = sizeof(XSaveZMM_Hi256) },
[XSTATE_Hi16_ZMM_BIT] =
{ .feature = FEAT_7_0_EBX, .bits = CPUID_7_0_EBX_AVX512F,
- .offset = offsetof(X86XSaveArea, hi16_zmm_state),
.size = sizeof(XSaveHi16_ZMM) },
[XSTATE_PKRU_BIT] =
{ .feature = FEAT_7_0_ECX, .bits = CPUID_7_0_ECX_PKU,
- .offset = offsetof(X86XSaveArea, pkru_state),
.size = sizeof(XSavePKRU) },
};
@@ -1377,7 +1377,7 @@ typedef struct ExtSaveArea {
#define XSAVE_STATE_AREA_COUNT (XSTATE_PKRU_BIT + 1)
-extern const ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT];
+extern ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT];
typedef enum TPRAccess {
TPR_ACCESS_READ,
@@ -30,6 +30,38 @@ static void hvf_cpu_max_instance_init(X86CPU *cpu)
hvf_get_supported_cpuid(0xC0000000, 0, R_EAX);
}
+static void hvf_cpu_xsave_init(void)
+{
+ int i;
+
+ /*
+ * The allocated storage must be large enough for all of the
+ * possible XSAVE state components.
+ */
+ assert(hvf_get_supported_cpuid(0xd, 0, R_ECX) <= 4096);
+
+ /* x87 state is in the legacy region of the XSAVE area. */
+ x86_ext_save_areas[XSTATE_FP_BIT].offset = 0;
+ /* SSE state is in the legacy region of the XSAVE area. */
+ x86_ext_save_areas[XSTATE_SSE_BIT].offset = 0;
+
+ for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) {
+ ExtSaveArea *esa = &x86_ext_save_areas[i];
+
+ if (esa->size) {
+ int sz = hvf_get_supported_cpuid(0xd, i, R_EAX);
+
+ if (sz != 0) {
+ assert(esa->size == sz);
+
+ esa->offset = hvf_get_supported_cpuid(0xd, i, R_EBX);
+ fprintf(stderr, "%s: state area %d: offset 0x%x, size 0x%x\n",
+ __func__, i, esa->offset, esa->size);
+ }
+ }
+ }
+}
+
static void hvf_cpu_instance_init(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -42,6 +74,8 @@ static void hvf_cpu_instance_init(CPUState *cs)
if (cpu->max_features) {
hvf_cpu_max_instance_init(cpu);
}
+
+ hvf_cpu_xsave_init();
}
static void hvf_cpu_accel_class_init(ObjectClass *oc, void *data)
@@ -122,6 +122,40 @@ static void kvm_cpu_max_instance_init(X86CPU *cpu)
kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
}
+static void kvm_cpu_xsave_init(void)
+{
+ KVMState *s = kvm_state;
+ int i;
+
+ /*
+ * The allocated storage must be large enough for all of the
+ * possible XSAVE state components.
+ */
+ assert(sizeof(struct kvm_xsave) >=
+ kvm_arch_get_supported_cpuid(s, 0xd, 0, R_ECX));
+
+ /* x87 state is in the legacy region of the XSAVE area. */
+ x86_ext_save_areas[XSTATE_FP_BIT].offset = 0;
+ /* SSE state is in the legacy region of the XSAVE area. */
+ x86_ext_save_areas[XSTATE_SSE_BIT].offset = 0;
+
+ for (i = XSTATE_SSE_BIT + 1; i < XSAVE_STATE_AREA_COUNT; i++) {
+ ExtSaveArea *esa = &x86_ext_save_areas[i];
+
+ if (esa->size) {
+ int sz = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EAX);
+
+ if (sz != 0) {
+ assert(esa->size == sz);
+
+ esa->offset = kvm_arch_get_supported_cpuid(s, 0xd, i, R_EBX);
+ fprintf(stderr, "%s: state area %d: offset 0x%x, size 0x%x\n",
+ __func__, i, esa->offset, esa->size);
+ }
+ }
+ }
+}
+
static void kvm_cpu_instance_init(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -141,6 +175,8 @@ static void kvm_cpu_instance_init(CPUState *cs)
if (cpu->max_features) {
kvm_cpu_max_instance_init(cpu);
}
+
+ kvm_cpu_xsave_init();
}
static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data)
@@ -80,6 +80,24 @@ static void tcg_cpu_class_init(CPUClass *cc)
cc->init_accel_cpu = tcg_cpu_init_ops;
}
+static void tcg_cpu_xsave_init(void)
+{
+#define XO(bit, field) \
+ x86_ext_save_areas[bit].offset = offsetof(X86XSaveArea, field);
+
+ XO(XSTATE_FP_BIT, legacy);
+ XO(XSTATE_SSE_BIT, legacy);
+ XO(XSTATE_YMM_BIT, avx_state);
+ XO(XSTATE_BNDREGS_BIT, bndreg_state);
+ XO(XSTATE_BNDCSR_BIT, bndcsr_state);
+ XO(XSTATE_OPMASK_BIT, opmask_state);
+ XO(XSTATE_ZMM_Hi256_BIT, zmm_hi256_state);
+ XO(XSTATE_Hi16_ZMM_BIT, hi16_zmm_state);
+ XO(XSTATE_PKRU_BIT, pkru_state);
+
+#undef XO
+}
+
/*
* TCG-specific defaults that override all CPU models when using TCG
*/
@@ -93,6 +111,8 @@ static void tcg_cpu_instance_init(CPUState *cs)
X86CPU *cpu = X86_CPU(cs);
/* Special cases not set in the X86CPUDefinition structs: */
x86_cpu_apply_props(cpu, tcg_default_props);
+
+ tcg_cpu_xsave_init();
}
static void tcg_cpu_accel_class_init(ObjectClass *oc, void *data)
Rather than relying on the X86XSaveArea structure definition, determine the offset of XSAVE state areas using CPUID leaf 0xd where possible (KVM and HVF). Signed-off-by: David Edmondson <david.edmondson@oracle.com> --- target/i386/cpu.c | 13 +------------ target/i386/cpu.h | 2 +- target/i386/hvf/hvf-cpu.c | 34 ++++++++++++++++++++++++++++++++++ target/i386/kvm/kvm-cpu.c | 36 ++++++++++++++++++++++++++++++++++++ target/i386/tcg/tcg-cpu.c | 20 ++++++++++++++++++++ 5 files changed, 92 insertions(+), 13 deletions(-)