aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNadav Har'El <nyh@il.ibm.com>2013-08-05 04:07:07 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2013-08-07 09:57:34 -0400
commit3633cfc3e8656a660953e701c189444831f44075 (patch)
tree272bfb48835cc3d86a1541e6e9b73b027158ce82
parent8049d651e8789b15baaf2a8b888d8919df1152a9 (diff)
nEPT: Fix cr3 handling in nested exit and entry
The existing code for handling cr3 and related VMCS fields during nested exit and entry wasn't correct in all cases: If L2 is allowed to control cr3 (and this is indeed the case in nested EPT), during nested exit we must copy the modified cr3 from vmcs02 to vmcs12, and we forgot to do so. This patch adds this copy. If L0 isn't controlling cr3 when running L2 (i.e., L0 is using EPT), and whoever does control cr3 (L1 or L2) is using PAE, the processor might have saved PDPTEs and we should also save them in vmcs12 (and restore later). Reviewed-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> Reviewed-by: Orit Wasserman <owasserm@redhat.com> Signed-off-by: Nadav Har'El <nyh@il.ibm.com> Signed-off-by: Jun Nakajima <jun.nakajima@intel.com> Signed-off-by: Xinhao Xu <xinhao.xu@intel.com> Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--arch/x86/kvm/vmx.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 25a650638305..e3c8e28aeb35 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -7595,6 +7595,16 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
7595 kvm_set_cr3(vcpu, vmcs12->guest_cr3); 7595 kvm_set_cr3(vcpu, vmcs12->guest_cr3);
7596 kvm_mmu_reset_context(vcpu); 7596 kvm_mmu_reset_context(vcpu);
7597 7597
7598 /*
7599 * L1 may access the L2's PDPTR, so save them to construct vmcs12
7600 */
7601 if (enable_ept) {
7602 vmcs_write64(GUEST_PDPTR0, vmcs12->guest_pdptr0);
7603 vmcs_write64(GUEST_PDPTR1, vmcs12->guest_pdptr1);
7604 vmcs_write64(GUEST_PDPTR2, vmcs12->guest_pdptr2);
7605 vmcs_write64(GUEST_PDPTR3, vmcs12->guest_pdptr3);
7606 }
7607
7598 kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp); 7608 kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->guest_rsp);
7599 kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip); 7609 kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->guest_rip);
7600} 7610}
@@ -7917,6 +7927,22 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
7917 vmcs12->guest_pending_dbg_exceptions = 7927 vmcs12->guest_pending_dbg_exceptions =
7918 vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS); 7928 vmcs_readl(GUEST_PENDING_DBG_EXCEPTIONS);
7919 7929
7930 /*
7931 * In some cases (usually, nested EPT), L2 is allowed to change its
7932 * own CR3 without exiting. If it has changed it, we must keep it.
7933 * Of course, if L0 is using shadow page tables, GUEST_CR3 was defined
7934 * by L0, not L1 or L2, so we mustn't unconditionally copy it to vmcs12.
7935 *
7936 * Additionally, restore L2's PDPTR to vmcs12.
7937 */
7938 if (enable_ept) {
7939 vmcs12->guest_cr3 = vmcs_read64(GUEST_CR3);
7940 vmcs12->guest_pdptr0 = vmcs_read64(GUEST_PDPTR0);
7941 vmcs12->guest_pdptr1 = vmcs_read64(GUEST_PDPTR1);
7942 vmcs12->guest_pdptr2 = vmcs_read64(GUEST_PDPTR2);
7943 vmcs12->guest_pdptr3 = vmcs_read64(GUEST_PDPTR3);
7944 }
7945
7920 vmcs12->vm_entry_controls = 7946 vmcs12->vm_entry_controls =
7921 (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) | 7947 (vmcs12->vm_entry_controls & ~VM_ENTRY_IA32E_MODE) |
7922 (vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_IA32E_MODE); 7948 (vmcs_read32(VM_ENTRY_CONTROLS) & VM_ENTRY_IA32E_MODE);