From 9e68f0cc222560b6d6516137cb451f84f2f1bab1 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 21 Jan 2025 12:12:51 +0000 Subject: [PATCH] ANDROID: ARM64: virtio_balloon: Disable balloon with warning if granule too large If the reporting granule is larger than guest page size, we cannot safely relinquish memory to the hypervisor. Bug: 381400679 Bug: 357781595 Change-Id: I84461c21e44209021afe617ed2796108c5c43718 Signed-off-by: Keir Fraser --- drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 6 ++++++ drivers/virtio/virtio_balloon.c | 3 +++ include/linux/mem_relinquish.h | 2 ++ 3 files changed, 11 insertions(+) diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c index fcd6823fa3a3..e90e347ed457 100644 --- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c @@ -114,6 +114,12 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size, static bool mem_relinquish_available; +bool page_relinquish_disallowed(void) +{ + return mem_relinquish_available && (pkvm_granule > PAGE_SIZE); +} +EXPORT_SYMBOL_GPL(page_relinquish_disallowed); + void page_relinquish(struct page *page) { phys_addr_t phys, end; diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 79dc6e2920fd..6d68b743033b 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -1182,6 +1182,9 @@ static int virtballoon_restore(struct virtio_device *vdev) static int virtballoon_validate(struct virtio_device *vdev) { + if (WARN_ON(page_relinquish_disallowed())) + return -EINVAL; + /* * Inform the hypervisor that our pages are poisoned or * initialized. If we cannot do that then we should disable diff --git a/include/linux/mem_relinquish.h b/include/linux/mem_relinquish.h index 3a006ae6ca79..efc4dde7acb1 100644 --- a/include/linux/mem_relinquish.h +++ b/include/linux/mem_relinquish.h @@ -11,10 +11,12 @@ struct page; #ifdef CONFIG_MEMORY_RELINQUISH +bool page_relinquish_disallowed(void); void page_relinquish(struct page *page); #else /* !CONFIG_MEMORY_RELINQUISH */ +static inline bool page_relinquish_disallowed(void) { return false; } static inline void page_relinquish(struct page *page) { } #endif /* CONFIG_MEMORY_RELINQUISH */