ANDROID: KVM: arm64: Cleanup unused ppage->pins

Since 10a77358c7 ("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 <vdonnefort@google.com>
This commit is contained in:
Vincent Donnefort
2025-08-19 18:47:53 +01:00
parent b3fdeb8b13
commit f6ffb4d5ab
4 changed files with 13 additions and 52 deletions
-1
View File
@@ -281,7 +281,6 @@ struct kvm_pinned_page {
u64 ipa;
u64 __subtree_last;
u8 order;
u16 pins;
};
struct kvm_pinned_page
-4
View File
@@ -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;
+1 -4
View File
@@ -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;
+12 -43
View File
@@ -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);