Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ 1f76b9b9

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
    uint16_t fptag, fpus, fpuc, fpregs_format;
30
    int32_t a20_mask;
31
    int32_t pending_irq;
32
    int i, bit;
33

    
34
    cpu_synchronize_state(env);
35

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

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

    
50
    qemu_put_be16s(f, &fpuc);
51
    qemu_put_be16s(f, &fpus);
52
    qemu_put_be16s(f, &fptag);
53

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

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

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

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

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

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

    
100
    /* MMU */
101
    a20_mask = (int32_t) env->a20_mask;
102
    qemu_put_sbe32s(f, &a20_mask);
103

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

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

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

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

    
144
    /* KVM-related states */
145

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

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

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

    
182
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
183
#define EXPBIAS1 1023
184
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
185
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
186

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

    
199
int cpu_load(QEMUFile *f, void *opaque, int version_id)
200
{
201
    CPUState *env = opaque;
202
    int i, guess_mmx;
203
    uint16_t fpus, fpuc, fptag, fpregs_format;
204
    int32_t a20_mask;
205
    int32_t pending_irq;
206

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

    
216
    qemu_get_be16s(f, &fpuc);
217
    qemu_get_be16s(f, &fpus);
218
    qemu_get_be16s(f, &fptag);
219
    qemu_get_be16s(f, &fpregs_format);
220

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

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

    
266
    env->fpuc = fpuc;
267
    /* XXX: restore FPU round state */
268
    env->fpstt = (fpus >> 11) & 7;
269
    env->fpus = fpus & ~0x3800;
270
    fptag ^= 0xff;
271
    for(i = 0; i < 8; i++) {
272
        env->fptags[i] = (fptag >> i) & 1;
273
    }
274

    
275
    for(i = 0; i < 6; i++)
276
        cpu_get_seg(f, &env->segs[i]);
277
    cpu_get_seg(f, &env->ldt);
278
    cpu_get_seg(f, &env->tr);
279
    cpu_get_seg(f, &env->gdt);
280
    cpu_get_seg(f, &env->idt);
281

    
282
    qemu_get_be32s(f, &env->sysenter_cs);
283
    if (version_id >= 7) {
284
        qemu_get_betls(f, &env->sysenter_esp);
285
        qemu_get_betls(f, &env->sysenter_eip);
286
    } else {
287
        env->sysenter_esp = qemu_get_be32(f);
288
        env->sysenter_eip = qemu_get_be32(f);
289
    }
290

    
291
    qemu_get_betls(f, &env->cr[0]);
292
    qemu_get_betls(f, &env->cr[2]);
293
    qemu_get_betls(f, &env->cr[3]);
294
    qemu_get_betls(f, &env->cr[4]);
295

    
296
    for(i = 0; i < 8; i++)
297
        qemu_get_betls(f, &env->dr[i]);
298
    cpu_breakpoint_remove_all(env, BP_CPU);
299
    cpu_watchpoint_remove_all(env, BP_CPU);
300
    for (i = 0; i < 4; i++)
301
        hw_breakpoint_insert(env, i);
302

    
303
    /* MMU */
304
    qemu_get_sbe32s(f, &a20_mask);
305
    env->a20_mask = a20_mask;
306

    
307
    qemu_get_be32s(f, &env->mxcsr);
308
    for(i = 0; i < CPU_NB_REGS; i++) {
309
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
310
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
311
    }
312

    
313
#ifdef TARGET_X86_64
314
    qemu_get_be64s(f, &env->efer);
315
    qemu_get_be64s(f, &env->star);
316
    qemu_get_be64s(f, &env->lstar);
317
    qemu_get_be64s(f, &env->cstar);
318
    qemu_get_be64s(f, &env->fmask);
319
    qemu_get_be64s(f, &env->kernelgsbase);
320
#endif
321
    if (version_id >= 4) {
322
        qemu_get_be32s(f, &env->smbase);
323
    }
324
    if (version_id >= 5) {
325
        qemu_get_be64s(f, &env->pat);
326
        qemu_get_be32s(f, &env->hflags2);
327
        if (version_id < 6)
328
            qemu_get_be32s(f, &env->halted);
329

    
330
        qemu_get_be64s(f, &env->vm_hsave);
331
        qemu_get_be64s(f, &env->vm_vmcb);
332
        qemu_get_be64s(f, &env->tsc_offset);
333
        qemu_get_be64s(f, &env->intercept);
334
        qemu_get_be16s(f, &env->intercept_cr_read);
335
        qemu_get_be16s(f, &env->intercept_cr_write);
336
        qemu_get_be16s(f, &env->intercept_dr_read);
337
        qemu_get_be16s(f, &env->intercept_dr_write);
338
        qemu_get_be32s(f, &env->intercept_exceptions);
339
        qemu_get_8s(f, &env->v_tpr);
340
    }
341

    
342
    if (version_id >= 8) {
343
        /* MTRRs */
344
        for(i = 0; i < 11; i++)
345
            qemu_get_be64s(f, &env->mtrr_fixed[i]);
346
        qemu_get_be64s(f, &env->mtrr_deftype);
347
        for(i = 0; i < 8; i++) {
348
            qemu_get_be64s(f, &env->mtrr_var[i].base);
349
            qemu_get_be64s(f, &env->mtrr_var[i].mask);
350
        }
351
    }
352

    
353
    if (version_id >= 9) {
354
        qemu_get_sbe32s(f, &pending_irq);
355
        memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap));
356
        if (pending_irq >= 0) {
357
            env->interrupt_bitmap[pending_irq / 64] |=
358
                (uint64_t)1 << (pending_irq % 64);
359
        }
360
        qemu_get_be32s(f, &env->mp_state);
361
        qemu_get_be64s(f, &env->tsc);
362
    }
363

    
364
    if (version_id >= 10) {
365
        qemu_get_be64s(f, &env->mcg_cap);
366
        if (env->mcg_cap) {
367
            qemu_get_be64s(f, &env->mcg_status);
368
            qemu_get_be64s(f, &env->mcg_ctl);
369
            for (i = 0; i < (env->mcg_cap & 0xff); i++) {
370
                qemu_get_be64s(f, &env->mce_banks[4*i]);
371
                qemu_get_be64s(f, &env->mce_banks[4*i + 1]);
372
                qemu_get_be64s(f, &env->mce_banks[4*i + 2]);
373
                qemu_get_be64s(f, &env->mce_banks[4*i + 3]);
374
            }
375
        }
376
    }
377

    
378
    if (version_id >= 11) {
379
        qemu_get_be64s(f, &env->tsc_aux);
380
    }
381

    
382
    tlb_flush(env, 1);
383
    return 0;
384
}