Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ 496eb021

History | View | Annotate | Download (10.6 kB)

1
#include "hw/hw.h"
2
#include "hw/boards.h"
3
#include "hw/pc.h"
4
#include "hw/isa.h"
5
#include "host-utils.h"
6

    
7
#include "exec-all.h"
8
#include "kvm.h"
9

    
10
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
11
{
12
    qemu_put_be32(f, dt->selector);
13
    qemu_put_betl(f, dt->base);
14
    qemu_put_be32(f, dt->limit);
15
    qemu_put_be32(f, dt->flags);
16
}
17

    
18
static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
19
{
20
    dt->selector = qemu_get_be32(f);
21
    dt->base = qemu_get_betl(f);
22
    dt->limit = qemu_get_be32(f);
23
    dt->flags = qemu_get_be32(f);
24
}
25

    
26
void cpu_save(QEMUFile *f, void *opaque)
27
{
28
    CPUState *env = opaque;
29
    int i, bit;
30

    
31
    cpu_synchronize_state(env);
32

    
33
    for(i = 0; i < CPU_NB_REGS; i++)
34
        qemu_put_betls(f, &env->regs[i]);
35
    qemu_put_betls(f, &env->eip);
36
    qemu_put_betls(f, &env->eflags);
37
    qemu_put_be32s(f, &env->hflags);
38

    
39
    /* FPU */
40
    env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
41
    env->fptag_vmstate = 0;
42
    for(i = 0; i < 8; i++) {
43
        env->fptag_vmstate |= ((!env->fptags[i]) << i);
44
    }
45

    
46
    qemu_put_be16s(f, &env->fpuc);
47
    qemu_put_be16s(f, &env->fpus_vmstate);
48
    qemu_put_be16s(f, &env->fptag_vmstate);
49

    
50
#ifdef USE_X86LDOUBLE
51
    env->fpregs_format_vmstate = 0;
52
#else
53
    env->fpregs_format_vmstate = 1;
54
#endif
55
    qemu_put_be16s(f, &env->fpregs_format_vmstate);
56

    
57
    for(i = 0; i < 8; i++) {
58
#ifdef USE_X86LDOUBLE
59
        {
60
            uint64_t mant;
61
            uint16_t exp;
62
            /* we save the real CPU data (in case of MMX usage only 'mant'
63
               contains the MMX register */
64
            cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
65
            qemu_put_be64(f, mant);
66
            qemu_put_be16(f, exp);
67
        }
68
#else
69
        /* if we use doubles for float emulation, we save the doubles to
70
           avoid losing information in case of MMX usage. It can give
71
           problems if the image is restored on a CPU where long
72
           doubles are used instead. */
73
        qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
74
#endif
75
    }
76

    
77
    for(i = 0; i < 6; i++)
78
        cpu_put_seg(f, &env->segs[i]);
79
    cpu_put_seg(f, &env->ldt);
80
    cpu_put_seg(f, &env->tr);
81
    cpu_put_seg(f, &env->gdt);
82
    cpu_put_seg(f, &env->idt);
83

    
84
    qemu_put_be32s(f, &env->sysenter_cs);
85
    qemu_put_betls(f, &env->sysenter_esp);
86
    qemu_put_betls(f, &env->sysenter_eip);
87

    
88
    qemu_put_betls(f, &env->cr[0]);
89
    qemu_put_betls(f, &env->cr[2]);
90
    qemu_put_betls(f, &env->cr[3]);
91
    qemu_put_betls(f, &env->cr[4]);
92

    
93
    for(i = 0; i < 8; i++)
94
        qemu_put_betls(f, &env->dr[i]);
95

    
96
    /* MMU */
97
    qemu_put_sbe32s(f, &env->a20_mask);
98

    
99
    /* XMM */
100
    qemu_put_be32s(f, &env->mxcsr);
101
    for(i = 0; i < CPU_NB_REGS; i++) {
102
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
103
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
104
    }
105

    
106
#ifdef TARGET_X86_64
107
    qemu_put_be64s(f, &env->efer);
108
    qemu_put_be64s(f, &env->star);
109
    qemu_put_be64s(f, &env->lstar);
110
    qemu_put_be64s(f, &env->cstar);
111
    qemu_put_be64s(f, &env->fmask);
112
    qemu_put_be64s(f, &env->kernelgsbase);
113
#endif
114
    qemu_put_be32s(f, &env->smbase);
115

    
116
    qemu_put_be64s(f, &env->pat);
117
    qemu_put_be32s(f, &env->hflags2);
118
    
119
    qemu_put_be64s(f, &env->vm_hsave);
120
    qemu_put_be64s(f, &env->vm_vmcb);
121
    qemu_put_be64s(f, &env->tsc_offset);
122
    qemu_put_be64s(f, &env->intercept);
123
    qemu_put_be16s(f, &env->intercept_cr_read);
124
    qemu_put_be16s(f, &env->intercept_cr_write);
125
    qemu_put_be16s(f, &env->intercept_dr_read);
126
    qemu_put_be16s(f, &env->intercept_dr_write);
127
    qemu_put_be32s(f, &env->intercept_exceptions);
128
    qemu_put_8s(f, &env->v_tpr);
129

    
130
    /* MTRRs */
131
    for(i = 0; i < 11; i++)
132
        qemu_put_be64s(f, &env->mtrr_fixed[i]);
133
    qemu_put_be64s(f, &env->mtrr_deftype);
134
    for(i = 0; i < 8; i++) {
135
        qemu_put_be64s(f, &env->mtrr_var[i].base);
136
        qemu_put_be64s(f, &env->mtrr_var[i].mask);
137
    }
138

    
139
    /* KVM-related states */
140

    
141
    /* There can only be one pending IRQ set in the bitmap at a time, so try
142
       to find it and save its number instead (-1 for none). */
143
    env->pending_irq_vmstate = -1;
144
    for (i = 0; i < ARRAY_SIZE(env->interrupt_bitmap); i++) {
145
        if (env->interrupt_bitmap[i]) {
146
            bit = ctz64(env->interrupt_bitmap[i]);
147
            env->pending_irq_vmstate = i * 64 + bit;
148
            break;
149
        }
150
    }
151
    qemu_put_sbe32s(f, &env->pending_irq_vmstate);
152
    qemu_put_be32s(f, &env->mp_state);
153
    qemu_put_be64s(f, &env->tsc);
154

    
155
    /* MCE */
156
    qemu_put_be64s(f, &env->mcg_cap);
157
    if (env->mcg_cap) {
158
        qemu_put_be64s(f, &env->mcg_status);
159
        qemu_put_be64s(f, &env->mcg_ctl);
160
        for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
161
            qemu_put_be64s(f, &env->mce_banks[i]);
162
        }
163
    }
164
    qemu_put_be64s(f, &env->tsc_aux);
165
 }
166

    
167
#ifdef USE_X86LDOUBLE
168
/* XXX: add that in a FPU generic layer */
169
union x86_longdouble {
170
    uint64_t mant;
171
    uint16_t exp;
172
};
173

    
174
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
175
#define EXPBIAS1 1023
176
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
177
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
178

    
179
static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
180
{
181
    int e;
182
    /* mantissa */
183
    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
184
    /* exponent + sign */
185
    e = EXPD1(temp) - EXPBIAS1 + 16383;
186
    e |= SIGND1(temp) >> 16;
187
    p->exp = e;
188
}
189
#endif
190

    
191
int cpu_load(QEMUFile *f, void *opaque, int version_id)
192
{
193
    CPUState *env = opaque;
194
    int i, guess_mmx;
195

    
196
    cpu_synchronize_state(env);
197
    if (version_id < 3 || version_id > CPU_SAVE_VERSION)
198
        return -EINVAL;
199
    for(i = 0; i < CPU_NB_REGS; i++)
200
        qemu_get_betls(f, &env->regs[i]);
201
    qemu_get_betls(f, &env->eip);
202
    qemu_get_betls(f, &env->eflags);
203
    qemu_get_be32s(f, &env->hflags);
204

    
205
    qemu_get_be16s(f, &env->fpuc);
206
    qemu_get_be16s(f, &env->fpus_vmstate);
207
    qemu_get_be16s(f, &env->fptag_vmstate);
208
    qemu_get_be16s(f, &env->fpregs_format_vmstate);
209

    
210
    /* NOTE: we cannot always restore the FPU state if the image come
211
       from a host with a different 'USE_X86LDOUBLE' define. We guess
212
       if we are in an MMX state to restore correctly in that case. */
213
    guess_mmx = ((env->fptag_vmstate == 0xff) && (env->fpus_vmstate & 0x3800) == 0);
214
    for(i = 0; i < 8; i++) {
215
        uint64_t mant;
216
        uint16_t exp;
217

    
218
        switch(env->fpregs_format_vmstate) {
219
        case 0:
220
            mant = qemu_get_be64(f);
221
            exp = qemu_get_be16(f);
222
#ifdef USE_X86LDOUBLE
223
            env->fpregs[i].d = cpu_set_fp80(mant, exp);
224
#else
225
            /* difficult case */
226
            if (guess_mmx)
227
                env->fpregs[i].mmx.MMX_Q(0) = mant;
228
            else
229
                env->fpregs[i].d = cpu_set_fp80(mant, exp);
230
#endif
231
            break;
232
        case 1:
233
            mant = qemu_get_be64(f);
234
#ifdef USE_X86LDOUBLE
235
            {
236
                union x86_longdouble *p;
237
                /* difficult case */
238
                p = (void *)&env->fpregs[i];
239
                if (guess_mmx) {
240
                    p->mant = mant;
241
                    p->exp = 0xffff;
242
                } else {
243
                    fp64_to_fp80(p, mant);
244
                }
245
            }
246
#else
247
            env->fpregs[i].mmx.MMX_Q(0) = mant;
248
#endif
249
            break;
250
        default:
251
            return -EINVAL;
252
        }
253
    }
254

    
255
    /* XXX: restore FPU round state */
256
    env->fpstt = (env->fpus_vmstate >> 11) & 7;
257
    env->fpus = env->fpus_vmstate & ~0x3800;
258
    env->fptag_vmstate ^= 0xff;
259
    for(i = 0; i < 8; i++) {
260
        env->fptags[i] = (env->fptag_vmstate >> i) & 1;
261
    }
262

    
263
    for(i = 0; i < 6; i++)
264
        cpu_get_seg(f, &env->segs[i]);
265
    cpu_get_seg(f, &env->ldt);
266
    cpu_get_seg(f, &env->tr);
267
    cpu_get_seg(f, &env->gdt);
268
    cpu_get_seg(f, &env->idt);
269

    
270
    qemu_get_be32s(f, &env->sysenter_cs);
271
    if (version_id >= 7) {
272
        qemu_get_betls(f, &env->sysenter_esp);
273
        qemu_get_betls(f, &env->sysenter_eip);
274
    } else {
275
        env->sysenter_esp = qemu_get_be32(f);
276
        env->sysenter_eip = qemu_get_be32(f);
277
    }
278

    
279
    qemu_get_betls(f, &env->cr[0]);
280
    qemu_get_betls(f, &env->cr[2]);
281
    qemu_get_betls(f, &env->cr[3]);
282
    qemu_get_betls(f, &env->cr[4]);
283

    
284
    for(i = 0; i < 8; i++)
285
        qemu_get_betls(f, &env->dr[i]);
286
    cpu_breakpoint_remove_all(env, BP_CPU);
287
    cpu_watchpoint_remove_all(env, BP_CPU);
288
    for (i = 0; i < 4; i++)
289
        hw_breakpoint_insert(env, i);
290

    
291
    qemu_get_sbe32s(f, &env->a20_mask);
292

    
293
    qemu_get_be32s(f, &env->mxcsr);
294
    for(i = 0; i < CPU_NB_REGS; i++) {
295
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
296
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
297
    }
298

    
299
#ifdef TARGET_X86_64
300
    qemu_get_be64s(f, &env->efer);
301
    qemu_get_be64s(f, &env->star);
302
    qemu_get_be64s(f, &env->lstar);
303
    qemu_get_be64s(f, &env->cstar);
304
    qemu_get_be64s(f, &env->fmask);
305
    qemu_get_be64s(f, &env->kernelgsbase);
306
#endif
307
    if (version_id >= 4) {
308
        qemu_get_be32s(f, &env->smbase);
309
    }
310
    if (version_id >= 5) {
311
        qemu_get_be64s(f, &env->pat);
312
        qemu_get_be32s(f, &env->hflags2);
313
        if (version_id < 6)
314
            qemu_get_be32s(f, &env->halted);
315

    
316
        qemu_get_be64s(f, &env->vm_hsave);
317
        qemu_get_be64s(f, &env->vm_vmcb);
318
        qemu_get_be64s(f, &env->tsc_offset);
319
        qemu_get_be64s(f, &env->intercept);
320
        qemu_get_be16s(f, &env->intercept_cr_read);
321
        qemu_get_be16s(f, &env->intercept_cr_write);
322
        qemu_get_be16s(f, &env->intercept_dr_read);
323
        qemu_get_be16s(f, &env->intercept_dr_write);
324
        qemu_get_be32s(f, &env->intercept_exceptions);
325
        qemu_get_8s(f, &env->v_tpr);
326
    }
327

    
328
    if (version_id >= 8) {
329
        /* MTRRs */
330
        for(i = 0; i < 11; i++)
331
            qemu_get_be64s(f, &env->mtrr_fixed[i]);
332
        qemu_get_be64s(f, &env->mtrr_deftype);
333
        for(i = 0; i < 8; i++) {
334
            qemu_get_be64s(f, &env->mtrr_var[i].base);
335
            qemu_get_be64s(f, &env->mtrr_var[i].mask);
336
        }
337
    }
338

    
339
    if (version_id >= 9) {
340
        qemu_get_sbe32s(f, &env->pending_irq_vmstate);
341
        memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap));
342
        if (env->pending_irq_vmstate >= 0) {
343
            env->interrupt_bitmap[env->pending_irq_vmstate / 64] |=
344
                (uint64_t)1 << (env->pending_irq_vmstate % 64);
345
        }
346
        qemu_get_be32s(f, &env->mp_state);
347
        qemu_get_be64s(f, &env->tsc);
348
    }
349

    
350
    if (version_id >= 10) {
351
        qemu_get_be64s(f, &env->mcg_cap);
352
        if (env->mcg_cap) {
353
            qemu_get_be64s(f, &env->mcg_status);
354
            qemu_get_be64s(f, &env->mcg_ctl);
355
            for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
356
                qemu_get_be64s(f, &env->mce_banks[i]);
357
            }
358
        }
359
    }
360

    
361
    if (version_id >= 11) {
362
        qemu_get_be64s(f, &env->tsc_aux);
363
    }
364

    
365
    tlb_flush(env, 1);
366
    return 0;
367
}