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