Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: nVMX: Enable unrestricted guest mode support

Now that we provide EPT support, there is no reason to torture our
guests by hiding the relieving unrestricted guest mode feature. We just
need to relax CR0 checks for always-on bits as PE and PG can now be
switched off.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Reviewed-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

authored by

Jan Kiszka and committed by
Paolo Bonzini
92fbc7b1 10ba54a5

+14 -4
+14 -4
arch/x86/kvm/vmx.c
··· 2252 2252 nested_vmx_secondary_ctls_low = 0; 2253 2253 nested_vmx_secondary_ctls_high &= 2254 2254 SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | 2255 + SECONDARY_EXEC_UNRESTRICTED_GUEST | 2255 2256 SECONDARY_EXEC_WBINVD_EXITING; 2256 2257 2257 2258 if (enable_ept) { ··· 4878 4877 hypercall[2] = 0xc1; 4879 4878 } 4880 4879 4880 + static bool nested_cr0_valid(struct vmcs12 *vmcs12, unsigned long val) 4881 + { 4882 + unsigned long always_on = VMXON_CR0_ALWAYSON; 4883 + 4884 + if (nested_vmx_secondary_ctls_high & 4885 + SECONDARY_EXEC_UNRESTRICTED_GUEST && 4886 + nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST)) 4887 + always_on &= ~(X86_CR0_PE | X86_CR0_PG); 4888 + return (val & always_on) == always_on; 4889 + } 4890 + 4881 4891 /* called to set cr0 as appropriate for a mov-to-cr0 exit. */ 4882 4892 static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val) 4883 4893 { ··· 4907 4895 val = (val & ~vmcs12->cr0_guest_host_mask) | 4908 4896 (vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask); 4909 4897 4910 - /* TODO: will have to take unrestricted guest mode into 4911 - * account */ 4912 - if ((val & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) 4898 + if (!nested_cr0_valid(vmcs12, val)) 4913 4899 return 1; 4914 4900 4915 4901 if (kvm_set_cr0(vcpu, val)) ··· 7886 7876 return 1; 7887 7877 } 7888 7878 7889 - if (((vmcs12->guest_cr0 & VMXON_CR0_ALWAYSON) != VMXON_CR0_ALWAYSON) || 7879 + if (!nested_cr0_valid(vmcs12, vmcs12->guest_cr0) || 7890 7880 ((vmcs12->guest_cr4 & VMXON_CR4_ALWAYSON) != VMXON_CR4_ALWAYSON)) { 7891 7881 nested_vmx_entry_failure(vcpu, vmcs12, 7892 7882 EXIT_REASON_INVALID_STATE, ENTRY_FAIL_DEFAULT);