Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ 8777643e

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