Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ 94909d9f

History | View | Annotate | Download (9.2 kB)

1 8dd3dca3 aurel32
#include "hw/hw.h"
2 8dd3dca3 aurel32
#include "hw/boards.h"
3 8dd3dca3 aurel32
#include "hw/pc.h"
4 8dd3dca3 aurel32
#include "hw/isa.h"
5 8dd3dca3 aurel32
6 8dd3dca3 aurel32
#include "exec-all.h"
7 8dd3dca3 aurel32
8 8dd3dca3 aurel32
void register_machines(void)
9 8dd3dca3 aurel32
{
10 8dd3dca3 aurel32
    qemu_register_machine(&pc_machine);
11 8dd3dca3 aurel32
    qemu_register_machine(&isapc_machine);
12 e37630ca aliguori
#ifdef CONFIG_XEN
13 e37630ca aliguori
    qemu_register_machine(&xenpv_machine);
14 e37630ca aliguori
#endif
15 8dd3dca3 aurel32
}
16 8dd3dca3 aurel32
17 8dd3dca3 aurel32
static void cpu_put_seg(QEMUFile *f, SegmentCache *dt)
18 8dd3dca3 aurel32
{
19 8dd3dca3 aurel32
    qemu_put_be32(f, dt->selector);
20 8dd3dca3 aurel32
    qemu_put_betl(f, dt->base);
21 8dd3dca3 aurel32
    qemu_put_be32(f, dt->limit);
22 8dd3dca3 aurel32
    qemu_put_be32(f, dt->flags);
23 8dd3dca3 aurel32
}
24 8dd3dca3 aurel32
25 8dd3dca3 aurel32
static void cpu_get_seg(QEMUFile *f, SegmentCache *dt)
26 8dd3dca3 aurel32
{
27 8dd3dca3 aurel32
    dt->selector = qemu_get_be32(f);
28 8dd3dca3 aurel32
    dt->base = qemu_get_betl(f);
29 8dd3dca3 aurel32
    dt->limit = qemu_get_be32(f);
30 8dd3dca3 aurel32
    dt->flags = qemu_get_be32(f);
31 8dd3dca3 aurel32
}
32 8dd3dca3 aurel32
33 8dd3dca3 aurel32
void cpu_save(QEMUFile *f, void *opaque)
34 8dd3dca3 aurel32
{
35 8dd3dca3 aurel32
    CPUState *env = opaque;
36 8dd3dca3 aurel32
    uint16_t fptag, fpus, fpuc, fpregs_format;
37 8dd3dca3 aurel32
    uint32_t hflags;
38 7caa33f7 aurel32
    int32_t a20_mask;
39 8dd3dca3 aurel32
    int i;
40 8dd3dca3 aurel32
41 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++)
42 8dd3dca3 aurel32
        qemu_put_betls(f, &env->regs[i]);
43 8dd3dca3 aurel32
    qemu_put_betls(f, &env->eip);
44 8dd3dca3 aurel32
    qemu_put_betls(f, &env->eflags);
45 8dd3dca3 aurel32
    hflags = env->hflags; /* XXX: suppress most of the redundant hflags */
46 8dd3dca3 aurel32
    qemu_put_be32s(f, &hflags);
47 8dd3dca3 aurel32
48 8dd3dca3 aurel32
    /* FPU */
49 8dd3dca3 aurel32
    fpuc = env->fpuc;
50 8dd3dca3 aurel32
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
51 8dd3dca3 aurel32
    fptag = 0;
52 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
53 8dd3dca3 aurel32
        fptag |= ((!env->fptags[i]) << i);
54 8dd3dca3 aurel32
    }
55 8dd3dca3 aurel32
56 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpuc);
57 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpus);
58 8dd3dca3 aurel32
    qemu_put_be16s(f, &fptag);
59 8dd3dca3 aurel32
60 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
61 8dd3dca3 aurel32
    fpregs_format = 0;
62 8dd3dca3 aurel32
#else
63 8dd3dca3 aurel32
    fpregs_format = 1;
64 8dd3dca3 aurel32
#endif
65 8dd3dca3 aurel32
    qemu_put_be16s(f, &fpregs_format);
66 8dd3dca3 aurel32
67 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
68 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
69 8dd3dca3 aurel32
        {
70 8dd3dca3 aurel32
            uint64_t mant;
71 8dd3dca3 aurel32
            uint16_t exp;
72 8dd3dca3 aurel32
            /* we save the real CPU data (in case of MMX usage only 'mant'
73 8dd3dca3 aurel32
               contains the MMX register */
74 8dd3dca3 aurel32
            cpu_get_fp80(&mant, &exp, env->fpregs[i].d);
75 8dd3dca3 aurel32
            qemu_put_be64(f, mant);
76 8dd3dca3 aurel32
            qemu_put_be16(f, exp);
77 8dd3dca3 aurel32
        }
78 8dd3dca3 aurel32
#else
79 8dd3dca3 aurel32
        /* if we use doubles for float emulation, we save the doubles to
80 8dd3dca3 aurel32
           avoid losing information in case of MMX usage. It can give
81 8dd3dca3 aurel32
           problems if the image is restored on a CPU where long
82 8dd3dca3 aurel32
           doubles are used instead. */
83 8dd3dca3 aurel32
        qemu_put_be64(f, env->fpregs[i].mmx.MMX_Q(0));
84 8dd3dca3 aurel32
#endif
85 8dd3dca3 aurel32
    }
86 8dd3dca3 aurel32
87 8dd3dca3 aurel32
    for(i = 0; i < 6; i++)
88 8dd3dca3 aurel32
        cpu_put_seg(f, &env->segs[i]);
89 8dd3dca3 aurel32
    cpu_put_seg(f, &env->ldt);
90 8dd3dca3 aurel32
    cpu_put_seg(f, &env->tr);
91 8dd3dca3 aurel32
    cpu_put_seg(f, &env->gdt);
92 8dd3dca3 aurel32
    cpu_put_seg(f, &env->idt);
93 8dd3dca3 aurel32
94 f5049756 aliguori
    qemu_put_be32s(f, &env->sysenter_cs);
95 2436b61a balrog
    qemu_put_betls(f, &env->sysenter_esp);
96 2436b61a balrog
    qemu_put_betls(f, &env->sysenter_eip);
97 8dd3dca3 aurel32
98 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[0]);
99 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[2]);
100 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[3]);
101 8dd3dca3 aurel32
    qemu_put_betls(f, &env->cr[4]);
102 8dd3dca3 aurel32
103 8dd3dca3 aurel32
    for(i = 0; i < 8; i++)
104 8dd3dca3 aurel32
        qemu_put_betls(f, &env->dr[i]);
105 8dd3dca3 aurel32
106 8dd3dca3 aurel32
    /* MMU */
107 7caa33f7 aurel32
    a20_mask = (int32_t) env->a20_mask;
108 b6c4f71f blueswir1
    qemu_put_sbe32s(f, &a20_mask);
109 8dd3dca3 aurel32
110 8dd3dca3 aurel32
    /* XMM */
111 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->mxcsr);
112 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++) {
113 8dd3dca3 aurel32
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(0));
114 8dd3dca3 aurel32
        qemu_put_be64s(f, &env->xmm_regs[i].XMM_Q(1));
115 8dd3dca3 aurel32
    }
116 8dd3dca3 aurel32
117 8dd3dca3 aurel32
#ifdef TARGET_X86_64
118 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->efer);
119 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->star);
120 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->lstar);
121 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->cstar);
122 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->fmask);
123 8dd3dca3 aurel32
    qemu_put_be64s(f, &env->kernelgsbase);
124 8dd3dca3 aurel32
#endif
125 8dd3dca3 aurel32
    qemu_put_be32s(f, &env->smbase);
126 5cc1d1e6 bellard
127 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->pat);
128 5cc1d1e6 bellard
    qemu_put_be32s(f, &env->hflags2);
129 5cc1d1e6 bellard
    
130 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->vm_hsave);
131 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->vm_vmcb);
132 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->tsc_offset);
133 5cc1d1e6 bellard
    qemu_put_be64s(f, &env->intercept);
134 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_cr_read);
135 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_cr_write);
136 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_dr_read);
137 5cc1d1e6 bellard
    qemu_put_be16s(f, &env->intercept_dr_write);
138 5cc1d1e6 bellard
    qemu_put_be32s(f, &env->intercept_exceptions);
139 5cc1d1e6 bellard
    qemu_put_8s(f, &env->v_tpr);
140 dd5e3b17 aliguori
141 dd5e3b17 aliguori
    /* MTRRs */
142 dd5e3b17 aliguori
    for(i = 0; i < 11; i++)
143 dd5e3b17 aliguori
        qemu_put_be64s(f, &env->mtrr_fixed[i]);
144 dd5e3b17 aliguori
    qemu_put_be64s(f, &env->mtrr_deftype);
145 dd5e3b17 aliguori
    for(i = 0; i < 8; i++) {
146 dd5e3b17 aliguori
        qemu_put_be64s(f, &env->mtrr_var[i].base);
147 dd5e3b17 aliguori
        qemu_put_be64s(f, &env->mtrr_var[i].mask);
148 dd5e3b17 aliguori
    }
149 8dd3dca3 aurel32
}
150 8dd3dca3 aurel32
151 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
152 8dd3dca3 aurel32
/* XXX: add that in a FPU generic layer */
153 8dd3dca3 aurel32
union x86_longdouble {
154 8dd3dca3 aurel32
    uint64_t mant;
155 8dd3dca3 aurel32
    uint16_t exp;
156 8dd3dca3 aurel32
};
157 8dd3dca3 aurel32
158 8dd3dca3 aurel32
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
159 8dd3dca3 aurel32
#define EXPBIAS1 1023
160 8dd3dca3 aurel32
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
161 8dd3dca3 aurel32
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
162 8dd3dca3 aurel32
163 8dd3dca3 aurel32
static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
164 8dd3dca3 aurel32
{
165 8dd3dca3 aurel32
    int e;
166 8dd3dca3 aurel32
    /* mantissa */
167 8dd3dca3 aurel32
    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
168 8dd3dca3 aurel32
    /* exponent + sign */
169 8dd3dca3 aurel32
    e = EXPD1(temp) - EXPBIAS1 + 16383;
170 8dd3dca3 aurel32
    e |= SIGND1(temp) >> 16;
171 8dd3dca3 aurel32
    p->exp = e;
172 8dd3dca3 aurel32
}
173 8dd3dca3 aurel32
#endif
174 8dd3dca3 aurel32
175 8dd3dca3 aurel32
int cpu_load(QEMUFile *f, void *opaque, int version_id)
176 8dd3dca3 aurel32
{
177 8dd3dca3 aurel32
    CPUState *env = opaque;
178 8dd3dca3 aurel32
    int i, guess_mmx;
179 8dd3dca3 aurel32
    uint32_t hflags;
180 8dd3dca3 aurel32
    uint16_t fpus, fpuc, fptag, fpregs_format;
181 7caa33f7 aurel32
    int32_t a20_mask;
182 8dd3dca3 aurel32
183 9656f324 pbrook
    if (version_id != 3 && version_id != 4 && version_id != 5
184 dd5e3b17 aliguori
        && version_id != 6 && version_id != 7 && version_id != 8)
185 8dd3dca3 aurel32
        return -EINVAL;
186 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++)
187 8dd3dca3 aurel32
        qemu_get_betls(f, &env->regs[i]);
188 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eip);
189 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eflags);
190 8dd3dca3 aurel32
    qemu_get_be32s(f, &hflags);
191 8dd3dca3 aurel32
192 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpuc);
193 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpus);
194 8dd3dca3 aurel32
    qemu_get_be16s(f, &fptag);
195 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpregs_format);
196 8dd3dca3 aurel32
197 8dd3dca3 aurel32
    /* NOTE: we cannot always restore the FPU state if the image come
198 8dd3dca3 aurel32
       from a host with a different 'USE_X86LDOUBLE' define. We guess
199 8dd3dca3 aurel32
       if we are in an MMX state to restore correctly in that case. */
200 8dd3dca3 aurel32
    guess_mmx = ((fptag == 0xff) && (fpus & 0x3800) == 0);
201 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
202 8dd3dca3 aurel32
        uint64_t mant;
203 8dd3dca3 aurel32
        uint16_t exp;
204 8dd3dca3 aurel32
205 8dd3dca3 aurel32
        switch(fpregs_format) {
206 8dd3dca3 aurel32
        case 0:
207 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
208 8dd3dca3 aurel32
            exp = qemu_get_be16(f);
209 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
210 8dd3dca3 aurel32
            env->fpregs[i].d = cpu_set_fp80(mant, exp);
211 8dd3dca3 aurel32
#else
212 8dd3dca3 aurel32
            /* difficult case */
213 8dd3dca3 aurel32
            if (guess_mmx)
214 8dd3dca3 aurel32
                env->fpregs[i].mmx.MMX_Q(0) = mant;
215 8dd3dca3 aurel32
            else
216 8dd3dca3 aurel32
                env->fpregs[i].d = cpu_set_fp80(mant, exp);
217 8dd3dca3 aurel32
#endif
218 8dd3dca3 aurel32
            break;
219 8dd3dca3 aurel32
        case 1:
220 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
221 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
222 8dd3dca3 aurel32
            {
223 8dd3dca3 aurel32
                union x86_longdouble *p;
224 8dd3dca3 aurel32
                /* difficult case */
225 8dd3dca3 aurel32
                p = (void *)&env->fpregs[i];
226 8dd3dca3 aurel32
                if (guess_mmx) {
227 8dd3dca3 aurel32
                    p->mant = mant;
228 8dd3dca3 aurel32
                    p->exp = 0xffff;
229 8dd3dca3 aurel32
                } else {
230 8dd3dca3 aurel32
                    fp64_to_fp80(p, mant);
231 8dd3dca3 aurel32
                }
232 8dd3dca3 aurel32
            }
233 8dd3dca3 aurel32
#else
234 8dd3dca3 aurel32
            env->fpregs[i].mmx.MMX_Q(0) = mant;
235 8dd3dca3 aurel32
#endif
236 8dd3dca3 aurel32
            break;
237 8dd3dca3 aurel32
        default:
238 8dd3dca3 aurel32
            return -EINVAL;
239 8dd3dca3 aurel32
        }
240 8dd3dca3 aurel32
    }
241 8dd3dca3 aurel32
242 8dd3dca3 aurel32
    env->fpuc = fpuc;
243 8dd3dca3 aurel32
    /* XXX: restore FPU round state */
244 8dd3dca3 aurel32
    env->fpstt = (fpus >> 11) & 7;
245 8dd3dca3 aurel32
    env->fpus = fpus & ~0x3800;
246 8dd3dca3 aurel32
    fptag ^= 0xff;
247 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
248 8dd3dca3 aurel32
        env->fptags[i] = (fptag >> i) & 1;
249 8dd3dca3 aurel32
    }
250 8dd3dca3 aurel32
251 8dd3dca3 aurel32
    for(i = 0; i < 6; i++)
252 8dd3dca3 aurel32
        cpu_get_seg(f, &env->segs[i]);
253 8dd3dca3 aurel32
    cpu_get_seg(f, &env->ldt);
254 8dd3dca3 aurel32
    cpu_get_seg(f, &env->tr);
255 8dd3dca3 aurel32
    cpu_get_seg(f, &env->gdt);
256 8dd3dca3 aurel32
    cpu_get_seg(f, &env->idt);
257 8dd3dca3 aurel32
258 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->sysenter_cs);
259 2436b61a balrog
    if (version_id >= 7) {
260 2436b61a balrog
        qemu_get_betls(f, &env->sysenter_esp);
261 2436b61a balrog
        qemu_get_betls(f, &env->sysenter_eip);
262 2436b61a balrog
    } else {
263 e5ceb244 aliguori
        env->sysenter_esp = qemu_get_be32(f);
264 e5ceb244 aliguori
        env->sysenter_eip = qemu_get_be32(f);
265 2436b61a balrog
    }
266 8dd3dca3 aurel32
267 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[0]);
268 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[2]);
269 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[3]);
270 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[4]);
271 8dd3dca3 aurel32
272 8dd3dca3 aurel32
    for(i = 0; i < 8; i++)
273 8dd3dca3 aurel32
        qemu_get_betls(f, &env->dr[i]);
274 01df040b aliguori
    cpu_breakpoint_remove_all(env, BP_CPU);
275 01df040b aliguori
    cpu_watchpoint_remove_all(env, BP_CPU);
276 01df040b aliguori
    for (i = 0; i < 4; i++)
277 01df040b aliguori
        hw_breakpoint_insert(env, i);
278 8dd3dca3 aurel32
279 8dd3dca3 aurel32
    /* MMU */
280 b6c4f71f blueswir1
    qemu_get_sbe32s(f, &a20_mask);
281 7caa33f7 aurel32
    env->a20_mask = a20_mask;
282 8dd3dca3 aurel32
283 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->mxcsr);
284 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++) {
285 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
286 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
287 8dd3dca3 aurel32
    }
288 8dd3dca3 aurel32
289 8dd3dca3 aurel32
#ifdef TARGET_X86_64
290 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->efer);
291 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->star);
292 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->lstar);
293 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->cstar);
294 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->fmask);
295 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->kernelgsbase);
296 8dd3dca3 aurel32
#endif
297 5cc1d1e6 bellard
    if (version_id >= 4) {
298 8dd3dca3 aurel32
        qemu_get_be32s(f, &env->smbase);
299 5cc1d1e6 bellard
    }
300 5cc1d1e6 bellard
    if (version_id >= 5) {
301 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->pat);
302 5cc1d1e6 bellard
        qemu_get_be32s(f, &env->hflags2);
303 9656f324 pbrook
        if (version_id < 6)
304 9656f324 pbrook
            qemu_get_be32s(f, &env->halted);
305 5cc1d1e6 bellard
306 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->vm_hsave);
307 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->vm_vmcb);
308 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->tsc_offset);
309 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->intercept);
310 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_cr_read);
311 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_cr_write);
312 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_dr_read);
313 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_dr_write);
314 5cc1d1e6 bellard
        qemu_get_be32s(f, &env->intercept_exceptions);
315 5cc1d1e6 bellard
        qemu_get_8s(f, &env->v_tpr);
316 5cc1d1e6 bellard
    }
317 dd5e3b17 aliguori
318 dd5e3b17 aliguori
    if (version_id >= 8) {
319 dd5e3b17 aliguori
        /* MTRRs */
320 dd5e3b17 aliguori
        for(i = 0; i < 11; i++)
321 dd5e3b17 aliguori
            qemu_get_be64s(f, &env->mtrr_fixed[i]);
322 dd5e3b17 aliguori
        qemu_get_be64s(f, &env->mtrr_deftype);
323 dd5e3b17 aliguori
        for(i = 0; i < 8; i++) {
324 dd5e3b17 aliguori
            qemu_get_be64s(f, &env->mtrr_var[i].base);
325 dd5e3b17 aliguori
            qemu_get_be64s(f, &env->mtrr_var[i].mask);
326 dd5e3b17 aliguori
        }
327 dd5e3b17 aliguori
    }
328 dd5e3b17 aliguori
329 5cc1d1e6 bellard
    /* XXX: ensure compatiblity for halted bit ? */
330 5cc1d1e6 bellard
    /* XXX: compute redundant hflags bits */
331 8dd3dca3 aurel32
    env->hflags = hflags;
332 8dd3dca3 aurel32
    tlb_flush(env, 1);
333 8dd3dca3 aurel32
    return 0;
334 8dd3dca3 aurel32
}