summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2020-09-02 11:18:29 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-09-17 13:47:54 +0200
commitd334a67d3ed06cb40f69fbd93efac2e565bebbe9 (patch)
treef33413ee6ae84be09b966c87e8537a7ae1a33f86 /virt
parenta86743ebe680f020454d7d091c82c31ff55372e2 (diff)
downloadlinux-stable-d334a67d3ed06cb40f69fbd93efac2e565bebbe9.tar.gz
linux-stable-d334a67d3ed06cb40f69fbd93efac2e565bebbe9.tar.bz2
linux-stable-d334a67d3ed06cb40f69fbd93efac2e565bebbe9.zip
KVM: arm64: Do not try to map PUDs when they are folded into PMD
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>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/mmu.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 7501ec8a4600..1e1c4f6a85c7 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -1814,7 +1814,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
(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);