Virtuozzo QEMU development (svt-core@virtuozzo.com)
 help / color / mirror / Atom feed
From: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
To: svt-core@virtuozzo.com
Cc: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Subject: [PATCH QEMU HCI-8.1 16/21] vfio/migration: don't migrate device state during CPR
Date: Fri, 09 Oct 2026 17:56:15 +0300	[thread overview]
Message-ID: <20261009-vfio_v1-v1-16-2ae91d5b8048@virtuozzo.com> (raw)
In-Reply-To: <20261009-vfio_v1-v1-0-2ae91d5b8048@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 in CPR modes: don't save or load the device state,
and don't change the device state on VM stop/start.  Use
cpr_incoming_needed(), which tells exactly when the device is preserved
by CPR, both on the old and the new QEMU side.

Signed-off-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
---
 hw/vfio/migration.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
index 4c06e3db936..99d285e7b20 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"
@@ -674,6 +675,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_incoming_needed(NULL)) {
+        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);
@@ -824,7 +835,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_incoming_needed(NULL);
+}
+
 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 +880,10 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running,
     Error *local_err = NULL;
     int ret;
 
+    if (cpr_incoming_needed(NULL)) {
+        return;
+    }
+
     new_state = migration->device_state == VFIO_DEVICE_STATE_PRE_COPY ?
                     VFIO_DEVICE_STATE_PRE_COPY_P2P :
                     VFIO_DEVICE_STATE_RUNNING_P2P;
@@ -882,6 +909,10 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state)
     Error *local_err = NULL;
     int ret;
 
+    if (cpr_incoming_needed(NULL)) {
+        return;
+    }
+
     if (running) {
         new_state = VFIO_DEVICE_STATE_RUNNING;
     } else {

-- 
2.47.1


  parent reply	other threads:[~2026-10-09 14:56 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-09 14:55 [PATCH QEMU HCI-8.1 00/21] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 01/21] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-10-09 15:09   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 02/21] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-10-09 15:09   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 03/21] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-10-09 15:10   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 04/21] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-10-09 15:10   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 05/21] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-10-09 15:13   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 06/21] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-10-09 15:10   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 07/21] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-10-09 15:12   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 08/21] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-10-09 15:13   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 09/21] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-10-09 15:17   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 10/21] migration: yank: Move register instance earlier Andrey Drobyshev
2026-10-09 15:16   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 11/21] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-10-09 15:17   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 12/21] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-10-09 15:18   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 13/21] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-10-09 15:20   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 14/21] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-10-09 15:22   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 15/21] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-10-09 15:22   ` no-reply
2026-10-09 14:56 ` Andrey Drobyshev [this message]
2026-10-09 15:29   ` [PATCH QEMU HCI-8.1 16/21] vfio/migration: don't migrate device state during CPR no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 17/21] vfio/listener: skip dirty page tracking " Andrey Drobyshev
2026-10-09 15:27   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 18/21] VZ: physmem: align fd-backed RAM like anonymous RAM #VSTOR-103860 Andrey Drobyshev
2026-10-09 15:31   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 19/21] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-10-09 15:31   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 20/21] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-10-09 15:36   ` no-reply
2026-10-09 14:56 ` [PATCH QEMU HCI-8.1 21/21] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-10-09 15:34   ` 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=20261009-vfio_v1-v1-16-2ae91d5b8048@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