Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ e37630ca

History | View | Annotate | Download (9.2 kB)

1
#include "hw/hw.h"
2
#include "hw/boards.h"
3
#include "hw/pc.h"
4
#include "hw/isa.h"
5

    
6
#include "exec-all.h"
7

    
8
void register_machines(void)
9
{
10
    qemu_register_machine(&pc_machine);
11
    qemu_register_machine(&isapc_machine);
12
#ifdef CONFIG_XEN
13
    qemu_register_machine(&xenpv_machine);
14
#endif
15
}
16

    
17
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
18
{
19
    qemu_put_be32(f, dt->selector);
20
    qemu_put_betl(f, dt->base);
21
    qemu_put_be32(f, dt->limit);
22
    qemu_put_be32(f, dt->flags);
23
}
24

    
25
static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
26
{
27
    dt->selector = qemu_get_be32(f);
28
    dt->base = qemu_get_betl(f);
29
    dt->limit = qemu_get_be32(f);
30
    dt->flags = qemu_get_be32(f);
31
}
32

    
33
void cpu_save(QEMUFile *f, void *opaque)
34
{
35
    CPUState *env = opaque;
36
    uint16_t fptag, fpus, fpuc, fpregs_format;
37
    uint32_t hflags;
38
    int32_t a20_mask;
39
    int i;
40

    
41
    for(i = 0; i < CPU_NB_REGS; i++)
42
        qemu_put_betls(f, &env->regs[i]);
43
    qemu_put_betls(f, &env->eip);
44
    qemu_put_betls(f, &env->eflags);
45
    hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
46
    qemu_put_be32s(f, &hflags);
47

    
48
    /* FPU */
49
    fpuc = env->fpuc;
50
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
51
    fptag = 0;
52
    for(i = 0; i < 8; i++) {
53
        fptag |= ((!env->fptags[i]) << i);
54
    }
55

    
56
    qemu_put_be16s(f, &fpuc);
57
    qemu_put_be16s(f, &fpus);
58
    qemu_put_be16s(f, &fptag);
59

    
60
#ifdef USE_X86LDOUBLE
61
    fpregs_format = 0;
62
#else
63
    fpregs_format = 1;
64
#endif
65
    qemu_put_be16s(f, &fpregs_format);
66

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

    
87
    for(i = 0; i < 6; i++)
88
        cpu_put_seg(f, &env->segs[i]);
89
    cpu_put_seg(f, &env->ldt);
90
    cpu_put_seg(f, &env->tr);
91
    cpu_put_seg(f, &env->gdt);
92
    cpu_put_seg(f, &env->idt);
93

    
94
    qemu_put_be32s(f, &env->sysenter_cs);
95
    qemu_put_betls(f, &env->sysenter_esp);
96
    qemu_put_betls(f, &env->sysenter_eip);
97

    
98
    qemu_put_betls(f, &env->cr[0]);
99
    qemu_put_betls(f, &env->cr[2]);
100
    qemu_put_betls(f, &env->cr[3]);
101
    qemu_put_betls(f, &env->cr[4]);
102

    
103
    for(i = 0; i < 8; i++)
104
        qemu_put_betls(f, &env->dr[i]);
105

    
106
    /* MMU */
107
    a20_mask = (int32_t) env->a20_mask;
108
    qemu_put_sbe32s(f, &a20_mask);
109

    
110
    /* XMM */
111
    qemu_put_be32s(f, &env->mxcsr);
112
    for(i = 0; i < CPU_NB_REGS; i++) {
113
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
114
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
115
    }
116

    
117
#ifdef TARGET_X86_64
118
    qemu_put_be64s(f, &env->efer);
119
    qemu_put_be64s(f, &env->star);
120
    qemu_put_be64s(f, &env->lstar);
121
    qemu_put_be64s(f, &env->cstar);
122
    qemu_put_be64s(f, &env->fmask);
123
    qemu_put_be64s(f, &env->kernelgsbase);
124
#endif
125
    qemu_put_be32s(f, &env->smbase);
126

    
127
    qemu_put_be64s(f, &env->pat);
128
    qemu_put_be32s(f, &env->hflags2);
129
    
130
    qemu_put_be64s(f, &env->vm_hsave);
131
    qemu_put_be64s(f, &env->vm_vmcb);
132
    qemu_put_be64s(f, &env->tsc_offset);
133
    qemu_put_be64s(f, &env->intercept);
134
    qemu_put_be16s(f, &env->intercept_cr_read);
135
    qemu_put_be16s(f, &env->intercept_cr_write);
136
    qemu_put_be16s(f, &env->intercept_dr_read);
137
    qemu_put_be16s(f, &env->intercept_dr_write);
138
    qemu_put_be32s(f, &env->intercept_exceptions);
139
    qemu_put_8s(f, &env->v_tpr);
140

    
141
    /* MTRRs */
142
    for(i = 0; i < 11; i++)
143
        qemu_put_be64s(f, &env->mtrr_fixed[i]);
144
    qemu_put_be64s(f, &env->mtrr_deftype);
145
    for(i = 0; i < 8; i++) {
146
        qemu_put_be64s(f, &env->mtrr_var[i].base);
147
        qemu_put_be64s(f, &env->mtrr_var[i].mask);
148
    }
149
}
150

    
151
#ifdef USE_X86LDOUBLE
152
/* XXX: add that in a FPU generic layer */
153
union x86_longdouble {
154
    uint64_t mant;
155
    uint16_t exp;
156
};
157

    
158
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
159
#define EXPBIAS1 1023
160
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
161
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
162

    
163
static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
164
{
165
    int e;
166
    /* mantissa */
167
    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
168
    /* exponent + sign */
169
    e = EXPD1(temp) - EXPBIAS1 + 16383;
170
    e |= SIGND1(temp) >> 16;
171
    p->exp = e;
172
}
173
#endif
174

    
175
int cpu_load(QEMUFile *f, void *opaque, int version_id)
176
{
177
    CPUState *env = opaque;
178
    int i, guess_mmx;
179
    uint32_t hflags;
180
    uint16_t fpus, fpuc, fptag, fpregs_format;
181
    int32_t a20_mask;
182

    
183
    if (version_id != 3 && version_id != 4 && version_id != 5
184
        && version_id != 6 && version_id != 7 && version_id != 8)
185
        return -EINVAL;
186
    for(i = 0; i < CPU_NB_REGS; i++)
187
        qemu_get_betls(f, &env->regs[i]);
188
    qemu_get_betls(f, &env->eip);
189
    qemu_get_betls(f, &env->eflags);
190
    qemu_get_be32s(f, &hflags);
191

    
192
    qemu_get_be16s(f, &fpuc);
193
    qemu_get_be16s(f, &fpus);
194
    qemu_get_be16s(f, &fptag);
195
    qemu_get_be16s(f, &fpregs_format);
196

    
197
    /* NOTE: we cannot always restore the FPU state if the image come
198
       from a host with a different 'USE_X86LDOUBLE' define. We guess
199
       if we are in an MMX state to restore correctly in that case. */
200
    guess_mmx = ((fptag == 0xff) && (fpus & 0x3800) == 0);
201
    for(i = 0; i < 8; i++) {
202
        uint64_t mant;
203
        uint16_t exp;
204

    
205
        switch(fpregs_format) {
206
        case 0:
207
            mant = qemu_get_be64(f);
208
            exp = qemu_get_be16(f);
209
#ifdef USE_X86LDOUBLE
210
            env->fpregs[i].d = cpu_set_fp80(mant, exp);
211
#else
212
            /* difficult case */
213
            if (guess_mmx)
214
                env->fpregs[i].mmx.MMX_Q(0) = mant;
215
            else
216
                env->fpregs[i].d = cpu_set_fp80(mant, exp);
217
#endif
218
            break;
219
        case 1:
220
            mant = qemu_get_be64(f);
221
#ifdef USE_X86LDOUBLE
222
            {
223
                union x86_longdouble *p;
224
                /* difficult case */
225
                p = (void *)&env->fpregs[i];
226
                if (guess_mmx) {
227
                    p->mant = mant;
228
                    p->exp = 0xffff;
229
                } else {
230
                    fp64_to_fp80(p, mant);
231
                }
232
            }
233
#else
234
            env->fpregs[i].mmx.MMX_Q(0) = mant;
235
#endif
236
            break;
237
        default:
238
            return -EINVAL;
239
        }
240
    }
241

    
242
    env->fpuc = fpuc;
243
    /* XXX: restore FPU round state */
244
    env->fpstt = (fpus >> 11) & 7;
245
    env->fpus = fpus & ~0x3800;
246
    fptag ^= 0xff;
247
    for(i = 0; i < 8; i++) {
248
        env->fptags[i] = (fptag >> i) & 1;
249
    }
250

    
251
    for(i = 0; i < 6; i++)
252
        cpu_get_seg(f, &env->segs[i]);
253
    cpu_get_seg(f, &env->ldt);
254
    cpu_get_seg(f, &env->tr);
255
    cpu_get_seg(f, &env->gdt);
256
    cpu_get_seg(f, &env->idt);
257

    
258
    qemu_get_be32s(f, &env->sysenter_cs);
259
    if (version_id >= 7) {
260
        qemu_get_betls(f, &env->sysenter_esp);
261
        qemu_get_betls(f, &env->sysenter_eip);
262
    } else {
263
        env->sysenter_esp = qemu_get_be32(f);
264
        env->sysenter_eip = qemu_get_be32(f);
265
    }
266

    
267
    qemu_get_betls(f, &env->cr[0]);
268
    qemu_get_betls(f, &env->cr[2]);
269
    qemu_get_betls(f, &env->cr[3]);
270
    qemu_get_betls(f, &env->cr[4]);
271

    
272
    for(i = 0; i < 8; i++)
273
        qemu_get_betls(f, &env->dr[i]);
274
    cpu_breakpoint_remove_all(env, BP_CPU);
275
    cpu_watchpoint_remove_all(env, BP_CPU);
276
    for (i = 0; i < 4; i++)
277
        hw_breakpoint_insert(env, i);
278

    
279
    /* MMU */
280
    qemu_get_sbe32s(f, &a20_mask);
281
    env->a20_mask = a20_mask;
282

    
283
    qemu_get_be32s(f, &env->mxcsr);
284
    for(i = 0; i < CPU_NB_REGS; i++) {
285
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
286
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
287
    }
288

    
289
#ifdef TARGET_X86_64
290
    qemu_get_be64s(f, &env->efer);
291
    qemu_get_be64s(f, &env->star);
292
    qemu_get_be64s(f, &env->lstar);
293
    qemu_get_be64s(f, &env->cstar);
294
    qemu_get_be64s(f, &env->fmask);
295
    qemu_get_be64s(f, &env->kernelgsbase);
296
#endif
297
    if (version_id >= 4) {
298
        qemu_get_be32s(f, &env->smbase);
299
    }
300
    if (version_id >= 5) {
301
        qemu_get_be64s(f, &env->pat);
302
        qemu_get_be32s(f, &env->hflags2);
303
        if (version_id < 6)
304
            qemu_get_be32s(f, &env->halted);
305

    
306
        qemu_get_be64s(f, &env->vm_hsave);
307
        qemu_get_be64s(f, &env->vm_vmcb);
308
        qemu_get_be64s(f, &env->tsc_offset);
309
        qemu_get_be64s(f, &env->intercept);
310
        qemu_get_be16s(f, &env->intercept_cr_read);
311
        qemu_get_be16s(f, &env->intercept_cr_write);
312
        qemu_get_be16s(f, &env->intercept_dr_read);
313
        qemu_get_be16s(f, &env->intercept_dr_write);
314
        qemu_get_be32s(f, &env->intercept_exceptions);
315
        qemu_get_8s(f, &env->v_tpr);
316
    }
317

    
318
    if (version_id >= 8) {
319
        /* MTRRs */
320
        for(i = 0; i < 11; i++)
321
            qemu_get_be64s(f, &env->mtrr_fixed[i]);
322
        qemu_get_be64s(f, &env->mtrr_deftype);
323
        for(i = 0; i < 8; i++) {
324
            qemu_get_be64s(f, &env->mtrr_var[i].base);
325
            qemu_get_be64s(f, &env->mtrr_var[i].mask);
326
        }
327
    }
328

    
329
    /* XXX: ensure compatiblity for halted bit ? */
330
    /* XXX: compute redundant hflags bits */
331
    env->hflags = hflags;
332
    tlb_flush(env, 1);
333
    return 0;
334
}