int kvm_arch_post_run(CPUState *env, struct kvm_run *run) { if (run->if_flag) env->eflags |= IF_MASK; else env->eflags &= ~IF_MASK; cpu_set_apic_tpr(env, run->cr8); cpu_set_apic_base(env, run->apic_base); return 0; }
void helper_wrmsr(CPUX86State *env) { uint64_t val; cpu_svm_check_intercept_param(env, SVM_EXIT_MSR, 1, GETPC()); val = ((uint32_t)env->regs[R_EAX]) | ((uint64_t)((uint32_t)env->regs[R_EDX]) << 32); switch ((uint32_t)env->regs[R_ECX]) { case MSR_IA32_SYSENTER_CS: env->sysenter_cs = val & 0xffff; break; case MSR_IA32_SYSENTER_ESP: env->sysenter_esp = val; break; case MSR_IA32_SYSENTER_EIP: env->sysenter_eip = val; break; case MSR_IA32_APICBASE: cpu_set_apic_base(x86_env_get_cpu(env)->apic_state, val); break; case MSR_EFER: { uint64_t update_mask; update_mask = 0; if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_SYSCALL) { update_mask |= MSR_EFER_SCE; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { update_mask |= MSR_EFER_LME; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { update_mask |= MSR_EFER_FFXSR; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_NX) { update_mask |= MSR_EFER_NXE; } if (env->features[FEAT_8000_0001_ECX] & CPUID_EXT3_SVM) { update_mask |= MSR_EFER_SVME; } if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_FFXSR) { update_mask |= MSR_EFER_FFXSR; } cpu_load_efer(env, (env->efer & ~update_mask) | (val & update_mask)); } break; case MSR_STAR: env->star = val; break; case MSR_PAT: env->pat = val; break; case MSR_VM_HSAVE_PA: env->vm_hsave = val; break; #ifdef TARGET_X86_64 case MSR_LSTAR: env->lstar = val; break; case MSR_CSTAR: env->cstar = val; break; case MSR_FMASK: env->fmask = val; break; case MSR_FSBASE: env->segs[R_FS].base = val; break; case MSR_GSBASE: env->segs[R_GS].base = val; break; case MSR_KERNELGSBASE: env->kernelgsbase = val; break; #endif case MSR_MTRRphysBase(0): case MSR_MTRRphysBase(1): case MSR_MTRRphysBase(2): case MSR_MTRRphysBase(3): case MSR_MTRRphysBase(4): case MSR_MTRRphysBase(5): case MSR_MTRRphysBase(6): case MSR_MTRRphysBase(7): env->mtrr_var[((uint32_t)env->regs[R_ECX] - MSR_MTRRphysBase(0)) / 2].base = val; break; case MSR_MTRRphysMask(0): case MSR_MTRRphysMask(1): case MSR_MTRRphysMask(2): case MSR_MTRRphysMask(3): case MSR_MTRRphysMask(4): case MSR_MTRRphysMask(5): case MSR_MTRRphysMask(6): case MSR_MTRRphysMask(7): env->mtrr_var[((uint32_t)env->regs[R_ECX] - MSR_MTRRphysMask(0)) / 2].mask = val; break; case MSR_MTRRfix64K_00000: env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix64K_00000] = val; break; case MSR_MTRRfix16K_80000: case MSR_MTRRfix16K_A0000: env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix16K_80000 + 1] = val; break; case MSR_MTRRfix4K_C0000: case MSR_MTRRfix4K_C8000: case MSR_MTRRfix4K_D0000: case MSR_MTRRfix4K_D8000: case MSR_MTRRfix4K_E0000: case MSR_MTRRfix4K_E8000: case MSR_MTRRfix4K_F0000: case MSR_MTRRfix4K_F8000: env->mtrr_fixed[(uint32_t)env->regs[R_ECX] - MSR_MTRRfix4K_C0000 + 3] = val; break; case MSR_MTRRdefType: env->mtrr_deftype = val; break; case MSR_MCG_STATUS: env->mcg_status = val; break; case MSR_MCG_CTL: if ((env->mcg_cap & MCG_CTL_P) && (val == 0 || val == ~(uint64_t)0)) { env->mcg_ctl = val; } break; case MSR_TSC_AUX: env->tsc_aux = val; break; case MSR_IA32_MISC_ENABLE: env->msr_ia32_misc_enable = val; break; case MSR_IA32_BNDCFGS: /* FIXME: #GP if reserved bits are set. */ /* FIXME: Extend highest implemented bit of linear address. */ env->msr_bndcfgs = val; cpu_sync_bndcs_hflags(env); break; default: if ((uint32_t)env->regs[R_ECX] >= MSR_MC0_CTL && (uint32_t)env->regs[R_ECX] < MSR_MC0_CTL + (4 * env->mcg_cap & 0xff)) { uint32_t offset = (uint32_t)env->regs[R_ECX] - MSR_MC0_CTL; if ((offset & 0x3) != 0 || (val == 0 || val == ~(uint64_t)0)) { env->mce_banks[offset] = val; } break; } /* XXX: exception? */ break; } }
static void whpx_get_registers(CPUState *cpu) { struct whpx_state *whpx = &whpx_global; struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu); struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr); X86CPU *x86_cpu = X86_CPU(cpu); struct whpx_register_set vcxt; uint64_t tpr, apic_base; HRESULT hr; int idx = 0; int i; assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); hr = WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index, whpx_register_names, RTL_NUMBER_OF(whpx_register_names), &vcxt.values[0]); if (FAILED(hr)) { error_report("WHPX: Failed to get virtual processor context, hr=%08lx", hr); } /* Indexes for first 16 registers match between HV and QEMU definitions */ for (idx = 0; idx < CPU_NB_REGS64; idx += 1) { env->regs[idx] = vcxt.values[idx].Reg64; } /* Same goes for RIP and RFLAGS */ assert(whpx_register_names[idx] == WHvX64RegisterRip); env->eip = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterRflags); env->eflags = vcxt.values[idx++].Reg64; /* Translate 6+4 segment registers. HV and QEMU order matches */ assert(idx == WHvX64RegisterEs); for (i = 0; i < 6; i += 1, idx += 1) { env->segs[i] = whpx_seg_h2q(&vcxt.values[idx].Segment); } assert(idx == WHvX64RegisterLdtr); env->ldt = whpx_seg_h2q(&vcxt.values[idx++].Segment); assert(idx == WHvX64RegisterTr); env->tr = whpx_seg_h2q(&vcxt.values[idx++].Segment); assert(idx == WHvX64RegisterIdtr); env->idt.base = vcxt.values[idx].Table.Base; env->idt.limit = vcxt.values[idx].Table.Limit; idx += 1; assert(idx == WHvX64RegisterGdtr); env->gdt.base = vcxt.values[idx].Table.Base; env->gdt.limit = vcxt.values[idx].Table.Limit; idx += 1; /* CR0, 2, 3, 4, 8 */ assert(whpx_register_names[idx] == WHvX64RegisterCr0); env->cr[0] = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterCr2); env->cr[2] = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterCr3); env->cr[3] = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterCr4); env->cr[4] = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterCr8); tpr = vcxt.values[idx++].Reg64; if (tpr != vcpu->tpr) { vcpu->tpr = tpr; cpu_set_apic_tpr(x86_cpu->apic_state, tpr); } /* 8 Debug Registers - Skipped */ /* 16 XMM registers */ assert(whpx_register_names[idx] == WHvX64RegisterXmm0); for (i = 0; i < 16; i += 1, idx += 1) { env->xmm_regs[i].ZMM_Q(0) = vcxt.values[idx].Reg128.Low64; env->xmm_regs[i].ZMM_Q(1) = vcxt.values[idx].Reg128.High64; } /* 8 FP registers */ assert(whpx_register_names[idx] == WHvX64RegisterFpMmx0); for (i = 0; i < 8; i += 1, idx += 1) { env->fpregs[i].mmx.MMX_Q(0) = vcxt.values[idx].Fp.AsUINT128.Low64; /* env->fpregs[i].mmx.MMX_Q(1) = vcxt.values[idx].Fp.AsUINT128.High64; */ } /* FP control status register */ assert(whpx_register_names[idx] == WHvX64RegisterFpControlStatus); env->fpuc = vcxt.values[idx].FpControlStatus.FpControl; env->fpstt = (vcxt.values[idx].FpControlStatus.FpStatus >> 11) & 0x7; env->fpus = vcxt.values[idx].FpControlStatus.FpStatus & ~0x3800; for (i = 0; i < 8; ++i) { env->fptags[i] = !((vcxt.values[idx].FpControlStatus.FpTag >> i) & 1); } env->fpop = vcxt.values[idx].FpControlStatus.LastFpOp; env->fpip = vcxt.values[idx].FpControlStatus.LastFpRip; idx += 1; /* XMM control status register */ assert(whpx_register_names[idx] == WHvX64RegisterXmmControlStatus); env->mxcsr = vcxt.values[idx].XmmControlStatus.XmmStatusControl; idx += 1; /* MSRs */ assert(whpx_register_names[idx] == WHvX64RegisterTsc); env->tsc = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterEfer); env->efer = vcxt.values[idx++].Reg64; #ifdef TARGET_X86_64 assert(whpx_register_names[idx] == WHvX64RegisterKernelGsBase); env->kernelgsbase = vcxt.values[idx++].Reg64; #endif assert(whpx_register_names[idx] == WHvX64RegisterApicBase); apic_base = vcxt.values[idx++].Reg64; if (apic_base != vcpu->apic_base) { vcpu->apic_base = apic_base; cpu_set_apic_base(x86_cpu->apic_state, vcpu->apic_base); } /* WHvX64RegisterPat - Skipped */ assert(whpx_register_names[idx] == WHvX64RegisterSysenterCs); env->sysenter_cs = vcxt.values[idx++].Reg64;; assert(whpx_register_names[idx] == WHvX64RegisterSysenterEip); env->sysenter_eip = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterSysenterEsp); env->sysenter_esp = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterStar); env->star = vcxt.values[idx++].Reg64; #ifdef TARGET_X86_64 assert(whpx_register_names[idx] == WHvX64RegisterLstar); env->lstar = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterCstar); env->cstar = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterSfmask); env->fmask = vcxt.values[idx++].Reg64; #endif /* Interrupt / Event Registers - Skipped */ assert(idx == RTL_NUMBER_OF(whpx_register_names)); return; }