aboutsummaryrefslogtreecommitdiff
path: root/target/i386/kvm
diff options
context:
space:
mode:
authorDavid Edmondson <david.edmondson@oracle.com>2021-07-05 11:46:31 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2021-07-06 08:33:48 +0200
commitfea4500841024195ec701713e05b92ebf667f192 (patch)
tree7901cb3679ee3b1177ff80493f874bade24d63ea /target/i386/kvm
parent3568987f78faff90829ea6c885bbdd5b083dc86c (diff)
target/i386: Populate x86_ext_save_areas offsets using cpuid where possible
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> Message-Id: <20210705104632.2902400-8-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'target/i386/kvm')
-rw-r--r--target/i386/kvm/kvm-cpu.c30
-rw-r--r--target/i386/kvm/kvm.c7
2 files changed, 37 insertions, 0 deletions
diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c
index 00369c2000..bbe817764d 100644
--- a/target/i386/kvm/kvm-cpu.c
+++ b/target/i386/kvm/kvm-cpu.c
@@ -122,6 +122,34 @@ 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)
+{
+ static bool first = true;
+ KVMState *s = kvm_state;
+ int i;
+
+ if (!first) {
+ return;
+ }
+ first = false;
+
+ /* x87 and SSE states are in the legacy region of the XSAVE area. */
+ x86_ext_save_areas[XSTATE_FP_BIT].offset = 0;
+ 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);
+ }
+ }
+ }
+}
+
static void kvm_cpu_instance_init(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -141,6 +169,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)
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 41b0764ab7..a85035492f 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1891,6 +1891,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
env->xsave_buf_len = sizeof(struct kvm_xsave);
env->xsave_buf = qemu_memalign(4096, env->xsave_buf_len);
memset(env->xsave_buf, 0, env->xsave_buf_len);
+
+ /*
+ * The allocated storage must be large enough for all of the
+ * possible XSAVE state components.
+ */
+ assert(kvm_arch_get_supported_cpuid(kvm_state, 0xd, 0, R_ECX)
+ <= env->xsave_buf_len);
}
max_nested_state_len = kvm_max_nested_state_length();