aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/i386/cpu.h5
-rw-r--r--target/i386/hvf/hvf.c3
-rw-r--r--target/i386/hvf/x86hvf.c19
-rw-r--r--target/i386/kvm/kvm.c13
-rw-r--r--target/i386/xsave_helper.c17
5 files changed, 29 insertions, 28 deletions
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 92f9ca2..ada2941 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1667,6 +1667,7 @@ typedef struct CPUX86State {
uint64_t apic_bus_freq;
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
void *xsave_buf;
+ uint32_t xsave_buf_len;
#endif
#if defined(CONFIG_KVM)
struct kvm_nested_state *nested_state;
@@ -2227,8 +2228,8 @@ void x86_cpu_dump_local_apic_state(CPUState *cs, int flags);
/* cpu.c */
bool cpu_is_bsp(X86CPU *cpu);
-void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf);
-void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf);
+void x86_cpu_xrstor_all_areas(X86CPU *cpu, const void *buf, uint32_t buflen);
+void x86_cpu_xsave_all_areas(X86CPU *cpu, void *buf, uint32_t buflen);
void x86_update_hflags(CPUX86State* env);
static inline bool hyperv_feat_enabled(X86CPU *cpu, int feat)
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index 346dbcc..e62e8df 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -267,7 +267,8 @@ int hvf_arch_init_vcpu(CPUState *cpu)
wvmcs(cpu->hvf->fd, VMCS_TPR_THRESHOLD, 0);
x86cpu = X86_CPU(cpu);
- x86cpu->env.xsave_buf = qemu_memalign(4096, 4096);
+ x86cpu->env.xsave_buf_len = 4096;
+ x86cpu->env.xsave_buf = qemu_memalign(4096, x86cpu->env.xsave_buf_len);
hv_vcpu_enable_native_msr(cpu->hvf->fd, MSR_STAR, 1);
hv_vcpu_enable_native_msr(cpu->hvf->fd, MSR_LSTAR, 1);
diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c
index 2ced2c2..05ec1bd 100644
--- a/target/i386/hvf/x86hvf.c
+++ b/target/i386/hvf/x86hvf.c
@@ -73,14 +73,12 @@ void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg)
void hvf_put_xsave(CPUState *cpu_state)
{
+ void *xsave = X86_CPU(cpu_state)->env.xsave_buf;
+ uint32_t xsave_len = X86_CPU(cpu_state)->env.xsave_buf_len;
- struct X86XSaveArea *xsave;
+ x86_cpu_xsave_all_areas(X86_CPU(cpu_state), xsave, xsave_len);
- xsave = X86_CPU(cpu_state)->env.xsave_buf;
-
- x86_cpu_xsave_all_areas(X86_CPU(cpu_state), xsave);
-
- if (hv_vcpu_write_fpstate(cpu_state->hvf->fd, (void*)xsave, 4096)) {
+ if (hv_vcpu_write_fpstate(cpu_state->hvf->fd, xsave, xsave_len)) {
abort();
}
}
@@ -158,15 +156,14 @@ void hvf_put_msrs(CPUState *cpu_state)
void hvf_get_xsave(CPUState *cpu_state)
{
- struct X86XSaveArea *xsave;
-
- xsave = X86_CPU(cpu_state)->env.xsave_buf;
+ void *xsave = X86_CPU(cpu_state)->env.xsave_buf;
+ uint32_t xsave_len = X86_CPU(cpu_state)->env.xsave_buf_len;
- if (hv_vcpu_read_fpstate(cpu_state->hvf->fd, (void*)xsave, 4096)) {
+ if (hv_vcpu_read_fpstate(cpu_state->hvf->fd, xsave, xsave_len)) {
abort();
}
- x86_cpu_xrstor_all_areas(X86_CPU(cpu_state), xsave);
+ x86_cpu_xrstor_all_areas(X86_CPU(cpu_state), xsave, xsave_len);
}
void hvf_get_segments(CPUState *cpu_state)
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 3ab1d71..41b0764 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -1888,8 +1888,9 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
if (has_xsave) {
- env->xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
- memset(env->xsave_buf, 0, sizeof(struct kvm_xsave));
+ 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);
}
max_nested_state_len = kvm_max_nested_state_length();
@@ -2469,12 +2470,12 @@ static int kvm_put_fpu(X86CPU *cpu)
static int kvm_put_xsave(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
- X86XSaveArea *xsave = env->xsave_buf;
+ void *xsave = env->xsave_buf;
if (!has_xsave) {
return kvm_put_fpu(cpu);
}
- x86_cpu_xsave_all_areas(cpu, xsave);
+ x86_cpu_xsave_all_areas(cpu, xsave, env->xsave_buf_len);
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave);
}
@@ -3119,7 +3120,7 @@ static int kvm_get_fpu(X86CPU *cpu)
static int kvm_get_xsave(X86CPU *cpu)
{
CPUX86State *env = &cpu->env;
- X86XSaveArea *xsave = env->xsave_buf;
+ void *xsave = env->xsave_buf;
int ret;
if (!has_xsave) {
@@ -3130,7 +3131,7 @@ static int kvm_get_xsave(X86CPU *cpu)
if (ret < 0) {
return ret;
}
- x86_cpu_xrstor_all_areas(cpu, xsave);
+ x86_cpu_xrstor_all_areas(cpu, xsave, env->xsave_buf_len);
return 0;
}
diff --git a/target/i386/xsave_helper.c b/target/i386/xsave_helper.c
index 818115e..b16c6ac 100644
--- a/target/i386/xsave_helper.c
+++ b/target/i386/xsave_helper.c
@@ -6,14 +6,16 @@
#include "cpu.h"
-void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf)
+void x86_cpu_xsave_all_areas(X86CPU *cpu, void *buf, uint32_t buflen)
{
CPUX86State *env = &cpu->env;
X86XSaveArea *xsave = buf;
-
uint16_t cwd, swd, twd;
int i;
- memset(xsave, 0, sizeof(X86XSaveArea));
+
+ assert(buflen >= sizeof(*xsave));
+
+ memset(xsave, 0, buflen);
twd = 0;
swd = env->fpus & ~(7 << 11);
swd |= (env->fpstt & 7) << 11;
@@ -56,17 +58,17 @@ void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf)
16 * sizeof env->xmm_regs[16]);
memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru);
#endif
-
}
-void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf)
+void x86_cpu_xrstor_all_areas(X86CPU *cpu, const void *buf, uint32_t buflen)
{
-
CPUX86State *env = &cpu->env;
const X86XSaveArea *xsave = buf;
-
int i;
uint16_t cwd, swd, twd;
+
+ assert(buflen >= sizeof(*xsave));
+
cwd = xsave->legacy.fcw;
swd = xsave->legacy.fsw;
twd = xsave->legacy.ftw;
@@ -108,5 +110,4 @@ void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf)
16 * sizeof env->xmm_regs[16]);
memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru);
#endif
-
}