]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: nVMX: pass PFERR_USER_MASK to MMU on EPT violations
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 8 Apr 2026 15:42:07 +0000 (11:42 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Sun, 10 May 2026 12:55:06 +0000 (14:55 +0200)
For EPT, PFERR_USER_MASK refers not to the CPL of the guest,
but to the AND of the U bits encountered while walking guest
page tables; this is consistent with how MBEC differentiates
between XS and XU.  This is available through the
"advanced vmexit information for EPT violations" feature.

Tested-by: David Riley <d.riley@proxmox.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/common.h
arch/x86/kvm/vmx/vmx.c

index 40fa72f31fc7990735a1d142ee48ba25187ebe94..08005676702c2b5c248ed168f550685249704a29 100644 (file)
@@ -100,9 +100,15 @@ static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
                error_code |= (exit_qualification & EPT_VIOLATION_PROT_USER_EXEC)
                              ? PFERR_PRESENT_MASK : 0;
 
-       if (exit_qualification & EPT_VIOLATION_GVA_IS_VALID)
-               error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) ?
-                             PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK;
+       if (exit_qualification & EPT_VIOLATION_GVA_IS_VALID) {
+               if (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) {
+                       error_code |= PFERR_GUEST_FINAL_MASK;
+                       if (exit_qualification & EPT_VIOLATION_GVA_USER)
+                               error_code |= PFERR_USER_MASK;
+               } else {
+                       error_code |= PFERR_GUEST_PAGE_MASK;
+               }
+       }
 
        if (vt_is_tdx_private_gpa(vcpu->kvm, gpa))
                error_code |= PFERR_PRIVATE_ACCESS;
index d9ba9f14ffd1214ffc0dfb09b239c67c2822e70b..3173b3a738361f2a6344a0d530f3e0ca575529a2 100644 (file)
@@ -2790,6 +2790,16 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
                vmx_cap->vpid = 0;
        }
 
+       /*
+        * Virtualizing MBEC requires advanced vmexit information in order to
+        * distinguish supervisor and user accesses.  For simplicity and clarity
+        * disable MBEC entirely if advanced vmexit information is not available,
+        * this way mbec=1 in the kvm_intel module parameters implies availability
+        * to nested guests as well.
+        */
+       if (!(vmx_cap->ept & VMX_EPT_ADVANCED_VMEXIT_INFO_BIT))
+               _cpu_based_2nd_exec_control &= ~SECONDARY_EXEC_MODE_BASED_EPT_EXEC;
+
        if (!cpu_has_sgx())
                _cpu_based_2nd_exec_control &= ~SECONDARY_EXEC_ENCLS_EXITING;