Optimise vmexits by save/restoring less state in those cases instead of the full state.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Reviewed-by: Bernhard Beschow <shentey@gmail.com>
---
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)