]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: nVMX: pass advanced EPT violation vmexit info to guest
authorPaolo Bonzini <pbonzini@redhat.com>
Wed, 8 Apr 2026 15:42:06 +0000 (11:42 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Sun, 10 May 2026 12:55:06 +0000 (14:55 +0200)
KVM will use advanced vmexit information for EPT violations to
virtualize MBEC.  Pass it to the guest since it is easy and allows
testing nested nested.

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

index 54aa5be50df945d2b52b344763b3e1c02a1dd21f..ed2ded531e554713470b48822e9d82c0bc258ce3 100644 (file)
@@ -535,6 +535,7 @@ enum vmcs_field {
 #define VMX_EPT_1GB_PAGE_BIT                   (1ull << 17)
 #define VMX_EPT_INVEPT_BIT                     (1ull << 20)
 #define VMX_EPT_AD_BIT                             (1ull << 21)
+#define VMX_EPT_ADVANCED_VMEXIT_INFO_BIT       (1ull << 22)
 #define VMX_EPT_EXTENT_CONTEXT_BIT             (1ull << 25)
 #define VMX_EPT_EXTENT_GLOBAL_BIT              (1ull << 26)
 
@@ -617,6 +618,9 @@ enum vm_entry_failure_code {
                                         EPT_VIOLATION_PROT_USER_EXEC)
 #define EPT_VIOLATION_GVA_IS_VALID     BIT(7)
 #define EPT_VIOLATION_GVA_TRANSLATED   BIT(8)
+#define EPT_VIOLATION_GVA_USER         BIT(9)
+#define EPT_VIOLATION_GVA_WRITABLE     BIT(10)
+#define EPT_VIOLATION_GVA_NX           BIT(11)
 
 #define EPT_VIOLATION_RWX_TO_PROT(__epte) (((__epte) & VMX_EPT_RWX_MASK) << 3)
 #define EPT_VIOLATION_USER_EXEC_TO_PROT(__epte) (((__epte) & VMX_EPT_USER_EXECUTABLE_MASK) >> 4)
index 8dd9d510fc34d6eaa972b6641bc108afa3f154b7..d4ce55195a7c051cafeab19c92163a723982c179 100644 (file)
@@ -494,7 +494,7 @@ error:
         * [2:0] - Derive from the access bits. The exit_qualification might be
         *         out of date if it is serving an EPT misconfiguration.
         * [5:3] - Calculated by the page walk of the guest EPT page tables
-        * [7:8] - Derived from [7:8] of real exit_qualification
+        * [7:11] - Derived from [7:11] of real exit_qualification
         *
         * The other bits are set to 0.
         */
index 299d4ca60fb3aebe6137060c9cca280175f7dd68..46b65475765d3dcf51256d80d7cfc8d0dd91f29c 100644 (file)
@@ -443,10 +443,14 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
                        vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
                        exit_qualification = 0;
                } else {
+                       u64 mask = EPT_VIOLATION_GVA_IS_VALID |
+                               EPT_VIOLATION_GVA_TRANSLATED;
+                       if (vmx->nested.msrs.ept_caps & VMX_EPT_ADVANCED_VMEXIT_INFO_BIT)
+                               mask |= EPT_VIOLATION_GVA_USER |
+                                              EPT_VIOLATION_GVA_WRITABLE |
+                                              EPT_VIOLATION_GVA_NX;
                        exit_qualification = fault->exit_qualification;
-                       exit_qualification |= vmx_get_exit_qual(vcpu) &
-                                             (EPT_VIOLATION_GVA_IS_VALID |
-                                              EPT_VIOLATION_GVA_TRANSLATED);
+                       exit_qualification |= vmx_get_exit_qual(vcpu) & mask;
                        vm_exit_reason = EXIT_REASON_EPT_VIOLATION;
                }
 
@@ -7240,7 +7244,8 @@ static void nested_vmx_setup_secondary_ctls(u32 ept_caps,
                        VMX_EPT_PAGE_WALK_5_BIT |
                        VMX_EPTP_WB_BIT |
                        VMX_EPT_INVEPT_BIT |
-                       VMX_EPT_EXECUTE_ONLY_BIT;
+                       VMX_EPT_EXECUTE_ONLY_BIT |
+                       VMX_EPT_ADVANCED_VMEXIT_INFO_BIT;
 
                msrs->ept_caps &= ept_caps;
                msrs->ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT |