Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: Fix protected mode handling of pages larger than 4kB

Since 3669ddd8fa8b5 ("KVM: arm64: Add a range to pkvm_mappings"),
pKVM tracks the memory that has been mapped into a guest in a
side data structure. Crucially, it uses it to find out whether
a page has already been mapped, and therefore refuses to map it
twice. So far, so good.

However, this very patch completely breaks non-4kB page support,
with guests being unable to boot. The most obvious symptom is that
we take the same fault repeatedly, and not making forward progress.
A quick investigation shows that this is because of the above
rejection code.

As it turns out, there are multiple issues at play:

- while the HPFAR_EL2 register gives you the faulting IPA minus
the bottom 12 bits, it will still give you the extra bits that
are part of the page offset for anything larger than 4kB,
even for a level-3 mapping

- pkvm_pgtable_stage2_map() assumes that the address passed as
a parameter is aligned to the size of the intended mapping

- the faulting address is only aligned for a non-page mapping

When the planets are suitably aligned (pun intended), the guest
faults on a page by accessing it past the bottom 4kB, and extra bits
get set in the HPFAR_EL2 register. If this results in a page mapping
(which is likely with large granule sizes), nothing aligns it further
down, and pkvm_mapping_iter_first() finds an intersection that
doesn't really exist. We assume this is a spurious fault and return
-EAGAIN. And again...

This doesn't hit outside of the protected code, as the page table
code always aligns the IPA down to a page boundary, hiding the issue
for everyone else.

Fix it by always forcing the alignment on vma_pagesize, irrespective
of the value of vma_pagesize.

Fixes: 3669ddd8fa8b5 ("KVM: arm64: Add a range to pkvm_mappings")
Reviewed-by: Fuad Tabba <tabba@google.com>
Tested-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://https://patch.msgid.link/20260222141000.3084258-1-maz@kernel.org
Cc: stable@vger.kernel.org

+5 -7
+5 -7
arch/arm64/kvm/mmu.c
··· 1753 1753 } 1754 1754 1755 1755 /* 1756 - * Both the canonical IPA and fault IPA must be hugepage-aligned to 1757 - * ensure we find the right PFN and lay down the mapping in the right 1758 - * place. 1756 + * Both the canonical IPA and fault IPA must be aligned to the 1757 + * mapping size to ensure we find the right PFN and lay down the 1758 + * mapping in the right place. 1759 1759 */ 1760 - if (vma_pagesize == PMD_SIZE || vma_pagesize == PUD_SIZE) { 1761 - fault_ipa &= ~(vma_pagesize - 1); 1762 - ipa &= ~(vma_pagesize - 1); 1763 - } 1760 + fault_ipa = ALIGN_DOWN(fault_ipa, vma_pagesize); 1761 + ipa = ALIGN_DOWN(ipa, vma_pagesize); 1764 1762 1765 1763 gfn = ipa >> PAGE_SHIFT; 1766 1764 mte_allowed = kvm_vma_mte_allowed(vma);