From 8a8d1ef278933a3c3a11f8d8c2985e0af71741b4 Mon Sep 17 00:00:00 2001 From: David Edmondson Date: Mon, 5 Jul 2021 11:46:28 +0100 Subject: [PATCH 4/7] target/i386: Pass buffer and length to XSAVE helper RH-Author: Dr. David Alan Gilbert RH-MergeRequest: 113: non-av 8.5z: Fix XSAVE on newer CPUs RH-Commit: [4/7] 77e093a6ed3928b9191b37faad3cb50b4bdd65e3 RH-Bugzilla: 2065239 RH-Acked-by: Jon Maloy RH-Acked-by: Paolo Bonzini RH-Acked-by: Bandan Das In preparation for removing assumptions about XSAVE area offsets, pass a buffer pointer and buffer length to the XSAVE helper functions. Signed-off-by: David Edmondson Message-Id: <20210705104632.2902400-5-david.edmondson@oracle.com> Signed-off-by: Paolo Bonzini (cherry picked from commit c0198c5f87b6db25712672292e01ab710d6ef631) dgilbert: Manual merge in target/i386/hvf/x86hvf.c --- target/i386/cpu.h | 5 +++-- target/i386/hvf/hvf.c | 3 ++- target/i386/hvf/x86hvf.c | 19 ++++++++----------- target/i386/kvm.c | 13 +++++++------ target/i386/xsave_helper.c | 17 +++++++++-------- 5 files changed, 29 insertions(+), 28 deletions(-) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index d586b5508d..8daa83a6a3 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1626,6 +1626,7 @@ typedef struct CPUX86State { int64_t user_tsc_khz; /* for sanity check only */ #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; @@ -2254,8 +2255,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 d72543dc31..bbede52fb7 100644 --- a/target/i386/hvf/hvf.c +++ b/target/i386/hvf/hvf.c @@ -609,7 +609,8 @@ int hvf_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 edefe5319a..7be0582f28 100644 --- a/target/i386/hvf/x86hvf.c +++ b/target/i386/hvf/x86hvf.c @@ -72,14 +72,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(); } } @@ -157,15 +155,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.c b/target/i386/kvm.c index 215487b17d..8167587445 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -1826,8 +1826,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(); @@ -2353,12 +2354,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); } @@ -2977,7 +2978,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) { @@ -2988,7 +2989,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 818115e7d2..b16c6ac0fe 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 - } -- 2.27.0