ANDROID: KVM: Do not memset hyp_page from reclaim_hyp_pool()

reclaim_hyp_pool() zeroes the entire struct hyp_page when returning a
page to the host. However, this is no longer the canonical way to do it
since we store the host ownership state in struct hyp_page.

Fix this by only changing the refcount and order members of the
hyp_page, and while at it make the code common with drain_hyp_pool()
which does something very similar.

Bug: 379022162
Change-Id: I58941ae6ef8e62ff17cba8508cb41cddfefebe1d
Signed-off-by: Quentin Perret <qperret@google.com>
This commit is contained in:
Quentin Perret
2024-11-15 17:13:52 +00:00
committed by Mostafa Saleh
parent 89d72fc11f
commit 49b37e78cb
2 changed files with 19 additions and 13 deletions
+1 -8
View File
@@ -2441,14 +2441,7 @@ void destroy_hyp_vm_pgt(struct pkvm_hyp_vm *vm)
void drain_hyp_pool(struct pkvm_hyp_vm *vm, struct kvm_hyp_memcache *mc)
{
void *addr = hyp_alloc_pages(&vm->pool, 0);
while (addr) {
hyp_page_ref_dec(hyp_virt_to_page(addr));
push_hyp_memcache(mc, addr, hyp_virt_to_phys, 0);
WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(addr), 1));
addr = hyp_alloc_pages(&vm->pool, 0);
}
WARN_ON(reclaim_hyp_pool(&vm->pool, mc, INT_MAX) != -ENOMEM);
}
int __pkvm_host_reclaim_page(struct pkvm_hyp_vm *vm, u64 pfn, u64 ipa)
+18 -5
View File
@@ -548,18 +548,31 @@ int refill_hyp_pool(struct hyp_pool *pool, struct kvm_hyp_memcache *host_mc)
int reclaim_hyp_pool(struct hyp_pool *pool, struct kvm_hyp_memcache *host_mc,
int nr_pages)
{
void *p;
struct hyp_page *page;
u8 order;
void *p;
while (nr_pages > 0) {
p = hyp_alloc_pages(pool, 0);
if (!p)
return -ENOMEM;
page = hyp_virt_to_page(p);
nr_pages -= (1 << page->order);
push_hyp_memcache(host_mc, p, hyp_virt_to_phys, page->order);
WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(p), 1 << page->order));
memset(page, 0, sizeof(struct hyp_page));
order = page->order;
nr_pages -= (1 << order);
/*
* For a compound page all the tail pages should normally
* have page->order == HYP_NO_ORDER which would need to be
* cleared one by one. But in this instance, the order 0
* allocation above can only return an _external_ compound
* page which is in fact ignored by the buddy logic, and the
* tail pages are never touched.
*/
page->order = 0;
hyp_page_ref_dec(page);
push_hyp_memcache(host_mc, p, hyp_virt_to_phys, order);
WARN_ON(__pkvm_hyp_donate_host(hyp_virt_to_pfn(p), 1 << order));
}
return 0;