Re: [PATCH 16/27] KVM: nVMX: pass advanced EPT violation vmexit info to guest
From: Jon Kohler
Date: Thu Apr 16 2026 - 21:19:03 EST
> On Apr 8, 2026, at 11:42 AM, Paolo Bonzini <pbonzini@xxxxxxxxxx> wrote:
>
> 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.
Is "nested nested" talking about testing double-nested scenarios?
Or is it a typo? Perhaps meaning to say "tested when nested"?
>
> Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
> ---
> arch/x86/include/asm/vmx.h | 4 ++++
> arch/x86/kvm/mmu/paging_tmpl.h | 2 +-
> arch/x86/kvm/vmx/nested.c | 13 +++++++++----
> 3 files changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
> index 2b449a3948d3..fcd623719334 100644
> --- a/arch/x86/include/asm/vmx.h
> +++ b/arch/x86/include/asm/vmx.h
> @@ -524,6 +524,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)
>
> @@ -606,6 +607,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)
> diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
> index de8770d2fcfc..f5f9e745f21d 100644
> --- a/arch/x86/kvm/mmu/paging_tmpl.h
> +++ b/arch/x86/kvm/mmu/paging_tmpl.h
> @@ -494,7 +494,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
> * [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.
> */
> diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
> index cdc35a2728d9..e0ef2cb8f2cd 100644
> --- a/arch/x86/kvm/vmx/nested.c
> +++ b/arch/x86/kvm/vmx/nested.c
> @@ -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;
> }
>
> @@ -7238,7 +7242,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 |
> --
> 2.52.0
>
>