blob: 396cafbbfe35579a1b453556b7d4373bd730bba2 [file] [log] [blame]
Jun Nakajima86797932011-01-29 14:24:24 -08001#include "hw/hw.h"
2#include "hw/boards.h"
David 'Digit' Turner2ec695a2013-12-17 10:03:39 +01003#include "hw/i386/pc.h"
4#include "hw/isa/isa.h"
Jun Nakajima86797932011-01-29 14:24:24 -08005
David 'Digit' Turnerbf2340f2014-03-18 14:41:25 +01006#include "cpu.h"
David 'Digit' Turner34c48ff2013-12-15 00:25:03 +01007#include "sysemu/kvm.h"
Jun Nakajima86797932011-01-29 14:24:24 -08008
9static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
10{
11 qemu_put_be32(f, dt->selector);
12 qemu_put_betl(f, dt->base);
13 qemu_put_be32(f, dt->limit);
14 qemu_put_be32(f, dt->flags);
15}
16
17static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
18{
19 dt->selector = qemu_get_be32(f);
20 dt->base = qemu_get_betl(f);
21 dt->limit = qemu_get_be32(f);
22 dt->flags = qemu_get_be32(f);
23}
24
25void cpu_save(QEMUFile *f, void *opaque)
26{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +010027 CPUX86State *env = opaque;
Jun Nakajima86797932011-01-29 14:24:24 -080028 uint16_t fptag, fpus, fpuc, fpregs_format;
29 uint32_t hflags;
30 int32_t a20_mask;
31 int i;
32
David 'Digit' Turnere36a6832014-03-25 18:02:39 +010033 cpu_synchronize_state(ENV_GET_CPU(env), 0);
Jun Nakajima86797932011-01-29 14:24:24 -080034
35 for(i = 0; i < CPU_NB_REGS; i++)
36 qemu_put_betls(f, &env->regs[i]);
37 qemu_put_betls(f, &env->eip);
38 qemu_put_betls(f, &env->eflags);
39 hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
40 qemu_put_be32s(f, &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
Jun Nakajima86797932011-01-29 14:24:24 -080054 fpregs_format = 1;
Jun Nakajima86797932011-01-29 14:24:24 -080055 qemu_put_be16s(f, &fpregs_format);
56
57 for(i = 0; i < 8; i++) {
Jun Nakajima86797932011-01-29 14:24:24 -080058 /* if we use doubles for float emulation, we save the doubles to
59 avoid losing information in case of MMX usage. It can give
60 problems if the image is restored on a CPU where long
61 doubles are used instead. */
62 qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
Jun Nakajima86797932011-01-29 14:24:24 -080063 }
64
65 for(i = 0; i < 6; i++)
66 cpu_put_seg(f, &env->segs[i]);
67 cpu_put_seg(f, &env->ldt);
68 cpu_put_seg(f, &env->tr);
69 cpu_put_seg(f, &env->gdt);
70 cpu_put_seg(f, &env->idt);
71
72 qemu_put_be32s(f, &env->sysenter_cs);
73 qemu_put_betls(f, &env->sysenter_esp);
74 qemu_put_betls(f, &env->sysenter_eip);
75
76 qemu_put_betls(f, &env->cr[0]);
77 qemu_put_betls(f, &env->cr[2]);
78 qemu_put_betls(f, &env->cr[3]);
79 qemu_put_betls(f, &env->cr[4]);
80
81 for(i = 0; i < 8; i++)
82 qemu_put_betls(f, &env->dr[i]);
83
84 /* MMU */
85 a20_mask = (int32_t) env->a20_mask;
86 qemu_put_sbe32s(f, &a20_mask);
87
88 /* XMM */
89 qemu_put_be32s(f, &env->mxcsr);
90 for(i = 0; i < CPU_NB_REGS; i++) {
91 qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
92 qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
93 }
94
95#ifdef TARGET_X86_64
96 qemu_put_be64s(f, &env->efer);
97 qemu_put_be64s(f, &env->star);
98 qemu_put_be64s(f, &env->lstar);
99 qemu_put_be64s(f, &env->cstar);
100 qemu_put_be64s(f, &env->fmask);
101 qemu_put_be64s(f, &env->kernelgsbase);
102#endif
103 qemu_put_be32s(f, &env->smbase);
104
105 qemu_put_be64s(f, &env->pat);
106 qemu_put_be32s(f, &env->hflags2);
David 'Digit' Turnerc0052462014-02-25 18:39:29 +0100107
Jun Nakajima86797932011-01-29 14:24:24 -0800108 qemu_put_be64s(f, &env->vm_hsave);
109 qemu_put_be64s(f, &env->vm_vmcb);
110 qemu_put_be64s(f, &env->tsc_offset);
111 qemu_put_be64s(f, &env->intercept);
112 qemu_put_be16s(f, &env->intercept_cr_read);
113 qemu_put_be16s(f, &env->intercept_cr_write);
114 qemu_put_be16s(f, &env->intercept_dr_read);
115 qemu_put_be16s(f, &env->intercept_dr_write);
116 qemu_put_be32s(f, &env->intercept_exceptions);
117 qemu_put_8s(f, &env->v_tpr);
118
119 /* MTRRs */
120 for(i = 0; i < 11; i++)
121 qemu_put_be64s(f, &env->mtrr_fixed[i]);
122 qemu_put_be64s(f, &env->mtrr_deftype);
123 for(i = 0; i < 8; i++) {
124 qemu_put_be64s(f, &env->mtrr_var[i].base);
125 qemu_put_be64s(f, &env->mtrr_var[i].mask);
126 }
127
128 for (i = 0; i < sizeof(env->interrupt_bitmap)/8; i++) {
129 qemu_put_be64s(f, &env->interrupt_bitmap[i]);
130 }
131 qemu_put_be64s(f, &env->tsc);
132 qemu_put_be32s(f, &env->mp_state);
133
134 /* MCE */
135 qemu_put_be64s(f, &env->mcg_cap);
136 if (env->mcg_cap) {
137 qemu_put_be64s(f, &env->mcg_status);
138 qemu_put_be64s(f, &env->mcg_ctl);
139 for (i = 0; i < (env->mcg_cap & 0xff); i++) {
140 qemu_put_be64s(f, &env->mce_banks[4*i]);
141 qemu_put_be64s(f, &env->mce_banks[4*i + 1]);
142 qemu_put_be64s(f, &env->mce_banks[4*i + 2]);
143 qemu_put_be64s(f, &env->mce_banks[4*i + 3]);
144 }
145 }
146}
147
Jun Nakajima86797932011-01-29 14:24:24 -0800148int cpu_load(QEMUFile *f, void *opaque, int version_id)
149{
David 'Digit' Turnere2678e12014-01-16 15:56:43 +0100150 CPUX86State *env = opaque;
Jun Nakajima86797932011-01-29 14:24:24 -0800151 int i, guess_mmx;
152 uint32_t hflags;
153 uint16_t fpus, fpuc, fptag, fpregs_format;
154 int32_t a20_mask;
155
156 if (version_id < 3 || version_id > CPU_SAVE_VERSION)
157 return -EINVAL;
158 for(i = 0; i < CPU_NB_REGS; i++)
159 qemu_get_betls(f, &env->regs[i]);
160 qemu_get_betls(f, &env->eip);
161 qemu_get_betls(f, &env->eflags);
162 qemu_get_be32s(f, &hflags);
163
164 qemu_get_be16s(f, &fpuc);
165 qemu_get_be16s(f, &fpus);
166 qemu_get_be16s(f, &fptag);
167 qemu_get_be16s(f, &fpregs_format);
168
169 /* NOTE: we cannot always restore the FPU state if the image come
170 from a host with a different 'USE_X86LDOUBLE' define. We guess
171 if we are in an MMX state to restore correctly in that case. */
172 guess_mmx = ((fptag == 0xff) && (fpus & 0x3800) == 0);
173 for(i = 0; i < 8; i++) {
174 uint64_t mant;
175 uint16_t exp;
176
177 switch(fpregs_format) {
178 case 0:
179 mant = qemu_get_be64(f);
180 exp = qemu_get_be16(f);
Jun Nakajima86797932011-01-29 14:24:24 -0800181 /* difficult case */
182 if (guess_mmx)
183 env->fpregs[i].mmx.MMX_Q(0) = mant;
184 else
185 env->fpregs[i].d = cpu_set_fp80(mant, exp);
Jun Nakajima86797932011-01-29 14:24:24 -0800186 break;
187 case 1:
188 mant = qemu_get_be64(f);
Jun Nakajima86797932011-01-29 14:24:24 -0800189 env->fpregs[i].mmx.MMX_Q(0) = mant;
Jun Nakajima86797932011-01-29 14:24:24 -0800190 break;
191 default:
192 return -EINVAL;
193 }
194 }
195
196 env->fpuc = fpuc;
197 /* XXX: restore FPU round state */
198 env->fpstt = (fpus >> 11) & 7;
199 env->fpus = fpus & ~0x3800;
200 fptag ^= 0xff;
201 for(i = 0; i < 8; i++) {
202 env->fptags[i] = (fptag >> i) & 1;
203 }
204
205 for(i = 0; i < 6; i++)
206 cpu_get_seg(f, &env->segs[i]);
207 cpu_get_seg(f, &env->ldt);
208 cpu_get_seg(f, &env->tr);
209 cpu_get_seg(f, &env->gdt);
210 cpu_get_seg(f, &env->idt);
211
212 qemu_get_be32s(f, &env->sysenter_cs);
213 if (version_id >= 7) {
214 qemu_get_betls(f, &env->sysenter_esp);
215 qemu_get_betls(f, &env->sysenter_eip);
216 } else {
217 env->sysenter_esp = qemu_get_be32(f);
218 env->sysenter_eip = qemu_get_be32(f);
219 }
220
221 qemu_get_betls(f, &env->cr[0]);
222 qemu_get_betls(f, &env->cr[2]);
223 qemu_get_betls(f, &env->cr[3]);
224 qemu_get_betls(f, &env->cr[4]);
225
226 for(i = 0; i < 8; i++)
227 qemu_get_betls(f, &env->dr[i]);
228 cpu_breakpoint_remove_all(env, BP_CPU);
229 cpu_watchpoint_remove_all(env, BP_CPU);
230 for (i = 0; i < 4; i++)
231 hw_breakpoint_insert(env, i);
232
233 /* MMU */
234 qemu_get_sbe32s(f, &a20_mask);
235 env->a20_mask = a20_mask;
236
237 qemu_get_be32s(f, &env->mxcsr);
238 for(i = 0; i < CPU_NB_REGS; i++) {
239 qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
240 qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
241 }
242
243#ifdef TARGET_X86_64
244 qemu_get_be64s(f, &env->efer);
245 qemu_get_be64s(f, &env->star);
246 qemu_get_be64s(f, &env->lstar);
247 qemu_get_be64s(f, &env->cstar);
248 qemu_get_be64s(f, &env->fmask);
249 qemu_get_be64s(f, &env->kernelgsbase);
250#endif
251 if (version_id >= 4) {
252 qemu_get_be32s(f, &env->smbase);
253 }
254 if (version_id >= 5) {
255 qemu_get_be64s(f, &env->pat);
256 qemu_get_be32s(f, &env->hflags2);
257 if (version_id < 6)
David 'Digit' Turner66576782014-03-24 16:57:57 +0100258 qemu_get_be32s(f, &ENV_GET_CPU(env)->halted);
Jun Nakajima86797932011-01-29 14:24:24 -0800259
260 qemu_get_be64s(f, &env->vm_hsave);
261 qemu_get_be64s(f, &env->vm_vmcb);
262 qemu_get_be64s(f, &env->tsc_offset);
263 qemu_get_be64s(f, &env->intercept);
264 qemu_get_be16s(f, &env->intercept_cr_read);
265 qemu_get_be16s(f, &env->intercept_cr_write);
266 qemu_get_be16s(f, &env->intercept_dr_read);
267 qemu_get_be16s(f, &env->intercept_dr_write);
268 qemu_get_be32s(f, &env->intercept_exceptions);
269 qemu_get_8s(f, &env->v_tpr);
270 }
271
272 if (version_id >= 8) {
273 /* MTRRs */
274 for(i = 0; i < 11; i++)
275 qemu_get_be64s(f, &env->mtrr_fixed[i]);
276 qemu_get_be64s(f, &env->mtrr_deftype);
277 for(i = 0; i < 8; i++) {
278 qemu_get_be64s(f, &env->mtrr_var[i].base);
279 qemu_get_be64s(f, &env->mtrr_var[i].mask);
280 }
281 }
282 if (version_id >= 9) {
283 for (i = 0; i < sizeof(env->interrupt_bitmap)/8; i++) {
284 qemu_get_be64s(f, &env->interrupt_bitmap[i]);
285 }
286 qemu_get_be64s(f, &env->tsc);
287 qemu_get_be32s(f, &env->mp_state);
288 }
289
290 if (version_id >= 10) {
291 qemu_get_be64s(f, &env->mcg_cap);
292 if (env->mcg_cap) {
293 qemu_get_be64s(f, &env->mcg_status);
294 qemu_get_be64s(f, &env->mcg_ctl);
295 for (i = 0; i < (env->mcg_cap & 0xff); i++) {
296 qemu_get_be64s(f, &env->mce_banks[4*i]);
297 qemu_get_be64s(f, &env->mce_banks[4*i + 1]);
298 qemu_get_be64s(f, &env->mce_banks[4*i + 2]);
299 qemu_get_be64s(f, &env->mce_banks[4*i + 3]);
300 }
301 }
302 }
303
304
305 /* XXX: ensure compatiblity for halted bit ? */
306 /* XXX: compute redundant hflags bits */
307 env->hflags = hflags;
308 tlb_flush(env, 1);
David 'Digit' Turnere36a6832014-03-25 18:02:39 +0100309 cpu_synchronize_state(ENV_GET_CPU(env), 1);
Jun Nakajima86797932011-01-29 14:24:24 -0800310 return 0;
311}