All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: no-reply@sashiko.virtuozzo.com
To: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>,
	 svt-core@virtuozzo.com
Cc: andrey.drobyshev@virtuozzo.com
Subject: Re: [PATCH QEMU HCI-8.1 v7 33/35] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860
Date: Tue, 3 Nov 2026 14:38:03 +0000	[thread overview]
Message-ID: <010701a1a1d88344-56f27a4c-ab30-4a82-8740-c48017502bb1-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261103-vfio_v1-v7-33-4467fdccbbe6@virtuozzo.com>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Medium] vfio: cpr-transfer blocked for every VFIO device, not only those with saved BAR mmaps
- [Medium] vfio: cpr-transfer blocker skipped for vfio-user, stale BAR mappings reused
- [Low] vfio/region: BAR mappings enter CPR ramblock list walked by cpr-ram-rdonly mprotect
- [Low] vfio: unclaimed BAR mappings preserved by cpr-exec are never cleaned up
--

commit 8715bbf752f1d56051fe39f5336635bb75b99caa
Author: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>

VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860

This patch saves each VFIO BAR mapping in the CPR ramblock list so that
cpr-exec preserves it with MADV_DOEXEC, and the new QEMU reuses it instead
of calling mmap() again. It also blocks cpr-transfer for all VFIO devices
and updates CPR.rst to say so.

> diff --git a/docs/devel/migration/CPR.rst b/docs/devel/migration/CPR.rst
> --- a/docs/devel/migration/CPR.rst
> +++ b/docs/devel/migration/CPR.rst

[ ... ]

> -RAM in place, albeit with new virtual addresses in new QEMU.  Devices
> -and their pinned memory pages are also preserved for VFIO and IOMMUFD.
> +RAM in place, albeit with new virtual addresses in new QEMU.  VFIO and
> +IOMMUFD devices are not supported in this mode: use cpr-exec for them.

This documents the new policy, but only this paragraph was changed. Are
the other cpr-transfer and VFIO descriptions in CPR.rst still accurate?

> diff --git a/hw/vfio/device.c b/hw/vfio/device.c
> --- a/hw/vfio/device.c
> +++ b/hw/vfio/device.c

[ ... ]

> @@ -464,12 +464,32 @@ bool vfio_device_attach(char *name, VFIODevice *vbasedev,
> +    error_setg(&vbasedev->cpr.mmap_blocker,
> +               "cpr-transfer is not supported with VFIO devices; "
> +               "use the cpr-exec mode");
> +    if (migrate_add_blocker_modes(&vbasedev->cpr.mmap_blocker, errp,
> +                                  MIG_MODE_CPR_TRANSFER, -1)) {
> +        return false;
> +    }

[Severity: Medium]
Is it intended that this blocker is installed in vfio_device_attach() for
every VFIO device?

The blocker is added before any backend-specific work and without checking
device type, no_mmap, or whether any region will ever be saved through
vfio_region_cpr_save(). Devices such as vfio-ap, vfio-ccw, x-no-mmap
devices, devices with no mmap-able BARs, and PCI devices whose drivers
allow re-mapping would also lose cpr-transfer.

The commit message gives the NVIDIA vGPU re-map restriction as the
rationale. Would it be narrower to block only when
vfio_region_cpr_save() actually saves a mapping, or only on the PCI path?

The series does not appear to narrow this blocker later. The final state
still has the same unconditional mmap_blocker in vfio_device_attach().

Also, the cpr-transfer specific VFIO code now looks unreachable for
cpr-transfer, but it is left in place: the id_blocker with
MIG_MODE_CPR_TRANSFER in device.c, the blockers in cpr-legacy.c and
cpr-iommufd.c, and the ones in cpr.c. Should that code be cleaned up?

[Severity: Medium]
Does this blocker cover vfio-user devices? vfio_user_pci_realize() in
hw/vfio-user/pci.c calls vfio_device_attach_by_iommu_type() directly:

    if (!vfio_device_attach_by_iommu_type(TYPE_VFIO_IOMMU_USER,
                                          vbasedev->name, vbasedev,
                                          as, errp)) {

That bypasses vfio_device_attach(), so vbasedev->cpr.mmap_blocker is never
installed for vfio-user. hw/vfio-user/ has no other CPR blocker.

vfio-user regions can be mmapped through server-supplied region fds, and
vfio_bar_register() in hw/vfio/pci.c calls vfio_region_mmap(). That now
reaches vfio_region_cpr_save(), which puts the mapping in
cpr_state.ramblocks. That list is serialized for both cpr-exec and
cpr-transfer.

On a cpr-transfer target, vfio_region_cpr_find() looks up
"<vbasedev->name> region N mmaps[i]". For vfio-user, vbasedev->name is
"vfio-user:<sock>", so the name matches the saved entry.

> +static void *vfio_region_cpr_find(VFIORegion *region, int index)
> +{
> +    g_autofree char *name = vfio_region_cpr_name(region, index);
> +    cpr_ramblock_t ram = cpr_find_ramblock(name);
> +
> +    if (ram.addr && ram.length != region->mmaps[index].size) {
[ ... ]
> +    return (void *)(uintptr_t)ram.addr;
> +}

Nothing checks that the incoming mode is cpr-exec here. Can a cpr-transfer
target take the old process's address from this function and pass it to
memory_region_init_ram_device_ptr() in vfio_region_mmap() as if it were a
local mapping? If so, the first guest access to that BAR would touch an
invalid or unrelated address.

Should vfio_region_cpr_find() be gated on cpr_exec_is_incoming(), or should
the vfio-user attach path also install the blocker?

> +static void vfio_region_cpr_save(VFIORegion *region, int index)
> +{
[ ... ]
> +    cpr_save_ramblock(name, (cpr_ramblock_t) { (uintptr_t)addr, size });
> +}

[Severity: Low]
Is it intended that BAR mappings, including read-only ones, now go into the
same ramblock list that cpr_exec_cb() walks for the -cpr-ram-rdonly debug
option?

With that option set, cpr_exec_cb() calls
cpr_walk_ramblock(mark_ram_rdonly), and mark_ram_rw() later calls
qemu_mprotect_rw() on each entry and abort()s on failure:

    if (qemu_mprotect_rw((void *) ram.addr, ram.length)) {
        error_report("qemu_mprotect_rw() failed on memory region %s:"
        ...
        abort();

A BAR that vfio_region_mmap() mapped read-only (no
VFIO_REGION_INFO_FLAG_WRITE) would be turned into PROT_READ|PROT_WRITE by
cpr_ram_restore_rw(). If a driver rejects mprotect on these device PFN
mappings, QEMU would abort.

I did not confirm that any driver refuses mprotect. Should these entries be
excluded from the mprotect walks?

[Severity: Low]
Can a preserved BAR mapping that new QEMU never claims be left behind?

The only place a saved mapping is claimed is vfio_region_mmap():

    region->mmaps[i].mmap = vfio_region_cpr_find(region, i);
    if (region->mmaps[i].mmap) {
        goto mapped;
    }

The only cleanup is cpr_delete_ramblock() in vfio_subregion_unmap() and
vfio_region_finalize(), and both run only for regions that were set up on
the new side. If new QEMU never reaches vfio_region_mmap() for a region
(for example a different x-no-mmap setting, a changed region layout, or a
failed realize), the mapping stays mapped with its MADV_DOEXEC mark and its
cpr_state.ramblocks entry.

A later cpr-exec would then apply MADV_DOEXEC to it again through
cpr_walk_ramblock(preserve_ram). Because it is never unmapped, a driver
such as the NVIDIA vGPU driver would still see the BAR as mapped.

Is there a sweep of unclaimed region entries planned? None of the later
patches in the series appear to add one.

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261103-vfio_v1-v7-0-4467fdccbbe6@virtuozzo.com?part=33

  reply	other threads:[~2026-11-03 14:38 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-03 13:57 [PATCH QEMU HCI-8.1 v7 00/35] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 01/35] VZ: migration/cpr-exec: fix Error leak in preserve_ram() Andrey Drobyshev
2026-11-03 14:00   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 02/35] migration/cpr-exec: restore RAM write access if exec fails Andrey Drobyshev
2026-11-03 14:01   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 03/35] vfio/region: create BAR dma-bufs with O_CLOEXEC Andrey Drobyshev
2026-11-03 14:02   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 04/35] migration/cpr-exec: require a file or exec migration URI Andrey Drobyshev
2026-11-03 14:02   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 05/35] migration: close the CPR state if the outgoing channel fails to open Andrey Drobyshev
2026-11-03 14:03   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 06/35] migration/cpr-exec: close the persisted state if the " Andrey Drobyshev
2026-11-03 14:04   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 07/35] migration/cpr-exec: don't leak the dup'd memfd if g_setenv() fails Andrey Drobyshev
2026-11-03 14:04   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 08/35] migration: don't refuse a blocker over a migration of another mode Andrey Drobyshev
2026-11-03 14:05   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 09/35] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-11-03 14:05   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 10/35] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-11-03 14:05   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 11/35] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-11-03 14:05   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 12/35] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-11-03 14:06   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 13/35] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-11-03 14:06   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 14/35] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-11-03 14:06   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 15/35] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-11-03 14:08   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 16/35] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-11-03 14:08   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 17/35] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-11-03 14:11   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 18/35] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-11-03 14:11   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 19/35] migration: yank: Move register instance earlier Andrey Drobyshev
2026-11-03 14:16   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 20/35] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-11-03 14:14   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 21/35] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-11-03 14:14   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 22/35] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-11-03 14:16   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 23/35] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-11-03 14:21   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 24/35] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-11-03 14:19   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 25/35] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-11-03 14:21   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 26/35] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
2026-11-03 14:26   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 27/35] vfio/migration: don't assume the device is running on CPR incoming Andrey Drobyshev
2026-11-03 14:25   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 28/35] migration/ram: don't start dirty logging in CPR modes Andrey Drobyshev
2026-11-03 14:27   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 29/35] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-11-03 14:29   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 30/35] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-11-03 14:29   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 31/35] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-11-03 14:32   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 32/35] VZ: migration/cpr-exec: don't exec if a vhost-net device can't be released Andrey Drobyshev
2026-11-03 14:30   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 33/35] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-11-03 14:38   ` no-reply [this message]
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 34/35] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-11-03 14:33   ` no-reply
2026-11-03 13:57 ` [PATCH QEMU HCI-8.1 v7 35/35] VZ: vfio/migration: don't wait for stop-copy-only device state #VSTOR-141821 Andrey Drobyshev
2026-11-03 14:35   ` no-reply
2026-11-04 13:11 ` [PATCH QEMU HCI-8.1 v7 00/35] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Denis V. Lunev

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=010701a1a1d88344-56f27a4c-ab30-4a82-8740-c48017502bb1-000000@eu-central-1.amazonses.com \
    --to=no-reply@sashiko.virtuozzo.com \
    --cc=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 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.