Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ 67b8f419

History | View | Annotate | Download (10.8 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
    uint16_t fptag, fpregs_format;
30
    int32_t pending_irq;
31
    int i, bit;
32

    
33
    cpu_synchronize_state(env);
34

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

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

    
48
    qemu_put_be16s(f, &env->fpuc);
49
    qemu_put_be16s(f, &env->fpus_vmstate);
50
    qemu_put_be16s(f, &fptag);
51

    
52
#ifdef USE_X86LDOUBLE
53
    fpregs_format = 0;
54
#else
55
    fpregs_format = 1;
56
#endif
57
    qemu_put_be16s(f, &fpregs_format);
58

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

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

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

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

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

    
98
    /* MMU */
99
    qemu_put_sbe32s(f, &env->a20_mask);
100

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

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

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

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

    
141
    /* KVM-related states */
142

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

    
157
    /* MCE */
158
    qemu_put_be64s(f, &env->mcg_cap);
159
    if (env->mcg_cap) {
160
        qemu_put_be64s(f, &env->mcg_status);
161
        qemu_put_be64s(f, &env->mcg_ctl);
162
        for (i = 0; i < (env->mcg_cap & 0xff); i++) {
163
            qemu_put_be64s(f, &env->mce_banks[4*i]);
164
            qemu_put_be64s(f, &env->mce_banks[4*i + 1]);
165
            qemu_put_be64s(f, &env->mce_banks[4*i + 2]);
166
            qemu_put_be64s(f, &env->mce_banks[4*i + 3]);
167
        }
168
    }
169
    qemu_put_be64s(f, &env->tsc_aux);
170
 }
171

    
172
#ifdef USE_X86LDOUBLE
173
/* XXX: add that in a FPU generic layer */
174
union x86_longdouble {
175
    uint64_t mant;
176
    uint16_t exp;
177
};
178

    
179
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
180
#define EXPBIAS1 1023
181
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
182
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
183

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

    
196
int cpu_load(QEMUFile *f, void *opaque, int version_id)
197
{
198
    CPUState *env = opaque;
199
    int i, guess_mmx;
200
    uint16_t fptag, fpregs_format;
201
    int32_t pending_irq;
202

    
203
    cpu_synchronize_state(env);
204
    if (version_id < 3 || version_id > CPU_SAVE_VERSION)
205
        return -EINVAL;
206
    for(i = 0; i < CPU_NB_REGS; i++)
207
        qemu_get_betls(f, &env->regs[i]);
208
    qemu_get_betls(f, &env->eip);
209
    qemu_get_betls(f, &env->eflags);
210
    qemu_get_be32s(f, &env->hflags);
211

    
212
    qemu_get_be16s(f, &env->fpuc);
213
    qemu_get_be16s(f, &env->fpus_vmstate);
214
    qemu_get_be16s(f, &fptag);
215
    qemu_get_be16s(f, &fpregs_format);
216

    
217
    /* NOTE: we cannot always restore the FPU state if the image come
218
       from a host with a different 'USE_X86LDOUBLE' define. We guess
219
       if we are in an MMX state to restore correctly in that case. */
220
    guess_mmx = ((fptag == 0xff) && (env->fpus_vmstate & 0x3800) == 0);
221
    for(i = 0; i < 8; i++) {
222
        uint64_t mant;
223
        uint16_t exp;
224

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

    
262
    /* XXX: restore FPU round state */
263
    env->fpstt = (env->fpus_vmstate >> 11) & 7;
264
    env->fpus = env->fpus_vmstate & ~0x3800;
265
    fptag ^= 0xff;
266
    for(i = 0; i < 8; i++) {
267
        env->fptags[i] = (fptag >> i) & 1;
268
    }
269

    
270
    for(i = 0; i < 6; i++)
271
        cpu_get_seg(f, &env->segs[i]);
272
    cpu_get_seg(f, &env->ldt);
273
    cpu_get_seg(f, &env->tr);
274
    cpu_get_seg(f, &env->gdt);
275
    cpu_get_seg(f, &env->idt);
276

    
277
    qemu_get_be32s(f, &env->sysenter_cs);
278
    if (version_id >= 7) {
279
        qemu_get_betls(f, &env->sysenter_esp);
280
        qemu_get_betls(f, &env->sysenter_eip);
281
    } else {
282
        env->sysenter_esp = qemu_get_be32(f);
283
        env->sysenter_eip = qemu_get_be32(f);
284
    }
285

    
286
    qemu_get_betls(f, &env->cr[0]);
287
    qemu_get_betls(f, &env->cr[2]);
288
    qemu_get_betls(f, &env->cr[3]);
289
    qemu_get_betls(f, &env->cr[4]);
290

    
291
    for(i = 0; i < 8; i++)
292
        qemu_get_betls(f, &env->dr[i]);
293
    cpu_breakpoint_remove_all(env, BP_CPU);
294
    cpu_watchpoint_remove_all(env, BP_CPU);
295
    for (i = 0; i < 4; i++)
296
        hw_breakpoint_insert(env, i);
297

    
298
    qemu_get_sbe32s(f, &env->a20_mask);
299

    
300
    qemu_get_be32s(f, &env->mxcsr);
301
    for(i = 0; i < CPU_NB_REGS; i++) {
302
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
303
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
304
    }
305

    
306
#ifdef TARGET_X86_64
307
    qemu_get_be64s(f, &env->efer);
308
    qemu_get_be64s(f, &env->star);
309
    qemu_get_be64s(f, &env->lstar);
310
    qemu_get_be64s(f, &env->cstar);
311
    qemu_get_be64s(f, &env->fmask);
312
    qemu_get_be64s(f, &env->kernelgsbase);
313
#endif
314
    if (version_id >= 4) {
315
        qemu_get_be32s(f, &env->smbase);
316
    }
317
    if (version_id >= 5) {
318
        qemu_get_be64s(f, &env->pat);
319
        qemu_get_be32s(f, &env->hflags2);
320
        if (version_id < 6)
321
            qemu_get_be32s(f, &env->halted);
322

    
323
        qemu_get_be64s(f, &env->vm_hsave);
324
        qemu_get_be64s(f, &env->vm_vmcb);
325
        qemu_get_be64s(f, &env->tsc_offset);
326
        qemu_get_be64s(f, &env->intercept);
327
        qemu_get_be16s(f, &env->intercept_cr_read);
328
        qemu_get_be16s(f, &env->intercept_cr_write);
329
        qemu_get_be16s(f, &env->intercept_dr_read);
330
        qemu_get_be16s(f, &env->intercept_dr_write);
331
        qemu_get_be32s(f, &env->intercept_exceptions);
332
        qemu_get_8s(f, &env->v_tpr);
333
    }
334

    
335
    if (version_id >= 8) {
336
        /* MTRRs */
337
        for(i = 0; i < 11; i++)
338
            qemu_get_be64s(f, &env->mtrr_fixed[i]);
339
        qemu_get_be64s(f, &env->mtrr_deftype);
340
        for(i = 0; i < 8; i++) {
341
            qemu_get_be64s(f, &env->mtrr_var[i].base);
342
            qemu_get_be64s(f, &env->mtrr_var[i].mask);
343
        }
344
    }
345

    
346
    if (version_id >= 9) {
347
        qemu_get_sbe32s(f, &pending_irq);
348
        memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap));
349
        if (pending_irq >= 0) {
350
            env->interrupt_bitmap[pending_irq / 64] |=
351
                (uint64_t)1 << (pending_irq % 64);
352
        }
353
        qemu_get_be32s(f, &env->mp_state);
354
        qemu_get_be64s(f, &env->tsc);
355
    }
356

    
357
    if (version_id >= 10) {
358
        qemu_get_be64s(f, &env->mcg_cap);
359
        if (env->mcg_cap) {
360
            qemu_get_be64s(f, &env->mcg_status);
361
            qemu_get_be64s(f, &env->mcg_ctl);
362
            for (i = 0; i < (env->mcg_cap & 0xff); i++) {
363
                qemu_get_be64s(f, &env->mce_banks[4*i]);
364
                qemu_get_be64s(f, &env->mce_banks[4*i + 1]);
365
                qemu_get_be64s(f, &env->mce_banks[4*i + 2]);
366
                qemu_get_be64s(f, &env->mce_banks[4*i + 3]);
367
            }
368
        }
369
    }
370

    
371
    if (version_id >= 11) {
372
        qemu_get_be64s(f, &env->tsc_aux);
373
    }
374

    
375
    tlb_flush(env, 1);
376
    return 0;
377
}