Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ ac74d0f1

History | View | Annotate | Download (10.9 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; i++) {
161
            qemu_put_be64s(f, &env->mce_banks[4*i]);
162
            qemu_put_be64s(f, &env->mce_banks[4*i + 1]);
163
            qemu_put_be64s(f, &env->mce_banks[4*i + 2]);
164
            qemu_put_be64s(f, &env->mce_banks[4*i + 3]);
165
        }
166
    }
167
    qemu_put_be64s(f, &env->tsc_aux);
168
 }
169

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

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

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

    
194
int cpu_load(QEMUFile *f, void *opaque, int version_id)
195
{
196
    CPUState *env = opaque;
197
    int i, guess_mmx;
198

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

    
208
    qemu_get_be16s(f, &env->fpuc);
209
    qemu_get_be16s(f, &env->fpus_vmstate);
210
    qemu_get_be16s(f, &env->fptag_vmstate);
211
    qemu_get_be16s(f, &env->fpregs_format_vmstate);
212

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

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

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

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

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

    
282
    qemu_get_betls(f, &env->cr[0]);
283
    qemu_get_betls(f, &env->cr[2]);
284
    qemu_get_betls(f, &env->cr[3]);
285
    qemu_get_betls(f, &env->cr[4]);
286

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

    
294
    qemu_get_sbe32s(f, &env->a20_mask);
295

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

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

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

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

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

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

    
367
    if (version_id >= 11) {
368
        qemu_get_be64s(f, &env->tsc_aux);
369
    }
370

    
371
    tlb_flush(env, 1);
372
    return 0;
373
}