[virtio-comment] virtio-balloon: proposal — free pag e reporting hold
"zhangjianming" <[email protected]>
| Newsgroups | dev.linux.lists.virtio-comment |
|---|---|
| Message-ID | <43fe2f5c-6c0c-4279-8e55-42ddd9daf637.zhangjianming@linux.alibaba.com> |
Hi all,
I'd like to propose a new virtio-balloon feature bit and would appreciate feedback on the semantics and naming.
Problem: On Windows, there is no driver-visible free page list — free pages live on OS-internal lists, so a driver implementing free page reporting must allocate pages out (via the Windows kernel API MmAllocatePagesForMdlEx), report them, and then return them to the OS. Measurements show that returning the pages to the OS itself re-touches them, and each touch is a fresh page fault on the host, so the host-side reclaim effect collapses back immediately; report-then-release is therefore not workable on Windows. What does work is report-then-hold: keep the reported pages allocated inside the driver — where the guest cannot touch them — and only hand them back when the guest actually needs memory (low-memory conditions / rising demand), effectively an adaptive balloon driven by the reporting queue. Measurements on a 4 GB Windows guest: steady-state host RSS 1.65 GB with ~2.4 GB parked, full re-park within seconds after load drops. Note that in this scheme the driver alone decides how much to hold and when to hand pages back — the host never directs the hold; it only observes what is reported (and, with the optional stats tag below, how much is held).
Why a new bit: Free Page Reporting in the current spec (virtio v1.4 cs01, section 5.5.6.7) says: "Reported free pages can be reused by the driver after the reporting request has been acknowledged without notifying the device", and the described flow assumes the driver eventually "put[s] them back to free page lists in the guest operating system". This wording is permissive — a driver that defers the reuse does not violate it — but it also says nothing about it: with a single negotiated feature, a driver that releases immediately and a driver that holds pages are indistinguishable to the host. A host that wants to treat reported memory as reclaimable for overcommit accounting cannot tell which behavior it got. A dedicated bit removes this ambiguity with zero migration cost: old drivers never accept it, so existing deployments stay unaffected in both directions.
Spec reference (section 5.5.6.7, unchanged since v1.2):
https://docs.oasis-open.org/virtio/virtio/v1.4/cs01/virtio-v1.4-cs01.html <https://docs.oasis-open.org/virtio/virtio/v1.4/cs01/virtio-v1.4-cs01.html >
Proposal:
- VIRTIO_BALLOON_F_PAGE_REPORTING_HOLD (bit 6, name open for discussion): when negotiated, the driver MAY keep reported pages off the guest free lists after the acknowledgement, and only return them when the guest needs them.
- Device MUST NOT offer HOLD unless REPORTING is also offered; driver MUST NOT accept HOLD unless REPORTING is negotiated. Why the dependency: HOLD is not a standalone mechanism, it modifies what the driver may do with pages it has already reported — and reported pages only exist inside the reporting flow. Without REPORTING there is no reporting virtqueue and no reported pages, so there is nothing for the "hold" semantics to apply to. On the host side the bit is equally tied to REPORTING: the host reclaims the corresponding memory when a report arrives, so without REPORTING the bit would have no observable effect at all. Existing virtio practice has the same pattern of features that may only be negotiated together (e.g. VIRTIO_NET_F_MQ requires VIRTIO_NET_F_CTRL_VQ).
- Optional: a new tag in the stats virtqueue (e.g. held-pages) so the host can observe how much memory is currently held rather than reported-and-released.
Reference implementation: A small QEMU patch (uapi define + DEFINE_PROP_BIT("free-page-reporting-hold") + a realize-time dependency check) is attached, verified with the four offer combinations, including rejection of hold-without-reporting at startup. The guest side is a Windows reporting driver that allocates pages via MmAllocatePagesForMdlEx and parks the reported MDLs instead of returning them via MmFreePagesFromMdl right away; it negotiates REPORTING, ignores the unknown new bit, and the measurements above come from this driver.
Prior art: VIRTIO_BALLOON_F_DEFLATE_ON_OOM already uses negotiation to declare a driver-side policy the device does not participate in; this proposal follows the same pattern.
Thoughts on the semantics, the dependency direction, and the naming (alternatives: F_REPORTING_HOLD, F_PAGE_REPORTING_DEFERRED_REUSE) are very welcome.
Thanks,
JianMing
0001-virtio-balloon-experimental-free-page-reporting-hold.patch
(application/octet-stream, 3.9 KB)
From 04b8d09081c1bc92e9eb4dcbd372c4439bde5206 Mon Sep 17 00:00:00 2001 From: Zhang JianMing <[email protected]> Date: Mon, 17 Aug 2026 19:09:16 +0800 Subject: [PATCH RFC] virtio-balloon: add experimental free-page-reporting-hold feature bit Reference implementation for the proposed VIRTIO_BALLOON_F_PAGE_REPORTING_HOLD feature bit, posted as an attachment to the virtio-comment discussion. Experimental, not for merge until the spec discussion settles the semantics and the final feature number. The new bit tells the driver that it may keep reported pages off its free page lists after the host has acked the report, reusing them only when needed, instead of returning them to the free lists right away. On Windows guests the immediate return defeats reporting altogether: the Windows memory manager touches every page it frees, so reported pages are instantly dirtied and reclaimed by the guest. - new define in the standard headers copy (not the kernel uapi) - "free-page-reporting-hold" property, default off - realize-time check: hold requires free-page-reporting No behavior change unless the property is explicitly enabled. Signed-off-by: Zhang JianMing <[email protected]> --- hw/virtio/virtio-balloon.c | 16 ++++++++++++++++ include/standard-headers/linux/virtio_balloon.h | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 02cdd807d7..aa02329d6b 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -872,6 +872,14 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp) VirtIOBalloon *s = VIRTIO_BALLOON(dev); int ret; + if (virtio_has_feature(s->host_features, + VIRTIO_BALLOON_F_PAGE_REPORTING_HOLD) && + !virtio_has_feature(s->host_features, VIRTIO_BALLOON_F_REPORTING)) { + error_setg(errp, + "'free-page-reporting-hold' requires 'free-page-reporting'"); + return; + } + virtio_init(vdev, VIRTIO_ID_BALLOON, virtio_balloon_config_size(s)); ret = qemu_add_balloon_handler(virtio_balloon_to_target, @@ -1050,6 +1058,14 @@ static const Property virtio_balloon_properties[] = { VIRTIO_BALLOON_F_PAGE_POISON, true), DEFINE_PROP_BIT("free-page-reporting", VirtIOBalloon, host_features, VIRTIO_BALLOON_F_REPORTING, false), + /* + * EXPERIMENTAL (pending virtio spec discussion): may only be enabled + * together with free-page-reporting. Tells the driver it is allowed to + * hold reported pages and only reuse them when needed, instead of + * returning them to the guest free page lists right away. + */ + DEFINE_PROP_BIT("free-page-reporting-hold", VirtIOBalloon, host_features, + VIRTIO_BALLOON_F_PAGE_REPORTING_HOLD, false), /* QEMU 4.0 accidentally changed the config size even when free-page-hint * is disabled, resulting in QEMU 3.1 migration incompatibility. This * property retains this quirk for QEMU 4.1 machine types. diff --git a/include/standard-headers/linux/virtio_balloon.h b/include/standard-headers/linux/virtio_balloon.h index 3121cd2e0e..686195bb2d 100644 --- a/include/standard-headers/linux/virtio_balloon.h +++ b/include/standard-headers/linux/virtio_balloon.h @@ -37,6 +37,12 @@ #define VIRTIO_BALLOON_F_FREE_PAGE_HINT 3 /* VQ to report free pages */ #define VIRTIO_BALLOON_F_PAGE_POISON 4 /* Guest is using page poisoning */ #define VIRTIO_BALLOON_F_REPORTING 5 /* Page reporting virtqueue */ +/* + * EXPERIMENTAL (pending virtio spec discussion, not yet in kernel uapi): + * driver may hold reported pages after ack instead of returning them to the + * guest free page lists right away, and only reuse them when needed. + */ +#define VIRTIO_BALLOON_F_PAGE_REPORTING_HOLD 6 /* Size of a PFN in the balloon interface. */ #define VIRTIO_BALLOON_PFN_SHIFT 12 -- 2.43.0