File:  [Qemu by Fabrice Bellard] / qemu / target-i386 / machine.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:54:54 2018 UTC (3 years, 9 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

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

unix.superglobalmegacorp.com