]> Git Repo - qemu.git/blob - target-i386/machine.c
x86: mcg_cap is never 0
[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 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 }
This page took 0.050065 seconds and 4 git commands to generate.