Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ b0a46a33

History | View | Annotate | Download (9.2 kB)

1 8dd3dca3 aurel32
#include "hw/hw.h"
2 8dd3dca3 aurel32
#include "hw/boards.h"
3 8dd3dca3 aurel32
#include "hw/pc.h"
4 8dd3dca3 aurel32
#include "hw/isa.h"
5 8dd3dca3 aurel32
6 8dd3dca3 aurel32
#include "exec-all.h"
7 b0a46a33 Jan Kiszka
#include "kvm.h"
8 8dd3dca3 aurel32
9 8dd3dca3 aurel32
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
10 8dd3dca3 aurel32
{
11 8dd3dca3 aurel32
    qemu_put_be32(f, dt->selector);
12 8dd3dca3 aurel32
    qemu_put_betl(f, dt->base);
13 8dd3dca3 aurel32
    qemu_put_be32(f, dt->limit);
14 8dd3dca3 aurel32
    qemu_put_be32(f, dt->flags);
15 8dd3dca3 aurel32
}
16 8dd3dca3 aurel32
17 8dd3dca3 aurel32
static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
18 8dd3dca3 aurel32
{
19 8dd3dca3 aurel32
    dt->selector = qemu_get_be32(f);
20 8dd3dca3 aurel32
    dt->base = qemu_get_betl(f);
21 8dd3dca3 aurel32
    dt->limit = qemu_get_be32(f);
22 8dd3dca3 aurel32
    dt->flags = qemu_get_be32(f);
23 8dd3dca3 aurel32
}
24 8dd3dca3 aurel32
25 8dd3dca3 aurel32
void cpu_save(QEMUFile *f, void *opaque)
26 8dd3dca3 aurel32
{
27 8dd3dca3 aurel32
    CPUState *env = opaque;
28 8dd3dca3 aurel32
    uint16_t fptag, fpus, fpuc, fpregs_format;
29 8dd3dca3 aurel32
    uint32_t hflags;
30 7caa33f7 aurel32
    int32_t a20_mask;
31 8dd3dca3 aurel32
    int i;
32 8dd3dca3 aurel32
33 b0a46a33 Jan Kiszka
    cpu_synchronize_state(env, 0);
34 b0a46a33 Jan Kiszka
35 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++)
36 8dd3dca3 aurel32
        qemu_put_betls(f, &env->regs[i]);
37 8dd3dca3 aurel32
    qemu_put_betls(f, &env->eip);
38 8dd3dca3 aurel32
    qemu_put_betls(f, &env->eflags);
39 8dd3dca3 aurel32
    hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
40 8dd3dca3 aurel32
    qemu_put_be32s(f, &hflags);
41 8dd3dca3 aurel32
42 8dd3dca3 aurel32
    /* FPU */
43 8dd3dca3 aurel32
    fpuc = env->fpuc;
44 8dd3dca3 aurel32
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
45 8dd3dca3 aurel32
    fptag = 0;
46 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
47 8dd3dca3 aurel32
        fptag |= ((!env->fptags[i]) << i);
48 8dd3dca3 aurel32
    }
49 8dd3dca3 aurel32
50 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpuc);
51 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpus);
52 8dd3dca3 aurel32
    qemu_put_be16s(f, &fptag);
53 8dd3dca3 aurel32
54 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
55 8dd3dca3 aurel32
    fpregs_format = 0;
56 8dd3dca3 aurel32
#else
57 8dd3dca3 aurel32
    fpregs_format = 1;
58 8dd3dca3 aurel32
#endif
59 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpregs_format);
60 8dd3dca3 aurel32
61 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
62 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
63 8dd3dca3 aurel32
        {
64 8dd3dca3 aurel32
            uint64_t mant;
65 8dd3dca3 aurel32
            uint16_t exp;
66 8dd3dca3 aurel32
            /* we save the real CPU data (in case of MMX usage only 'mant'
67 8dd3dca3 aurel32
               contains the MMX register */
68 8dd3dca3 aurel32
            cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
69 8dd3dca3 aurel32
            qemu_put_be64(f, mant);
70 8dd3dca3 aurel32
            qemu_put_be16(f, exp);
71 8dd3dca3 aurel32
        }
72 8dd3dca3 aurel32
#else
73 8dd3dca3 aurel32
        /* if we use doubles for float emulation, we save the doubles to
74 8dd3dca3 aurel32
           avoid losing information in case of MMX usage. It can give
75 8dd3dca3 aurel32
           problems if the image is restored on a CPU where long
76 8dd3dca3 aurel32
           doubles are used instead. */
77 8dd3dca3 aurel32
        qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
78 8dd3dca3 aurel32
#endif
79 8dd3dca3 aurel32
    }
80 8dd3dca3 aurel32
81 8dd3dca3 aurel32
    for(i = 0; i < 6; i++)
82 8dd3dca3 aurel32
        cpu_put_seg(f, &env->segs[i]);
83 8dd3dca3 aurel32
    cpu_put_seg(f, &env->ldt);
84 8dd3dca3 aurel32
    cpu_put_seg(f, &env->tr);
85 8dd3dca3 aurel32
    cpu_put_seg(f, &env->gdt);
86 8dd3dca3 aurel32
    cpu_put_seg(f, &env->idt);
87 8dd3dca3 aurel32
88 f5049756 aliguori
    qemu_put_be32s(f, &env->sysenter_cs);
89 2436b61a balrog
    qemu_put_betls(f, &env->sysenter_esp);
90 2436b61a balrog
    qemu_put_betls(f, &env->sysenter_eip);
91 8dd3dca3 aurel32
92 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[0]);
93 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[2]);
94 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[3]);
95 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[4]);
96 8dd3dca3 aurel32
97 8dd3dca3 aurel32
    for(i = 0; i < 8; i++)
98 8dd3dca3 aurel32
        qemu_put_betls(f, &env->dr[i]);
99 8dd3dca3 aurel32
100 8dd3dca3 aurel32
    /* MMU */
101 7caa33f7 aurel32
    a20_mask = (int32_t) env->a20_mask;
102 b6c4f71f blueswir1
    qemu_put_sbe32s(f, &a20_mask);
103 8dd3dca3 aurel32
104 8dd3dca3 aurel32
    /* XMM */
105 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->mxcsr);
106 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++) {
107 8dd3dca3 aurel32
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
108 8dd3dca3 aurel32
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
109 8dd3dca3 aurel32
    }
110 8dd3dca3 aurel32
111 8dd3dca3 aurel32
#ifdef TARGET_X86_64
112 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->efer);
113 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->star);
114 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->lstar);
115 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->cstar);
116 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->fmask);
117 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->kernelgsbase);
118 8dd3dca3 aurel32
#endif
119 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->smbase);
120 5cc1d1e6 bellard
121 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->pat);
122 5cc1d1e6 bellard
    qemu_put_be32s(f, &env->hflags2);
123 5cc1d1e6 bellard
    
124 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->vm_hsave);
125 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->vm_vmcb);
126 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->tsc_offset);
127 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->intercept);
128 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_cr_read);
129 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_cr_write);
130 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_dr_read);
131 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_dr_write);
132 5cc1d1e6 bellard
    qemu_put_be32s(f, &env->intercept_exceptions);
133 5cc1d1e6 bellard
    qemu_put_8s(f, &env->v_tpr);
134 dd5e3b17 aliguori
135 dd5e3b17 aliguori
    /* MTRRs */
136 dd5e3b17 aliguori
    for(i = 0; i < 11; i++)
137 dd5e3b17 aliguori
        qemu_put_be64s(f, &env->mtrr_fixed[i]);
138 dd5e3b17 aliguori
    qemu_put_be64s(f, &env->mtrr_deftype);
139 dd5e3b17 aliguori
    for(i = 0; i < 8; i++) {
140 dd5e3b17 aliguori
        qemu_put_be64s(f, &env->mtrr_var[i].base);
141 dd5e3b17 aliguori
        qemu_put_be64s(f, &env->mtrr_var[i].mask);
142 dd5e3b17 aliguori
    }
143 8dd3dca3 aurel32
}
144 8dd3dca3 aurel32
145 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
146 8dd3dca3 aurel32
/* XXX: add that in a FPU generic layer */
147 8dd3dca3 aurel32
union x86_longdouble {
148 8dd3dca3 aurel32
    uint64_t mant;
149 8dd3dca3 aurel32
    uint16_t exp;
150 8dd3dca3 aurel32
};
151 8dd3dca3 aurel32
152 8dd3dca3 aurel32
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
153 8dd3dca3 aurel32
#define EXPBIAS1 1023
154 8dd3dca3 aurel32
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
155 8dd3dca3 aurel32
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
156 8dd3dca3 aurel32
157 8dd3dca3 aurel32
static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
158 8dd3dca3 aurel32
{
159 8dd3dca3 aurel32
    int e;
160 8dd3dca3 aurel32
    /* mantissa */
161 8dd3dca3 aurel32
    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
162 8dd3dca3 aurel32
    /* exponent + sign */
163 8dd3dca3 aurel32
    e = EXPD1(temp) - EXPBIAS1 + 16383;
164 8dd3dca3 aurel32
    e |= SIGND1(temp) >> 16;
165 8dd3dca3 aurel32
    p->exp = e;
166 8dd3dca3 aurel32
}
167 8dd3dca3 aurel32
#endif
168 8dd3dca3 aurel32
169 8dd3dca3 aurel32
int cpu_load(QEMUFile *f, void *opaque, int version_id)
170 8dd3dca3 aurel32
{
171 8dd3dca3 aurel32
    CPUState *env = opaque;
172 8dd3dca3 aurel32
    int i, guess_mmx;
173 8dd3dca3 aurel32
    uint32_t hflags;
174 8dd3dca3 aurel32
    uint16_t fpus, fpuc, fptag, fpregs_format;
175 7caa33f7 aurel32
    int32_t a20_mask;
176 8dd3dca3 aurel32
177 9656f324 pbrook
    if (version_id != 3 && version_id != 4 && version_id != 5
178 dd5e3b17 aliguori
        && version_id != 6 && version_id != 7 && version_id != 8)
179 8dd3dca3 aurel32
        return -EINVAL;
180 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++)
181 8dd3dca3 aurel32
        qemu_get_betls(f, &env->regs[i]);
182 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eip);
183 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eflags);
184 8dd3dca3 aurel32
    qemu_get_be32s(f, &hflags);
185 8dd3dca3 aurel32
186 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpuc);
187 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpus);
188 8dd3dca3 aurel32
    qemu_get_be16s(f, &fptag);
189 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpregs_format);
190 8dd3dca3 aurel32
191 8dd3dca3 aurel32
    /* NOTE: we cannot always restore the FPU state if the image come
192 8dd3dca3 aurel32
       from a host with a different 'USE_X86LDOUBLE' define. We guess
193 8dd3dca3 aurel32
       if we are in an MMX state to restore correctly in that case. */
194 8dd3dca3 aurel32
    guess_mmx = ((fptag == 0xff) && (fpus & 0x3800) == 0);
195 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
196 8dd3dca3 aurel32
        uint64_t mant;
197 8dd3dca3 aurel32
        uint16_t exp;
198 8dd3dca3 aurel32
199 8dd3dca3 aurel32
        switch(fpregs_format) {
200 8dd3dca3 aurel32
        case 0:
201 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
202 8dd3dca3 aurel32
            exp = qemu_get_be16(f);
203 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
204 8dd3dca3 aurel32
            env->fpregs[i].d = cpu_set_fp80(mant, exp);
205 8dd3dca3 aurel32
#else
206 8dd3dca3 aurel32
            /* difficult case */
207 8dd3dca3 aurel32
            if (guess_mmx)
208 8dd3dca3 aurel32
                env->fpregs[i].mmx.MMX_Q(0) = mant;
209 8dd3dca3 aurel32
            else
210 8dd3dca3 aurel32
                env->fpregs[i].d = cpu_set_fp80(mant, exp);
211 8dd3dca3 aurel32
#endif
212 8dd3dca3 aurel32
            break;
213 8dd3dca3 aurel32
        case 1:
214 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
215 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
216 8dd3dca3 aurel32
            {
217 8dd3dca3 aurel32
                union x86_longdouble *p;
218 8dd3dca3 aurel32
                /* difficult case */
219 8dd3dca3 aurel32
                p = (void *)&env->fpregs[i];
220 8dd3dca3 aurel32
                if (guess_mmx) {
221 8dd3dca3 aurel32
                    p->mant = mant;
222 8dd3dca3 aurel32
                    p->exp = 0xffff;
223 8dd3dca3 aurel32
                } else {
224 8dd3dca3 aurel32
                    fp64_to_fp80(p, mant);
225 8dd3dca3 aurel32
                }
226 8dd3dca3 aurel32
            }
227 8dd3dca3 aurel32
#else
228 8dd3dca3 aurel32
            env->fpregs[i].mmx.MMX_Q(0) = mant;
229 8dd3dca3 aurel32
#endif
230 8dd3dca3 aurel32
            break;
231 8dd3dca3 aurel32
        default:
232 8dd3dca3 aurel32
            return -EINVAL;
233 8dd3dca3 aurel32
        }
234 8dd3dca3 aurel32
    }
235 8dd3dca3 aurel32
236 8dd3dca3 aurel32
    env->fpuc = fpuc;
237 8dd3dca3 aurel32
    /* XXX: restore FPU round state */
238 8dd3dca3 aurel32
    env->fpstt = (fpus >> 11) & 7;
239 8dd3dca3 aurel32
    env->fpus = fpus & ~0x3800;
240 8dd3dca3 aurel32
    fptag ^= 0xff;
241 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
242 8dd3dca3 aurel32
        env->fptags[i] = (fptag >> i) & 1;
243 8dd3dca3 aurel32
    }
244 8dd3dca3 aurel32
245 8dd3dca3 aurel32
    for(i = 0; i < 6; i++)
246 8dd3dca3 aurel32
        cpu_get_seg(f, &env->segs[i]);
247 8dd3dca3 aurel32
    cpu_get_seg(f, &env->ldt);
248 8dd3dca3 aurel32
    cpu_get_seg(f, &env->tr);
249 8dd3dca3 aurel32
    cpu_get_seg(f, &env->gdt);
250 8dd3dca3 aurel32
    cpu_get_seg(f, &env->idt);
251 8dd3dca3 aurel32
252 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->sysenter_cs);
253 2436b61a balrog
    if (version_id >= 7) {
254 2436b61a balrog
        qemu_get_betls(f, &env->sysenter_esp);
255 2436b61a balrog
        qemu_get_betls(f, &env->sysenter_eip);
256 2436b61a balrog
    } else {
257 e5ceb244 aliguori
        env->sysenter_esp = qemu_get_be32(f);
258 e5ceb244 aliguori
        env->sysenter_eip = qemu_get_be32(f);
259 2436b61a balrog
    }
260 8dd3dca3 aurel32
261 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[0]);
262 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[2]);
263 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[3]);
264 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[4]);
265 8dd3dca3 aurel32
266 8dd3dca3 aurel32
    for(i = 0; i < 8; i++)
267 8dd3dca3 aurel32
        qemu_get_betls(f, &env->dr[i]);
268 01df040b aliguori
    cpu_breakpoint_remove_all(env, BP_CPU);
269 01df040b aliguori
    cpu_watchpoint_remove_all(env, BP_CPU);
270 01df040b aliguori
    for (i = 0; i < 4; i++)
271 01df040b aliguori
        hw_breakpoint_insert(env, i);
272 8dd3dca3 aurel32
273 8dd3dca3 aurel32
    /* MMU */
274 b6c4f71f blueswir1
    qemu_get_sbe32s(f, &a20_mask);
275 7caa33f7 aurel32
    env->a20_mask = a20_mask;
276 8dd3dca3 aurel32
277 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->mxcsr);
278 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++) {
279 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
280 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
281 8dd3dca3 aurel32
    }
282 8dd3dca3 aurel32
283 8dd3dca3 aurel32
#ifdef TARGET_X86_64
284 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->efer);
285 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->star);
286 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->lstar);
287 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->cstar);
288 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->fmask);
289 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->kernelgsbase);
290 8dd3dca3 aurel32
#endif
291 5cc1d1e6 bellard
    if (version_id >= 4) {
292 8dd3dca3 aurel32
        qemu_get_be32s(f, &env->smbase);
293 5cc1d1e6 bellard
    }
294 5cc1d1e6 bellard
    if (version_id >= 5) {
295 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->pat);
296 5cc1d1e6 bellard
        qemu_get_be32s(f, &env->hflags2);
297 9656f324 pbrook
        if (version_id < 6)
298 9656f324 pbrook
            qemu_get_be32s(f, &env->halted);
299 5cc1d1e6 bellard
300 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->vm_hsave);
301 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->vm_vmcb);
302 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->tsc_offset);
303 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->intercept);
304 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_cr_read);
305 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_cr_write);
306 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_dr_read);
307 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_dr_write);
308 5cc1d1e6 bellard
        qemu_get_be32s(f, &env->intercept_exceptions);
309 5cc1d1e6 bellard
        qemu_get_8s(f, &env->v_tpr);
310 5cc1d1e6 bellard
    }
311 dd5e3b17 aliguori
312 dd5e3b17 aliguori
    if (version_id >= 8) {
313 dd5e3b17 aliguori
        /* MTRRs */
314 dd5e3b17 aliguori
        for(i = 0; i < 11; i++)
315 dd5e3b17 aliguori
            qemu_get_be64s(f, &env->mtrr_fixed[i]);
316 dd5e3b17 aliguori
        qemu_get_be64s(f, &env->mtrr_deftype);
317 dd5e3b17 aliguori
        for(i = 0; i < 8; i++) {
318 dd5e3b17 aliguori
            qemu_get_be64s(f, &env->mtrr_var[i].base);
319 dd5e3b17 aliguori
            qemu_get_be64s(f, &env->mtrr_var[i].mask);
320 dd5e3b17 aliguori
        }
321 dd5e3b17 aliguori
    }
322 dd5e3b17 aliguori
323 5cc1d1e6 bellard
    /* XXX: ensure compatiblity for halted bit ? */
324 5cc1d1e6 bellard
    /* XXX: compute redundant hflags bits */
325 8dd3dca3 aurel32
    env->hflags = hflags;
326 8dd3dca3 aurel32
    tlb_flush(env, 1);
327 b0a46a33 Jan Kiszka
    cpu_synchronize_state(env, 1);
328 8dd3dca3 aurel32
    return 0;
329 8dd3dca3 aurel32
}