aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorNadav Har'El <nyh@il.ibm.com>2011-05-25 16:03:24 -0400
committerAvi Kivity <avi@redhat.com>2011-07-12 04:45:10 -0400
commit5e1746d6205d1efa3193cc0c67aa2d15e54799bd (patch)
tree9234ab8fddb5e7a8d86b506a19d7697566d51cfb /arch/x86/kvm/vmx.c
parentec378aeef9dfc7c4ba72e9bd6cd4bd6f7d5fd0cc (diff)
KVM: nVMX: Allow setting the VMXE bit in CR4
This patch allows the guest to enable the VMXE bit in CR4, which is a prerequisite to running VMXON. Whether to allow setting the VMXE bit now depends on the architecture (svm or vmx), so its checking has moved to kvm_x86_ops->set_cr4(). This function now returns an int: If kvm_x86_ops->set_cr4() returns 1, __kvm_set_cr4() will also return 1, and this will cause kvm_set_cr4() will throw a #GP. Turning on the VMXE bit is allowed only when the nested VMX feature is enabled, and turning it off is forbidden after a vmxon. Signed-off-by: Nadav Har'El <nyh@il.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 3a727ca02f24..eda2cb619c25 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2121,7 +2121,7 @@ static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
2121 (unsigned long *)&vcpu->arch.regs_dirty); 2121 (unsigned long *)&vcpu->arch.regs_dirty);
2122} 2122}
2123 2123
2124static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4); 2124static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
2125 2125
2126static void ept_update_paging_mode_cr0(unsigned long *hw_cr0, 2126static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
2127 unsigned long cr0, 2127 unsigned long cr0,
@@ -2219,11 +2219,23 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
2219 vmcs_writel(GUEST_CR3, guest_cr3); 2219 vmcs_writel(GUEST_CR3, guest_cr3);
2220} 2220}
2221 2221
2222static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4) 2222static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
2223{ 2223{
2224 unsigned long hw_cr4 = cr4 | (to_vmx(vcpu)->rmode.vm86_active ? 2224 unsigned long hw_cr4 = cr4 | (to_vmx(vcpu)->rmode.vm86_active ?
2225 KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON); 2225 KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
2226 2226
2227 if (cr4 & X86_CR4_VMXE) {
2228 /*
2229 * To use VMXON (and later other VMX instructions), a guest
2230 * must first be able to turn on cr4.VMXE (see handle_vmon()).
2231 * So basically the check on whether to allow nested VMX
2232 * is here.
2233 */
2234 if (!nested_vmx_allowed(vcpu))
2235 return 1;
2236 } else if (to_vmx(vcpu)->nested.vmxon)
2237 return 1;
2238
2227 vcpu->arch.cr4 = cr4; 2239 vcpu->arch.cr4 = cr4;
2228 if (enable_ept) { 2240 if (enable_ept) {
2229 if (!is_paging(vcpu)) { 2241 if (!is_paging(vcpu)) {
@@ -2236,6 +2248,7 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
2236 2248
2237 vmcs_writel(CR4_READ_SHADOW, cr4); 2249 vmcs_writel(CR4_READ_SHADOW, cr4);
2238 vmcs_writel(GUEST_CR4, hw_cr4); 2250 vmcs_writel(GUEST_CR4, hw_cr4);
2251 return 0;
2239} 2252}
2240 2253
2241static void vmx_get_segment(struct kvm_vcpu *vcpu, 2254static void vmx_get_segment(struct kvm_vcpu *vcpu,