[PATCH v1 3/6] KVM: arm64: Move pkvm_mem_abort()
COOLING5d
From: Vincent Donnefort <hidden>
Date: 2026-09-22 13:08:30
Also in:
kvmarm
Subsystem:
arm64 port (aarch64 architecture), kernel virtual machine for arm64 (kvm/arm64), the rest · Maintainers:
Catalin Marinas, Will Deacon, Marc Zyngier, Oliver Upton, Linus Torvalds
Move pkvm_mem_abort() below kvm_s2_fault_get_vma_info() so it can resolve stage-2 fault VMA metadata without forward declarations. No functional change intended. Signed-off-by: Vincent Donnefort <redacted> --- arch/arm64/kvm/mmu.c | 138 +++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 69 deletions(-)
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 9dfaf4f277b5..242f63066252 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c@@ -1706,75 +1706,6 @@ struct kvm_s2_fault_vma_info { bool map_non_cacheable; }; -static int pkvm_mem_abort(const struct kvm_s2_fault_desc *s2fd) -{ - unsigned int flags = FOLL_HWPOISON | FOLL_LONGTERM | FOLL_WRITE; - struct kvm_vcpu *vcpu = s2fd->vcpu; - struct kvm_pgtable *pgt = vcpu->arch.hw_mmu->pgt; - struct mm_struct *mm = current->mm; - struct kvm *kvm = vcpu->kvm; - void *hyp_memcache; - struct page *page; - int ret; - - hyp_memcache = get_mmu_memcache(vcpu); - ret = topup_mmu_memcache(vcpu, hyp_memcache); - if (ret) - return -ENOMEM; - - ret = account_locked_vm(mm, 1, true); - if (ret) - return ret; - - mmap_read_lock(mm); - ret = pin_user_pages(s2fd->hva, 1, flags, &page); - mmap_read_unlock(mm); - - if (ret == -EHWPOISON) { - kvm_send_hwpoison_signal(s2fd->hva, PAGE_SHIFT); - ret = 0; - goto dec_account; - } else if (ret != 1) { - ret = -EFAULT; - goto dec_account; - } else if (!folio_test_swapbacked(page_folio(page))) { - /* - * We really can't deal with page-cache pages returned by GUP - * because (a) we may trigger writeback of a page for which we - * no longer have access and (b) page_mkclean() won't find the - * stage-2 mapping in the rmap so we can get out-of-whack with - * the filesystem when marking the page dirty during unpinning - * (see cc5095747edf ("ext4: don't BUG if someone dirty pages - * without asking ext4 first")). - * - * Ideally we'd just restrict ourselves to anonymous pages, but - * we also want to allow memfd (i.e. shmem) pages, so check for - * pages backed by swap in the knowledge that the GUP pin will - * prevent try_to_unmap() from succeeding. - */ - ret = -EIO; - goto unpin; - } - - write_lock(&kvm->mmu_lock); - ret = pkvm_pgtable_stage2_map(pgt, s2fd->fault_ipa, PAGE_SIZE, - page_to_phys(page), KVM_PGTABLE_PROT_RWX, - hyp_memcache, 0); - write_unlock(&kvm->mmu_lock); - if (ret) { - if (ret == -EAGAIN) - ret = 0; - goto unpin; - } - - return 0; -unpin: - unpin_user_pages(&page, 1); -dec_account: - account_locked_vm(mm, 1, false); - return ret; -} - static short kvm_s2_resolve_vma_size(const struct kvm_s2_fault_desc *s2fd, struct kvm_s2_fault_vma_info *s2vi, struct vm_area_struct *vma)
@@ -2235,6 +2166,75 @@ int kvm_handle_guest_sea(struct kvm_vcpu *vcpu) return 0; } +static int pkvm_mem_abort(const struct kvm_s2_fault_desc *s2fd) +{ + unsigned int flags = FOLL_HWPOISON | FOLL_LONGTERM | FOLL_WRITE; + struct kvm_vcpu *vcpu = s2fd->vcpu; + struct kvm_pgtable *pgt = vcpu->arch.hw_mmu->pgt; + struct mm_struct *mm = current->mm; + struct kvm *kvm = vcpu->kvm; + void *hyp_memcache; + struct page *page; + int ret; + + hyp_memcache = get_mmu_memcache(vcpu); + ret = topup_mmu_memcache(vcpu, hyp_memcache); + if (ret) + return -ENOMEM; + + ret = account_locked_vm(mm, 1, true); + if (ret) + return ret; + + mmap_read_lock(mm); + ret = pin_user_pages(s2fd->hva, 1, flags, &page); + mmap_read_unlock(mm); + + if (ret == -EHWPOISON) { + kvm_send_hwpoison_signal(s2fd->hva, PAGE_SHIFT); + ret = 0; + goto dec_account; + } else if (ret != 1) { + ret = -EFAULT; + goto dec_account; + } else if (!folio_test_swapbacked(page_folio(page))) { + /* + * We really can't deal with page-cache pages returned by GUP + * because (a) we may trigger writeback of a page for which we + * no longer have access and (b) page_mkclean() won't find the + * stage-2 mapping in the rmap so we can get out-of-whack with + * the filesystem when marking the page dirty during unpinning + * (see cc5095747edf ("ext4: don't BUG if someone dirty pages + * without asking ext4 first")). + * + * Ideally we'd just restrict ourselves to anonymous pages, but + * we also want to allow memfd (i.e. shmem) pages, so check for + * pages backed by swap in the knowledge that the GUP pin will + * prevent try_to_unmap() from succeeding. + */ + ret = -EIO; + goto unpin; + } + + write_lock(&kvm->mmu_lock); + ret = pkvm_pgtable_stage2_map(pgt, s2fd->fault_ipa, PAGE_SIZE, + page_to_phys(page), KVM_PGTABLE_PROT_RWX, + hyp_memcache, 0); + write_unlock(&kvm->mmu_lock); + if (ret) { + if (ret == -EAGAIN) + ret = 0; + goto unpin; + } + + return 0; +unpin: + unpin_user_pages(&page, 1); +dec_account: + account_locked_vm(mm, 1, false); + return ret; +} + /** * kvm_handle_guest_abort - handles all 2nd stage aborts * @vcpu: the VCPU pointer
--
2.55.0.1082.g2b9226bbc0-goog