All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sean Christopherson <sean.j.christopherson@intel.com>
To: "Paolo Bonzini" <pbonzini@redhat.com>,
	"Radim Krčmář" <rkrcmar@redhat.com>
Cc: kvm@vger.kernel.org, Nadav Amit <nadav.amit@gmail.com>,
	Liran Alon <liran.alon@oracle.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>
Subject: [PATCH 15/15] KVM: nVMX: Copy PDPTRs to/from vmcs12 only when necessary
Date: Tue,  7 May 2019 09:06:40 -0700	[thread overview]
Message-ID: <20190507160640.4812-16-sean.j.christopherson@intel.com> (raw)
In-Reply-To: <20190507160640.4812-1-sean.j.christopherson@intel.com>

Per Intel's SDM:

  ... the logical processor uses PAE paging if CR0.PG=1, CR4.PAE=1 and
  IA32_EFER.LME=0.  A VM entry to a guest that uses PAE paging loads the
  PDPTEs into internal, non-architectural registers based on the setting
  of the "enable EPT" VM-execution control.

and:

  [GUEST_PDPTR] values are saved into the four PDPTE fields as follows:

    - If the "enable EPT" VM-execution control is 0 or the logical
      processor was not using PAE paging at the time of the VM exit,
      the values saved are undefined.

In other words, if EPT is disabled or the guest isn't using PAE paging,
then the PDPTRS aren't consumed by hardware on VM-Entry and are loaded
with junk on VM-Exit.  From a nesting perspective, all of the above hold
true, i.e. KVM can effectively ignore the VMCS PDPTRs.  E.g. KVM already
loads the PDPTRs from memory when nested EPT is disabled (see
nested_vmx_load_cr3()).

Because KVM intercepts setting CR4.PAE, there is no danger of consuming
a stale value or crushing L1's VMWRITEs regardless of whether L1
intercepts CR4.PAE. The vmcs12's values are unchanged up until the
VM-Exit where L2 sets CR4.PAE, i.e. L0 will see the new PAE state on the
subsequent VM-Entry and propagate the PDPTRs from vmcs12 to vmcs02.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kvm/vmx/nested.c | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index cfdc04fde8eb..b8bd446b2c8b 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -2184,17 +2184,6 @@ static void prepare_vmcs02_full(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
 		vmcs_writel(GUEST_SYSENTER_ESP, vmcs12->guest_sysenter_esp);
 		vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->guest_sysenter_eip);
 
-		/*
-		 * L1 may access the L2's PDPTR, so save them to construct
-		 * vmcs12
-		 */
-		if (enable_ept) {
-			vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0);
-			vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
-			vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
-			vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
-		}
-
 		if (vmx->nested.nested_run_pending &&
 		    (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))
 			vmcs_write64(GUEST_IA32_DEBUGCTL,
@@ -2256,10 +2245,15 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	struct hv_enlightened_vmcs *hv_evmcs = vmx->nested.hv_evmcs;
+	bool load_guest_pdptrs_vmcs12 = false;
 
 	if (vmx->nested.dirty_vmcs12 || vmx->nested.hv_evmcs) {
 		prepare_vmcs02_full(vmx, vmcs12);
 		vmx->nested.dirty_vmcs12 = false;
+
+		load_guest_pdptrs_vmcs12 = !vmx->nested.hv_evmcs ||
+			!(vmx->nested.hv_evmcs->hv_clean_fields &
+			  HV_VMX_ENLIGHTENED_CLEAN_FIELD_GUEST_GRP1);
 	}
 
 	/*
@@ -2366,6 +2360,15 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
 		return -EINVAL;
 	}
 
+	/* Late preparation of GUEST_PDPTRs now that EFER and CRs are set. */
+	if (load_guest_pdptrs_vmcs12 && nested_cpu_has_ept(vmcs12) &&
+	    !is_long_mode(vcpu) && is_pae(vcpu) && is_paging(vcpu)) {
+		vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0);
+		vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
+		vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
+		vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
+	}
+
 	/* Shadow page tables on either EPT or shadow page tables. */
 	if (nested_vmx_load_cr3(vcpu, vmcs12->guest_cr3, nested_cpu_has_ept(vmcs12),
 				entry_failure_code))
@@ -3467,10 +3470,13 @@ static void sync_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
 	 */
 	if (enable_ept) {
 		vmcs12->guest_cr3 = vmcs_readl(GUEST_CR3);
-		vmcs12->guest_pdptr0 = vmcs_read64(GUEST_PDPTR0);
-		vmcs12->guest_pdptr1 = vmcs_read64(GUEST_PDPTR1);
-		vmcs12->guest_pdptr2 = vmcs_read64(GUEST_PDPTR2);
-		vmcs12->guest_pdptr3 = vmcs_read64(GUEST_PDPTR3);
+		if (nested_cpu_has_ept(vmcs12) && !is_long_mode(vcpu) &&
+		    is_pae(vcpu) && is_paging(vcpu)) {
+			vmcs12->guest_pdptr0 = vmcs_read64(GUEST_PDPTR0);
+			vmcs12->guest_pdptr1 = vmcs_read64(GUEST_PDPTR1);
+			vmcs12->guest_pdptr2 = vmcs_read64(GUEST_PDPTR2);
+			vmcs12->guest_pdptr3 = vmcs_read64(GUEST_PDPTR3);
+		}
 	}
 
 	vmcs12->guest_linear_address = vmcs_readl(GUEST_LINEAR_ADDRESS);
-- 
2.21.0


  parent reply	other threads:[~2019-05-07 16:06 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-05-07 16:06 [PATCH 00/15] KVM: nVMX: Optimize nested VM-Entry Sean Christopherson
2019-05-07 16:06 ` [PATCH 01/15] KVM: nVMX: Don't dump VMCS if virtual APIC page can't be mapped Sean Christopherson
2019-05-07 20:09   ` Paolo Bonzini
2019-05-07 16:06 ` [PATCH 02/15] KVM: VMX: Always signal #GP on WRMSR to MSR_IA32_CR_PAT with bad value Sean Christopherson
2019-05-07 16:06 ` [PATCH 03/15] KVM: nVMX: Always sync GUEST_BNDCFGS when it comes from vmcs01 Sean Christopherson
2019-05-07 16:06 ` [PATCH 04/15] KVM: nVMX: Write ENCLS-exiting bitmap once per vmcs02 Sean Christopherson
2019-05-07 16:06 ` [PATCH 05/15] KVM: nVMX: Don't rewrite GUEST_PML_INDEX during nested VM-Entry Sean Christopherson
2019-06-06 15:49   ` Paolo Bonzini
2019-05-07 16:06 ` [PATCH 06/15] KVM: nVMX: Don't "put" vCPU or host state when switching VMCS Sean Christopherson
2019-06-06 16:24   ` Paolo Bonzini
2019-06-06 18:57     ` Sean Christopherson
2019-06-07 17:00       ` Paolo Bonzini
2019-06-07 17:08         ` Sean Christopherson
2019-05-07 16:06 ` [PATCH 07/15] KVM: nVMX: Don't reread VMCS-agnostic " Sean Christopherson
2019-05-07 21:01   ` Paolo Bonzini
2019-05-07 16:06 ` [PATCH 08/15] KVM: nVMX: Don't speculatively write virtual-APIC page address Sean Christopherson
2019-05-07 16:06 ` [PATCH 09/15] KVM: nVMX: Don't speculatively write APIC-access " Sean Christopherson
2019-05-07 16:06 ` [PATCH 10/15] KVM: nVMX: Update vmcs12 for MSR_IA32_CR_PAT when it's written Sean Christopherson
2019-05-07 16:06 ` [PATCH 11/15] KVM: nVMX: Update vmcs12 for SYSENTER MSRs when they're written Sean Christopherson
2019-06-06 16:35   ` Paolo Bonzini
2019-05-07 16:06 ` [PATCH 12/15] KVM: nVMX: Update vmcs12 for MSR_IA32_DEBUGCTLMSR when it's written Sean Christopherson
2019-05-07 16:06 ` [PATCH 13/15] KVM: nVMX: Update vmcs02 GUEST_IA32_DEBUGCTL only when vmcs12 is dirty Sean Christopherson
2019-06-06 16:39   ` Paolo Bonzini
2019-05-07 16:06 ` [PATCH 14/15] KVM: nVMX: Don't update GUEST_BNDCFGS if it's clean in HV eVMCS Sean Christopherson
2019-05-07 16:06 ` Sean Christopherson [this message]
2019-06-06 16:53   ` [PATCH 15/15] KVM: nVMX: Copy PDPTRs to/from vmcs12 only when necessary Paolo Bonzini
2019-06-06 16:54 ` [PATCH 00/15] KVM: nVMX: Optimize nested VM-Entry Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190507160640.4812-16-sean.j.christopherson@intel.com \
    --to=sean.j.christopherson@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=liran.alon@oracle.com \
    --cc=nadav.amit@gmail.com \
    --cc=pbonzini@redhat.com \
    --cc=rkrcmar@redhat.com \
    --cc=vkuznets@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.