From 9d6f55bedcba50cca68c83e0f5dc4809ef378cfe Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 11 Mar 2025 16:19:34 +0000 Subject: [PATCH] ANDROID: virtio_balloon: Replace generic mem_relinquish api with a driver-specific alternative The old API was used only by virtio_balloon, and this way we end up less scattered around the kernel tree. Bug: 381400679 Bug: 357781595 Change-Id: Ic896d1da83565cc260567b5a1183e94a4d13daab Signed-off-by: Keir Fraser --- arch/Kconfig | 2 +- drivers/virt/coco/pkvm-guest/Kconfig | 2 +- drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 20 +++++---- drivers/virtio/Kconfig | 5 +++ drivers/virtio/Makefile | 1 + drivers/virtio/virtio_balloon.c | 9 +++- drivers/virtio/virtio_balloon_hyp_ops.c | 7 +++ include/linux/mem_relinquish.h | 24 ---------- include/linux/virtio_balloon.h | 45 +++++++++++++++++++ mm/Kconfig | 7 --- 10 files changed, 79 insertions(+), 43 deletions(-) create mode 100644 drivers/virtio/virtio_balloon_hyp_ops.c delete mode 100644 include/linux/mem_relinquish.h create mode 100644 include/linux/virtio_balloon.h diff --git a/arch/Kconfig b/arch/Kconfig index 3187986c9541..471ba7606108 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1539,7 +1539,7 @@ config RELR config ARCH_HAS_MEM_ENCRYPT bool -config ARCH_HAS_MEM_RELINQUISH +config ARCH_HAS_VIRTIO_BALLOON_HYP_OPS bool config ARCH_HAS_CC_PLATFORM diff --git a/drivers/virt/coco/pkvm-guest/Kconfig b/drivers/virt/coco/pkvm-guest/Kconfig index dac8b71069fb..8fa686603839 100644 --- a/drivers/virt/coco/pkvm-guest/Kconfig +++ b/drivers/virt/coco/pkvm-guest/Kconfig @@ -1,7 +1,7 @@ config ARM_PKVM_GUEST bool "Arm pKVM protected guest driver" depends on ARM64 - select ARCH_HAS_MEM_RELINQUISH + select ARCH_HAS_VIRTIO_BALLOON_HYP_OPS help Protected guests running under the pKVM hypervisor on arm64 are isolated from the host and must issue hypercalls to enable diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c index bd7c8451c0f7..fae2a1376f8e 100644 --- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c +++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c @@ -11,10 +11,10 @@ #include #include #include -#include #include #include #include +#include #include @@ -125,17 +125,16 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size, return 0; } -#ifdef CONFIG_MEMORY_RELINQUISH +#ifdef CONFIG_VIRTIO_BALLOON_HYP_OPS static bool mem_relinquish_available; -bool page_relinquish_disallowed(void) +static bool pkvm_page_relinquish_disallowed(void) { return mem_relinquish_available && (pkvm_granule > PAGE_SIZE); } -EXPORT_SYMBOL_GPL(page_relinquish_disallowed); -void page_relinquish(struct page *page) +static void pkvm_page_relinquish(struct page *page, unsigned int nr) { phys_addr_t phys, end; u32 func_id = ARM_SMCCC_VENDOR_HYP_KVM_MEM_RELINQUISH_FUNC_ID; @@ -144,7 +143,7 @@ void page_relinquish(struct page *page) return; phys = page_to_phys(page); - end = phys + PAGE_SIZE; + end = phys + PAGE_SIZE * nr; while (phys < end) { struct arm_smccc_res res; @@ -155,7 +154,11 @@ void page_relinquish(struct page *page) phys += pkvm_granule; } } -EXPORT_SYMBOL_GPL(page_relinquish); + +static struct virtio_balloon_hyp_ops pkvm_virtio_balloon_hyp_ops = { + .page_relinquish_disallowed = pkvm_page_relinquish_disallowed, + .page_relinquish = pkvm_page_relinquish +}; #endif @@ -208,7 +211,8 @@ void pkvm_init_hyp_services(void) __dram_is_aligned(pkvm_granule)) arm64_ioremap_prot_hook_register(&mmio_guard_ioremap_hook); -#ifdef CONFIG_MEMORY_RELINQUISH +#ifdef CONFIG_VIRTIO_BALLOON_HYP_OPS + virtio_balloon_hyp_ops = &pkvm_virtio_balloon_hyp_ops; if (kvm_arm_hyp_service_available(ARM_SMCCC_KVM_FUNC_MEM_RELINQUISH)) mem_relinquish_available = true; #endif diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 7de015a578d3..723fecec12b9 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -120,6 +120,11 @@ config VIRTIO_BALLOON If unsure, say M. +config VIRTIO_BALLOON_HYP_OPS + def_bool y + depends on VIRTIO_BALLOON + depends on ARCH_HAS_VIRTIO_BALLOON_HYP_OPS + config VIRTIO_MEM tristate "Virtio mem driver" depends on X86_64 || ARM64 || RISCV diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile index 58b2b0489fc9..373c3f8d2782 100644 --- a/drivers/virtio/Makefile +++ b/drivers/virtio/Makefile @@ -9,6 +9,7 @@ virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o virtio_pci-$(CONFIG_VIRTIO_PCI_ADMIN_LEGACY) += virtio_pci_admin_legacy_io.o obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o +obj-$(CONFIG_VIRTIO_BALLOON_HYP_OPS) += virtio_balloon_hyp_ops.o obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o obj-$(CONFIG_VIRTIO_VDPA) += virtio_vdpa.o obj-$(CONFIG_VIRTIO_MEM) += virtio_mem.o diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 6d68b743033b..2fc74f4738f6 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -197,15 +197,19 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq) } static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_info, - struct scatterlist *sg, unsigned int nents) + struct scatterlist *sgl, unsigned int nents) { struct virtio_balloon *vb = container_of(pr_dev_info, struct virtio_balloon, pr_dev_info); struct virtqueue *vq = vb->reporting_vq; unsigned int unused, err; + struct scatterlist *sg; + + for (sg = sgl; sg != NULL; sg = sg_next(sg)) + page_relinquish(sg_page(sg), sg->length >> PAGE_SHIFT); /* We should always be able to add these buffers to an empty queue. */ - err = virtqueue_add_inbuf(vq, sg, nents, vb, GFP_NOWAIT | __GFP_NOWARN); + err = virtqueue_add_inbuf(vq, sgl, nents, vb, GFP_NOWAIT | __GFP_NOWARN); /* * In the extremely unlikely case that something has occurred and we @@ -263,6 +267,7 @@ static unsigned int fill_balloon(struct virtio_balloon *vb, size_t num) } balloon_page_push(&pages, page); + page_relinquish(page, 1); } mutex_lock(&vb->balloon_lock); diff --git a/drivers/virtio/virtio_balloon_hyp_ops.c b/drivers/virtio/virtio_balloon_hyp_ops.c new file mode 100644 index 000000000000..e45f0c556a05 --- /dev/null +++ b/drivers/virtio/virtio_balloon_hyp_ops.c @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include +#include + +struct virtio_balloon_hyp_ops *virtio_balloon_hyp_ops; +EXPORT_SYMBOL_GPL(virtio_balloon_hyp_ops); diff --git a/include/linux/mem_relinquish.h b/include/linux/mem_relinquish.h deleted file mode 100644 index efc4dde7acb1..000000000000 --- a/include/linux/mem_relinquish.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2022 Google LLC - * Author: Keir Fraser - */ - -#ifndef __MEM_RELINQUISH_H__ -#define __MEM_RELINQUISH_H__ - -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 */ - -#endif /* __MEM_RELINQUISH_H__ */ diff --git a/include/linux/virtio_balloon.h b/include/linux/virtio_balloon.h new file mode 100644 index 000000000000..032596592679 --- /dev/null +++ b/include/linux/virtio_balloon.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2022 Google LLC + * Author: Keir Fraser + */ + +#ifndef _LINUX_VIRTIO_BALLOON_H +#define _LINUX_VIRTIO_BALLOON_H + +#include + +struct page; + +#ifdef CONFIG_VIRTIO_BALLOON_HYP_OPS + +struct virtio_balloon_hyp_ops { + bool (*page_relinquish_disallowed)(void); + void (*page_relinquish)(struct page *page, unsigned int nr); +}; + +extern struct virtio_balloon_hyp_ops *virtio_balloon_hyp_ops; + +static inline bool page_relinquish_disallowed(void) +{ + if (virtio_balloon_hyp_ops && + virtio_balloon_hyp_ops->page_relinquish_disallowed) + return virtio_balloon_hyp_ops->page_relinquish_disallowed(); + return false; +} + +static inline void page_relinquish(struct page *page, unsigned int nr) +{ + if (virtio_balloon_hyp_ops && + virtio_balloon_hyp_ops->page_relinquish_disallowed) + return virtio_balloon_hyp_ops->page_relinquish(page, nr); +} + +#else /* !CONFIG_VIRTIO_BALLOON_HYP_OPS */ + +static inline bool page_relinquish_disallowed(void) { return false; } +static inline void page_relinquish(struct page *page, unsigned int nr) { } + +#endif /* CONFIG_VIRTIO_BALLOON_HYP_OPS */ + +#endif /* _LINUX_VIRTIO_BALLOON_H */ diff --git a/mm/Kconfig b/mm/Kconfig index 6e187ffd607d..d43735806138 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -613,13 +613,6 @@ config SPLIT_PMD_PTLOCKS config MEMORY_BALLOON bool -# -# support for memory relinquish -config MEMORY_RELINQUISH - def_bool y - depends on ARCH_HAS_MEM_RELINQUISH - depends on MEMORY_BALLOON || PAGE_REPORTING - # # support for memory balloon compaction config BALLOON_COMPACTION