From: Marc Zyngier maz@kernel.org
commit 3fb884ffe921c99483a84b0175f3c03f048e9069 upstream.
For the obscure cases where PMD and PUD are the same size (64kB pages with 42bit VA, for example, which results in only two levels of page tables), we can't map anything as a PUD, because there is... erm... no PUD to speak of. Everything is either a PMD or a PTE.
So let's only try and map a PUD when its size is different from that of a PMD.
Cc: stable@vger.kernel.org Fixes: b8e0ba7c8bea ("KVM: arm64: Add support for creating PUD hugepages at stage 2") Reported-by: Gavin Shan gshan@redhat.com Reported-by: Eric Auger eric.auger@redhat.com Reviewed-by: Alexandru Elisei alexandru.elisei@arm.com Reviewed-by: Gavin Shan gshan@redhat.com Tested-by: Gavin Shan gshan@redhat.com Tested-by: Eric Auger eric.auger@redhat.com Tested-by: Alexandru Elisei alexandru.elisei@arm.com Signed-off-by: Marc Zyngier maz@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
--- arch/arm64/kvm/mmu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
--- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1968,7 +1968,12 @@ static int user_mem_abort(struct kvm_vcp (fault_status == FSC_PERM && stage2_is_exec(kvm, fault_ipa, vma_pagesize));
- if (vma_pagesize == PUD_SIZE) { + /* + * If PUD_SIZE == PMD_SIZE, there is no real PUD level, and + * all we have is a 2-level page table. Trying to map a PUD in + * this case would be fatally wrong. + */ + if (PUD_SIZE != PMD_SIZE && vma_pagesize == PUD_SIZE) { pud_t new_pud = kvm_pfn_pud(pfn, mem_type);
new_pud = kvm_pud_mkhuge(new_pud);