Skip to content

Commit c171caf

Browse files
peterfeinergregkh
authored andcommitted
kvm: vmx: ensure VMCS is current while enabling PML
commit 4e59516a12a6ef6dcb660cb3a3f70c64bd60cfec upstream. Between loading the new VMCS and enabling PML, the CPU was unpinned. If the vCPU thread were migrated to another CPU in the interim (e.g., due to preemption or sleeping alloc_page), then the VMWRITEs to enable PML would target the wrong VMCS -- or no VMCS at all: [ 2087.266950] vmwrite error: reg 200e value 3fe1d52000 (err -506126336) [ 2087.267062] vmwrite error: reg 812 value 1ff (err 511) [ 2087.267125] vmwrite error: reg 401e value 12229c00 (err 304258048) This patch ensures that the VMCS remains current while enabling PML by doing the VMWRITEs while the CPU is pinned. Allocation of the PML buffer is hoisted out of the critical section. Signed-off-by: Peter Feiner <pfeiner@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Cc: "Herongguang (Stephen)" <herongguang.he@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent e0913cc commit c171caf

1 file changed

Lines changed: 24 additions & 32 deletions

File tree

arch/x86/kvm/vmx.c

Lines changed: 24 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4867,6 +4867,12 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
48674867
if (vmx_xsaves_supported())
48684868
vmcs_write64(XSS_EXIT_BITMAP, VMX_XSS_EXIT_BITMAP);
48694869

4870+
if (enable_pml) {
4871+
ASSERT(vmx->pml_pg);
4872+
vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
4873+
vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
4874+
}
4875+
48704876
return 0;
48714877
}
48724878

@@ -7839,22 +7845,6 @@ static void vmx_get_exit_info(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2)
78397845
*info2 = vmcs_read32(VM_EXIT_INTR_INFO);
78407846
}
78417847

7842-
static int vmx_create_pml_buffer(struct vcpu_vmx *vmx)
7843-
{
7844-
struct page *pml_pg;
7845-
7846-
pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
7847-
if (!pml_pg)
7848-
return -ENOMEM;
7849-
7850-
vmx->pml_pg = pml_pg;
7851-
7852-
vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg));
7853-
vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
7854-
7855-
return 0;
7856-
}
7857-
78587848
static void vmx_destroy_pml_buffer(struct vcpu_vmx *vmx)
78597849
{
78607850
if (vmx->pml_pg) {
@@ -8789,14 +8779,26 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
87898779
if (err)
87908780
goto free_vcpu;
87918781

8782+
err = -ENOMEM;
8783+
8784+
/*
8785+
* If PML is turned on, failure on enabling PML just results in failure
8786+
* of creating the vcpu, therefore we can simplify PML logic (by
8787+
* avoiding dealing with cases, such as enabling PML partially on vcpus
8788+
* for the guest, etc.
8789+
*/
8790+
if (enable_pml) {
8791+
vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
8792+
if (!vmx->pml_pg)
8793+
goto uninit_vcpu;
8794+
}
8795+
87928796
vmx->guest_msrs = kmalloc(PAGE_SIZE, GFP_KERNEL);
87938797
BUILD_BUG_ON(ARRAY_SIZE(vmx_msr_index) * sizeof(vmx->guest_msrs[0])
87948798
> PAGE_SIZE);
87958799

8796-
err = -ENOMEM;
8797-
if (!vmx->guest_msrs) {
8798-
goto uninit_vcpu;
8799-
}
8800+
if (!vmx->guest_msrs)
8801+
goto free_pml;
88008802

88018803
vmx->loaded_vmcs = &vmx->vmcs01;
88028804
vmx->loaded_vmcs->vmcs = alloc_vmcs();
@@ -8840,25 +8842,15 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)
88408842
vmx->nested.current_vmptr = -1ull;
88418843
vmx->nested.current_vmcs12 = NULL;
88428844

8843-
/*
8844-
* If PML is turned on, failure on enabling PML just results in failure
8845-
* of creating the vcpu, therefore we can simplify PML logic (by
8846-
* avoiding dealing with cases, such as enabling PML partially on vcpus
8847-
* for the guest, etc.
8848-
*/
8849-
if (enable_pml) {
8850-
err = vmx_create_pml_buffer(vmx);
8851-
if (err)
8852-
goto free_vmcs;
8853-
}
8854-
88558845
return &vmx->vcpu;
88568846

88578847
free_vmcs:
88588848
free_vpid(vmx->nested.vpid02);
88598849
free_loaded_vmcs(vmx->loaded_vmcs);
88608850
free_msrs:
88618851
kfree(vmx->guest_msrs);
8852+
free_pml:
8853+
vmx_destroy_pml_buffer(vmx);
88628854
uninit_vcpu:
88638855
kvm_vcpu_uninit(&vmx->vcpu);
88648856
free_vcpu:

0 commit comments

Comments
 (0)