From: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
To: svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com
Subject: [PATCH QEMU HCI-8.1 v3 21/28] vfio/migration: don't migrate device state during CPR
Date: Fri, 16 Oct 2026 18:26:19 +0300 [thread overview]
Message-ID: <20261016-vfio_v1-v3-21-47487cb5a8e5@virtuozzo.com> (raw)
In-Reply-To: <20261016-vfio_v1-v3-0-47487cb5a8e5@virtuozzo.com>
cpr-transfer and cpr-exec hand the running VFIO device over to the new
QEMU as is: the device fd, its mappings and interrupts are preserved, and
the device itself is never stopped.
But if the device supports VFIO migration, its migration handlers still
run. The old QEMU stops the device and saves its state, then the new
QEMU puts the very same device into RESUMING and loads that state back.
On top of that, vfio_pci_load_config() re-programs MSI-X and disables
vector 0.
For an NVIDIA vGPU this breaks the device after qemu-update: restoring
the state into the live vGPU fails and the guest loses the device.
Devices without migration support aren't affected, since no migration
handlers are registered for them.
Skip VFIO migration while a CPR migration is in progress: don't save or
load the device state, and don't change the device state on VM
stop/start. All of it is gated on cpr_is_in_progress(), not on the mode
alone: the mode may merely be set, and then a plain stop/cont must still
change the device state, and a snapshot must still save it.
Also reset multifd_transfer in vfio_multifd_cleanup(): it's only set in
vfio_multifd_setup(), which CPR now skips, so a stale value from an
earlier migration would still let the multifd save thread run.
Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
hw/vfio/migration-multifd.c | 2 ++
hw/vfio/migration.c | 38 +++++++++++++++++++++++++++++++++++++-
2 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/hw/vfio/migration-multifd.c b/hw/vfio/migration-multifd.c
index e4785031a73..452f772dd7a 100644
--- a/hw/vfio/migration-multifd.c
+++ b/hw/vfio/migration-multifd.c
@@ -567,6 +567,8 @@ void vfio_multifd_cleanup(VFIODevice *vbasedev)
VFIOMigration *migration = vbasedev->migration;
g_clear_pointer(&migration->multifd, vfio_multifd_free);
+ /* Decided anew by vfio_multifd_setup() of the next migration */
+ migration->multifd_transfer = false;
}
bool vfio_multifd_transfer_supported(void)
diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
index 4c06e3db936..b142c9f2289 100644
--- a/hw/vfio/migration.c
+++ b/hw/vfio/migration.c
@@ -19,6 +19,7 @@
#include "hw/vfio/vfio-device.h"
#include "hw/vfio/vfio-migration.h"
#include "migration/misc.h"
+#include "migration/cpr.h"
#include "migration/savevm.h"
#include "migration/vmstate.h"
#include "migration/qemu-file.h"
@@ -513,7 +514,6 @@ static void vfio_save_cleanup(void *opaque)
Error *local_err = NULL;
int ret;
- /* Currently a NOP, done for symmetry with load_cleanup() */
vfio_multifd_cleanup(vbasedev);
/*
@@ -674,6 +674,16 @@ static void vfio_save_state(QEMUFile *f, void *opaque)
Error *local_err = NULL;
int ret;
+ /*
+ * .is_active doesn't cover the non-iterable stage, so the section is
+ * still sent: leave it empty, or new QEMU would load the config into
+ * the preserved device and re-program its MSI-X.
+ */
+ if (cpr_is_in_progress()) {
+ qemu_put_be64(f, VFIO_MIG_FLAG_END_OF_STATE);
+ return;
+ }
+
if (vfio_multifd_transfer_enabled(vbasedev)) {
if (vfio_load_config_after_iter(vbasedev)) {
qemu_put_be64(f, VFIO_MIG_FLAG_DEV_CONFIG_LOAD_READY);
@@ -810,6 +820,11 @@ static bool vfio_switchover_ack_needed(void *opaque)
{
VFIODevice *vbasedev = opaque;
+ /* No device state is sent during CPR, so no ACK to wait for */
+ if (cpr_is_in_progress()) {
+ return false;
+ }
+
return vfio_precopy_supported(vbasedev);
}
@@ -824,7 +839,19 @@ static int vfio_switchover_start(void *opaque)
return 0;
}
+/*
+ * cpr-transfer and cpr-exec hand the running device over to the new QEMU
+ * as is: its fds, mappings and interrupts are preserved and it never stops.
+ * Device state migration must stay out of it, else the device is stopped,
+ * its state saved and then resumed into the very same device.
+ */
+static bool vfio_is_active(void *opaque)
+{
+ return !cpr_is_in_progress();
+}
+
static const SaveVMHandlers savevm_vfio_handlers = {
+ .is_active = vfio_is_active,
.save_prepare = vfio_save_prepare,
.save_setup = vfio_save_setup,
.save_cleanup = vfio_save_cleanup,
@@ -857,6 +884,11 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running,
Error *local_err = NULL;
int ret;
+ /* The device is preserved, not a plain stop/cont: keep its state */
+ if (cpr_is_in_progress()) {
+ return;
+ }
+
new_state = migration->device_state == VFIO_DEVICE_STATE_PRE_COPY ?
VFIO_DEVICE_STATE_PRE_COPY_P2P :
VFIO_DEVICE_STATE_RUNNING_P2P;
@@ -882,6 +914,10 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state)
Error *local_err = NULL;
int ret;
+ if (cpr_is_in_progress()) {
+ return;
+ }
+
if (running) {
new_state = VFIO_DEVICE_STATE_RUNNING;
} else {
--
2.47.1
next prev parent reply other threads:[~2026-10-16 15:26 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 15:25 [PATCH QEMU HCI-8.1 v3 00/28] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-16 15:25 ` [PATCH QEMU HCI-8.1 v3 01/28] VZ: migration/cpr-exec: fix Error leak in preserve_ram() Andrey Drobyshev
2026-10-16 15:28 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 02/28] migration/cpr-exec: restore RAM write access if exec fails Andrey Drobyshev
2026-10-16 15:28 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 03/28] vfio/region: create BAR dma-bufs with O_CLOEXEC Andrey Drobyshev
2026-10-16 15:30 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 04/28] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-10-16 15:29 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 05/28] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-10-16 15:30 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 06/28] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-10-16 15:30 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 07/28] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-10-16 15:31 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 08/28] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-10-16 15:32 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 09/28] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-10-16 15:31 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 10/28] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-10-16 15:33 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 11/28] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-10-16 15:32 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 12/28] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-10-16 15:35 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 13/28] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-10-16 15:38 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 14/28] migration: yank: Move register instance earlier Andrey Drobyshev
2026-10-16 15:41 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 15/28] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-10-16 15:39 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 16/28] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-10-16 15:40 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 17/28] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-10-16 15:44 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 18/28] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-10-16 15:44 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 19/28] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-10-16 15:46 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 20/28] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-10-16 15:46 ` no-reply
2026-10-16 15:26 ` Andrey Drobyshev [this message]
2026-10-16 15:55 ` [PATCH QEMU HCI-8.1 v3 21/28] vfio/migration: don't migrate device state during CPR no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 22/28] vfio/listener: skip dirty page tracking " Andrey Drobyshev
2026-10-16 15:50 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 23/28] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-10-16 15:52 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 24/28] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-10-16 15:55 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 25/28] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-10-16 15:58 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 26/28] VZ: migration/cpr-exec: don't exec if a vhost-net device can't be released Andrey Drobyshev
2026-10-16 15:56 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 27/28] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-10-16 16:02 ` no-reply
2026-10-16 15:26 ` [PATCH QEMU HCI-8.1 v3 28/28] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-10-16 15:59 ` no-reply
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=20261016-vfio_v1-v3-21-47487cb5a8e5@virtuozzo.com \
--to=andrey.drobyshev@virtuozzo.com \
--cc=svt-core@virtuozzo.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox