Re: [PATCH v4 4/5] KVM: VMX: Synthesize nested EPT violation GVA_IS_VALID/GVA_TRANSLATED bits

From: Kevin Cheng

Date: Mon Jul 06 2026 - 20:01:08 EST


> @@ -516,6 +517,14 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
> else
> walker->fault.exit_qualification |= EPT_VIOLATION_ACC_READ;
>
> + /*
> + * KVM doesn't emulate features that access GPAs directly, e.g.
> + * Intel Processor Trace. Assume the GVA is always valid; when
> + * propagating faults from hardware, KVM will discard this info
> + * and use the EXIT_QUALIFICATION bits from the VMCS.
> + */
> + walker->fault.exit_qualification |= EPT_VIOLATION_GVA_IS_VALID;
> +

Sashiko flagged this internally:

"Since this code asserts to L1 that the GVA is valid by setting
EPT_VIOLATION_GVA_IS_VALID, does it also need to populate the access
rights bits (EPT_VIOLATION_GVA_USER, EPT_VIOLATION_GVA_WRITABLE, and
EPT_VIOLATION_GVA_NX)?"

The Intel SDM states that if bit 8 is set, bits 9-11 support advanced
VM Exit information. Would a change like the following be needed to
populate bits 9-11 of the exit qualification?

diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
index cfc30695adf4..355150a21b0b 100644
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -449,8 +449,24 @@ static int FNAME(walk_addr_generic)(struct
guest_walker *walker,
real_gpa = kvm_translate_gpa(vcpu, mmu, gfn_to_gpa(gfn),
access | PFERR_GUEST_FINAL_MASK,
&walker->fault);
- if (real_gpa == INVALID_GPA)
+ if (real_gpa == INVALID_GPA) {
+#if PTTYPE != PTTYPE_EPT
+ /*
+ * Architecturally, bits 11:9 are only valid if bit 8
+ * (GVA_TRANSLATED) is set. If bit 8 is 0, bits 11:9 are
+ * undefined and must be 0.
+ */
+ if (walker->fault.exit_qualification &
EPT_VIOLATION_GVA_TRANSLATED) {
+ if (walker->pte_access & ACC_USER_MASK)
+ walker->fault.exit_qualification |=
EPT_VIOLATION_GVA_USER;
+ if (walker->pte_access & ACC_WRITE_MASK)
+ walker->fault.exit_qualification |=
EPT_VIOLATION_GVA_WRITABLE;
+ if (!(walker->pte_access & ACC_EXEC_MASK))
+ walker->fault.exit_qualification |=
EPT_VIOLATION_GVA_NX;
+ }
+#endif
return 0;
+ }