]> git.proxmox.com Git - qemu.git/blame - target-i386/machine.c
vmstate: Add suppot for field_exist() test
[qemu.git] / target-i386 / machine.c
CommitLineData
8dd3dca3
AJ
1#include "hw/hw.h"
2#include "hw/boards.h"
3#include "hw/pc.h"
4#include "hw/isa.h"
6ad8702a 5#include "host-utils.h"
8dd3dca3
AJ
6
7#include "exec-all.h"
b0a46a33 8#include "kvm.h"
8dd3dca3 9
66e6d55b
JQ
10static const VMStateDescription vmstate_segment = {
11 .name = "segment",
12 .version_id = 1,
13 .minimum_version_id = 1,
14 .minimum_version_id_old = 1,
15 .fields = (VMStateField []) {
16 VMSTATE_UINT32(selector, SegmentCache),
17 VMSTATE_UINTTL(base, SegmentCache),
18 VMSTATE_UINT32(limit, SegmentCache),
19 VMSTATE_UINT32(flags, SegmentCache),
20 VMSTATE_END_OF_LIST()
21 }
22};
23
8dd3dca3
AJ
24static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
25{
66e6d55b 26 vmstate_save_state(f, &vmstate_segment, dt);
8dd3dca3
AJ
27}
28
29static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
30{
66e6d55b 31 vmstate_load_state(f, &vmstate_segment, dt, vmstate_segment.version_id);
8dd3dca3
AJ
32}
33
fc3b0aa2
JQ
34static const VMStateDescription vmstate_xmm_reg = {
35 .name = "xmm_reg",
36 .version_id = 1,
37 .minimum_version_id = 1,
38 .minimum_version_id_old = 1,
39 .fields = (VMStateField []) {
40 VMSTATE_UINT64(XMM_Q(0), XMMReg),
41 VMSTATE_UINT64(XMM_Q(1), XMMReg),
42 VMSTATE_END_OF_LIST()
43 }
44};
45
46static void cpu_put_xmm_reg(QEMUFile *f, XMMReg *xmm_reg)
47{
48 vmstate_save_state(f, &vmstate_xmm_reg, xmm_reg);
49}
50
51static void cpu_get_xmm_reg(QEMUFile *f, XMMReg *xmm_reg)
52{
53 vmstate_load_state(f, &vmstate_xmm_reg, xmm_reg, vmstate_xmm_reg.version_id);
54}
55
216c07c3
JQ
56static const VMStateDescription vmstate_mtrr_var = {
57 .name = "mtrr_var",
58 .version_id = 1,
59 .minimum_version_id = 1,
60 .minimum_version_id_old = 1,
61 .fields = (VMStateField []) {
62 VMSTATE_UINT64(base, MTRRVar),
63 VMSTATE_UINT64(mask, MTRRVar),
64 VMSTATE_END_OF_LIST()
65 }
66};
67
68static void cpu_put_mtrr_var(QEMUFile *f, MTRRVar *mtrr_var)
69{
70 vmstate_save_state(f, &vmstate_mtrr_var, mtrr_var);
71}
72
73static void cpu_get_mtrr_var(QEMUFile *f, MTRRVar *mtrr_var)
74{
75 vmstate_load_state(f, &vmstate_mtrr_var, mtrr_var, vmstate_mtrr_var.version_id);
76}
77
3c8ce630
JQ
78#ifdef USE_X86LDOUBLE
79/* XXX: add that in a FPU generic layer */
80union x86_longdouble {
81 uint64_t mant;
82 uint16_t exp;
83};
84
85#define MANTD1(fp) (fp & ((1LL << 52) - 1))
86#define EXPBIAS1 1023
87#define EXPD1(fp) ((fp >> 52) & 0x7FF)
88#define SIGND1(fp) ((fp >> 32) & 0x80000000)
89
90static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
91{
92 int e;
93 /* mantissa */
94 p->mant = (MANTD1(temp) << 11) | (1LL << 63);
95 /* exponent + sign */
96 e = EXPD1(temp) - EXPBIAS1 + 16383;
97 e |= SIGND1(temp) >> 16;
98 p->exp = e;
99}
100
101static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
102{
103 FPReg *fp_reg = opaque;
104 uint64_t mant;
105 uint16_t exp;
106
107 qemu_get_be64s(f, &mant);
108 qemu_get_be16s(f, &exp);
109 fp_reg->d = cpu_set_fp80(mant, exp);
110 return 0;
111}
112
113static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
114{
115 FPReg *fp_reg = opaque;
116 uint64_t mant;
117 uint16_t exp;
118 /* we save the real CPU data (in case of MMX usage only 'mant'
119 contains the MMX register */
120 cpu_get_fp80(&mant, &exp, fp_reg->d);
121 qemu_put_be64s(f, &mant);
122 qemu_put_be16s(f, &exp);
123}
124
125static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
126{
127 union x86_longdouble *p = opaque;
128 uint64_t mant;
129
130 qemu_get_be64s(f, &mant);
131 p->mant = mant;
132 p->exp = 0xffff;
133 return 0;
134}
135
136static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
137{
138 union x86_longdouble *p = opaque;
139 uint64_t mant;
140
141 qemu_get_be64s(f, &mant);
142 fp64_to_fp80(p, mant);
143 return 0;
144}
145
146#else
147static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
148{
149 FPReg *fp_reg = opaque;
150
151 qemu_get_be64s(f, &fp_reg->mmx.MMX_Q(0));
152 return 0;
153}
154
155static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
156{
157 FPReg *fp_reg = opaque;
158 /* if we use doubles for float emulation, we save the doubles to
159 avoid losing information in case of MMX usage. It can give
160 problems if the image is restored on a CPU where long
161 doubles are used instead. */
162 qemu_put_be64s(f, &fp_reg->mmx.MMX_Q(0));
163}
164
165static int get_fpreg_0_mmx(QEMUFile *f, void *opaque, size_t size)
166{
167 FPReg *fp_reg = opaque;
168 uint64_t mant;
169 uint16_t exp;
170
171 qemu_get_be64s(f, &mant);
172 qemu_get_be16s(f, &exp);
173 fp_reg->mmx.MMX_Q(0) = mant;
174 return 0;
175}
176
177static int get_fpreg_0_no_mmx(QEMUFile *f, void *opaque, size_t size)
178{
179 FPReg *fp_reg = opaque;
180 uint64_t mant;
181 uint16_t exp;
182
183 qemu_get_be64s(f, &mant);
184 qemu_get_be16s(f, &exp);
185
186 fp_reg->d = cpu_set_fp80(mant, exp);
187 return 0;
188}
189
190#endif /* USE_X86LDOUBLE */
191
c4c38c8c 192static void cpu_pre_save(void *opaque)
8dd3dca3
AJ
193{
194 CPUState *env = opaque;
059b8b1e 195 int i, bit;
8dd3dca3 196
4c0960c0 197 cpu_synchronize_state(env);
b0a46a33 198
8dd3dca3 199 /* FPU */
67b8f419 200 env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
cdc0c58f 201 env->fptag_vmstate = 0;
8dd3dca3 202 for(i = 0; i < 8; i++) {
cdc0c58f 203 env->fptag_vmstate |= ((!env->fptags[i]) << i);
8dd3dca3
AJ
204 }
205
8dd3dca3 206#ifdef USE_X86LDOUBLE
60a902f1 207 env->fpregs_format_vmstate = 0;
8dd3dca3 208#else
60a902f1 209 env->fpregs_format_vmstate = 1;
8dd3dca3 210#endif
c4c38c8c
JQ
211
212 /* There can only be one pending IRQ set in the bitmap at a time, so try
213 to find it and save its number instead (-1 for none). */
214 env->pending_irq_vmstate = -1;
215 for (i = 0; i < ARRAY_SIZE(env->interrupt_bitmap); i++) {
216 if (env->interrupt_bitmap[i]) {
217 bit = ctz64(env->interrupt_bitmap[i]);
218 env->pending_irq_vmstate = i * 64 + bit;
219 break;
220 }
221 }
222}
223
224void cpu_save(QEMUFile *f, void *opaque)
225{
226 CPUState *env = opaque;
227 int i;
228
229 cpu_pre_save(opaque);
230
231 for(i = 0; i < CPU_NB_REGS; i++)
232 qemu_put_betls(f, &env->regs[i]);
233 qemu_put_betls(f, &env->eip);
234 qemu_put_betls(f, &env->eflags);
235 qemu_put_be32s(f, &env->hflags);
236
237 /* FPU */
238 qemu_put_be16s(f, &env->fpuc);
239 qemu_put_be16s(f, &env->fpus_vmstate);
240 qemu_put_be16s(f, &env->fptag_vmstate);
241
60a902f1 242 qemu_put_be16s(f, &env->fpregs_format_vmstate);
8dd3dca3
AJ
243
244 for(i = 0; i < 8; i++) {
3c8ce630 245 put_fpreg(f, &env->fpregs[i], 0);
8dd3dca3
AJ
246 }
247
248 for(i = 0; i < 6; i++)
249 cpu_put_seg(f, &env->segs[i]);
250 cpu_put_seg(f, &env->ldt);
251 cpu_put_seg(f, &env->tr);
252 cpu_put_seg(f, &env->gdt);
253 cpu_put_seg(f, &env->idt);
254
f5049756 255 qemu_put_be32s(f, &env->sysenter_cs);
2436b61a
AZ
256 qemu_put_betls(f, &env->sysenter_esp);
257 qemu_put_betls(f, &env->sysenter_eip);
8dd3dca3
AJ
258
259 qemu_put_betls(f, &env->cr[0]);
260 qemu_put_betls(f, &env->cr[2]);
261 qemu_put_betls(f, &env->cr[3]);
262 qemu_put_betls(f, &env->cr[4]);
263
264 for(i = 0; i < 8; i++)
265 qemu_put_betls(f, &env->dr[i]);
266
267 /* MMU */
5ee0ffaa 268 qemu_put_sbe32s(f, &env->a20_mask);
8dd3dca3
AJ
269
270 /* XMM */
271 qemu_put_be32s(f, &env->mxcsr);
272 for(i = 0; i < CPU_NB_REGS; i++) {
fc3b0aa2 273 cpu_put_xmm_reg(f, &env->xmm_regs[i]);
8dd3dca3
AJ
274 }
275
276#ifdef TARGET_X86_64
277 qemu_put_be64s(f, &env->efer);
278 qemu_put_be64s(f, &env->star);
279 qemu_put_be64s(f, &env->lstar);
280 qemu_put_be64s(f, &env->cstar);
281 qemu_put_be64s(f, &env->fmask);
282 qemu_put_be64s(f, &env->kernelgsbase);
283#endif
284 qemu_put_be32s(f, &env->smbase);
5cc1d1e6
FB
285
286 qemu_put_be64s(f, &env->pat);
287 qemu_put_be32s(f, &env->hflags2);
5cc1d1e6
FB
288
289 qemu_put_be64s(f, &env->vm_hsave);
290 qemu_put_be64s(f, &env->vm_vmcb);
291 qemu_put_be64s(f, &env->tsc_offset);
292 qemu_put_be64s(f, &env->intercept);
293 qemu_put_be16s(f, &env->intercept_cr_read);
294 qemu_put_be16s(f, &env->intercept_cr_write);
295 qemu_put_be16s(f, &env->intercept_dr_read);
296 qemu_put_be16s(f, &env->intercept_dr_write);
297 qemu_put_be32s(f, &env->intercept_exceptions);
298 qemu_put_8s(f, &env->v_tpr);
dd5e3b17
AL
299
300 /* MTRRs */
301 for(i = 0; i < 11; i++)
302 qemu_put_be64s(f, &env->mtrr_fixed[i]);
303 qemu_put_be64s(f, &env->mtrr_deftype);
304 for(i = 0; i < 8; i++) {
216c07c3 305 cpu_put_mtrr_var(f, &env->mtrr_var[i]);
dd5e3b17 306 }
f8d926e9 307
059b8b1e
JK
308 /* KVM-related states */
309
bfc179b6 310 qemu_put_sbe32s(f, &env->pending_irq_vmstate);
f8d926e9 311 qemu_put_be32s(f, &env->mp_state);
059b8b1e 312 qemu_put_be64s(f, &env->tsc);
79c4f6b0
HY
313
314 /* MCE */
315 qemu_put_be64s(f, &env->mcg_cap);
e5cc6429
JQ
316 qemu_put_be64s(f, &env->mcg_status);
317 qemu_put_be64s(f, &env->mcg_ctl);
318 for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
319 qemu_put_be64s(f, &env->mce_banks[i]);
79c4f6b0 320 }
1b050077 321 qemu_put_be64s(f, &env->tsc_aux);
79c4f6b0 322 }
8dd3dca3 323
468f6581
JQ
324static int cpu_pre_load(void *opaque)
325{
326 CPUState *env = opaque;
327
328 cpu_synchronize_state(env);
329 return 0;
330}
331
332static int cpu_post_load(void *opaque, int version_id)
333{
334 CPUState *env = opaque;
335 int i;
336
337 /* XXX: restore FPU round state */
338 env->fpstt = (env->fpus_vmstate >> 11) & 7;
339 env->fpus = env->fpus_vmstate & ~0x3800;
340 env->fptag_vmstate ^= 0xff;
341 for(i = 0; i < 8; i++) {
342 env->fptags[i] = (env->fptag_vmstate >> i) & 1;
343 }
344
345 cpu_breakpoint_remove_all(env, BP_CPU);
346 cpu_watchpoint_remove_all(env, BP_CPU);
347 for (i = 0; i < 4; i++)
348 hw_breakpoint_insert(env, i);
349
350 if (version_id >= 9) {
351 memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap));
352 if (env->pending_irq_vmstate >= 0) {
353 env->interrupt_bitmap[env->pending_irq_vmstate / 64] |=
354 (uint64_t)1 << (env->pending_irq_vmstate % 64);
355 }
356 }
357
358 return cpu_post_load(env, version_id);
359}
360
8dd3dca3
AJ
361int cpu_load(QEMUFile *f, void *opaque, int version_id)
362{
363 CPUState *env = opaque;
364 int i, guess_mmx;
8dd3dca3 365
468f6581
JQ
366 cpu_pre_load(env);
367
f8d926e9 368 if (version_id < 3 || version_id > CPU_SAVE_VERSION)
8dd3dca3
AJ
369 return -EINVAL;
370 for(i = 0; i < CPU_NB_REGS; i++)
371 qemu_get_betls(f, &env->regs[i]);
372 qemu_get_betls(f, &env->eip);
373 qemu_get_betls(f, &env->eflags);
1f76b9b9 374 qemu_get_be32s(f, &env->hflags);
8dd3dca3 375
eb831623 376 qemu_get_be16s(f, &env->fpuc);
67b8f419 377 qemu_get_be16s(f, &env->fpus_vmstate);
cdc0c58f 378 qemu_get_be16s(f, &env->fptag_vmstate);
60a902f1 379 qemu_get_be16s(f, &env->fpregs_format_vmstate);
8dd3dca3 380
cdc0c58f 381 guess_mmx = ((env->fptag_vmstate == 0xff) && (env->fpus_vmstate & 0x3800) == 0);
8dd3dca3 382
3c8ce630
JQ
383 for(i = 0; i < 8; i++) {
384#ifdef USE_X86LDOUBLE
60a902f1 385 switch(env->fpregs_format_vmstate) {
8dd3dca3 386 case 0:
3c8ce630 387 get_fpreg(f, &env->fpregs[i], 0);
8dd3dca3
AJ
388 break;
389 case 1:
3c8ce630
JQ
390 if (guess_mmx) {
391 get_fpreg_1_mmx(f, &env->fpregs[i], 0);
392 } else {
393 get_fpreg_1_no_mmx(f, &env->fpregs[i], 0);
8dd3dca3 394 }
3c8ce630
JQ
395 break;
396 default:
397 return -EINVAL;
398 }
8dd3dca3 399#else
3c8ce630
JQ
400 switch(env->fpregs_format_vmstate) {
401 case 0:
402 if (guess_mmx) {
403 get_fpreg_0_mmx(f, &env->fpregs[i], 0);
404 } else {
405 get_fpreg_0_no_mmx(f, &env->fpregs[i], 0);
406 }
407 break;
408 case 1:
409 get_fpreg(f, &env->fpregs[i], 0);
8dd3dca3
AJ
410 break;
411 default:
412 return -EINVAL;
413 }
3c8ce630 414#endif
8dd3dca3
AJ
415 }
416
8dd3dca3
AJ
417 for(i = 0; i < 6; i++)
418 cpu_get_seg(f, &env->segs[i]);
419 cpu_get_seg(f, &env->ldt);
420 cpu_get_seg(f, &env->tr);
421 cpu_get_seg(f, &env->gdt);
422 cpu_get_seg(f, &env->idt);
423
424 qemu_get_be32s(f, &env->sysenter_cs);
2436b61a
AZ
425 if (version_id >= 7) {
426 qemu_get_betls(f, &env->sysenter_esp);
427 qemu_get_betls(f, &env->sysenter_eip);
428 } else {
e5ceb244
AL
429 env->sysenter_esp = qemu_get_be32(f);
430 env->sysenter_eip = qemu_get_be32(f);
2436b61a 431 }
8dd3dca3
AJ
432
433 qemu_get_betls(f, &env->cr[0]);
434 qemu_get_betls(f, &env->cr[2]);
435 qemu_get_betls(f, &env->cr[3]);
436 qemu_get_betls(f, &env->cr[4]);
437
438 for(i = 0; i < 8; i++)
439 qemu_get_betls(f, &env->dr[i]);
440
5ee0ffaa 441 qemu_get_sbe32s(f, &env->a20_mask);
8dd3dca3
AJ
442
443 qemu_get_be32s(f, &env->mxcsr);
444 for(i = 0; i < CPU_NB_REGS; i++) {
fc3b0aa2 445 cpu_get_xmm_reg(f, &env->xmm_regs[i]);
8dd3dca3
AJ
446 }
447
448#ifdef TARGET_X86_64
449 qemu_get_be64s(f, &env->efer);
450 qemu_get_be64s(f, &env->star);
451 qemu_get_be64s(f, &env->lstar);
452 qemu_get_be64s(f, &env->cstar);
453 qemu_get_be64s(f, &env->fmask);
454 qemu_get_be64s(f, &env->kernelgsbase);
455#endif
5cc1d1e6 456 if (version_id >= 4) {
8dd3dca3 457 qemu_get_be32s(f, &env->smbase);
5cc1d1e6
FB
458 }
459 if (version_id >= 5) {
460 qemu_get_be64s(f, &env->pat);
461 qemu_get_be32s(f, &env->hflags2);
9656f324
PB
462 if (version_id < 6)
463 qemu_get_be32s(f, &env->halted);
5cc1d1e6
FB
464
465 qemu_get_be64s(f, &env->vm_hsave);
466 qemu_get_be64s(f, &env->vm_vmcb);
467 qemu_get_be64s(f, &env->tsc_offset);
468 qemu_get_be64s(f, &env->intercept);
469 qemu_get_be16s(f, &env->intercept_cr_read);
470 qemu_get_be16s(f, &env->intercept_cr_write);
471 qemu_get_be16s(f, &env->intercept_dr_read);
472 qemu_get_be16s(f, &env->intercept_dr_write);
473 qemu_get_be32s(f, &env->intercept_exceptions);
474 qemu_get_8s(f, &env->v_tpr);
475 }
dd5e3b17
AL
476
477 if (version_id >= 8) {
478 /* MTRRs */
479 for(i = 0; i < 11; i++)
480 qemu_get_be64s(f, &env->mtrr_fixed[i]);
481 qemu_get_be64s(f, &env->mtrr_deftype);
482 for(i = 0; i < 8; i++) {
216c07c3 483 cpu_get_mtrr_var(f, &env->mtrr_var[i]);
dd5e3b17
AL
484 }
485 }
059b8b1e 486
f8d926e9 487 if (version_id >= 9) {
bfc179b6 488 qemu_get_sbe32s(f, &env->pending_irq_vmstate);
f8d926e9 489 qemu_get_be32s(f, &env->mp_state);
059b8b1e 490 qemu_get_be64s(f, &env->tsc);
f8d926e9 491 }
dd5e3b17 492
79c4f6b0
HY
493 if (version_id >= 10) {
494 qemu_get_be64s(f, &env->mcg_cap);
e5cc6429
JQ
495 qemu_get_be64s(f, &env->mcg_status);
496 qemu_get_be64s(f, &env->mcg_ctl);
497 for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
498 qemu_get_be64s(f, &env->mce_banks[i]);
79c4f6b0
HY
499 }
500 }
501
1b050077
AP
502 if (version_id >= 11) {
503 qemu_get_be64s(f, &env->tsc_aux);
504 }
1f76b9b9 505
8dd3dca3
AJ
506 tlb_flush(env, 1);
507 return 0;
508}