KVM: VMX: Explicitly initialize controls shadow at VMCS allocation
Or: Don't re-initialize vmcs02's controls on every nested VM-Entry. VMWRITEs to the major VMCS controls are deceptively expensive. Intel CPUs with VMCS caching (Westmere and later) also optimize away consistency checks on VM-Entry, i.e. skip consistency checks if the relevant fields have not changed since the last successful VM-Entry (of the cached VMCS). Because uops are a precious commodity, uCode's dirty VMCS field tracking isn't as precise as software would prefer. Notably, writing any of the major VMCS fields effectively marks the entire VMCS dirty, i.e. causes the next VM-Entry to perform all consistency checks, which consumes several hundred cycles. Zero out the controls' shadow copies during VMCS allocation and use the optimized setter when "initializing" controls. While this technically affects both non-nested and nested virtualization, nested virtualization is the primary beneficiary as avoid VMWRITEs when prepare vmcs02 allows hardware to optimizie away consistency checks. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:

committed by
Paolo Bonzini

parent
ae81d08993
commit
3af80fec6e
@@ -2485,6 +2485,8 @@ int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
|
||||
}
|
||||
|
||||
memset(&loaded_vmcs->host_state, 0, sizeof(struct vmcs_host_state));
|
||||
memset(&loaded_vmcs->controls_shadow, 0,
|
||||
sizeof(struct vmcs_controls_shadow));
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -4040,14 +4042,14 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
||||
vmcs_write64(VMCS_LINK_POINTER, -1ull); /* 22.3.1.5 */
|
||||
|
||||
/* Control */
|
||||
pin_controls_init(vmx, vmx_pin_based_exec_ctrl(vmx));
|
||||
pin_controls_set(vmx, vmx_pin_based_exec_ctrl(vmx));
|
||||
vmx->hv_deadline_tsc = -1;
|
||||
|
||||
exec_controls_init(vmx, vmx_exec_control(vmx));
|
||||
exec_controls_set(vmx, vmx_exec_control(vmx));
|
||||
|
||||
if (cpu_has_secondary_exec_ctrls()) {
|
||||
vmx_compute_secondary_exec_control(vmx);
|
||||
secondary_exec_controls_init(vmx, vmx->secondary_exec_control);
|
||||
secondary_exec_controls_set(vmx, vmx->secondary_exec_control);
|
||||
}
|
||||
|
||||
if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
|
||||
@@ -4105,10 +4107,10 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
|
||||
++vmx->nmsrs;
|
||||
}
|
||||
|
||||
vm_exit_controls_init(vmx, vmx_vmexit_ctrl());
|
||||
vm_exit_controls_set(vmx, vmx_vmexit_ctrl());
|
||||
|
||||
/* 22.2.1, 20.8.1 */
|
||||
vm_entry_controls_init(vmx, vmx_vmentry_ctrl());
|
||||
vm_entry_controls_set(vmx, vmx_vmentry_ctrl());
|
||||
|
||||
vmx->vcpu.arch.cr0_guest_owned_bits = X86_CR0_TS;
|
||||
vmcs_writel(CR0_GUEST_HOST_MASK, ~X86_CR0_TS);
|
||||
|
Reference in New Issue
Block a user