]> Git Repo - qemu.git/blob - target-i386/machine.c
x86: factor out cpu_pre_save()
[qemu.git] / target-i386 / machine.c
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 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
24 static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
25 {
26     vmstate_save_state(f, &vmstate_segment, dt);
27 }
28
29 static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
30 {
31     vmstate_load_state(f, &vmstate_segment, dt, vmstate_segment.version_id);
32 }
33
34 static void cpu_pre_save(void *opaque)
35 {
36     CPUState *env = opaque;
37     int i, bit;
38
39     cpu_synchronize_state(env);
40
41     /* FPU */
42     env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
43     env->fptag_vmstate = 0;
44     for(i = 0; i < 8; i++) {
45         env->fptag_vmstate |= ((!env->fptags[i]) << i);
46     }
47
48 #ifdef USE_X86LDOUBLE
49     env->fpregs_format_vmstate = 0;
50 #else
51     env->fpregs_format_vmstate = 1;
52 #endif
53
54     /* There can only be one pending IRQ set in the bitmap at a time, so try
55        to find it and save its number instead (-1 for none). */
56     env->pending_irq_vmstate = -1;
57     for (i = 0; i < ARRAY_SIZE(env->interrupt_bitmap); i++) {
58         if (env->interrupt_bitmap[i]) {
59             bit = ctz64(env->interrupt_bitmap[i]);
60             env->pending_irq_vmstate = i * 64 + bit;
61             break;
62         }
63     }
64 }
65
66 void cpu_save(QEMUFile *f, void *opaque)
67 {
68     CPUState *env = opaque;
69     int i;
70
71     cpu_pre_save(opaque);
72
73     for(i = 0; i < CPU_NB_REGS; i++)
74         qemu_put_betls(f, &env->regs[i]);
75     qemu_put_betls(f, &env->eip);
76     qemu_put_betls(f, &env->eflags);
77     qemu_put_be32s(f, &env->hflags);
78
79     /* FPU */
80     qemu_put_be16s(f, &env->fpuc);
81     qemu_put_be16s(f, &env->fpus_vmstate);
82     qemu_put_be16s(f, &env->fptag_vmstate);
83
84     qemu_put_be16s(f, &env->fpregs_format_vmstate);
85
86     for(i = 0; i < 8; i++) {
87 #ifdef USE_X86LDOUBLE
88         {
89             uint64_t mant;
90             uint16_t exp;
91             /* we save the real CPU data (in case of MMX usage only 'mant'
92                contains the MMX register */
93             cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
94             qemu_put_be64(f, mant);
95             qemu_put_be16(f, exp);
96         }
97 #else
98         /* if we use doubles for float emulation, we save the doubles to
99            avoid losing information in case of MMX usage. It can give
100            problems if the image is restored on a CPU where long
101            doubles are used instead. */
102         qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
103 #endif
104     }
105
106     for(i = 0; i < 6; i++)
107         cpu_put_seg(f, &env->segs[i]);
108     cpu_put_seg(f, &env->ldt);
109     cpu_put_seg(f, &env->tr);
110     cpu_put_seg(f, &env->gdt);
111     cpu_put_seg(f, &env->idt);
112
113     qemu_put_be32s(f, &env->sysenter_cs);
114     qemu_put_betls(f, &env->sysenter_esp);
115     qemu_put_betls(f, &env->sysenter_eip);
116
117     qemu_put_betls(f, &env->cr[0]);
118     qemu_put_betls(f, &env->cr[2]);
119     qemu_put_betls(f, &env->cr[3]);
120     qemu_put_betls(f, &env->cr[4]);
121
122     for(i = 0; i < 8; i++)
123         qemu_put_betls(f, &env->dr[i]);
124
125     /* MMU */
126     qemu_put_sbe32s(f, &env->a20_mask);
127
128     /* XMM */
129     qemu_put_be32s(f, &env->mxcsr);
130     for(i = 0; i < CPU_NB_REGS; i++) {
131         qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
132         qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
133     }
134
135 #ifdef TARGET_X86_64
136     qemu_put_be64s(f, &env->efer);
137     qemu_put_be64s(f, &env->star);
138     qemu_put_be64s(f, &env->lstar);
139     qemu_put_be64s(f, &env->cstar);
140     qemu_put_be64s(f, &env->fmask);
141     qemu_put_be64s(f, &env->kernelgsbase);
142 #endif
143     qemu_put_be32s(f, &env->smbase);
144
145     qemu_put_be64s(f, &env->pat);
146     qemu_put_be32s(f, &env->hflags2);
147     
148     qemu_put_be64s(f, &env->vm_hsave);
149     qemu_put_be64s(f, &env->vm_vmcb);
150     qemu_put_be64s(f, &env->tsc_offset);
151     qemu_put_be64s(f, &env->intercept);
152     qemu_put_be16s(f, &env->intercept_cr_read);
153     qemu_put_be16s(f, &env->intercept_cr_write);
154     qemu_put_be16s(f, &env->intercept_dr_read);
155     qemu_put_be16s(f, &env->intercept_dr_write);
156     qemu_put_be32s(f, &env->intercept_exceptions);
157     qemu_put_8s(f, &env->v_tpr);
158
159     /* MTRRs */
160     for(i = 0; i < 11; i++)
161         qemu_put_be64s(f, &env->mtrr_fixed[i]);
162     qemu_put_be64s(f, &env->mtrr_deftype);
163     for(i = 0; i < 8; i++) {
164         qemu_put_be64s(f, &env->mtrr_var[i].base);
165         qemu_put_be64s(f, &env->mtrr_var[i].mask);
166     }
167
168     /* KVM-related states */
169
170     qemu_put_sbe32s(f, &env->pending_irq_vmstate);
171     qemu_put_be32s(f, &env->mp_state);
172     qemu_put_be64s(f, &env->tsc);
173
174     /* MCE */
175     qemu_put_be64s(f, &env->mcg_cap);
176     qemu_put_be64s(f, &env->mcg_status);
177     qemu_put_be64s(f, &env->mcg_ctl);
178     for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
179         qemu_put_be64s(f, &env->mce_banks[i]);
180     }
181     qemu_put_be64s(f, &env->tsc_aux);
182  }
183
184 #ifdef USE_X86LDOUBLE
185 /* XXX: add that in a FPU generic layer */
186 union x86_longdouble {
187     uint64_t mant;
188     uint16_t exp;
189 };
190
191 #define MANTD1(fp)      (fp & ((1LL << 52) - 1))
192 #define EXPBIAS1 1023
193 #define EXPD1(fp)       ((fp >> 52) & 0x7FF)
194 #define SIGND1(fp)      ((fp >> 32) & 0x80000000)
195
196 static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
197 {
198     int e;
199     /* mantissa */
200     p->mant = (MANTD1(temp) << 11) | (1LL << 63);
201     /* exponent + sign */
202     e = EXPD1(temp) - EXPBIAS1 + 16383;
203     e |= SIGND1(temp) >> 16;
204     p->exp = e;
205 }
206 #endif
207
208 int cpu_load(QEMUFile *f, void *opaque, int version_id)
209 {
210     CPUState *env = opaque;
211     int i, guess_mmx;
212
213     cpu_synchronize_state(env);
214     if (version_id < 3 || version_id > CPU_SAVE_VERSION)
215         return -EINVAL;
216     for(i = 0; i < CPU_NB_REGS; i++)
217         qemu_get_betls(f, &env->regs[i]);
218     qemu_get_betls(f, &env->eip);
219     qemu_get_betls(f, &env->eflags);
220     qemu_get_be32s(f, &env->hflags);
221
222     qemu_get_be16s(f, &env->fpuc);
223     qemu_get_be16s(f, &env->fpus_vmstate);
224     qemu_get_be16s(f, &env->fptag_vmstate);
225     qemu_get_be16s(f, &env->fpregs_format_vmstate);
226
227     /* NOTE: we cannot always restore the FPU state if the image come
228        from a host with a different 'USE_X86LDOUBLE' define. We guess
229        if we are in an MMX state to restore correctly in that case. */
230     guess_mmx = ((env->fptag_vmstate == 0xff) && (env->fpus_vmstate & 0x3800) == 0);
231     for(i = 0; i < 8; i++) {
232         uint64_t mant;
233         uint16_t exp;
234
235         switch(env->fpregs_format_vmstate) {
236         case 0:
237             mant = qemu_get_be64(f);
238             exp = qemu_get_be16(f);
239 #ifdef USE_X86LDOUBLE
240             env->fpregs[i].d = cpu_set_fp80(mant, exp);
241 #else
242             /* difficult case */
243             if (guess_mmx)
244                 env->fpregs[i].mmx.MMX_Q(0) = mant;
245             else
246                 env->fpregs[i].d = cpu_set_fp80(mant, exp);
247 #endif
248             break;
249         case 1:
250             mant = qemu_get_be64(f);
251 #ifdef USE_X86LDOUBLE
252             {
253                 union x86_longdouble *p;
254                 /* difficult case */
255                 p = (void *)&env->fpregs[i];
256                 if (guess_mmx) {
257                     p->mant = mant;
258                     p->exp = 0xffff;
259                 } else {
260                     fp64_to_fp80(p, mant);
261                 }
262             }
263 #else
264             env->fpregs[i].mmx.MMX_Q(0) = mant;
265 #endif
266             break;
267         default:
268             return -EINVAL;
269         }
270     }
271
272     /* XXX: restore FPU round state */
273     env->fpstt = (env->fpus_vmstate >> 11) & 7;
274     env->fpus = env->fpus_vmstate & ~0x3800;
275     env->fptag_vmstate ^= 0xff;
276     for(i = 0; i < 8; i++) {
277         env->fptags[i] = (env->fptag_vmstate >> i) & 1;
278     }
279
280     for(i = 0; i < 6; i++)
281         cpu_get_seg(f, &env->segs[i]);
282     cpu_get_seg(f, &env->ldt);
283     cpu_get_seg(f, &env->tr);
284     cpu_get_seg(f, &env->gdt);
285     cpu_get_seg(f, &env->idt);
286
287     qemu_get_be32s(f, &env->sysenter_cs);
288     if (version_id >= 7) {
289         qemu_get_betls(f, &env->sysenter_esp);
290         qemu_get_betls(f, &env->sysenter_eip);
291     } else {
292         env->sysenter_esp = qemu_get_be32(f);
293         env->sysenter_eip = qemu_get_be32(f);
294     }
295
296     qemu_get_betls(f, &env->cr[0]);
297     qemu_get_betls(f, &env->cr[2]);
298     qemu_get_betls(f, &env->cr[3]);
299     qemu_get_betls(f, &env->cr[4]);
300
301     for(i = 0; i < 8; i++)
302         qemu_get_betls(f, &env->dr[i]);
303     cpu_breakpoint_remove_all(env, BP_CPU);
304     cpu_watchpoint_remove_all(env, BP_CPU);
305     for (i = 0; i < 4; i++)
306         hw_breakpoint_insert(env, i);
307
308     qemu_get_sbe32s(f, &env->a20_mask);
309
310     qemu_get_be32s(f, &env->mxcsr);
311     for(i = 0; i < CPU_NB_REGS; i++) {
312         qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
313         qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
314     }
315
316 #ifdef TARGET_X86_64
317     qemu_get_be64s(f, &env->efer);
318     qemu_get_be64s(f, &env->star);
319     qemu_get_be64s(f, &env->lstar);
320     qemu_get_be64s(f, &env->cstar);
321     qemu_get_be64s(f, &env->fmask);
322     qemu_get_be64s(f, &env->kernelgsbase);
323 #endif
324     if (version_id >= 4) {
325         qemu_get_be32s(f, &env->smbase);
326     }
327     if (version_id >= 5) {
328         qemu_get_be64s(f, &env->pat);
329         qemu_get_be32s(f, &env->hflags2);
330         if (version_id < 6)
331             qemu_get_be32s(f, &env->halted);
332
333         qemu_get_be64s(f, &env->vm_hsave);
334         qemu_get_be64s(f, &env->vm_vmcb);
335         qemu_get_be64s(f, &env->tsc_offset);
336         qemu_get_be64s(f, &env->intercept);
337         qemu_get_be16s(f, &env->intercept_cr_read);
338         qemu_get_be16s(f, &env->intercept_cr_write);
339         qemu_get_be16s(f, &env->intercept_dr_read);
340         qemu_get_be16s(f, &env->intercept_dr_write);
341         qemu_get_be32s(f, &env->intercept_exceptions);
342         qemu_get_8s(f, &env->v_tpr);
343     }
344
345     if (version_id >= 8) {
346         /* MTRRs */
347         for(i = 0; i < 11; i++)
348             qemu_get_be64s(f, &env->mtrr_fixed[i]);
349         qemu_get_be64s(f, &env->mtrr_deftype);
350         for(i = 0; i < 8; i++) {
351             qemu_get_be64s(f, &env->mtrr_var[i].base);
352             qemu_get_be64s(f, &env->mtrr_var[i].mask);
353         }
354     }
355
356     if (version_id >= 9) {
357         qemu_get_sbe32s(f, &env->pending_irq_vmstate);
358         memset(&env->interrupt_bitmap, 0, sizeof(env->interrupt_bitmap));
359         if (env->pending_irq_vmstate >= 0) {
360             env->interrupt_bitmap[env->pending_irq_vmstate / 64] |=
361                 (uint64_t)1 << (env->pending_irq_vmstate % 64);
362         }
363         qemu_get_be32s(f, &env->mp_state);
364         qemu_get_be64s(f, &env->tsc);
365     }
366
367     if (version_id >= 10) {
368         qemu_get_be64s(f, &env->mcg_cap);
369         qemu_get_be64s(f, &env->mcg_status);
370         qemu_get_be64s(f, &env->mcg_ctl);
371         for (i = 0; i < MCE_BANKS_DEF * 4; i++) {
372             qemu_get_be64s(f, &env->mce_banks[i]);
373         }
374     }
375
376     if (version_id >= 11) {
377         qemu_get_be64s(f, &env->tsc_aux);
378     }
379
380     tlb_flush(env, 1);
381     return 0;
382 }
This page took 0.049434 seconds and 4 git commands to generate.