From f6ffb4d5abfb3d1ce8dc36d044e8a2ec47f1015b Mon Sep 17 00:00:00 2001 From: Vincent Donnefort Date: Tue, 19 Aug 2025 18:47:53 +0100 Subject: [PATCH] ANDROID: KVM: arm64: Cleanup unused ppage->pins Since 10a77358c7a8 ("ANDROID: KVM: arm64: Allow relinqush for p-guest with huge-mappings"), pKVM issues a hyp_req to ask for a huge-mapping split before a page relinquish happens. This made the ppage->pins field deprecated. This field was meant to handle the previous broken approach of relinquish where the kvm_pinned_page tree wasn't updated on a block split. While at it, remove the now unnecessary error handling in pkvm_call_hyp_nvhe_ppage(). The hypervisor can only split blocks behind the back of the host in the guest_share_host case. Bug: 439812370 Bug: 357781595 Bug: 278011447 Change-Id: I705a010be8afaaadc9ba15a2b2c02eb1efa2194c Signed-off-by: Vincent Donnefort --- arch/arm64/include/asm/kvm_host.h | 1 - arch/arm64/include/asm/kvm_pkvm.h | 4 --- arch/arm64/kvm/mmu.c | 5 +-- arch/arm64/kvm/pkvm.c | 55 +++++++------------------------ 4 files changed, 13 insertions(+), 52 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index cd40f62844b0..1c751d52560c 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -281,7 +281,6 @@ struct kvm_pinned_page { u64 ipa; u64 __subtree_last; u8 order; - u16 pins; }; struct kvm_pinned_page diff --git a/arch/arm64/include/asm/kvm_pkvm.h b/arch/arm64/include/asm/kvm_pkvm.h index 459aad063c66..db161943f99b 100644 --- a/arch/arm64/include/asm/kvm_pkvm.h +++ b/arch/arm64/include/asm/kvm_pkvm.h @@ -512,10 +512,6 @@ struct pkvm_ptdump_log_hdr { u64 w_index: 16; }; -int pkvm_call_hyp_nvhe_ppage(struct kvm_pinned_page *ppage, - int (*call_hyp_nvhe)(u64, u64, u8, void*), - void *args, bool unmap); - struct pkvm_mapping { struct rb_node node; u64 gfn; diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 0c7177fd050b..8abd4ba9d00b 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1758,9 +1758,8 @@ __pkvm_pages_to_ppages(struct kvm *kvm, struct kvm_memory_slot *memslot, gfn_t g ppage->page = pfn_to_page(pfn); ppage->ipa = ipa; ppage->order = get_order(page_size); - ppage->pins = 1 << ppage->order; list_add_tail(&ppage->list_node, ppages); - nr_ppages += ppage->pins; + nr_ppages += 1 << ppage->order; next: /* Number of pages to skip (covered by a THP) */ @@ -2081,7 +2080,6 @@ int __pkvm_pgtable_stage2_split(struct kvm_vcpu *vcpu, phys_addr_t ipa, size_t s goto end; ppage->order = 0; - ppage->pins = 1; pfn = page_to_pfn(ppage->page) + 1; ipa = ipa + PAGE_SIZE; @@ -2093,7 +2091,6 @@ int __pkvm_pgtable_stage2_split(struct kvm_vcpu *vcpu, phys_addr_t ipa, size_t s ppage->page = pfn_to_page(pfn); ppage->ipa = ipa; ppage->order = 0; - ppage->pins = 1; insert_ppage(kvm, ppage); pfn += 1; diff --git a/arch/arm64/kvm/pkvm.c b/arch/arm64/kvm/pkvm.c index 6953ce7ba429..135095e916fb 100644 --- a/arch/arm64/kvm/pkvm.c +++ b/arch/arm64/kvm/pkvm.c @@ -327,27 +327,21 @@ err_free_reqs: } /* - * Handle broken down huge pages which have not been reported to the - * kvm_pinned_page. + * Handle split huge pages which have not been reported to the kvm_pinned_page tree. */ -int pkvm_call_hyp_nvhe_ppage(struct kvm_pinned_page *ppage, - int (*call_hyp_nvhe)(u64 pfn, u64 gfn, u8 order, void* args), - void *args, bool unmap) +static int pkvm_call_hyp_nvhe_ppage(struct kvm_pinned_page *ppage, + int (*call_hyp_nvhe)(u64 pfn, u64 gfn, u8 order, void *args), + void *args) { size_t page_size, size = PAGE_SIZE << ppage->order; u64 pfn = page_to_pfn(ppage->page); u8 order = ppage->order; u64 gfn = ppage->ipa >> PAGE_SHIFT; - /* We already know this huge-page has been broken down in the stage-2 */ - if (ppage->pins < (1 << order)) - order = 0; - while (size) { int err = call_hyp_nvhe(pfn, gfn, order, args); switch (err) { - /* The stage-2 huge page has been broken down */ case -E2BIG: if (order) order = 0; @@ -355,16 +349,6 @@ int pkvm_call_hyp_nvhe_ppage(struct kvm_pinned_page *ppage, /* Something is really wrong ... */ return -EINVAL; break; - /* This has been unmapped already */ - case -ENOENT: - /* - * We are not supposed to lose track of PAGE_SIZE pinned - * page. - */ - if (!ppage->order) - return -EINVAL; - - fallthrough; case 0: page_size = PAGE_SIZE << order; gfn += 1 << order; @@ -373,13 +357,6 @@ int pkvm_call_hyp_nvhe_ppage(struct kvm_pinned_page *ppage, if (page_size > size) return -EINVAL; - /* If -ENOENT, the pin was already dropped. */ - if (unmap && !err) - ppage->pins -= 1 << order; - - if (!ppage->pins) - return 0; - size -= page_size; break; default: @@ -466,11 +443,9 @@ retry: ppage = kvm_pinned_pages_iter_first(&host_kvm->arch.pkvm.pinned_pages, 0, ~(0UL)); while (ppage) { struct kvm_pinned_page *next; - u16 pins = ppage->pins; - ret = pkvm_call_hyp_nvhe_ppage(ppage, - __reclaim_dying_guest_page_call, - host_kvm, true); + ret = pkvm_call_hyp_nvhe_ppage(ppage, __reclaim_dying_guest_page_call, + host_kvm); cond_resched(); if (ret == -EBUSY) { nr_busy++; @@ -483,7 +458,7 @@ retry: unpin_user_pages_dirty_lock(&ppage->page, 1, true); next = kvm_pinned_pages_iter_next(ppage, 0, ~(0UL)); kvm_pinned_pages_remove(ppage, &host_kvm->arch.pkvm.pinned_pages); - pages += pins; + pages += 1 << ppage->order; kfree(ppage); ppage = next; } @@ -816,25 +791,19 @@ void pkvm_host_reclaim_page(struct kvm *host_kvm, phys_addr_t ipa) { struct mm_struct *mm = current->mm; struct kvm_pinned_page *ppage; - u16 pins; + u8 order; write_lock(&host_kvm->mmu_lock); ppage = kvm_pinned_pages_iter_first(&host_kvm->arch.pkvm.pinned_pages, ipa, ipa + PAGE_SIZE - 1); if (ppage) { - WARN_ON_ONCE(ppage->pins != 1); - - if (ppage->pins) - ppage->pins--; - - pins = ppage->pins; - if (!pins) - kvm_pinned_pages_remove(ppage, - &host_kvm->arch.pkvm.pinned_pages); + order = ppage->order; + if (!order) + kvm_pinned_pages_remove(ppage, &host_kvm->arch.pkvm.pinned_pages); } write_unlock(&host_kvm->mmu_lock); - if (WARN_ON(!ppage) || pins) + if (WARN_ON(!ppage || order)) return; account_locked_vm(mm, 1 << ppage->order, false);