1 /* 2 * This work is licensed under the terms of the GNU GPL, version 2 or later. 3 * See the COPYING file in the top-level directory. 4 */ 5 #include "qemu/osdep.h" 6 #include "qapi/error.h" 7 8 #include "qemu-common.h" 9 #include "cpu.h" 10 11 void x86_cpu_xsave_all_areas(X86CPU *cpu, X86XSaveArea *buf) 12 { 13 CPUX86State *env = &cpu->env; 14 X86XSaveArea *xsave = buf; 15 16 uint16_t cwd, swd, twd; 17 int i; 18 memset(xsave, 0, sizeof(X86XSaveArea)); 19 twd = 0; 20 swd = env->fpus & ~(7 << 11); 21 swd |= (env->fpstt & 7) << 11; 22 cwd = env->fpuc; 23 for (i = 0; i < 8; ++i) { 24 twd |= (!env->fptags[i]) << i; 25 } 26 xsave->legacy.fcw = cwd; 27 xsave->legacy.fsw = swd; 28 xsave->legacy.ftw = twd; 29 xsave->legacy.fpop = env->fpop; 30 xsave->legacy.fpip = env->fpip; 31 xsave->legacy.fpdp = env->fpdp; 32 memcpy(&xsave->legacy.fpregs, env->fpregs, 33 sizeof env->fpregs); 34 xsave->legacy.mxcsr = env->mxcsr; 35 xsave->header.xstate_bv = env->xstate_bv; 36 memcpy(&xsave->bndreg_state.bnd_regs, env->bnd_regs, 37 sizeof env->bnd_regs); 38 xsave->bndcsr_state.bndcsr = env->bndcs_regs; 39 memcpy(&xsave->opmask_state.opmask_regs, env->opmask_regs, 40 sizeof env->opmask_regs); 41 42 for (i = 0; i < CPU_NB_REGS; i++) { 43 uint8_t *xmm = xsave->legacy.xmm_regs[i]; 44 uint8_t *ymmh = xsave->avx_state.ymmh[i]; 45 uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i]; 46 stq_p(xmm, env->xmm_regs[i].ZMM_Q(0)); 47 stq_p(xmm+8, env->xmm_regs[i].ZMM_Q(1)); 48 stq_p(ymmh, env->xmm_regs[i].ZMM_Q(2)); 49 stq_p(ymmh+8, env->xmm_regs[i].ZMM_Q(3)); 50 stq_p(zmmh, env->xmm_regs[i].ZMM_Q(4)); 51 stq_p(zmmh+8, env->xmm_regs[i].ZMM_Q(5)); 52 stq_p(zmmh+16, env->xmm_regs[i].ZMM_Q(6)); 53 stq_p(zmmh+24, env->xmm_regs[i].ZMM_Q(7)); 54 } 55 56 #ifdef TARGET_X86_64 57 memcpy(&xsave->hi16_zmm_state.hi16_zmm, &env->xmm_regs[16], 58 16 * sizeof env->xmm_regs[16]); 59 memcpy(&xsave->pkru_state, &env->pkru, sizeof env->pkru); 60 #endif 61 62 } 63 64 void x86_cpu_xrstor_all_areas(X86CPU *cpu, const X86XSaveArea *buf) 65 { 66 67 CPUX86State *env = &cpu->env; 68 const X86XSaveArea *xsave = buf; 69 70 int i; 71 uint16_t cwd, swd, twd; 72 cwd = xsave->legacy.fcw; 73 swd = xsave->legacy.fsw; 74 twd = xsave->legacy.ftw; 75 env->fpop = xsave->legacy.fpop; 76 env->fpstt = (swd >> 11) & 7; 77 env->fpus = swd; 78 env->fpuc = cwd; 79 for (i = 0; i < 8; ++i) { 80 env->fptags[i] = !((twd >> i) & 1); 81 } 82 env->fpip = xsave->legacy.fpip; 83 env->fpdp = xsave->legacy.fpdp; 84 env->mxcsr = xsave->legacy.mxcsr; 85 memcpy(env->fpregs, &xsave->legacy.fpregs, 86 sizeof env->fpregs); 87 env->xstate_bv = xsave->header.xstate_bv; 88 memcpy(env->bnd_regs, &xsave->bndreg_state.bnd_regs, 89 sizeof env->bnd_regs); 90 env->bndcs_regs = xsave->bndcsr_state.bndcsr; 91 memcpy(env->opmask_regs, &xsave->opmask_state.opmask_regs, 92 sizeof env->opmask_regs); 93 94 for (i = 0; i < CPU_NB_REGS; i++) { 95 const uint8_t *xmm = xsave->legacy.xmm_regs[i]; 96 const uint8_t *ymmh = xsave->avx_state.ymmh[i]; 97 const uint8_t *zmmh = xsave->zmm_hi256_state.zmm_hi256[i]; 98 env->xmm_regs[i].ZMM_Q(0) = ldq_p(xmm); 99 env->xmm_regs[i].ZMM_Q(1) = ldq_p(xmm+8); 100 env->xmm_regs[i].ZMM_Q(2) = ldq_p(ymmh); 101 env->xmm_regs[i].ZMM_Q(3) = ldq_p(ymmh+8); 102 env->xmm_regs[i].ZMM_Q(4) = ldq_p(zmmh); 103 env->xmm_regs[i].ZMM_Q(5) = ldq_p(zmmh+8); 104 env->xmm_regs[i].ZMM_Q(6) = ldq_p(zmmh+16); 105 env->xmm_regs[i].ZMM_Q(7) = ldq_p(zmmh+24); 106 } 107 108 #ifdef TARGET_X86_64 109 memcpy(&env->xmm_regs[16], &xsave->hi16_zmm_state.hi16_zmm, 110 16 * sizeof env->xmm_regs[16]); 111 memcpy(&env->pkru, &xsave->pkru_state, sizeof env->pkru); 112 #endif 113 114 } 115