* [PATCH] KVM: x86/mmu: Fail nested EPT walks for GPAs beyond the EPT width
@ 2026-10-05 19:20 Mushahid Hussain
2026-10-06 5:23 ` Sean Christopherson
0 siblings, 1 reply; 2+ messages in thread
From: Mushahid Hussain @ 2026-10-05 19:20 UTC (permalink / raw)
To: Sean Christopherson, Paolo Bonzini
Cc: kvm, linux-kernel, nh-open-source, mushi.shar
Fail the nested EPT walk when the L2 guest-physical address has bits
above the width of L1's EPT. The width is 48 bits for a 4-level EPT
and 57 bits for a 5-level EPT. Report no RWX bits in the exit
qualification, as for a translation that no table entry provides. L1
then handles the EPT violation itself.
Hardware signals an EPT violation for such an address without a table
walk. KVM's shadow walker instead indexes the tables with PT_INDEX(),
which drops the high bits. The walk resolves the aliased address and
KVM installs a shadow mapping for the alias. The CPU faults on the
original address again, and KVM repeats the walk without end. L1 does
not see an EPT violation for the access, and the L2 vCPU is stuck.
Any L2 that references an address at or above 2^48 under a 4-level
EPT triggers the hang. The easy way to get there is a MAXPHYADDR that
differs between L1 and the host. Take L1 MAXPHYADDR 48 on a 52-bit
host with KVM's default allow_smaller_maxphyaddr=0. A PTE bit that L1
treats as reserved is then valid for the CPU. kvm-unit-tests "access"
and "vmx_pf_exception_test", run as L2 under an L1 KVM with MAXPHYADDR
48, hang at the first present PTE with bit 51 set.
Fixes: 37406aaaeebc ("nEPT: Add EPT tables support to paging_tmpl.h")
Assisted-by: Claude:claude-fable-5.1
Signed-off-by: Mushahid Hussain <hmushi@amazon.co.uk>
---
Reproducer:
L1: KVM, CPUID MAXPHYADDR 48, 4-level EPT.
Host: 52-bit MAXPHYADDR, allow_smaller_maxphyaddr=0.
L2: kvm-unit-tests "access" and "vmx_pf_exception_test" under QEMU.
Both set a PTE with bit 51, which L1 treats as reserved and the
CPU treats as an address bit.
Without the patch both tests hang at the first such PTE. L1 sees no
EPT violation.
With the patch L1 receives the EPT violation. Both tests pass with the
bit-51 cases excluded, as access.c does for MAXPHYADDR >= 52. This holds
with ept=1 and ept=0.
arch/x86/kvm/mmu/paging_tmpl.h | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h
index 8e350095508c5..6ba4439e56b10 100644
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -378,6 +378,21 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
KVM_BUG_ON(walker->max_level > PT_MAX_FULL_LEVELS, vcpu->kvm))
goto error;
+#if PTTYPE == PTTYPE_EPT
+ /*
+ * EPT translates 48-bit guest-physical addresses with 4-level tables
+ * and 57-bit ones with 5-level tables; hardware raises an EPT
+ * violation for an address with bits above that width without
+ * consulting the tables. PT_INDEX() drops those bits, so walking
+ * would resolve the aliased address and the shadow mapping built for
+ * it can never satisfy the CPU. Fail the walk the way hardware does.
+ */
+ if (unlikely(addr >> (PAGE_SHIFT + walker->level * PT_LEVEL_BITS))) {
+ pte_access = 0;
+ goto error;
+ }
+#endif
+
++walker->level;
do {
base-commit: 6bd2905303c58679e303941b7d8ae8c074cd95ce
--
2.47.3
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] KVM: x86/mmu: Fail nested EPT walks for GPAs beyond the EPT width
2026-10-05 19:20 [PATCH] KVM: x86/mmu: Fail nested EPT walks for GPAs beyond the EPT width Mushahid Hussain
@ 2026-10-06 5:23 ` Sean Christopherson
0 siblings, 0 replies; 2+ messages in thread
From: Sean Christopherson @ 2026-10-06 5:23 UTC (permalink / raw)
To: Mushahid Hussain
Cc: Paolo Bonzini, kvm, linux-kernel, nh-open-source, mushi.shar
On Mon, Oct 05, 2026, Mushahid Hussain wrote:
> Fail the nested EPT walk when the L2 guest-physical address has bits
> above the width of L1's EPT. The width is 48 bits for a 4-level EPT
> and 57 bits for a 5-level EPT. Report no RWX bits in the exit
> qualification, as for a translation that no table entry provides. L1
> then handles the EPT violation itself.
>
> Hardware signals an EPT violation for such an address without a table
> walk.
No, hardware does not do that. See commit b628cb523c65 ("KVM: x86: Advertise
max mappable GPA in CPUID.0x80000008.GuestPhysBits").
> KVM's shadow walker instead indexes the tables with PT_INDEX(),
> which drops the high bits. The walk resolves the aliased address and
> KVM installs a shadow mapping for the alias. The CPU faults on the
> original address again, and KVM repeats the walk without end. L1 does
> not see an EPT violation for the access, and the L2 vCPU is stuck.
>
> Any L2 that references an address at or above 2^48 under a 4-level
> EPT triggers the hang. The easy way to get there is a MAXPHYADDR that
> differs between L1 and the host. Take L1 MAXPHYADDR 48 on a 52-bit
> host with KVM's default allow_smaller_maxphyaddr=0.
Which isn't supported when allow_smaller_maxphyaddr=0. And allow_smaller_maxphyaddr=1
is basically a failed experiment.
> A PTE bit that L1 treats as reserved is then valid for the CPU.
> kvm-unit-tests "access" and "vmx_pf_exception_test", run as L2 under an L1
> KVM with MAXPHYADDR 48, hang at the first present PTE with bit 51 set.
>
> Fixes: 37406aaaeebc ("nEPT: Add EPT tables support to paging_tmpl.h")
> Assisted-by: Claude:claude-fable-5.1
> Signed-off-by: Mushahid Hussain <hmushi@amazon.co.uk>
> ---
> Reproducer:
> L1: KVM, CPUID MAXPHYADDR 48, 4-level EPT.
> Host: 52-bit MAXPHYADDR, allow_smaller_maxphyaddr=0.
As above, this is an unsupported, invalid configuration.
> L2: kvm-unit-tests "access" and "vmx_pf_exception_test" under QEMU.
> Both set a PTE with bit 51, which L1 treats as reserved and the
> CPU treats as an address bit.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-06 5:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-05 19:20 [PATCH] KVM: x86/mmu: Fail nested EPT walks for GPAs beyond the EPT width Mushahid Hussain
2026-10-06 5:23 ` Sean Christopherson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®