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>
This commit is contained in:
@@ -2121,7 +2121,7 @@ static void ept_save_pdptrs(struct kvm_vcpu *vcpu)
|
||||
(unsigned long *)&vcpu->arch.regs_dirty);
|
||||
}
|
||||
|
||||
static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
|
||||
static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
|
||||
|
||||
static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
|
||||
unsigned long cr0,
|
||||
@@ -2219,11 +2219,23 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
|
||||
vmcs_writel(GUEST_CR3, guest_cr3);
|
||||
}
|
||||
|
||||
static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
||||
static int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
||||
{
|
||||
unsigned long hw_cr4 = cr4 | (to_vmx(vcpu)->rmode.vm86_active ?
|
||||
KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
|
||||
|
||||
if (cr4 & X86_CR4_VMXE) {
|
||||
/*
|
||||
* To use VMXON (and later other VMX instructions), a guest
|
||||
* must first be able to turn on cr4.VMXE (see handle_vmon()).
|
||||
* So basically the check on whether to allow nested VMX
|
||||
* is here.
|
||||
*/
|
||||
if (!nested_vmx_allowed(vcpu))
|
||||
return 1;
|
||||
} else if (to_vmx(vcpu)->nested.vmxon)
|
||||
return 1;
|
||||
|
||||
vcpu->arch.cr4 = cr4;
|
||||
if (enable_ept) {
|
||||
if (!is_paging(vcpu)) {
|
||||
@@ -2236,6 +2248,7 @@ static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
|
||||
|
||||
vmcs_writel(CR4_READ_SHADOW, cr4);
|
||||
vmcs_writel(GUEST_CR4, hw_cr4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vmx_get_segment(struct kvm_vcpu *vcpu,
|
||||
|
Reference in New Issue
Block a user