From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Peter Maydell" <peter.maydell@linaro.org>,
"Daniel P. Berrangé" <berrange@redhat.com>,
"David Hildenbrand" <david@redhat.com>
Subject: [PULL 25/41] hw/virtio: reset virtio balloon stats on machine reset
Date: Fri, 21 Feb 2025 07:23:57 -0500 [thread overview]
Message-ID: <1456e90653c46aceb3dd83a7b9889a32aad7700d.1740140520.git.mst@redhat.com> (raw)
In-Reply-To: <cover.1740140520.git.mst@redhat.com>
From: Daniel P. Berrangé <berrange@redhat.com>
When a machine is first booted, all virtio balloon stats are initialized
to their default value -1 (18446744073709551615 when represented as
unsigned).
They remain that way while the firmware is loading, and early phase of
guest OS boot, until the virtio-balloon driver is activated. Thereafter
the reported stats reflect the guest OS activity.
When a machine reset is performed, however, the virtio-balloon stats are
left unchanged by QEMU, despite the guest OS no longer updating them,
nor indeed even still existing.
IOW, the mgmt app keeps getting stale stats until the guest OS starts
once more and loads the virtio-balloon driver (if ever). At that point
the app will see a discontinuity in the reported values as they sudden
jump from the stale value to the new value. This jump is indigituishable
from a valid data update.
While there is an "last-updated" field to report on the freshness of
the stats, that does not unambiguously tell the mgmt app whether the
stats are still conceptually relevant to the current running workload.
It is more conceptually useful to reset the stats to their default
values on machine reset, given that the previous guest workload the
stats reflect no longer exists. The mgmt app can now clearly identify
that there are is no stats information available from the current
executing workload.
The 'last-updated' time is also reset back to 0.
IOW, on every machine reset, the virtio stats are in the same clean
state they were when the macine first powered on.
A functional test is added to validate this behaviour with a real
world guest OS.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Message-Id: <20250204094202.2183262-1-berrange@redhat.com>
Acked-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
include/hw/virtio/virtio-balloon.h | 4 +
hw/virtio/virtio-balloon.c | 30 ++++-
MAINTAINERS | 1 +
tests/functional/meson.build | 2 +
tests/functional/test_virtio_balloon.py | 161 ++++++++++++++++++++++++
5 files changed, 197 insertions(+), 1 deletion(-)
create mode 100755 tests/functional/test_virtio_balloon.py
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index b12c18a43b..0456c211c6 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -16,6 +16,7 @@
#define QEMU_VIRTIO_BALLOON_H
#include "standard-headers/linux/virtio_balloon.h"
+#include "hw/resettable.h"
#include "hw/virtio/virtio.h"
#include "system/iothread.h"
#include "qom/object.h"
@@ -71,6 +72,9 @@ struct VirtIOBalloon {
bool qemu_4_0_config_size;
uint32_t poison_val;
+
+ /* State of the resettable container */
+ ResettableState reset_state;
};
#endif
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index ad05768ded..2eb5a14fa2 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -31,7 +31,7 @@
#include "trace.h"
#include "qemu/error-report.h"
#include "migration/misc.h"
-
+#include "system/reset.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
@@ -910,6 +910,8 @@ static void virtio_balloon_device_realize(DeviceState *dev, Error **errp)
}
reset_stats(s);
+ s->stats_last_update = 0;
+ qemu_register_resettable(OBJECT(dev));
}
static void virtio_balloon_device_unrealize(DeviceState *dev)
@@ -917,6 +919,7 @@ static void virtio_balloon_device_unrealize(DeviceState *dev)
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
VirtIOBalloon *s = VIRTIO_BALLOON(dev);
+ qemu_unregister_resettable(OBJECT(dev));
if (s->free_page_bh) {
qemu_bh_delete(s->free_page_bh);
object_unref(OBJECT(s->iothread));
@@ -987,6 +990,27 @@ static void virtio_balloon_set_status(VirtIODevice *vdev, uint8_t status)
}
}
+static ResettableState *virtio_balloon_get_reset_state(Object *obj)
+{
+ VirtIOBalloon *s = VIRTIO_BALLOON(obj);
+ return &s->reset_state;
+}
+
+static void virtio_balloon_reset_enter(Object *obj, ResetType type)
+{
+ VirtIOBalloon *s = VIRTIO_BALLOON(obj);
+
+ /*
+ * When waking up from standby/suspend-to-ram, do not reset stats.
+ */
+ if (type == RESET_TYPE_WAKEUP) {
+ return;
+ }
+
+ reset_stats(s);
+ s->stats_last_update = 0;
+}
+
static void virtio_balloon_instance_init(Object *obj)
{
VirtIOBalloon *s = VIRTIO_BALLOON(obj);
@@ -1038,6 +1062,7 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
device_class_set_props(dc, virtio_balloon_properties);
dc->vmsd = &vmstate_virtio_balloon;
@@ -1050,6 +1075,9 @@ static void virtio_balloon_class_init(ObjectClass *klass, void *data)
vdc->get_features = virtio_balloon_get_features;
vdc->set_status = virtio_balloon_set_status;
vdc->vmsd = &vmstate_virtio_balloon_device;
+
+ rc->get_state = virtio_balloon_get_reset_state;
+ rc->phases.enter = virtio_balloon_reset_enter;
}
static const TypeInfo virtio_balloon_info = {
diff --git a/MAINTAINERS b/MAINTAINERS
index a928ce3e41..013a57d5bf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2246,6 +2246,7 @@ F: include/hw/virtio/virtio-balloon.h
F: system/balloon.c
F: include/system/balloon.h
F: tests/qtest/virtio-balloon-test.c
+F: tests/functional/test_virtio_balloon.py
virtio-9p
M: Greg Kurz <groug@kaod.org>
diff --git a/tests/functional/meson.build b/tests/functional/meson.build
index cf80924ddc..2d399cc464 100644
--- a/tests/functional/meson.build
+++ b/tests/functional/meson.build
@@ -44,6 +44,7 @@ test_timeouts = {
'riscv64_tuxrun' : 120,
's390x_ccw_virtio' : 420,
'sh4_tuxrun' : 240,
+ 'virtio_balloon': 120,
}
tests_generic_system = [
@@ -242,6 +243,7 @@ tests_x86_64_system_thorough = [
'linux_initrd',
'multiprocess',
'netdev_ethtool',
+ 'virtio_balloon',
'virtio_gpu',
'x86_64_hotplug_cpu',
'x86_64_tuxrun',
diff --git a/tests/functional/test_virtio_balloon.py b/tests/functional/test_virtio_balloon.py
new file mode 100755
index 0000000000..67b48e1b4e
--- /dev/null
+++ b/tests/functional/test_virtio_balloon.py
@@ -0,0 +1,161 @@
+#!/usr/bin/env python3
+#
+# virtio-balloon tests
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
+
+import time
+
+from qemu_test import QemuSystemTest, Asset
+from qemu_test import wait_for_console_pattern
+from qemu_test import exec_command_and_wait_for_pattern
+
+UNSET_STATS_VALUE = 18446744073709551615
+
+
+class VirtioBalloonx86(QemuSystemTest):
+
+ ASSET_KERNEL = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
+ '/31/Server/x86_64/os/images/pxeboot/vmlinuz'),
+ 'd4738d03dbbe083ca610d0821d0a8f1488bebbdccef54ce33e3adb35fda00129')
+
+ ASSET_INITRD = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
+ '/31/Server/x86_64/os/images/pxeboot/initrd.img'),
+ '277cd6c7adf77c7e63d73bbb2cded8ef9e2d3a2f100000e92ff1f8396513cd8b')
+
+ ASSET_DISKIMAGE = Asset(
+ ('https://archives.fedoraproject.org/pub/archive/fedora/linux/releases'
+ '/31/Cloud/x86_64/images/Fedora-Cloud-Base-31-1.9.x86_64.qcow2'),
+ 'e3c1b309d9203604922d6e255c2c5d098a309c2d46215d8fc026954f3c5c27a0')
+
+ DEFAULT_KERNEL_PARAMS = ('root=/dev/vda1 console=ttyS0 net.ifnames=0 '
+ 'rd.rescue')
+
+ def wait_for_console_pattern(self, success_message, vm=None):
+ wait_for_console_pattern(
+ self,
+ success_message,
+ failure_message="Kernel panic - not syncing",
+ vm=vm,
+ )
+
+ def mount_root(self):
+ self.wait_for_console_pattern('Entering emergency mode.')
+ prompt = '# '
+ self.wait_for_console_pattern(prompt)
+
+ exec_command_and_wait_for_pattern(self, 'mount /dev/vda1 /sysroot',
+ prompt)
+ exec_command_and_wait_for_pattern(self, 'chroot /sysroot',
+ prompt)
+ exec_command_and_wait_for_pattern(self, "modprobe virtio-balloon",
+ prompt)
+
+ def assert_initial_stats(self):
+ ret = self.vm.qmp('qom-get',
+ {'path': '/machine/peripheral/balloon',
+ 'property': 'guest-stats'})['return']
+ when = ret.get('last-update')
+ assert when == 0
+ stats = ret.get('stats')
+ for name, val in stats.items():
+ assert val == UNSET_STATS_VALUE
+
+ def assert_running_stats(self, then):
+ ret = self.vm.qmp('qom-get',
+ {'path': '/machine/peripheral/balloon',
+ 'property': 'guest-stats'})['return']
+ when = ret.get('last-update')
+ now = time.time()
+
+ assert when > then and when < now
+ stats = ret.get('stats')
+ # Stat we expect this particular Kernel to have set
+ expectData = [
+ "stat-available-memory",
+ "stat-disk-caches",
+ "stat-free-memory",
+ "stat-htlb-pgalloc",
+ "stat-htlb-pgfail",
+ "stat-major-faults",
+ "stat-minor-faults",
+ "stat-swap-in",
+ "stat-swap-out",
+ "stat-total-memory",
+ ]
+ for name, val in stats.items():
+ if name in expectData:
+ assert val != UNSET_STATS_VALUE
+ else:
+ assert val == UNSET_STATS_VALUE
+
+ def test_virtio_balloon_stats(self):
+ self.set_machine('q35')
+ kernel_path = self.ASSET_KERNEL.fetch()
+ initrd_path = self.ASSET_INITRD.fetch()
+ diskimage_path = self.ASSET_DISKIMAGE.fetch()
+
+ self.vm.set_console()
+ self.vm.add_args("-S")
+ self.vm.add_args("-cpu", "max")
+ self.vm.add_args("-m", "2G")
+ # Slow down BIOS phase with boot menu, so that after a system
+ # reset, we can reliably catch the clean stats again in BIOS
+ # phase before the guest OS launches
+ self.vm.add_args("-boot", "menu=on")
+ self.vm.add_args("-machine", "q35,accel=kvm:tcg")
+ self.vm.add_args("-device", "virtio-balloon,id=balloon")
+ self.vm.add_args('-drive',
+ f'file={diskimage_path},if=none,id=drv0,snapshot=on')
+ self.vm.add_args('-device', 'virtio-blk-pci,bus=pcie.0,' +
+ 'drive=drv0,id=virtio-disk0,bootindex=1')
+
+ self.vm.add_args(
+ "-kernel",
+ kernel_path,
+ "-initrd",
+ initrd_path,
+ "-append",
+ self.DEFAULT_KERNEL_PARAMS
+ )
+ self.vm.launch()
+
+ # Poll stats at 100ms
+ self.vm.qmp('qom-set',
+ {'path': '/machine/peripheral/balloon',
+ 'property': 'guest-stats-polling-interval',
+ 'value': 100 })
+
+ # We've not run any guest code yet, neither BIOS or guest,
+ # so stats should be all default values
+ self.assert_initial_stats()
+
+ self.vm.qmp('cont')
+
+ then = time.time()
+ self.mount_root()
+ self.assert_running_stats(then)
+
+ # Race window between these two commands, where we
+ # rely on '-boot menu=on' to (hopefully) ensure we're
+ # still executing the BIOS when QEMU processes the
+ # 'stop', and thus have not loaded the virtio-balloon
+ # driver in the guest
+ self.vm.qmp('system_reset')
+ self.vm.qmp('stop')
+
+ # If the above assumption held, we're in BIOS now and
+ # stats should be all back at their default values
+ self.assert_initial_stats()
+ self.vm.qmp('cont')
+
+ then = time.time()
+ self.mount_root()
+ self.assert_running_stats(then)
+
+
+if __name__ == '__main__':
+ QemuSystemTest.main()
--
MST
next prev parent reply other threads:[~2025-02-21 12:32 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-21 12:22 [PULL 00/41] virtio,pc,pci: features, fixes, cleanups Michael S. Tsirkin
2025-02-21 12:22 ` [PULL 01/41] docs/about: Change notes on x86 machine type deprecation into a general one Michael S. Tsirkin
2025-02-21 12:22 ` [PULL 02/41] hw/net: Fix NULL dereference with software RSS Michael S. Tsirkin
2025-02-27 9:51 ` Michael Tokarev
2025-02-21 12:22 ` [PULL 03/41] hw/ppc/spapr_pci: Do not create DT for disabled PCI device Michael S. Tsirkin
2025-02-21 12:22 ` [PULL 04/41] hw/ppc/spapr_pci: Do not reject VFs created after a PF Michael S. Tsirkin
2025-02-21 12:22 ` [PULL 05/41] s390x/pci: Avoid creating zpci for VFs Michael S. Tsirkin
2025-02-21 12:22 ` [PULL 06/41] s390x/pci: Allow plugging SR-IOV devices Michael S. Tsirkin
2025-02-21 12:22 ` [PULL 07/41] s390x/pci: Check for multifunction after device realization Michael S. Tsirkin
2025-02-21 12:22 ` [PULL 08/41] pcie_sriov: Do not manually unrealize Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 09/41] pcie_sriov: Ensure VF addr does not overflow Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 10/41] pcie_sriov: Reuse SR-IOV VF device instances Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 11/41] pcie_sriov: Release VFs failed to realize Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 12/41] pcie_sriov: Remove num_vfs from PCIESriovPF Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 13/41] pcie_sriov: Register VFs after migration Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 14/41] qtest/libqos/pci: Do not write to PBA memory Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 15/41] hw/pci/msix: Warn on PBA writes Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 16/41] hw/pci: Assert a bar is not registered multiple times Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 17/41] hw/i386/pc: Fix crash that occurs when introspecting TYPE_PC_MACHINE machines Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 18/41] hw/i386/microvm: Fix crash that occurs when introspecting the microvm machine Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 19/41] tests/qtest/vhost-user-test: Use modern virtio for vhost-user tests Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 20/41] hw/cxl: Introduce CXL_T3_MSIX_VECTOR enumeration Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 21/41] hw/mem/cxl_type3: Add paired msix_uninit_exclusive_bar() call Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 22/41] hw/mem/cxl_type3: Fix special_ops memory leak on msix_init_exclusive_bar() failure Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 23/41] hw/mem/cxl_type3: Ensure errp is set on realization failure Michael S. Tsirkin
2025-02-21 12:23 ` [PULL 24/41] mem/cxl_type3: support 3, 6, 12 and 16 interleave ways Michael S. Tsirkin
2025-02-21 12:23 ` Michael S. Tsirkin [this message]
2025-02-21 12:24 ` [PULL 26/41] amd_iommu: Use correct DTE field for interrupt passthrough Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 27/41] amd_iommu: Use correct bitmask to set capability BAR Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 28/41] vhost-iova-tree: Implement an IOVA-only tree Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 29/41] vhost-iova-tree, svq: Implement GPA->IOVA & partial IOVA->HVA trees Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 30/41] vhost-iova-tree: Update documentation Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 31/41] cryptodev/vhost: allocate CryptoDevBackendVhost using g_mem0() Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 32/41] MAINTAINERS: add more files to `vhost` Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 33/41] vdpa: Fix endian bugs in shadow virtqueue Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 34/41] hw/virtio/virtio-nsm: Respond with correct length Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 35/41] net: vhost-user: add QAPI events to report connection state Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 36/41] vhost-user-snd: correct the calculation of config_size Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 37/41] hw/virtio/virtio-iommu: Migrate to 3-phase reset Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 38/41] hw/i386/intel-iommu: " Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 39/41] hw/arm/smmuv3: Move reset to exit phase Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 40/41] hw/vfio/common: Add a trace point in vfio_reset_handler Michael S. Tsirkin
2025-02-21 12:24 ` [PULL 41/41] docs/devel/reset: Document reset expectations for DMA and IOMMU Michael S. Tsirkin
2025-02-21 23:17 ` [PULL 00/41] virtio,pc,pci: features, fixes, cleanups Stefan Hajnoczi
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=1456e90653c46aceb3dd83a7b9889a32aad7700d.1740140520.git.mst@redhat.com \
--to=mst@redhat.com \
--cc=berrange@redhat.com \
--cc=david@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-devel@nongnu.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).