Home | History | Annotate | Download | only in target-i386
      1 #include "hw/hw.h"
      2 #include "hw/boards.h"
      3 #include "hw/i386/pc.h"
      4 #include "hw/isa/isa.h"
      5 
      6 #include "cpu.h"
      7 #include "sysemu/kvm.h"
      8 
      9 static 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 
     17 static 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 
     25 void cpu_save(QEMUFile *f, void *opaque)
     26 {
     27     CPUX86State *env = opaque;
     28     uint16_t fptag, fpus, fpuc, fpregs_format;
     29     uint32_t hflags;
     30     int32_t a20_mask;
     31     int i;
     32 
     33     cpu_synchronize_state(ENV_GET_CPU(env), 0);
     34 
     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 
     54     fpregs_format = 1;
     55     qemu_put_be16s(f, &fpregs_format);
     56 
     57     for(i = 0; i < 8; i++) {
     58         /* 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));
     63     }
     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);
    107 
    108     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 
    148 int cpu_load(QEMUFile *f, void *opaque, int version_id)
    149 {
    150     CPUX86State *env = opaque;
    151     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);
    181             /* 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);
    186             break;
    187         case 1:
    188             mant = qemu_get_be64(f);
    189             env->fpregs[i].mmx.MMX_Q(0) = mant;
    190             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)
    258             qemu_get_be32s(f, &ENV_GET_CPU(env)->halted);
    259 
    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);
    309     cpu_synchronize_state(ENV_GET_CPU(env), 1);
    310     return 0;
    311 }
    312