target-i386: kvm: Use X86XSaveArea struct for xsave save/load

Instead of using offset macros and bit operations in a uint32_t
array, use the X86XSaveArea struct to perform the loading/saving
operations in kvm_put_xsave() and kvm_get_xsave().

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
Eduardo Habkost 2015-11-23 10:43:26 -02:00
parent ee1b09f695
commit 86cd2ea071
1 changed files with 38 additions and 40 deletions

View File

@ -1333,9 +1333,8 @@ ASSERT_OFFSET(XSAVE_PKRU, pkru_state);
static int kvm_put_xsave(X86CPU *cpu) static int kvm_put_xsave(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
struct kvm_xsave* xsave = env->kvm_xsave_buf; X86XSaveArea *xsave = env->kvm_xsave_buf;
uint16_t cwd, swd, twd; uint16_t cwd, swd, twd;
uint8_t *xmm, *ymmh, *zmmh;
int i, r; int i, r;
if (!has_xsave) { if (!has_xsave) {
@ -1350,25 +1349,26 @@ static int kvm_put_xsave(X86CPU *cpu)
for (i = 0; i < 8; ++i) { for (i = 0; i < 8; ++i) {
twd |= (!env->fptags[i]) << i; twd |= (!env->fptags[i]) << i;
} }
xsave->region[XSAVE_FCW_FSW] = (uint32_t)(swd << 16) + cwd; xsave->legacy.fcw = cwd;
xsave->region[XSAVE_FTW_FOP] = (uint32_t)(env->fpop << 16) + twd; xsave->legacy.fsw = swd;
memcpy(&xsave->region[XSAVE_CWD_RIP], &env->fpip, sizeof(env->fpip)); xsave->legacy.ftw = twd;
memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp)); xsave->legacy.fpop = env->fpop;
memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs, xsave->legacy.fpip = env->fpip;
xsave->legacy.fpdp = env->fpdp;
memcpy(&xsave->legacy.fpregs, env->fpregs,
sizeof env->fpregs); sizeof env->fpregs);
xsave->region[XSAVE_MXCSR] = env->mxcsr; xsave->legacy.mxcsr = env->mxcsr;
*(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv; xsave->header.xstate_bv = env->xstate_bv;
memcpy(&xsave->region[XSAVE_BNDREGS], env->bnd_regs, memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs,
sizeof env->bnd_regs); sizeof env->bnd_regs);
memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs, xsave->bndcsr_state.bndcsr = env->bndcs_regs;
sizeof(env->bndcs_regs)); memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs,
memcpy(&xsave->region[XSAVE_OPMASK], env->opmask_regs,
sizeof env->opmask_regs); sizeof env->opmask_regs);
xmm = (uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; for (i = 0; i < CPU_NB_REGS; i++) {
ymmh = (uint8_t *)&xsave->region[XSAVE_YMMH_SPACE]; uint8_t *xmm = xsave->legacy.xmm_regs[i];
zmmh = (uint8_t *)&xsave->region[XSAVE_ZMM_Hi256]; uint8_t *ymmh = xsave->avx_state.ymmh[i];
for (i = 0; i < CPU_NB_REGS; i++, xmm += 16, ymmh += 16, zmmh += 32) { uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
stq_p(xmm, env->xmm_regs[i].ZMM_Q(0)); stq_p(xmm, env->xmm_regs[i].ZMM_Q(0));
stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1)); stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1));
stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2)); stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2));
@ -1380,9 +1380,9 @@ static int kvm_put_xsave(X86CPU *cpu)
} }
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
memcpy(&xsave->region[XSAVE_Hi16_ZMM], &env->xmm_regs[16], memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16],
16 * sizeof env->xmm_regs[16]); 16 * sizeof env->xmm_regs[16]);
memcpy(&xsave->region[XSAVE_PKRU], &env->pkru, sizeof env->pkru); memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru);
#endif #endif
r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave); r = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_XSAVE, xsave);
return r; return r;
@ -1771,9 +1771,8 @@ static int kvm_get_fpu(X86CPU *cpu)
static int kvm_get_xsave(X86CPU *cpu) static int kvm_get_xsave(X86CPU *cpu)
{ {
CPUX86State *env = &cpu->env; CPUX86State *env = &cpu->env;
struct kvm_xsave* xsave = env->kvm_xsave_buf; X86XSaveArea *xsave = env->kvm_xsave_buf;
int ret, i; int ret, i;
const uint8_t *xmm, *ymmh, *zmmh;
uint16_t cwd, swd, twd; uint16_t cwd, swd, twd;
if (!has_xsave) { if (!has_xsave) {
@ -1785,33 +1784,32 @@ static int kvm_get_xsave(X86CPU *cpu)
return ret; return ret;
} }
cwd = (uint16_t)xsave->region[XSAVE_FCW_FSW]; cwd = xsave->legacy.fcw;
swd = (uint16_t)(xsave->region[XSAVE_FCW_FSW] >> 16); swd = xsave->legacy.fsw;
twd = (uint16_t)xsave->region[XSAVE_FTW_FOP]; twd = xsave->legacy.ftw;
env->fpop = (uint16_t)(xsave->region[XSAVE_FTW_FOP] >> 16); env->fpop = xsave->legacy.fpop;
env->fpstt = (swd >> 11) & 7; env->fpstt = (swd >> 11) & 7;
env->fpus = swd; env->fpus = swd;
env->fpuc = cwd; env->fpuc = cwd;
for (i = 0; i < 8; ++i) { for (i = 0; i < 8; ++i) {
env->fptags[i] = !((twd >> i) & 1); env->fptags[i] = !((twd >> i) & 1);
} }
memcpy(&env->fpip, &xsave->region[XSAVE_CWD_RIP], sizeof(env->fpip)); env->fpip = xsave->legacy.fpip;
memcpy(&env->fpdp, &xsave->region[XSAVE_CWD_RDP], sizeof(env->fpdp)); env->fpdp = xsave->legacy.fpdp;
env->mxcsr = xsave->region[XSAVE_MXCSR]; env->mxcsr = xsave->legacy.mxcsr;
memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE], memcpy(env->fpregs, &xsave->legacy.fpregs,
sizeof env->fpregs); sizeof env->fpregs);
env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV]; env->xstate_bv = xsave->header.xstate_bv;
memcpy(env->bnd_regs, &xsave->region[XSAVE_BNDREGS], memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs,
sizeof env->bnd_regs); sizeof env->bnd_regs);
memcpy(&env->bndcs_regs, &xsave->region[XSAVE_BNDCSR], env->bndcs_regs = xsave->bndcsr_state.bndcsr;
sizeof(env->bndcs_regs)); memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs,
memcpy(env->opmask_regs, &xsave->region[XSAVE_OPMASK],
sizeof env->opmask_regs); sizeof env->opmask_regs);
xmm = (const uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; for (i = 0; i < CPU_NB_REGS; i++) {
ymmh = (const uint8_t *)&xsave->region[XSAVE_YMMH_SPACE]; uint8_t *xmm = xsave->legacy.xmm_regs[i];
zmmh = (const uint8_t *)&xsave->region[XSAVE_ZMM_Hi256]; uint8_t *ymmh = xsave->avx_state.ymmh[i];
for (i = 0; i < CPU_NB_REGS; i++, xmm += 16, ymmh += 16, zmmh += 32) { uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i];
env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm); env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm);
env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8); env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8);
env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh); env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh);
@ -1823,9 +1821,9 @@ static int kvm_get_xsave(X86CPU *cpu)
} }
#ifdef TARGET_X86_64 #ifdef TARGET_X86_64
memcpy(&env->xmm_regs[16], &xsave->region[XSAVE_Hi16_ZMM], memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm,
16 * sizeof env->xmm_regs[16]); 16 * sizeof env->xmm_regs[16]);
memcpy(&env->pkru, &xsave->region[XSAVE_PKRU], sizeof env->pkru); memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru);
#endif #endif
return 0; return 0;
} }