Statistics
| Branch: | Revision:

root / target-i386 / machine.c @ f5049756

History | View | Annotate | Download (8.4 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 2ca83a8d blueswir1
    qemu_put_be32s(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 8dd3dca3 aurel32
}
138 8dd3dca3 aurel32
139 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
140 8dd3dca3 aurel32
/* XXX: add that in a FPU generic layer */
141 8dd3dca3 aurel32
union x86_longdouble {
142 8dd3dca3 aurel32
    uint64_t mant;
143 8dd3dca3 aurel32
    uint16_t exp;
144 8dd3dca3 aurel32
};
145 8dd3dca3 aurel32
146 8dd3dca3 aurel32
#define MANTD1(fp)        (fp & ((1LL << 52) - 1))
147 8dd3dca3 aurel32
#define EXPBIAS1 1023
148 8dd3dca3 aurel32
#define EXPD1(fp)        ((fp >> 52) & 0x7FF)
149 8dd3dca3 aurel32
#define SIGND1(fp)        ((fp >> 32) & 0x80000000)
150 8dd3dca3 aurel32
151 8dd3dca3 aurel32
static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
152 8dd3dca3 aurel32
{
153 8dd3dca3 aurel32
    int e;
154 8dd3dca3 aurel32
    /* mantissa */
155 8dd3dca3 aurel32
    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
156 8dd3dca3 aurel32
    /* exponent + sign */
157 8dd3dca3 aurel32
    e = EXPD1(temp) - EXPBIAS1 + 16383;
158 8dd3dca3 aurel32
    e |= SIGND1(temp) >> 16;
159 8dd3dca3 aurel32
    p->exp = e;
160 8dd3dca3 aurel32
}
161 8dd3dca3 aurel32
#endif
162 8dd3dca3 aurel32
163 8dd3dca3 aurel32
int cpu_load(QEMUFile *f, void *opaque, int version_id)
164 8dd3dca3 aurel32
{
165 8dd3dca3 aurel32
    CPUState *env = opaque;
166 8dd3dca3 aurel32
    int i, guess_mmx;
167 8dd3dca3 aurel32
    uint32_t hflags;
168 8dd3dca3 aurel32
    uint16_t fpus, fpuc, fptag, fpregs_format;
169 7caa33f7 aurel32
    int32_t a20_mask;
170 8dd3dca3 aurel32
171 9656f324 pbrook
    if (version_id != 3 && version_id != 4 && version_id != 5
172 2436b61a balrog
        && version_id != 6 && version_id != 7)
173 8dd3dca3 aurel32
        return -EINVAL;
174 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++)
175 8dd3dca3 aurel32
        qemu_get_betls(f, &env->regs[i]);
176 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eip);
177 8dd3dca3 aurel32
    qemu_get_betls(f, &env->eflags);
178 8dd3dca3 aurel32
    qemu_get_be32s(f, &hflags);
179 8dd3dca3 aurel32
180 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpuc);
181 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpus);
182 8dd3dca3 aurel32
    qemu_get_be16s(f, &fptag);
183 8dd3dca3 aurel32
    qemu_get_be16s(f, &fpregs_format);
184 8dd3dca3 aurel32
185 8dd3dca3 aurel32
    /* NOTE: we cannot always restore the FPU state if the image come
186 8dd3dca3 aurel32
       from a host with a different 'USE_X86LDOUBLE' define. We guess
187 8dd3dca3 aurel32
       if we are in an MMX state to restore correctly in that case. */
188 8dd3dca3 aurel32
    guess_mmx = ((fptag == 0xff) && (fpus & 0x3800) == 0);
189 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
190 8dd3dca3 aurel32
        uint64_t mant;
191 8dd3dca3 aurel32
        uint16_t exp;
192 8dd3dca3 aurel32
193 8dd3dca3 aurel32
        switch(fpregs_format) {
194 8dd3dca3 aurel32
        case 0:
195 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
196 8dd3dca3 aurel32
            exp = qemu_get_be16(f);
197 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
198 8dd3dca3 aurel32
            env->fpregs[i].d = cpu_set_fp80(mant, exp);
199 8dd3dca3 aurel32
#else
200 8dd3dca3 aurel32
            /* difficult case */
201 8dd3dca3 aurel32
            if (guess_mmx)
202 8dd3dca3 aurel32
                env->fpregs[i].mmx.MMX_Q(0) = mant;
203 8dd3dca3 aurel32
            else
204 8dd3dca3 aurel32
                env->fpregs[i].d = cpu_set_fp80(mant, exp);
205 8dd3dca3 aurel32
#endif
206 8dd3dca3 aurel32
            break;
207 8dd3dca3 aurel32
        case 1:
208 8dd3dca3 aurel32
            mant = qemu_get_be64(f);
209 8dd3dca3 aurel32
#ifdef USE_X86LDOUBLE
210 8dd3dca3 aurel32
            {
211 8dd3dca3 aurel32
                union x86_longdouble *p;
212 8dd3dca3 aurel32
                /* difficult case */
213 8dd3dca3 aurel32
                p = (void *)&env->fpregs[i];
214 8dd3dca3 aurel32
                if (guess_mmx) {
215 8dd3dca3 aurel32
                    p->mant = mant;
216 8dd3dca3 aurel32
                    p->exp = 0xffff;
217 8dd3dca3 aurel32
                } else {
218 8dd3dca3 aurel32
                    fp64_to_fp80(p, mant);
219 8dd3dca3 aurel32
                }
220 8dd3dca3 aurel32
            }
221 8dd3dca3 aurel32
#else
222 8dd3dca3 aurel32
            env->fpregs[i].mmx.MMX_Q(0) = mant;
223 8dd3dca3 aurel32
#endif
224 8dd3dca3 aurel32
            break;
225 8dd3dca3 aurel32
        default:
226 8dd3dca3 aurel32
            return -EINVAL;
227 8dd3dca3 aurel32
        }
228 8dd3dca3 aurel32
    }
229 8dd3dca3 aurel32
230 8dd3dca3 aurel32
    env->fpuc = fpuc;
231 8dd3dca3 aurel32
    /* XXX: restore FPU round state */
232 8dd3dca3 aurel32
    env->fpstt = (fpus >> 11) & 7;
233 8dd3dca3 aurel32
    env->fpus = fpus & ~0x3800;
234 8dd3dca3 aurel32
    fptag ^= 0xff;
235 8dd3dca3 aurel32
    for(i = 0; i < 8; i++) {
236 8dd3dca3 aurel32
        env->fptags[i] = (fptag >> i) & 1;
237 8dd3dca3 aurel32
    }
238 8dd3dca3 aurel32
239 8dd3dca3 aurel32
    for(i = 0; i < 6; i++)
240 8dd3dca3 aurel32
        cpu_get_seg(f, &env->segs[i]);
241 8dd3dca3 aurel32
    cpu_get_seg(f, &env->ldt);
242 8dd3dca3 aurel32
    cpu_get_seg(f, &env->tr);
243 8dd3dca3 aurel32
    cpu_get_seg(f, &env->gdt);
244 8dd3dca3 aurel32
    cpu_get_seg(f, &env->idt);
245 8dd3dca3 aurel32
246 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->sysenter_cs);
247 2436b61a balrog
    if (version_id >= 7) {
248 2436b61a balrog
        qemu_get_betls(f, &env->sysenter_esp);
249 2436b61a balrog
        qemu_get_betls(f, &env->sysenter_eip);
250 2436b61a balrog
    } else {
251 2436b61a balrog
        qemu_get_be32s(f, &env->sysenter_esp);
252 2436b61a balrog
        qemu_get_be32s(f, &env->sysenter_eip);
253 2436b61a balrog
    }
254 8dd3dca3 aurel32
255 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[0]);
256 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[2]);
257 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[3]);
258 8dd3dca3 aurel32
    qemu_get_betls(f, &env->cr[4]);
259 8dd3dca3 aurel32
260 8dd3dca3 aurel32
    for(i = 0; i < 8; i++)
261 8dd3dca3 aurel32
        qemu_get_betls(f, &env->dr[i]);
262 8dd3dca3 aurel32
263 8dd3dca3 aurel32
    /* MMU */
264 2ca83a8d blueswir1
    qemu_get_be32s(f, &a20_mask);
265 7caa33f7 aurel32
    env->a20_mask = a20_mask;
266 8dd3dca3 aurel32
267 8dd3dca3 aurel32
    qemu_get_be32s(f, &env->mxcsr);
268 8dd3dca3 aurel32
    for(i = 0; i < CPU_NB_REGS; i++) {
269 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(0));
270 8dd3dca3 aurel32
        qemu_get_be64s(f, &env->xmm_regs[i].XMM_Q(1));
271 8dd3dca3 aurel32
    }
272 8dd3dca3 aurel32
273 8dd3dca3 aurel32
#ifdef TARGET_X86_64
274 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->efer);
275 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->star);
276 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->lstar);
277 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->cstar);
278 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->fmask);
279 8dd3dca3 aurel32
    qemu_get_be64s(f, &env->kernelgsbase);
280 8dd3dca3 aurel32
#endif
281 5cc1d1e6 bellard
    if (version_id >= 4) {
282 8dd3dca3 aurel32
        qemu_get_be32s(f, &env->smbase);
283 5cc1d1e6 bellard
    }
284 5cc1d1e6 bellard
    if (version_id >= 5) {
285 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->pat);
286 5cc1d1e6 bellard
        qemu_get_be32s(f, &env->hflags2);
287 9656f324 pbrook
        if (version_id < 6)
288 9656f324 pbrook
            qemu_get_be32s(f, &env->halted);
289 5cc1d1e6 bellard
290 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->vm_hsave);
291 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->vm_vmcb);
292 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->tsc_offset);
293 5cc1d1e6 bellard
        qemu_get_be64s(f, &env->intercept);
294 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_cr_read);
295 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_cr_write);
296 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_dr_read);
297 5cc1d1e6 bellard
        qemu_get_be16s(f, &env->intercept_dr_write);
298 5cc1d1e6 bellard
        qemu_get_be32s(f, &env->intercept_exceptions);
299 5cc1d1e6 bellard
        qemu_get_8s(f, &env->v_tpr);
300 5cc1d1e6 bellard
    }
301 5cc1d1e6 bellard
    /* XXX: ensure compatiblity for halted bit ? */
302 5cc1d1e6 bellard
    /* XXX: compute redundant hflags bits */
303 8dd3dca3 aurel32
    env->hflags = hflags;
304 8dd3dca3 aurel32
    tlb_flush(env, 1);
305 8dd3dca3 aurel32
    return 0;
306 8dd3dca3 aurel32
}