]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
KVM: nVMX: KVM needs to unset "unrestricted guest" VM-execution control in vmcs02...
authorKrish Sadhukhan <krish.sadhukhan@oracle.com>
Mon, 21 Sep 2020 08:10:25 +0000 (08:10 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 28 Sep 2020 11:57:18 +0000 (07:57 -0400)
Currently, prepare_vmcs02_early() does not check if the "unrestricted guest"
VM-execution control in vmcs12 is turned off and leaves the corresponding
bit on in vmcs02. Due to this setting, vmentry checks which are supposed to
render the nested guest state as invalid when this VM-execution control is
not set, are passing in hardware.

This patch turns off the "unrestricted guest" VM-execution control in vmcs02
if vmcs12 has turned it off.

Suggested-by: Jim Mattson <jmattson@google.com>
Suggested-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
Message-Id: <20200921081027.23047-2-krish.sadhukhan@oracle.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h

index b6ce9ce91029e5c02bb4d708bca2d06eb888f1fd..9861179d9a8cc056871ddec19234716d51f0f637 100644 (file)
@@ -2314,6 +2314,9 @@ static void prepare_vmcs02_early(struct vcpu_vmx *vmx, struct vmcs12 *vmcs12)
                        vmcs_write16(GUEST_INTR_STATUS,
                                vmcs12->guest_intr_status);
 
+               if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_UNRESTRICTED_GUEST))
+                   exec_control &= ~SECONDARY_EXEC_UNRESTRICTED_GUEST;
+
                secondary_exec_controls_set(vmx, exec_control);
        }
 
index 1d20705193c2f01c1af06a4ab56f9f863b7b97ff..b73901699ecc789ee316436dde3ba5c09d7cff3a 100644 (file)
@@ -1441,7 +1441,7 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        unsigned long old_rflags;
 
-       if (enable_unrestricted_guest) {
+       if (is_unrestricted_guest(vcpu)) {
                kvm_register_mark_available(vcpu, VCPU_EXREG_RFLAGS);
                vmx->rflags = rflags;
                vmcs_writel(GUEST_RFLAGS, rflags);
@@ -2240,7 +2240,8 @@ static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg)
                vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & guest_owned_bits;
                break;
        case VCPU_EXREG_CR3:
-               if (enable_unrestricted_guest || (enable_ept && is_paging(vcpu)))
+               if (is_unrestricted_guest(vcpu) ||
+                   (enable_ept && is_paging(vcpu)))
                        vcpu->arch.cr3 = vmcs_readl(GUEST_CR3);
                break;
        case VCPU_EXREG_CR4:
@@ -3006,7 +3007,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        unsigned long hw_cr0;
 
        hw_cr0 = (cr0 & ~KVM_VM_CR0_ALWAYS_OFF);
-       if (enable_unrestricted_guest)
+       if (is_unrestricted_guest(vcpu))
                hw_cr0 |= KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST;
        else {
                hw_cr0 |= KVM_VM_CR0_ALWAYS_ON;
@@ -3027,7 +3028,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        }
 #endif
 
-       if (enable_ept && !enable_unrestricted_guest)
+       if (enable_ept && !is_unrestricted_guest(vcpu))
                ept_update_paging_mode_cr0(&hw_cr0, cr0, vcpu);
 
        vmcs_writel(CR0_READ_SHADOW, cr0);
@@ -3107,7 +3108,7 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        unsigned long hw_cr4;
 
        hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE);
-       if (enable_unrestricted_guest)
+       if (is_unrestricted_guest(vcpu))
                hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST;
        else if (vmx->rmode.vm86_active)
                hw_cr4 |= KVM_RMODE_VM_CR4_ALWAYS_ON;
@@ -3142,7 +3143,7 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        vcpu->arch.cr4 = cr4;
        kvm_register_mark_available(vcpu, VCPU_EXREG_CR4);
 
-       if (!enable_unrestricted_guest) {
+       if (!is_unrestricted_guest(vcpu)) {
                if (enable_ept) {
                        if (!is_paging(vcpu)) {
                                hw_cr4 &= ~X86_CR4_PAE;
@@ -3282,7 +3283,7 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
         * tree. Newer qemu binaries with that qemu fix would not need this
         * kvm hack.
         */
-       if (enable_unrestricted_guest && (seg != VCPU_SREG_LDTR))
+       if (is_unrestricted_guest(vcpu) && (seg != VCPU_SREG_LDTR))
                var->type |= 0x1; /* Accessed */
 
        vmcs_write32(sf->ar_bytes, vmx_segment_access_rights(var));
@@ -3473,7 +3474,7 @@ static bool cs_ss_rpl_check(struct kvm_vcpu *vcpu)
  */
 static bool guest_state_valid(struct kvm_vcpu *vcpu)
 {
-       if (enable_unrestricted_guest)
+       if (is_unrestricted_guest(vcpu))
                return true;
 
        /* real mode guest state checks */
index d7ec66db5eb853270d5f6faee23000b509a72f46..941336dc5ee4883f5c25d809a18d7dc244b0f921 100644 (file)
@@ -553,6 +553,13 @@ static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu)
        return !enable_ept || cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits;
 }
 
+static inline bool is_unrestricted_guest(struct kvm_vcpu *vcpu)
+{
+       return enable_unrestricted_guest && (!is_guest_mode(vcpu) ||
+           (secondary_exec_controls_get(to_vmx(vcpu)) &
+           SECONDARY_EXEC_UNRESTRICTED_GUEST));
+}
+
 void dump_vmcs(void);
 
 #endif /* __KVM_X86_VMX_H */