Optimise vmexits by save/restoring less state in those cases instead of the full state.
Signed-off-by: Mohamed Mediouni <[email protected]> Reviewed-by: Bernhard Beschow <[email protected]> --- target/i386/whpx/whpx-all.c | 202 +++++++++++++++++++----------------- 1 file changed, 104 insertions(+), 98 deletions(-) diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index c09d9affef..ab583e922d 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -422,118 +422,124 @@ void whpx_set_registers(CPUState *cpu, WHPXStateLevel level) } assert(idx == WHvX64RegisterLdtr); - vcxt.values[idx++].Segment = whpx_seg_q2h(&env->ldt, 0, 0); - - assert(idx == WHvX64RegisterTr); - vcxt.values[idx++].Segment = whpx_seg_q2h(&env->tr, 0, 0); - - assert(idx == WHvX64RegisterIdtr); - vcxt.values[idx].Table.Base = env->idt.base; - vcxt.values[idx].Table.Limit = env->idt.limit; - idx += 1; - - assert(idx == WHvX64RegisterGdtr); - vcxt.values[idx].Table.Base = env->gdt.base; - vcxt.values[idx].Table.Limit = env->gdt.limit; - idx += 1; - - /* CR0, 2, 3, 4, 8 */ - assert(whpx_register_names[idx] == WHvX64RegisterCr0); - vcxt.values[idx++].Reg64 = env->cr[0]; - assert(whpx_register_names[idx] == WHvX64RegisterCr2); - vcxt.values[idx++].Reg64 = env->cr[2]; - assert(whpx_register_names[idx] == WHvX64RegisterCr3); - vcxt.values[idx++].Reg64 = env->cr[3]; - assert(whpx_register_names[idx] == WHvX64RegisterCr4); - vcxt.values[idx++].Reg64 = env->cr[4]; - assert(whpx_register_names[idx] == WHvX64RegisterCr8); - vcxt.values[idx++].Reg64 = vcpu->tpr; - - /* 8 Debug Registers - Skipped */ - /* - * Extended control registers needs to be handled separately depending - * on whether xsave is supported/enabled or not. + * Skip those registers for synchronisation after MMIO accesses + * as they're not going to be modified in that case. */ - whpx_set_xcrs(cpu); - - /* 16 XMM registers */ - assert(whpx_register_names[idx] == WHvX64RegisterXmm0); - idx_next = idx + 16; - for (i = 0; i < sizeof(env->xmm_regs) / sizeof(ZMMReg); i += 1, idx += 1) { - vcxt.values[idx].Reg128.Low64 = env->xmm_regs[i].ZMM_Q(0); - vcxt.values[idx].Reg128.High64 = env->xmm_regs[i].ZMM_Q(1); - } - idx = idx_next; - - /* 8 FP registers */ - assert(whpx_register_names[idx] == WHvX64RegisterFpMmx0); - for (i = 0; i < 8; i += 1, idx += 1) { - vcxt.values[idx].Fp.AsUINT128.Low64 = env->fpregs[i].mmx.MMX_Q(0); - /* vcxt.values[idx].Fp.AsUINT128.High64 = - env->fpregs[i].mmx.MMX_Q(1); - */ - } + if (level > WHPX_LEVEL_FAST_RUNTIME_STATE) { + vcxt.values[idx++].Segment = whpx_seg_q2h(&env->ldt, 0, 0); + + assert(idx == WHvX64RegisterTr); + vcxt.values[idx++].Segment = whpx_seg_q2h(&env->tr, 0, 0); + + assert(idx == WHvX64RegisterIdtr); + vcxt.values[idx].Table.Base = env->idt.base; + vcxt.values[idx].Table.Limit = env->idt.limit; + idx += 1; + + assert(idx == WHvX64RegisterGdtr); + vcxt.values[idx].Table.Base = env->gdt.base; + vcxt.values[idx].Table.Limit = env->gdt.limit; + idx += 1; + + /* CR0, 2, 3, 4, 8 */ + assert(whpx_register_names[idx] == WHvX64RegisterCr0); + vcxt.values[idx++].Reg64 = env->cr[0]; + assert(whpx_register_names[idx] == WHvX64RegisterCr2); + vcxt.values[idx++].Reg64 = env->cr[2]; + assert(whpx_register_names[idx] == WHvX64RegisterCr3); + vcxt.values[idx++].Reg64 = env->cr[3]; + assert(whpx_register_names[idx] == WHvX64RegisterCr4); + vcxt.values[idx++].Reg64 = env->cr[4]; + assert(whpx_register_names[idx] == WHvX64RegisterCr8); + vcxt.values[idx++].Reg64 = vcpu->tpr; + + /* 8 Debug Registers - Skipped */ - /* FP control status register */ - assert(whpx_register_names[idx] == WHvX64RegisterFpControlStatus); - vcxt.values[idx].FpControlStatus.FpControl = env->fpuc; - vcxt.values[idx].FpControlStatus.FpStatus = - (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; - vcxt.values[idx].FpControlStatus.FpTag = 0; - for (i = 0; i < 8; ++i) { - vcxt.values[idx].FpControlStatus.FpTag |= (!env->fptags[i]) << i; - } - vcxt.values[idx].FpControlStatus.Reserved = 0; - vcxt.values[idx].FpControlStatus.LastFpOp = env->fpop; - vcxt.values[idx].FpControlStatus.LastFpRip = env->fpip; - idx += 1; - - /* XMM control status register */ - assert(whpx_register_names[idx] == WHvX64RegisterXmmControlStatus); - vcxt.values[idx].XmmControlStatus.LastFpRdp = 0; - vcxt.values[idx].XmmControlStatus.XmmStatusControl = env->mxcsr; - vcxt.values[idx].XmmControlStatus.XmmStatusControlMask = 0x0000ffff; - idx += 1; + /* + * Extended control registers needs to be handled separately depending + * on whether xsave is supported/enabled or not. + */ + whpx_set_xcrs(cpu); + + /* 16 XMM registers */ + assert(whpx_register_names[idx] == WHvX64RegisterXmm0); + idx_next = idx + 16; + for (i = 0; i < sizeof(env->xmm_regs) / sizeof(ZMMReg); i += 1, idx += 1) { + vcxt.values[idx].Reg128.Low64 = env->xmm_regs[i].ZMM_Q(0); + vcxt.values[idx].Reg128.High64 = env->xmm_regs[i].ZMM_Q(1); + } + idx = idx_next; + + /* 8 FP registers */ + assert(whpx_register_names[idx] == WHvX64RegisterFpMmx0); + for (i = 0; i < 8; i += 1, idx += 1) { + vcxt.values[idx].Fp.AsUINT128.Low64 = env->fpregs[i].mmx.MMX_Q(0); + /* vcxt.values[idx].Fp.AsUINT128.High64 = + env->fpregs[i].mmx.MMX_Q(1); + */ + } - /* MSRs */ - assert(whpx_register_names[idx] == WHvX64RegisterEfer); - vcxt.values[idx++].Reg64 = env->efer; + /* FP control status register */ + assert(whpx_register_names[idx] == WHvX64RegisterFpControlStatus); + vcxt.values[idx].FpControlStatus.FpControl = env->fpuc; + vcxt.values[idx].FpControlStatus.FpStatus = + (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; + vcxt.values[idx].FpControlStatus.FpTag = 0; + for (i = 0; i < 8; ++i) { + vcxt.values[idx].FpControlStatus.FpTag |= (!env->fptags[i]) << i; + } + vcxt.values[idx].FpControlStatus.Reserved = 0; + vcxt.values[idx].FpControlStatus.LastFpOp = env->fpop; + vcxt.values[idx].FpControlStatus.LastFpRip = env->fpip; + idx += 1; + + /* XMM control status register */ + assert(whpx_register_names[idx] == WHvX64RegisterXmmControlStatus); + vcxt.values[idx].XmmControlStatus.LastFpRdp = 0; + vcxt.values[idx].XmmControlStatus.XmmStatusControl = env->mxcsr; + vcxt.values[idx].XmmControlStatus.XmmStatusControlMask = 0x0000ffff; + idx += 1; + + /* MSRs */ + assert(whpx_register_names[idx] == WHvX64RegisterEfer); + vcxt.values[idx++].Reg64 = env->efer; #ifdef TARGET_X86_64 - assert(whpx_register_names[idx] == WHvX64RegisterKernelGsBase); - vcxt.values[idx++].Reg64 = env->kernelgsbase; + assert(whpx_register_names[idx] == WHvX64RegisterKernelGsBase); + vcxt.values[idx++].Reg64 = env->kernelgsbase; #endif - assert(whpx_register_names[idx] == WHvX64RegisterApicBase); - vcxt.values[idx++].Reg64 = vcpu->apic_base; + assert(whpx_register_names[idx] == WHvX64RegisterApicBase); + vcxt.values[idx++].Reg64 = vcpu->apic_base; - /* WHvX64RegisterPat - Skipped */ + /* WHvX64RegisterPat - Skipped */ - assert(whpx_register_names[idx] == WHvX64RegisterSysenterCs); - vcxt.values[idx++].Reg64 = env->sysenter_cs; - assert(whpx_register_names[idx] == WHvX64RegisterSysenterEip); - vcxt.values[idx++].Reg64 = env->sysenter_eip; - assert(whpx_register_names[idx] == WHvX64RegisterSysenterEsp); - vcxt.values[idx++].Reg64 = env->sysenter_esp; - assert(whpx_register_names[idx] == WHvX64RegisterStar); - vcxt.values[idx++].Reg64 = env->star; + assert(whpx_register_names[idx] == WHvX64RegisterSysenterCs); + vcxt.values[idx++].Reg64 = env->sysenter_cs; + assert(whpx_register_names[idx] == WHvX64RegisterSysenterEip); + vcxt.values[idx++].Reg64 = env->sysenter_eip; + assert(whpx_register_names[idx] == WHvX64RegisterSysenterEsp); + vcxt.values[idx++].Reg64 = env->sysenter_esp; + assert(whpx_register_names[idx] == WHvX64RegisterStar); + vcxt.values[idx++].Reg64 = env->star; #ifdef TARGET_X86_64 - assert(whpx_register_names[idx] == WHvX64RegisterLstar); - vcxt.values[idx++].Reg64 = env->lstar; - assert(whpx_register_names[idx] == WHvX64RegisterCstar); - vcxt.values[idx++].Reg64 = env->cstar; - assert(whpx_register_names[idx] == WHvX64RegisterSfmask); - vcxt.values[idx++].Reg64 = env->fmask; + assert(whpx_register_names[idx] == WHvX64RegisterLstar); + vcxt.values[idx++].Reg64 = env->lstar; + assert(whpx_register_names[idx] == WHvX64RegisterCstar); + vcxt.values[idx++].Reg64 = env->cstar; + assert(whpx_register_names[idx] == WHvX64RegisterSfmask); + vcxt.values[idx++].Reg64 = env->fmask; #endif - /* Interrupt / Event Registers - Skipped */ + /* Interrupt / Event Registers - Skipped */ - assert(idx == RTL_NUMBER_OF(whpx_register_names)); + assert(idx == RTL_NUMBER_OF(whpx_register_names)); + } hr = whp_dispatch.WHvSetVirtualProcessorRegisters( whpx->partition, cpu->cpu_index, whpx_register_names, - RTL_NUMBER_OF(whpx_register_names), + idx, &vcxt.values[0]); if (FAILED(hr)) { @@ -613,7 +619,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level) hr); } - if (whpx_irqchip_in_kernel()) { + if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel()) { /* * Fetch the TPR value from the emulated APIC. It may get overwritten * below with the value from CR8 returned by @@ -670,7 +676,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level) env->cr[4] = vcxt.values[idx++].Reg64; assert(whpx_register_names[idx] == WHvX64RegisterCr8); tpr = vcxt.values[idx++].Reg64; - if (tpr != vcpu->tpr) { + if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && tpr != vcpu->tpr) { vcpu->tpr = tpr; cpu_set_apic_tpr(x86_cpu->apic_state, whpx_cr8_to_apic_tpr(tpr)); } @@ -756,7 +762,7 @@ void whpx_get_registers(CPUState *cpu, WHPXStateLevel level) assert(idx == RTL_NUMBER_OF(whpx_register_names)); - if (whpx_irqchip_in_kernel()) { + if (level > WHPX_LEVEL_FAST_RUNTIME_STATE && whpx_irqchip_in_kernel()) { whpx_apic_get(x86_cpu->apic_state); } -- 2.50.1 (Apple Git-155)
