Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: VMX: Fix commit which broke PML

I found PML was broken since below commit:

commit feda805fe7c4ed9cf78158e73b1218752e3b4314
Author: Xiao Guangrong <guangrong.xiao@linux.intel.com>
Date: Wed Sep 9 14:05:55 2015 +0800

KVM: VMX: unify SECONDARY_VM_EXEC_CONTROL update

Unify the update in vmx_cpuid_update()

Signed-off-by: Xiao Guangrong <guangrong.xiao@linux.intel.com>
[Rewrite to use vmcs_set_secondary_exec_control. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

The reason is in above commit vmx_cpuid_update calls vmx_secondary_exec_control,
in which currently SECONDARY_EXEC_ENABLE_PML bit is cleared unconditionally (as
PML is enabled in creating vcpu). Therefore if vcpu_cpuid_update is called after
vcpu is created, PML will be disabled unexpectedly while log-dirty code still
thinks PML is used.

Fix this by clearing SECONDARY_EXEC_ENABLE_PML in vmx_secondary_exec_control
only when PML is not supported or not enabled (!enable_pml). This is more
reasonable as PML is currently either always enabled or disabled. With this
explicit updating SECONDARY_EXEC_ENABLE_PML in vmx_enable{disable}_pml is not
needed so also rename vmx_enable{disable}_pml to vmx_create{destroy}_pml_buffer.

Fixes: feda805fe7c4ed9cf78158e73b1218752e3b4314
Signed-off-by: Kai Huang <kai.huang@linux.intel.com>
[While at it, change a wrong ASSERT to an "if". The condition can happen
if creating the VCPU fails with ENOMEM. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Kai Huang and committed by
Paolo Bonzini
a3eaa864 879ae188

+11 -13
+11 -13
arch/x86/kvm/vmx.c
··· 4718 4718 a current VMCS12 4719 4719 */ 4720 4720 exec_control &= ~SECONDARY_EXEC_SHADOW_VMCS; 4721 - /* PML is enabled/disabled in creating/destorying vcpu */ 4722 - exec_control &= ~SECONDARY_EXEC_ENABLE_PML; 4721 + 4722 + if (!enable_pml) 4723 + exec_control &= ~SECONDARY_EXEC_ENABLE_PML; 4723 4724 4724 4725 /* Currently, we allow L1 guest to directly run pcommit instruction. */ 4725 4726 exec_control &= ~SECONDARY_EXEC_PCOMMIT; ··· 7805 7804 *info2 = vmcs_read32(VM_EXIT_INTR_INFO); 7806 7805 } 7807 7806 7808 - static int vmx_enable_pml(struct vcpu_vmx *vmx) 7807 + static int vmx_create_pml_buffer(struct vcpu_vmx *vmx) 7809 7808 { 7810 7809 struct page *pml_pg; 7811 7810 ··· 7818 7817 vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); 7819 7818 vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1); 7820 7819 7821 - vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_ENABLE_PML); 7822 - 7823 7820 return 0; 7824 7821 } 7825 7822 7826 - static void vmx_disable_pml(struct vcpu_vmx *vmx) 7823 + static void vmx_destroy_pml_buffer(struct vcpu_vmx *vmx) 7827 7824 { 7828 - ASSERT(vmx->pml_pg); 7829 - __free_page(vmx->pml_pg); 7830 - vmx->pml_pg = NULL; 7831 - 7832 - vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL, SECONDARY_EXEC_ENABLE_PML); 7825 + if (vmx->pml_pg) { 7826 + __free_page(vmx->pml_pg); 7827 + vmx->pml_pg = NULL; 7828 + } 7833 7829 } 7834 7830 7835 7831 static void vmx_flush_pml_buffer(struct kvm_vcpu *vcpu) ··· 8704 8706 struct vcpu_vmx *vmx = to_vmx(vcpu); 8705 8707 8706 8708 if (enable_pml) 8707 - vmx_disable_pml(vmx); 8709 + vmx_destroy_pml_buffer(vmx); 8708 8710 free_vpid(vmx->vpid); 8709 8711 leave_guest_mode(vcpu); 8710 8712 vmx_load_vmcs01(vcpu); ··· 8788 8790 * for the guest, etc. 8789 8791 */ 8790 8792 if (enable_pml) { 8791 - err = vmx_enable_pml(vmx); 8793 + err = vmx_create_pml_buffer(vmx); 8792 8794 if (err) 8793 8795 goto free_vmcs; 8794 8796 }