From: "Michael S. Tsirkin" <mst@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: "David Hildenbrand (Arm)" <david@kernel.org>,
"Jason Wang" <jasowang@redhat.com>,
"Xuan Zhuo" <xuanzhuo@linux.alibaba.com>,
"Eugenio Pérez" <eperezma@redhat.com>,
"Muchun Song" <muchun.song@linux.dev>,
"Oscar Salvador" <osalvador@suse.de>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Lorenzo Stoakes" <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
"Vlastimil Babka" <vbabka@kernel.org>,
"Mike Rapoport" <rppt@kernel.org>,
"Suren Baghdasaryan" <surenb@google.com>,
"Michal Hocko" <mhocko@suse.com>,
"Brendan Jackman" <jackmanb@google.com>,
"Johannes Weiner" <hannes@cmpxchg.org>, "Zi Yan" <ziy@nvidia.com>,
"Baolin Wang" <baolin.wang@linux.alibaba.com>,
"Nico Pache" <npache@redhat.com>,
"Ryan Roberts" <ryan.roberts@arm.com>,
"Dev Jain" <dev.jain@arm.com>, "Barry Song" <baohua@kernel.org>,
"Lance Yang" <lance.yang@linux.dev>,
"Hugh Dickins" <hughd@google.com>,
"Matthew Brost" <matthew.brost@intel.com>,
"Joshua Hahn" <joshua.hahnjy@gmail.com>,
"Rakie Kim" <rakie.kim@sk.com>,
"Byungchul Park" <byungchul@sk.com>,
"Gregory Price" <gourry@gourry.net>,
"Ying Huang" <ying.huang@linux.alibaba.com>,
"Alistair Popple" <apopple@nvidia.com>,
"Christoph Lameter" <cl@gentwo.org>,
"David Rientjes" <rientjes@google.com>,
"Roman Gushchin" <roman.gushchin@linux.dev>,
"Harry Yoo" <harry.yoo@oracle.com>,
"Axel Rasmussen" <axelrasmussen@google.com>,
"Yuanchu Xie" <yuanchu@google.com>, "Wei Xu" <weixugc@google.com>,
"Chris Li" <chrisl@kernel.org>,
"Kairui Song" <kasong@tencent.com>,
"Kemeng Shi" <shikemeng@huaweicloud.com>,
"Nhat Pham" <nphamcs@gmail.com>, "Baoquan He" <bhe@redhat.com>,
virtualization@lists.linux.dev, linux-mm@kvack.org,
"Andrea Arcangeli" <aarcange@redhat.com>
Subject: [PATCH v7 30/31] virtio_balloon: implement VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE
Date: Tue, 12 May 2026 17:07:46 -0400 [thread overview]
Message-ID: <3b2729a80c19e634f9bc93ca2a8baed8cd760b45.1778616612.git.mst@redhat.com> (raw)
In-Reply-To: <cover.1778616612.git.mst@redhat.com>
When the device offers DEVICE_INIT_ON_INFLATE (bit 7), the device
initializes inflated pages and returns a per-page bitmap indicating
which pages were successfully initialized.
The driver appends a device-writable bitmap buffer to each inflate
descriptor chain via virtqueue_add_sgs. After the host acknowledges,
the driver checks bitmap bits (bounded by used_len) and marks pages
with SetPageZeroed.
tell_host() returns used_len from virtqueue_get_buf(). Bitmap reads
are bounded: fill_balloon() and virtballoon_migratepage() only trust
bits within the used_len range.
On deflate, release_pages_balloon checks PageZeroed per page and
uses put_page_zeroed for pages the host initialized, propagating
the zeroed hint to the buddy allocator.
If inflate_vq has fewer than 2 descriptors, probe fails with
-ENOSPC. If PAGE_POISON is negotiated with non-zero poison_val,
the feature is cleared in validate().
See the virtio spec change:
https://lore.kernel.org/all/9c69b992c3dd83dfef3db92cd86b2fd8a0730d48.1777731396.git.mst@redhat.com
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Assisted-by: Claude:claude-opus-4-6
Assisted-by: cursor-agent:GPT-5.4-xhigh
---
drivers/virtio/virtio_balloon.c | 102 ++++++++++++++++++++++++----
include/uapi/linux/virtio_balloon.h | 1 +
2 files changed, 90 insertions(+), 13 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 02d21147d4c6..f3929a238c8b 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -121,6 +121,9 @@ struct virtio_balloon {
struct virtqueue *reporting_vq;
struct page_reporting_dev_info pr_dev_info;
+ /* Bitmap returned by host for DEVICE_INIT_ON_INFLATE */
+ DECLARE_BITMAP(inflate_bitmap, VIRTIO_BALLOON_ARRAY_PFNS_MAX);
+
/* State for keeping the wakeup_source active while adjusting the balloon */
spinlock_t wakeup_lock;
bool processing_wakeup_event;
@@ -181,20 +184,30 @@ static void balloon_ack(struct virtqueue *vq)
wake_up(&vb->acked);
}
-static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
+static unsigned int tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
{
- struct scatterlist sg;
+ struct scatterlist sg_out, sg_in;
+ struct scatterlist *sgs[] = { &sg_out, &sg_in };
unsigned int len;
- sg_init_one(&sg, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
+ sg_init_one(&sg_out, vb->pfns, sizeof(vb->pfns[0]) * vb->num_pfns);
- /* We should always be able to add one buffer to an empty queue. */
- virtqueue_add_outbuf(vq, &sg, 1, vb, GFP_KERNEL);
+ if (vq == vb->inflate_vq &&
+ virtio_has_feature(vb->vdev,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE)) {
+ unsigned int bitmap_bytes;
+
+ bitmap_bytes = DIV_ROUND_UP(vb->num_pfns, 8);
+ bitmap_zero(vb->inflate_bitmap, vb->num_pfns);
+ sg_init_one(&sg_in, vb->inflate_bitmap, bitmap_bytes);
+ virtqueue_add_sgs(vq, sgs, 1, 1, vb, GFP_KERNEL);
+ } else {
+ virtqueue_add_outbuf(vq, &sg_out, 1, vb, GFP_KERNEL);
+ }
virtqueue_kick(vq);
- /* When host has read buffer, this completes via balloon_ack */
wait_event(vb->acked, virtqueue_get_buf(vq, &len));
-
+ return len;
}
static int virtballoon_free_page_report(struct page_reporting_dev_info *pr_dev_info,
@@ -297,8 +310,37 @@ static unsigned int fill_balloon(struct virtio_balloon *vb, size_t num)
num_allocated_pages = vb->num_pfns;
/* Did we get any? */
- if (vb->num_pfns != 0)
- tell_host(vb, vb->inflate_vq);
+ if (vb->num_pfns != 0) {
+ unsigned int used_len = tell_host(vb, vb->inflate_vq);
+
+ if (virtio_has_feature(vb->vdev,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE)) {
+ unsigned int i;
+ unsigned int valid_bits = used_len * 8;
+
+ for (i = 0; i < vb->num_pfns;
+ i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
+ unsigned int pfn, j;
+ bool zeroed = true;
+
+ if (i + VIRTIO_BALLOON_PAGES_PER_PAGE > valid_bits)
+ break;
+ for (j = 0; j < VIRTIO_BALLOON_PAGES_PER_PAGE; j++) {
+ if (!test_bit(i + j, vb->inflate_bitmap)) {
+ zeroed = false;
+ break;
+ }
+ }
+ if (zeroed) {
+ pfn = virtio32_to_cpu(vb->vdev,
+ vb->pfns[i]);
+ __SetPageZeroed(pfn_to_page(pfn >>
+ (PAGE_SHIFT -
+ VIRTIO_BALLOON_PFN_SHIFT)));
+ }
+ }
+ }
+ }
mutex_unlock(&vb->balloon_lock);
return num_allocated_pages;
@@ -311,7 +353,12 @@ static void release_pages_balloon(struct virtio_balloon *vb,
list_for_each_entry_safe(page, next, pages, lru) {
list_del(&page->lru);
- put_page(page); /* balloon reference */
+ if (PageZeroed(page)) {
+ __ClearPageZeroed(page);
+ put_page_zeroed(page);
+ } else {
+ put_page(page);
+ }
}
}
@@ -858,7 +905,25 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
/* balloon's page migration 1st step -- inflate "newpage" */
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
set_page_pfns(vb, vb->pfns, newpage);
- tell_host(vb, vb->inflate_vq);
+ {
+ unsigned int used_len = tell_host(vb, vb->inflate_vq);
+
+ if (virtio_has_feature(vb->vdev,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE) &&
+ used_len >= DIV_ROUND_UP(VIRTIO_BALLOON_PAGES_PER_PAGE, 8)) {
+ unsigned int j;
+ bool zeroed = true;
+
+ for (j = 0; j < VIRTIO_BALLOON_PAGES_PER_PAGE; j++) {
+ if (!test_bit(j, vb->inflate_bitmap)) {
+ zeroed = false;
+ break;
+ }
+ }
+ if (zeroed)
+ __SetPageZeroed(newpage);
+ }
+ }
/* balloon's page migration 2nd step -- deflate "page" */
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
@@ -963,6 +1028,12 @@ static int virtballoon_probe(struct virtio_device *vdev)
if (err)
goto out_free_vb;
+ if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE) &&
+ virtqueue_get_vring_size(vb->inflate_vq) < 2) {
+ err = -ENOSPC;
+ goto out_del_vqs;
+ }
+
if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
vb->vb_dev_info.adjust_managed_page_count = true;
#ifdef CONFIG_BALLOON_MIGRATION
@@ -1188,11 +1259,15 @@ static int virtballoon_validate(struct virtio_device *vdev)
/* Device fills with poison_val, not zeros; disable zeroed hint */
if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_PAGE_POISON) &&
- !want_init_on_free())
+ !want_init_on_free()) {
__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED);
+ __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE);
+ }
- if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT))
+ if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
__virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED);
+ __virtio_clear_bit(vdev, VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE);
+ }
__virtio_clear_bit(vdev, VIRTIO_F_ACCESS_PLATFORM);
return 0;
}
@@ -1205,6 +1280,7 @@ static unsigned int features[] = {
VIRTIO_BALLOON_F_PAGE_POISON,
VIRTIO_BALLOON_F_REPORTING,
VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED,
+ VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE,
};
static struct virtio_driver virtio_balloon_driver = {
diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h
index 13074631f300..cbaf18e0b17c 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -38,6 +38,7 @@
#define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */
#define VIRTIO_BALLOON_F_REPORTING 5 /* Page reporting virtqueue */
#define VIRTIO_BALLOON_F_DEVICE_INIT_REPORTED 6 /* Device initializes reported pages */
+#define VIRTIO_BALLOON_F_DEVICE_INIT_ON_INFLATE 7 /* Device initializes pages on inflate */
/* Size of a PFN in the balloon interface. */
#define VIRTIO_BALLOON_PFN_SHIFT 12
--
MST
next prev parent reply other threads:[~2026-05-12 21:07 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-12 21:04 [PATCH v7 00/31] mm/virtio: skip redundant zeroing of host-zeroed pages Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 01/31] mm: mempolicy: fix interleave index for unaligned VMA start Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 02/31] mm: page_alloc: propagate PageReported flag across buddy splits Michael S. Tsirkin
2026-05-14 11:51 ` Gregory Price
2026-05-14 14:48 ` Michael S. Tsirkin
2026-05-14 15:32 ` Gregory Price
2026-05-14 15:34 ` Michael S. Tsirkin
2026-05-14 15:41 ` Gregory Price
2026-05-14 15:47 ` Michael S. Tsirkin
2026-05-14 17:48 ` Gregory Price
2026-05-14 17:51 ` Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 03/31] mm: page_reporting: allow driver to set batch capacity Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 04/31] mm: hugetlb: remove dead alloc_hugetlb_folio stub Michael S. Tsirkin
2026-05-14 11:53 ` Gregory Price
2026-05-12 21:05 ` [PATCH v7 05/31] mm: move vma_alloc_folio_noprof to page_alloc.c Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 06/31] mm: thread user_addr through page allocator for cache-friendly zeroing Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 07/31] mm: add folio_zero_user stub for configs without THP/HUGETLBFS Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 08/31] mm: page_alloc: move prep_compound_page before post_alloc_hook Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 09/31] mm: use folio_zero_user for user pages in post_alloc_hook Michael S. Tsirkin
2026-05-14 13:49 ` Gregory Price
2026-05-14 18:00 ` Michael S. Tsirkin
2026-05-14 18:56 ` Gregory Price
2026-05-14 19:08 ` Michael S. Tsirkin
2026-05-15 15:39 ` Gregory Price
2026-05-15 15:45 ` Michael S. Tsirkin
2026-05-12 21:05 ` [PATCH v7 10/31] mm: use __GFP_ZERO in vma_alloc_zeroed_movable_folio Michael S. Tsirkin
2026-05-12 21:06 ` [PATCH v7 11/31] mm: remove arch vma_alloc_zeroed_movable_folio overrides Michael S. Tsirkin
2026-05-14 13:53 ` Gregory Price
2026-05-12 21:06 ` [PATCH v7 12/31] mm: alloc_anon_folio: pass raw fault address to vma_alloc_folio Michael S. Tsirkin
2026-05-12 21:06 ` [PATCH v7 13/31] mm: alloc_swap_folio: " Michael S. Tsirkin
2026-05-14 13:54 ` Gregory Price
2026-05-12 21:06 ` [PATCH v7 14/31] mm: use __GFP_ZERO in alloc_anon_folio Michael S. Tsirkin
2026-05-12 21:06 ` [PATCH v7 15/31] mm: vma_alloc_anon_folio_pmd: pass raw fault address to vma_alloc_folio Michael S. Tsirkin
2026-05-14 13:55 ` Gregory Price
2026-05-12 21:06 ` [PATCH v7 16/31] mm: use __GFP_ZERO in vma_alloc_anon_folio_pmd Michael S. Tsirkin
2026-05-12 21:06 ` [PATCH v7 17/31] mm: hugetlb: add gfp parameter and skip zeroing for zeroed pages Michael S. Tsirkin
2026-05-12 22:03 ` Gregory Price
2026-05-12 23:08 ` Michael S. Tsirkin
2026-05-12 21:06 ` [PATCH v7 18/31] mm: memfd: skip zeroing for zeroed hugetlb pool pages Michael S. Tsirkin
2026-05-14 14:07 ` Gregory Price
2026-05-12 21:06 ` [PATCH v7 19/31] mm: page_reporting: skip redundant zeroing of host-zeroed reported pages Michael S. Tsirkin
2026-05-14 14:13 ` Gregory Price
2026-05-12 21:06 ` [PATCH v7 20/31] mm: page_reporting: add per-page zeroed bitmap for host feedback Michael S. Tsirkin
2026-05-12 21:06 ` [PATCH v7 21/31] mm: page_alloc: clear PG_zeroed on buddy merge if not both zero Michael S. Tsirkin
2026-05-12 21:07 ` [PATCH v7 22/31] mm: page_alloc: preserve PG_zeroed in page_del_and_expand Michael S. Tsirkin
2026-05-14 14:15 ` Gregory Price
2026-05-12 21:07 ` [PATCH v7 23/31] virtio_balloon: submit reported pages as individual buffers Michael S. Tsirkin
2026-05-12 21:07 ` [PATCH v7 24/31] mm: page_reporting: add flush parameter with page budget Michael S. Tsirkin
2026-05-12 21:07 ` [PATCH v7 25/31] mm: page_alloc: propagate PG_zeroed in split_large_buddy Michael S. Tsirkin
2026-05-14 14:18 ` Gregory Price
2026-05-12 21:07 ` [PATCH v7 26/31] virtio_balloon: skip zeroing for host-zeroed reported pages Michael S. Tsirkin
2026-05-12 21:07 ` [PATCH v7 27/31] virtio_balloon: disable reporting zeroed optimization for confidential guests Michael S. Tsirkin
2026-05-12 21:07 ` [PATCH v7 28/31] mm: add free_frozen_pages_zeroed Michael S. Tsirkin
2026-05-12 21:07 ` [PATCH v7 29/31] mm: add put_page_zeroed and folio_put_zeroed Michael S. Tsirkin
2026-05-12 21:07 ` Michael S. Tsirkin [this message]
2026-05-12 21:07 ` [PATCH v7 31/31] mm: balloon: use put_page_zeroed for zeroed balloon pages Michael S. Tsirkin
2026-05-13 7:36 ` [PATCH v7 00/31] mm/virtio: skip redundant zeroing of host-zeroed pages David Hildenbrand (Arm)
2026-05-13 16:34 ` Gregory Price
2026-05-13 23:29 ` Michael S. Tsirkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3b2729a80c19e634f9bc93ca2a8baed8cd760b45.1778616612.git.mst@redhat.com \
--to=mst@redhat.com \
--cc=aarcange@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=apopple@nvidia.com \
--cc=axelrasmussen@google.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=bhe@redhat.com \
--cc=byungchul@sk.com \
--cc=chrisl@kernel.org \
--cc=cl@gentwo.org \
--cc=david@kernel.org \
--cc=dev.jain@arm.com \
--cc=eperezma@redhat.com \
--cc=gourry@gourry.net \
--cc=hannes@cmpxchg.org \
--cc=harry.yoo@oracle.com \
--cc=hughd@google.com \
--cc=jackmanb@google.com \
--cc=jasowang@redhat.com \
--cc=joshua.hahnjy@gmail.com \
--cc=kasong@tencent.com \
--cc=lance.yang@linux.dev \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=matthew.brost@intel.com \
--cc=mhocko@suse.com \
--cc=muchun.song@linux.dev \
--cc=npache@redhat.com \
--cc=nphamcs@gmail.com \
--cc=osalvador@suse.de \
--cc=rakie.kim@sk.com \
--cc=rientjes@google.com \
--cc=roman.gushchin@linux.dev \
--cc=rppt@kernel.org \
--cc=ryan.roberts@arm.com \
--cc=shikemeng@huaweicloud.com \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=virtualization@lists.linux.dev \
--cc=weixugc@google.com \
--cc=xuanzhuo@linux.alibaba.com \
--cc=ying.huang@linux.alibaba.com \
--cc=yuanchu@google.com \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.