aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorNadav Har'El <nyh@il.ibm.com>2013-08-05 04:07:06 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2013-08-07 09:57:34 -0400
commit8049d651e8789b15baaf2a8b888d8919df1152a9 (patch)
treefcc048550ed2bc48c2ee56c2a615e3f16a8956a3 /arch/x86
parent027664216d37afe80101de91f73dfbaf6b36ee65 (diff)
nEPT: Support LOAD_IA32_EFER entry/exit controls for L1
Recent KVM, since http://kerneltrap.org/mailarchive/linux-kvm/2010/5/2/6261577 switch the EFER MSR when EPT is used and the host and guest have different NX bits. So if we add support for nested EPT (L1 guest using EPT to run L2) and want to be able to run recent KVM as L1, we need to allow L1 to use this EFER switching feature. To do this EFER switching, KVM uses VM_ENTRY/EXIT_LOAD_IA32_EFER if available, and if it isn't, it uses the generic VM_ENTRY/EXIT_MSR_LOAD. This patch adds support for the former (the latter is still unsupported). Nested entry and exit emulation (prepare_vmcs_02 and load_vmcs12_host_state, respectively) already handled VM_ENTRY/EXIT_LOAD_IA32_EFER correctly. So all that's left to do in this patch is to properly advertise this feature to L1. Note that vmcs12's VM_ENTRY/EXIT_LOAD_IA32_EFER are emulated by L0, by using vmx_set_efer (which itself sets one of several vmcs02 fields), so we always support this feature, regardless of whether the host supports it. 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>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/kvm/vmx.c23
1 files changed, 16 insertions, 7 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 30974c3efa45..25a650638305 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2198,7 +2198,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
2198#else 2198#else
2199 nested_vmx_exit_ctls_high = 0; 2199 nested_vmx_exit_ctls_high = 0;
2200#endif 2200#endif
2201 nested_vmx_exit_ctls_high |= VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR; 2201 nested_vmx_exit_ctls_high |= (VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR |
2202 VM_EXIT_LOAD_IA32_EFER);
2202 2203
2203 /* entry controls */ 2204 /* entry controls */
2204 rdmsr(MSR_IA32_VMX_ENTRY_CTLS, 2205 rdmsr(MSR_IA32_VMX_ENTRY_CTLS,
@@ -2207,8 +2208,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
2207 nested_vmx_entry_ctls_low = VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR; 2208 nested_vmx_entry_ctls_low = VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
2208 nested_vmx_entry_ctls_high &= 2209 nested_vmx_entry_ctls_high &=
2209 VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_IA32E_MODE; 2210 VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_IA32E_MODE;
2210 nested_vmx_entry_ctls_high |= VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR; 2211 nested_vmx_entry_ctls_high |= (VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR |
2211 2212 VM_ENTRY_LOAD_IA32_EFER);
2212 /* cpu-based controls */ 2213 /* cpu-based controls */
2213 rdmsr(MSR_IA32_VMX_PROCBASED_CTLS, 2214 rdmsr(MSR_IA32_VMX_PROCBASED_CTLS,
2214 nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high); 2215 nested_vmx_procbased_ctls_low, nested_vmx_procbased_ctls_high);
@@ -7529,10 +7530,18 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
7529 vcpu->arch.cr0_guest_owned_bits &= ~vmcs12->cr0_guest_host_mask; 7530 vcpu->arch.cr0_guest_owned_bits &= ~vmcs12->cr0_guest_host_mask;
7530 vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits); 7531 vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
7531 7532
7532 /* Note: IA32_MODE, LOAD_IA32_EFER are modified by vmx_set_efer below */ 7533 /* L2->L1 exit controls are emulated - the hardware exit is to L0 so
7533 vmcs_write32(VM_EXIT_CONTROLS, 7534 * we should use its exit controls. Note that VM_EXIT_LOAD_IA32_EFER
7534 vmcs12->vm_exit_controls | vmcs_config.vmexit_ctrl); 7535 * bits are further modified by vmx_set_efer() below.
7535 vmcs_write32(VM_ENTRY_CONTROLS, vmcs12->vm_entry_controls | 7536 */
7537 vmcs_write32(VM_EXIT_CONTROLS, vmcs_config.vmexit_ctrl);
7538
7539 /* vmcs12's VM_ENTRY_LOAD_IA32_EFER and VM_ENTRY_IA32E_MODE are
7540 * emulated by vmx_set_efer(), below.
7541 */
7542 vmcs_write32(VM_ENTRY_CONTROLS,
7543 (vmcs12->vm_entry_controls & ~VM_ENTRY_LOAD_IA32_EFER &
7544 ~VM_ENTRY_IA32E_MODE) |
7536 (vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE)); 7545 (vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE));
7537 7546
7538 if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT) 7547 if (vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT)