machine.c 24.7 KB
Newer Older
aurel32's avatar
aurel32 committed
1 2
#include "hw/hw.h"
#include "hw/boards.h"
3 4
#include "hw/i386/pc.h"
#include "hw/isa/isa.h"
aurel32's avatar
aurel32 committed
5

6
#include "cpu.h"
7
#include "sysemu/kvm.h"
aurel32's avatar
aurel32 committed
8

9 10 11 12
static const VMStateDescription vmstate_segment = {
    .name = "segment",
    .version_id = 1,
    .minimum_version_id = 1,
13
    .fields = (VMStateField[]) {
14 15 16 17 18 19 20 21
        VMSTATE_UINT32(selector, SegmentCache),
        VMSTATE_UINTTL(base, SegmentCache),
        VMSTATE_UINT32(limit, SegmentCache),
        VMSTATE_UINT32(flags, SegmentCache),
        VMSTATE_END_OF_LIST()
    }
};

Juan Quintela's avatar
Juan Quintela committed
22 23 24 25 26 27 28
#define VMSTATE_SEGMENT(_field, _state) {                            \
    .name       = (stringify(_field)),                               \
    .size       = sizeof(SegmentCache),                              \
    .vmsd       = &vmstate_segment,                                  \
    .flags      = VMS_STRUCT,                                        \
    .offset     = offsetof(_state, _field)                           \
            + type_check(SegmentCache,typeof_field(_state, _field))  \
aurel32's avatar
aurel32 committed
29 30
}

Juan Quintela's avatar
Juan Quintela committed
31 32
#define VMSTATE_SEGMENT_ARRAY(_field, _state, _n)                    \
    VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_segment, SegmentCache)
aurel32's avatar
aurel32 committed
33

34 35 36 37
static const VMStateDescription vmstate_xmm_reg = {
    .name = "xmm_reg",
    .version_id = 1,
    .minimum_version_id = 1,
38
    .fields = (VMStateField[]) {
39 40 41 42 43 44
        VMSTATE_UINT64(XMM_Q(0), XMMReg),
        VMSTATE_UINT64(XMM_Q(1), XMMReg),
        VMSTATE_END_OF_LIST()
    }
};

Juan Quintela's avatar
Juan Quintela committed
45 46
#define VMSTATE_XMM_REGS(_field, _state, _n)                         \
    VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_xmm_reg, XMMReg)
47

48 49 50 51 52
/* YMMH format is the same as XMM */
static const VMStateDescription vmstate_ymmh_reg = {
    .name = "ymmh_reg",
    .version_id = 1,
    .minimum_version_id = 1,
53
    .fields = (VMStateField[]) {
54 55 56 57 58 59 60 61 62
        VMSTATE_UINT64(XMM_Q(0), XMMReg),
        VMSTATE_UINT64(XMM_Q(1), XMMReg),
        VMSTATE_END_OF_LIST()
    }
};

#define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v)                         \
    VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_ymmh_reg, XMMReg)

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
static const VMStateDescription vmstate_zmmh_reg = {
    .name = "zmmh_reg",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(YMM_Q(0), YMMReg),
        VMSTATE_UINT64(YMM_Q(1), YMMReg),
        VMSTATE_UINT64(YMM_Q(2), YMMReg),
        VMSTATE_UINT64(YMM_Q(3), YMMReg),
        VMSTATE_END_OF_LIST()
    }
};

#define VMSTATE_ZMMH_REGS_VARS(_field, _state, _n)                             \
    VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_zmmh_reg, YMMReg)

#ifdef TARGET_X86_64
static const VMStateDescription vmstate_hi16_zmm_reg = {
    .name = "hi16_zmm_reg",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(ZMM_Q(0), ZMMReg),
        VMSTATE_UINT64(ZMM_Q(1), ZMMReg),
        VMSTATE_UINT64(ZMM_Q(2), ZMMReg),
        VMSTATE_UINT64(ZMM_Q(3), ZMMReg),
        VMSTATE_UINT64(ZMM_Q(4), ZMMReg),
        VMSTATE_UINT64(ZMM_Q(5), ZMMReg),
        VMSTATE_UINT64(ZMM_Q(6), ZMMReg),
        VMSTATE_UINT64(ZMM_Q(7), ZMMReg),
        VMSTATE_END_OF_LIST()
    }
};

#define VMSTATE_Hi16_ZMM_REGS_VARS(_field, _state, _n)                         \
    VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_hi16_zmm_reg, ZMMReg)
#endif

Liu Jinsong's avatar
Liu Jinsong committed
101 102 103 104
static const VMStateDescription vmstate_bnd_regs = {
    .name = "bnd_regs",
    .version_id = 1,
    .minimum_version_id = 1,
105
    .fields = (VMStateField[]) {
Liu Jinsong's avatar
Liu Jinsong committed
106 107 108 109 110 111 112 113 114
        VMSTATE_UINT64(lb, BNDReg),
        VMSTATE_UINT64(ub, BNDReg),
        VMSTATE_END_OF_LIST()
    }
};

#define VMSTATE_BND_REGS(_field, _state, _n)          \
    VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_bnd_regs, BNDReg)

115 116 117 118
static const VMStateDescription vmstate_mtrr_var = {
    .name = "mtrr_var",
    .version_id = 1,
    .minimum_version_id = 1,
119
    .fields = (VMStateField[]) {
120 121 122 123 124 125
        VMSTATE_UINT64(base, MTRRVar),
        VMSTATE_UINT64(mask, MTRRVar),
        VMSTATE_END_OF_LIST()
    }
};

Juan Quintela's avatar
Juan Quintela committed
126 127
#define VMSTATE_MTRR_VARS(_field, _state, _n, _v)                    \
    VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar)
128

Juan Quintela's avatar
Juan Quintela committed
129
static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size)
130
{
Juan Quintela's avatar
Juan Quintela committed
131 132
    fprintf(stderr, "call put_fpreg() with invalid arguments\n");
    exit(0);
133 134
}

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
/* XXX: add that in a FPU generic layer */
union x86_longdouble {
    uint64_t mant;
    uint16_t exp;
};

#define MANTD1(fp)	(fp & ((1LL << 52) - 1))
#define EXPBIAS1 1023
#define EXPD1(fp)	((fp >> 52) & 0x7FF)
#define SIGND1(fp)	((fp >> 32) & 0x80000000)

static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp)
{
    int e;
    /* mantissa */
    p->mant = (MANTD1(temp) << 11) | (1LL << 63);
    /* exponent + sign */
    e = EXPD1(temp) - EXPBIAS1 + 16383;
    e |= SIGND1(temp) >> 16;
    p->exp = e;
}

static int get_fpreg(QEMUFile *f, void *opaque, size_t size)
{
    FPReg *fp_reg = opaque;
    uint64_t mant;
    uint16_t exp;

    qemu_get_be64s(f, &mant);
    qemu_get_be16s(f, &exp);
    fp_reg->d = cpu_set_fp80(mant, exp);
    return 0;
}

static void put_fpreg(QEMUFile *f, void *opaque, size_t size)
{
    FPReg *fp_reg = opaque;
    uint64_t mant;
    uint16_t exp;
    /* we save the real CPU data (in case of MMX usage only 'mant'
       contains the MMX register */
    cpu_get_fp80(&mant, &exp, fp_reg->d);
    qemu_put_be64s(f, &mant);
    qemu_put_be16s(f, &exp);
}

181
static const VMStateInfo vmstate_fpreg = {
Juan Quintela's avatar
Juan Quintela committed
182 183 184 185 186
    .name = "fpreg",
    .get  = get_fpreg,
    .put  = put_fpreg,
};

187 188 189 190 191 192 193 194 195 196 197
static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size)
{
    union x86_longdouble *p = opaque;
    uint64_t mant;

    qemu_get_be64s(f, &mant);
    p->mant = mant;
    p->exp = 0xffff;
    return 0;
}

198
static const VMStateInfo vmstate_fpreg_1_mmx = {
Juan Quintela's avatar
Juan Quintela committed
199 200 201 202 203
    .name = "fpreg_1_mmx",
    .get  = get_fpreg_1_mmx,
    .put  = put_fpreg_error,
};

204 205 206 207 208 209 210 211 212 213
static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size)
{
    union x86_longdouble *p = opaque;
    uint64_t mant;

    qemu_get_be64s(f, &mant);
    fp64_to_fp80(p, mant);
    return 0;
}

214
static const VMStateInfo vmstate_fpreg_1_no_mmx = {
Juan Quintela's avatar
Juan Quintela committed
215 216 217 218 219 220 221
    .name = "fpreg_1_no_mmx",
    .get  = get_fpreg_1_no_mmx,
    .put  = put_fpreg_error,
};

static bool fpregs_is_0(void *opaque, int version_id)
{
222 223
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
Juan Quintela's avatar
Juan Quintela committed
224 225 226 227 228 229

    return (env->fpregs_format_vmstate == 0);
}

static bool fpregs_is_1_mmx(void *opaque, int version_id)
{
230 231
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
Juan Quintela's avatar
Juan Quintela committed
232 233 234 235 236 237 238 239 240
    int guess_mmx;

    guess_mmx = ((env->fptag_vmstate == 0xff) &&
                 (env->fpus_vmstate & 0x3800) == 0);
    return (guess_mmx && (env->fpregs_format_vmstate == 1));
}

static bool fpregs_is_1_no_mmx(void *opaque, int version_id)
{
241 242
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
Juan Quintela's avatar
Juan Quintela committed
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
    int guess_mmx;

    guess_mmx = ((env->fptag_vmstate == 0xff) &&
                 (env->fpus_vmstate & 0x3800) == 0);
    return (!guess_mmx && (env->fpregs_format_vmstate == 1));
}

#define VMSTATE_FP_REGS(_field, _state, _n)                               \
    VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_0, vmstate_fpreg, FPReg), \
    VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_mmx, vmstate_fpreg_1_mmx, FPReg), \
    VMSTATE_ARRAY_TEST(_field, _state, _n, fpregs_is_1_no_mmx, vmstate_fpreg_1_no_mmx, FPReg)

static bool version_is_5(void *opaque, int version_id)
{
    return version_id == 5;
}

#ifdef TARGET_X86_64
static bool less_than_7(void *opaque, int version_id)
{
    return version_id < 7;
}

static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
{
    uint64_t *v = pv;
    *v = qemu_get_be32(f);
    return 0;
}

static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size)
{
    uint64_t *v = pv;
    qemu_put_be32(f, *v);
}

279
static const VMStateInfo vmstate_hack_uint64_as_uint32 = {
Juan Quintela's avatar
Juan Quintela committed
280 281 282 283 284 285
    .name = "uint64_as_uint32",
    .get  = get_uint64_as_uint32,
    .put  = put_uint64_as_uint32,
};

#define VMSTATE_HACK_UINT32(_f, _s, _t)                                  \
286
    VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_hack_uint64_as_uint32, uint64_t)
Juan Quintela's avatar
Juan Quintela committed
287 288
#endif

289
static void cpu_pre_save(void *opaque)
aurel32's avatar
aurel32 committed
290
{
291 292
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
293
    int i;
aurel32's avatar
aurel32 committed
294 295

    /* FPU */
296
    env->fpus_vmstate = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
297
    env->fptag_vmstate = 0;
aurel32's avatar
aurel32 committed
298
    for(i = 0; i < 8; i++) {
299
        env->fptag_vmstate |= ((!env->fptags[i]) << i);
aurel32's avatar
aurel32 committed
300 301
    }

302
    env->fpregs_format_vmstate = 0;
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320

    /*
     * Real mode guest segments register DPL should be zero.
     * Older KVM version were setting it wrongly.
     * Fixing it will allow live migration to host with unrestricted guest
     * support (otherwise the migration will fail with invalid guest state
     * error).
     */
    if (!(env->cr[0] & CR0_PE_MASK) &&
        (env->segs[R_CS].flags >> DESC_DPL_SHIFT & 3) != 0) {
        env->segs[R_CS].flags &= ~(env->segs[R_CS].flags & DESC_DPL_MASK);
        env->segs[R_DS].flags &= ~(env->segs[R_DS].flags & DESC_DPL_MASK);
        env->segs[R_ES].flags &= ~(env->segs[R_ES].flags & DESC_DPL_MASK);
        env->segs[R_FS].flags &= ~(env->segs[R_FS].flags & DESC_DPL_MASK);
        env->segs[R_GS].flags &= ~(env->segs[R_GS].flags & DESC_DPL_MASK);
        env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK);
    }

321 322
}

323 324
static int cpu_post_load(void *opaque, int version_id)
{
325
    X86CPU *cpu = opaque;
326
    CPUState *cs = CPU(cpu);
327
    CPUX86State *env = &cpu->env;
328 329
    int i;

330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
    /*
     * Real mode guest segments register DPL should be zero.
     * Older KVM version were setting it wrongly.
     * Fixing it will allow live migration from such host that don't have
     * restricted guest support to a host with unrestricted guest support
     * (otherwise the migration will fail with invalid guest state
     * error).
     */
    if (!(env->cr[0] & CR0_PE_MASK) &&
        (env->segs[R_CS].flags >> DESC_DPL_SHIFT & 3) != 0) {
        env->segs[R_CS].flags &= ~(env->segs[R_CS].flags & DESC_DPL_MASK);
        env->segs[R_DS].flags &= ~(env->segs[R_DS].flags & DESC_DPL_MASK);
        env->segs[R_ES].flags &= ~(env->segs[R_ES].flags & DESC_DPL_MASK);
        env->segs[R_FS].flags &= ~(env->segs[R_FS].flags & DESC_DPL_MASK);
        env->segs[R_GS].flags &= ~(env->segs[R_GS].flags & DESC_DPL_MASK);
        env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK);
    }

348 349 350 351 352 353 354 355
    /* Older versions of QEMU incorrectly used CS.DPL as the CPL when
     * running under KVM.  This is wrong for conforming code segments.
     * Luckily, in our implementation the CPL field of hflags is redundant
     * and we can get the right value from the SS descriptor privilege level.
     */
    env->hflags &= ~HF_CPL_MASK;
    env->hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;

356 357 358 359 360 361
    env->fpstt = (env->fpus_vmstate >> 11) & 7;
    env->fpus = env->fpus_vmstate & ~0x3800;
    env->fptag_vmstate ^= 0xff;
    for(i = 0; i < 8; i++) {
        env->fptags[i] = (env->fptag_vmstate >> i) & 1;
    }
362
    update_fp_status(env);
363

364
    cpu_breakpoint_remove_all(cs, BP_CPU);
365
    cpu_watchpoint_remove_all(cs, BP_CPU);
366
    for (i = 0; i < DR7_MAX_BP; i++) {
367
        hw_breakpoint_insert(env, i);
368
    }
369
    tlb_flush(cs, 1);
370

Juan Quintela's avatar
Juan Quintela committed
371
    return 0;
372 373
}

374 375
static bool async_pf_msr_needed(void *opaque)
{
376
    X86CPU *cpu = opaque;
377

378
    return cpu->env.async_pf_en_msr != 0;
379 380
}

381 382
static bool pv_eoi_msr_needed(void *opaque)
{
383
    X86CPU *cpu = opaque;
384

385
    return cpu->env.pv_eoi_en_msr != 0;
386 387
}

388 389
static bool steal_time_msr_needed(void *opaque)
{
390
    X86CPU *cpu = opaque;
391

392
    return cpu->env.steal_time_msr != 0;
393 394 395 396 397 398
}

static const VMStateDescription vmstate_steal_time_msr = {
    .name = "cpu/steal_time_msr",
    .version_id = 1,
    .minimum_version_id = 1,
399
    .fields = (VMStateField[]) {
400
        VMSTATE_UINT64(env.steal_time_msr, X86CPU),
401 402 403 404
        VMSTATE_END_OF_LIST()
    }
};

405 406 407 408
static const VMStateDescription vmstate_async_pf_msr = {
    .name = "cpu/async_pf_msr",
    .version_id = 1,
    .minimum_version_id = 1,
409
    .fields = (VMStateField[]) {
410
        VMSTATE_UINT64(env.async_pf_en_msr, X86CPU),
411 412 413 414
        VMSTATE_END_OF_LIST()
    }
};

415 416 417 418
static const VMStateDescription vmstate_pv_eoi_msr = {
    .name = "cpu/async_pv_eoi_msr",
    .version_id = 1,
    .minimum_version_id = 1,
419
    .fields = (VMStateField[]) {
420
        VMSTATE_UINT64(env.pv_eoi_en_msr, X86CPU),
421 422 423 424
        VMSTATE_END_OF_LIST()
    }
};

425 426
static bool fpop_ip_dp_needed(void *opaque)
{
427 428
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
429 430 431 432 433 434 435 436

    return env->fpop != 0 || env->fpip != 0 || env->fpdp != 0;
}

static const VMStateDescription vmstate_fpop_ip_dp = {
    .name = "cpu/fpop_ip_dp",
    .version_id = 1,
    .minimum_version_id = 1,
437
    .fields = (VMStateField[]) {
438 439 440
        VMSTATE_UINT16(env.fpop, X86CPU),
        VMSTATE_UINT64(env.fpip, X86CPU),
        VMSTATE_UINT64(env.fpdp, X86CPU),
441 442 443 444
        VMSTATE_END_OF_LIST()
    }
};

445 446
static bool tsc_adjust_needed(void *opaque)
{
447 448
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
449 450 451 452 453 454 455 456

    return env->tsc_adjust != 0;
}

static const VMStateDescription vmstate_msr_tsc_adjust = {
    .name = "cpu/msr_tsc_adjust",
    .version_id = 1,
    .minimum_version_id = 1,
457
    .fields = (VMStateField[]) {
458
        VMSTATE_UINT64(env.tsc_adjust, X86CPU),
459 460 461 462
        VMSTATE_END_OF_LIST()
    }
};

463 464
static bool tscdeadline_needed(void *opaque)
{
465 466
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
467 468 469 470 471 472 473 474

    return env->tsc_deadline != 0;
}

static const VMStateDescription vmstate_msr_tscdeadline = {
    .name = "cpu/msr_tscdeadline",
    .version_id = 1,
    .minimum_version_id = 1,
475
    .fields = (VMStateField[]) {
476
        VMSTATE_UINT64(env.tsc_deadline, X86CPU),
477 478 479 480
        VMSTATE_END_OF_LIST()
    }
};

481 482
static bool misc_enable_needed(void *opaque)
{
483 484
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
485 486 487 488

    return env->msr_ia32_misc_enable != MSR_IA32_MISC_ENABLE_DEFAULT;
}

489 490 491 492 493 494 495 496
static bool feature_control_needed(void *opaque)
{
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;

    return env->msr_ia32_feature_control != 0;
}

497 498 499 500
static const VMStateDescription vmstate_msr_ia32_misc_enable = {
    .name = "cpu/msr_ia32_misc_enable",
    .version_id = 1,
    .minimum_version_id = 1,
501
    .fields = (VMStateField[]) {
502
        VMSTATE_UINT64(env.msr_ia32_misc_enable, X86CPU),
503 504 505 506
        VMSTATE_END_OF_LIST()
    }
};

507 508 509 510
static const VMStateDescription vmstate_msr_ia32_feature_control = {
    .name = "cpu/msr_ia32_feature_control",
    .version_id = 1,
    .minimum_version_id = 1,
511
    .fields = (VMStateField[]) {
512 513 514 515 516
        VMSTATE_UINT64(env.msr_ia32_feature_control, X86CPU),
        VMSTATE_END_OF_LIST()
    }
};

Paolo Bonzini's avatar
Paolo Bonzini committed
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
static bool pmu_enable_needed(void *opaque)
{
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
    int i;

    if (env->msr_fixed_ctr_ctrl || env->msr_global_ctrl ||
        env->msr_global_status || env->msr_global_ovf_ctrl) {
        return true;
    }
    for (i = 0; i < MAX_FIXED_COUNTERS; i++) {
        if (env->msr_fixed_counters[i]) {
            return true;
        }
    }
    for (i = 0; i < MAX_GP_COUNTERS; i++) {
        if (env->msr_gp_counters[i] || env->msr_gp_evtsel[i]) {
            return true;
        }
    }

    return false;
}

static const VMStateDescription vmstate_msr_architectural_pmu = {
    .name = "cpu/msr_architectural_pmu",
    .version_id = 1,
    .minimum_version_id = 1,
545
    .fields = (VMStateField[]) {
Paolo Bonzini's avatar
Paolo Bonzini committed
546 547 548 549 550 551 552 553 554 555 556
        VMSTATE_UINT64(env.msr_fixed_ctr_ctrl, X86CPU),
        VMSTATE_UINT64(env.msr_global_ctrl, X86CPU),
        VMSTATE_UINT64(env.msr_global_status, X86CPU),
        VMSTATE_UINT64(env.msr_global_ovf_ctrl, X86CPU),
        VMSTATE_UINT64_ARRAY(env.msr_fixed_counters, X86CPU, MAX_FIXED_COUNTERS),
        VMSTATE_UINT64_ARRAY(env.msr_gp_counters, X86CPU, MAX_GP_COUNTERS),
        VMSTATE_UINT64_ARRAY(env.msr_gp_evtsel, X86CPU, MAX_GP_COUNTERS),
        VMSTATE_END_OF_LIST()
    }
};

Liu Jinsong's avatar
Liu Jinsong committed
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
static bool mpx_needed(void *opaque)
{
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
    unsigned int i;

    for (i = 0; i < 4; i++) {
        if (env->bnd_regs[i].lb || env->bnd_regs[i].ub) {
            return true;
        }
    }

    if (env->bndcs_regs.cfgu || env->bndcs_regs.sts) {
        return true;
    }

    return !!env->msr_bndcfgs;
}

static const VMStateDescription vmstate_mpx = {
    .name = "cpu/mpx",
    .version_id = 1,
    .minimum_version_id = 1,
580
    .fields = (VMStateField[]) {
Liu Jinsong's avatar
Liu Jinsong committed
581 582 583 584 585 586 587 588
        VMSTATE_BND_REGS(env.bnd_regs, X86CPU, 4),
        VMSTATE_UINT64(env.bndcs_regs.cfgu, X86CPU),
        VMSTATE_UINT64(env.bndcs_regs.sts, X86CPU),
        VMSTATE_UINT64(env.msr_bndcfgs, X86CPU),
        VMSTATE_END_OF_LIST()
    }
};

589 590 591 592 593 594 595 596 597 598 599 600
static bool hyperv_hypercall_enable_needed(void *opaque)
{
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;

    return env->msr_hv_hypercall != 0 || env->msr_hv_guest_os_id != 0;
}

static const VMStateDescription vmstate_msr_hypercall_hypercall = {
    .name = "cpu/msr_hyperv_hypercall",
    .version_id = 1,
    .minimum_version_id = 1,
601
    .fields = (VMStateField[]) {
602
        VMSTATE_UINT64(env.msr_hv_guest_os_id, X86CPU),
603
        VMSTATE_UINT64(env.msr_hv_hypercall, X86CPU),
604 605 606 607
        VMSTATE_END_OF_LIST()
    }
};

608 609 610 611 612 613 614 615 616 617 618 619
static bool hyperv_vapic_enable_needed(void *opaque)
{
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;

    return env->msr_hv_vapic != 0;
}

static const VMStateDescription vmstate_msr_hyperv_vapic = {
    .name = "cpu/msr_hyperv_vapic",
    .version_id = 1,
    .minimum_version_id = 1,
620
    .fields = (VMStateField[]) {
621 622 623 624 625
        VMSTATE_UINT64(env.msr_hv_vapic, X86CPU),
        VMSTATE_END_OF_LIST()
    }
};

626 627 628 629 630 631 632 633 634 635 636 637
static bool hyperv_time_enable_needed(void *opaque)
{
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;

    return env->msr_hv_tsc != 0;
}

static const VMStateDescription vmstate_msr_hyperv_time = {
    .name = "cpu/msr_hyperv_time",
    .version_id = 1,
    .minimum_version_id = 1,
638
    .fields = (VMStateField[]) {
639 640 641 642 643
        VMSTATE_UINT64(env.msr_hv_tsc, X86CPU),
        VMSTATE_END_OF_LIST()
    }
};

644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
static bool avx512_needed(void *opaque)
{
    X86CPU *cpu = opaque;
    CPUX86State *env = &cpu->env;
    unsigned int i;

    for (i = 0; i < NB_OPMASK_REGS; i++) {
        if (env->opmask_regs[i]) {
            return true;
        }
    }

    for (i = 0; i < CPU_NB_REGS; i++) {
#define ENV_ZMMH(reg, field) (env->zmmh_regs[reg].YMM_Q(field))
        if (ENV_ZMMH(i, 0) || ENV_ZMMH(i, 1) ||
            ENV_ZMMH(i, 2) || ENV_ZMMH(i, 3)) {
            return true;
        }
#ifdef TARGET_X86_64
#define ENV_Hi16_ZMM(reg, field) (env->hi16_zmm_regs[reg].ZMM_Q(field))
        if (ENV_Hi16_ZMM(i, 0) || ENV_Hi16_ZMM(i, 1) ||
            ENV_Hi16_ZMM(i, 2) || ENV_Hi16_ZMM(i, 3) ||
            ENV_Hi16_ZMM(i, 4) || ENV_Hi16_ZMM(i, 5) ||
            ENV_Hi16_ZMM(i, 6) || ENV_Hi16_ZMM(i, 7)) {
            return true;
        }
#endif
    }

    return false;
}

static const VMStateDescription vmstate_avx512 = {
    .name = "cpu/avx512",
    .version_id = 1,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64_ARRAY(env.opmask_regs, X86CPU, NB_OPMASK_REGS),
        VMSTATE_ZMMH_REGS_VARS(env.zmmh_regs, X86CPU, CPU_NB_REGS),
#ifdef TARGET_X86_64
        VMSTATE_Hi16_ZMM_REGS_VARS(env.hi16_zmm_regs, X86CPU, CPU_NB_REGS),
#endif
        VMSTATE_END_OF_LIST()
    }
};

690
VMStateDescription vmstate_x86_cpu = {
Juan Quintela's avatar
Juan Quintela committed
691
    .name = "cpu",
692
    .version_id = 12,
Juan Quintela's avatar
Juan Quintela committed
693 694 695
    .minimum_version_id = 3,
    .pre_save = cpu_pre_save,
    .post_load = cpu_post_load,
696
    .fields = (VMStateField[]) {
697 698 699 700
        VMSTATE_UINTTL_ARRAY(env.regs, X86CPU, CPU_NB_REGS),
        VMSTATE_UINTTL(env.eip, X86CPU),
        VMSTATE_UINTTL(env.eflags, X86CPU),
        VMSTATE_UINT32(env.hflags, X86CPU),
Juan Quintela's avatar
Juan Quintela committed
701
        /* FPU */
702 703 704 705 706 707 708 709 710 711 712 713 714
        VMSTATE_UINT16(env.fpuc, X86CPU),
        VMSTATE_UINT16(env.fpus_vmstate, X86CPU),
        VMSTATE_UINT16(env.fptag_vmstate, X86CPU),
        VMSTATE_UINT16(env.fpregs_format_vmstate, X86CPU),
        VMSTATE_FP_REGS(env.fpregs, X86CPU, 8),

        VMSTATE_SEGMENT_ARRAY(env.segs, X86CPU, 6),
        VMSTATE_SEGMENT(env.ldt, X86CPU),
        VMSTATE_SEGMENT(env.tr, X86CPU),
        VMSTATE_SEGMENT(env.gdt, X86CPU),
        VMSTATE_SEGMENT(env.idt, X86CPU),

        VMSTATE_UINT32(env.sysenter_cs, X86CPU),
Juan Quintela's avatar
Juan Quintela committed
715 716
#ifdef TARGET_X86_64
        /* Hack: In v7 size changed from 32 to 64 bits on x86_64 */
717 718 719 720
        VMSTATE_HACK_UINT32(env.sysenter_esp, X86CPU, less_than_7),
        VMSTATE_HACK_UINT32(env.sysenter_eip, X86CPU, less_than_7),
        VMSTATE_UINTTL_V(env.sysenter_esp, X86CPU, 7),
        VMSTATE_UINTTL_V(env.sysenter_eip, X86CPU, 7),
aurel32's avatar
aurel32 committed
721
#else
722 723
        VMSTATE_UINTTL(env.sysenter_esp, X86CPU),
        VMSTATE_UINTTL(env.sysenter_eip, X86CPU),
724
#endif
aurel32's avatar
aurel32 committed
725

726 727 728 729 730
        VMSTATE_UINTTL(env.cr[0], X86CPU),
        VMSTATE_UINTTL(env.cr[2], X86CPU),
        VMSTATE_UINTTL(env.cr[3], X86CPU),
        VMSTATE_UINTTL(env.cr[4], X86CPU),
        VMSTATE_UINTTL_ARRAY(env.dr, X86CPU, 8),
Juan Quintela's avatar
Juan Quintela committed
731
        /* MMU */
732
        VMSTATE_INT32(env.a20_mask, X86CPU),
Juan Quintela's avatar
Juan Quintela committed
733
        /* XMM */
734 735
        VMSTATE_UINT32(env.mxcsr, X86CPU),
        VMSTATE_XMM_REGS(env.xmm_regs, X86CPU, CPU_NB_REGS),
aurel32's avatar
aurel32 committed
736 737

#ifdef TARGET_X86_64
738 739 740 741 742 743
        VMSTATE_UINT64(env.efer, X86CPU),
        VMSTATE_UINT64(env.star, X86CPU),
        VMSTATE_UINT64(env.lstar, X86CPU),
        VMSTATE_UINT64(env.cstar, X86CPU),
        VMSTATE_UINT64(env.fmask, X86CPU),
        VMSTATE_UINT64(env.kernelgsbase, X86CPU),
aurel32's avatar
aurel32 committed
744
#endif
745 746 747 748 749
        VMSTATE_UINT32_V(env.smbase, X86CPU, 4),

        VMSTATE_UINT64_V(env.pat, X86CPU, 5),
        VMSTATE_UINT32_V(env.hflags2, X86CPU, 5),

750
        VMSTATE_UINT32_TEST(parent_obj.halted, X86CPU, version_is_5),
751 752 753 754 755 756 757 758 759 760
        VMSTATE_UINT64_V(env.vm_hsave, X86CPU, 5),
        VMSTATE_UINT64_V(env.vm_vmcb, X86CPU, 5),
        VMSTATE_UINT64_V(env.tsc_offset, X86CPU, 5),
        VMSTATE_UINT64_V(env.intercept, X86CPU, 5),
        VMSTATE_UINT16_V(env.intercept_cr_read, X86CPU, 5),
        VMSTATE_UINT16_V(env.intercept_cr_write, X86CPU, 5),
        VMSTATE_UINT16_V(env.intercept_dr_read, X86CPU, 5),
        VMSTATE_UINT16_V(env.intercept_dr_write, X86CPU, 5),
        VMSTATE_UINT32_V(env.intercept_exceptions, X86CPU, 5),
        VMSTATE_UINT8_V(env.v_tpr, X86CPU, 5),
761
        /* MTRRs */
762 763
        VMSTATE_UINT64_ARRAY_V(env.mtrr_fixed, X86CPU, 11, 8),
        VMSTATE_UINT64_V(env.mtrr_deftype, X86CPU, 8),
764
        VMSTATE_MTRR_VARS(env.mtrr_var, X86CPU, MSR_MTRRcap_VCNT, 8),
Juan Quintela's avatar
Juan Quintela committed
765
        /* KVM-related states */
766 767 768 769 770 771 772 773 774
        VMSTATE_INT32_V(env.interrupt_injected, X86CPU, 9),
        VMSTATE_UINT32_V(env.mp_state, X86CPU, 9),
        VMSTATE_UINT64_V(env.tsc, X86CPU, 9),
        VMSTATE_INT32_V(env.exception_injected, X86CPU, 11),
        VMSTATE_UINT8_V(env.soft_interrupt, X86CPU, 11),
        VMSTATE_UINT8_V(env.nmi_injected, X86CPU, 11),
        VMSTATE_UINT8_V(env.nmi_pending, X86CPU, 11),
        VMSTATE_UINT8_V(env.has_error_code, X86CPU, 11),
        VMSTATE_UINT32_V(env.sipi_vector, X86CPU, 11),
Juan Quintela's avatar
Juan Quintela committed
775
        /* MCE */
776 777 778 779
        VMSTATE_UINT64_V(env.mcg_cap, X86CPU, 10),
        VMSTATE_UINT64_V(env.mcg_status, X86CPU, 10),
        VMSTATE_UINT64_V(env.mcg_ctl, X86CPU, 10),
        VMSTATE_UINT64_ARRAY_V(env.mce_banks, X86CPU, MCE_BANKS_DEF * 4, 10),
Juan Quintela's avatar
Juan Quintela committed
780
        /* rdtscp */
781
        VMSTATE_UINT64_V(env.tsc_aux, X86CPU, 11),
782
        /* KVM pvclock msr */
783 784
        VMSTATE_UINT64_V(env.system_time_msr, X86CPU, 11),
        VMSTATE_UINT64_V(env.wall_clock_msr, X86CPU, 11),
785
        /* XSAVE related fields */
786 787 788
        VMSTATE_UINT64_V(env.xcr0, X86CPU, 12),
        VMSTATE_UINT64_V(env.xstate_bv, X86CPU, 12),
        VMSTATE_YMMH_REGS_VARS(env.ymmh_regs, X86CPU, CPU_NB_REGS, 12),
Juan Quintela's avatar
Juan Quintela committed
789
        VMSTATE_END_OF_LIST()
790
        /* The above list is not sorted /wrt version numbers, watch out! */
791 792 793 794 795
    },
    .subsections = (VMStateSubsection []) {
        {
            .vmsd = &vmstate_async_pf_msr,
            .needed = async_pf_msr_needed,
796 797 798
        } , {
            .vmsd = &vmstate_pv_eoi_msr,
            .needed = pv_eoi_msr_needed,
799 800 801
        } , {
            .vmsd = &vmstate_steal_time_msr,
            .needed = steal_time_msr_needed,
802 803 804
        } , {
            .vmsd = &vmstate_fpop_ip_dp,
            .needed = fpop_ip_dp_needed,
805 806 807
        }, {
            .vmsd = &vmstate_msr_tsc_adjust,
            .needed = tsc_adjust_needed,
808 809 810
        }, {
            .vmsd = &vmstate_msr_tscdeadline,
            .needed = tscdeadline_needed,
811 812 813
        }, {
            .vmsd = &vmstate_msr_ia32_misc_enable,
            .needed = misc_enable_needed,
814 815 816
        }, {
            .vmsd = &vmstate_msr_ia32_feature_control,
            .needed = feature_control_needed,
Paolo Bonzini's avatar
Paolo Bonzini committed
817 818 819
        }, {
            .vmsd = &vmstate_msr_architectural_pmu,
            .needed = pmu_enable_needed,
Liu Jinsong's avatar
Liu Jinsong committed
820 821 822
        } , {
            .vmsd = &vmstate_mpx,
            .needed = mpx_needed,
823 824 825
        }, {
            .vmsd = &vmstate_msr_hypercall_hypercall,
            .needed = hyperv_hypercall_enable_needed,
826 827 828
        }, {
            .vmsd = &vmstate_msr_hyperv_vapic,
            .needed = hyperv_vapic_enable_needed,
829 830 831
        }, {
            .vmsd = &vmstate_msr_hyperv_time,
            .needed = hyperv_time_enable_needed,
832 833 834
        }, {
            .vmsd = &vmstate_avx512,
            .needed = avx512_needed,
835 836 837
        } , {
            /* empty */
        }
838
    }
Juan Quintela's avatar
Juan Quintela committed
839
};