Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ e5cc6429

History | View | Annotate | Download (10.5 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
    qemu_put_be64s(f, &env->mcg_status);
158
    qemu_put_be64s(f, &env->mcg_ctl);
159
    for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
160
        qemu_put_be64s(f, &env->mce_banks[i]);
161
    }
162
    qemu_put_be64s(f, &env->tsc_aux);
163
 }
164

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

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

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

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

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

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

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

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

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

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

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

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

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

    
289
    qemu_get_sbe32s(f, &env->a20_mask);
290

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

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

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

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

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

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

    
357
    if (version_id >= 11) {
358
        qemu_get_be64s(f, &env->tsc_aux);
359
    }
360

    
361
    tlb_flush(env, 1);
362
    return 0;
363
}