All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: no-reply@sashiko.virtuozzo.com
To: svt-core@virtuozzo.com,
	 Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
Subject: Re: [PATCH QEMU HCI-8.1 v4 29/31] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860
Date: Tue, 20 Oct 2026 17:08:48 +0000	[thread overview]
Message-ID: <010701a15a497e88-17499b09-190a-4242-a21f-73d0a45590b7-000000@eu-central-1.amazonses.com> (raw)
In-Reply-To: <20261020-vfio_v1-v4-29-83a5668230e5@virtuozzo.com>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [Medium] vfio: vfio_device_attach() now fails hotplug while migration/snapshot runs
- [Medium] vfio: unconditional cpr-transfer blocker in vfio_device_attach() for all VFIO devices
- [Low] vfio/region: vfio_region_cpr_find() aborts on mmap size mismatch via assert()
- [Low] vfio: BAR mappings joined to CPR ramblock list hit abort()-on-failure mprotect in cpr-ram-rdonly mode
- [Low] vfio: preserved display-region mapping not released if never remapped after cpr-exec
--

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

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

This patch saves each VFIO BAR mmap in the CPR ramblock list so that
cpr_exec_cb() marks it with MADV_DOEXEC. New QEMU then reuses the saved
mapping instead of calling mmap() again. It also adds a blocker that stops
cpr-transfer for all VFIO devices.

> 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,
>                               TYPE_VFIO_IOMMU_IOMMUFD :
>                               TYPE_VFIO_IOMMU_LEGACY;
>  
> -    return vfio_device_attach_by_iommu_type(iommu_type, name, vbasedev,
> -                                            as, errp);
> +    /*
> +     * Only cpr-exec keeps the address space and so the region mappings,
> +     * see vfio_region_mmap().  A cpr-transfer target would have to map the
> +     * regions anew, which some drivers (NVIDIA vGPU) refuse.
> +     */
> +    error_setg(&vbasedev->cpr.mmap_blocker,
> +               "cpr-transfer is not supported with VFIO devices; "
> +               "use the cpr-exec mode");

[Severity: Medium]
The blocker is installed here for every VFIO device, before no_mmap, the
device type or the region state is looked at. Does this also disable
cpr-transfer for devices that never map a BAR (no_mmap=on, vfio-ap,
vfio-ccw) and for drivers that accept a re-mmap?

The stated reason is the NVIDIA vGPU re-mmap problem, which only exists
once vfio_region_cpr_save() has actually saved a mapping. Could the
blocker be added only when a BAR mapping is saved, or be made opt-in per
device?

Also, docs/devel/migration/CPR.rst still says in the cpr-transfer mode
section that VFIO devices are supported:

    This mode supports VFIO devices provided the user first puts the

Should the documentation be updated along with this change?

> +    if (migrate_add_blocker_modes(&vbasedev->cpr.mmap_blocker, errp,
> +                                  MIG_MODE_CPR_TRANSFER, -1)) {
> +        return false;
> +    }

[Severity: Medium]
Can this make vfio_device_attach() fail during a migration or snapshot,
whatever the CPR mode? migrate_add_blocker_modes() runs is_busy() no
matter which mode mask is passed:

vfio_device_attach()
  migrate_add_blocker_modes()
    is_busy()
      if (runstate_check(RUN_STATE_SAVE_VM) || migration_is_running()) {
          error_propagate_prepend(errp, *reasonp,
              "disallowing migration blocker (migration/snapshot in progress) for: ");
          ...
          return true;
      }

This returns -EBUSY, so realizing or hotplugging any VFIO device (PCI,
AP, CCW; legacy or iommufd) while a migration is running or
RUN_STATE_SAVE_VM is set would now fail. Is that intended?

The later patches in the series do not change this call.

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

[ ... ]

> +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) {
> +        assert(ram.length == region->mmaps[index].size);
> +    }

[Severity: Low]
If the preserved length differs from the size that new QEMU computes for
this mmap slot, this aborts after old QEMU has already exec'd. Could this
report an error with error_report() and exit(1), as the ramblock reuse
path in system/physmem.c does under cpr_exec_is_incoming()?

Only the length is compared here. Offset, prot and fd_offset are not
validated, so a layout change that keeps the same length would silently
reuse a mapping of the wrong window. Is a check of those intended?

[ ... ]

> +static void vfio_region_cpr_save(VFIORegion *region, int index)
> +{
> +    g_autofree char *name = vfio_region_cpr_name(region, index);
> +    void *addr = region->mmaps[index].mmap;
> +    size_t size = region->mmaps[index].size;
> +
> +    cpr_save_ramblock(name, (cpr_ramblock_t) { (uintptr_t)addr, size });
> +}

[Severity: Low]
This puts device BAR mappings into the list that migration/cpr-exec.c
walks. vfio_region_mmap() can map a BAR PROT_READ only, depending on
region->flags. With the debug-only -cpr-ram-rdonly option, cpr_exec_cb()
calls mark_ram_rdonly() on every entry. On the exec-failure path, and when
cpr_exec_is_incoming() && cpr_ram_rdonly, mark_ram_rw() requests RW on
every entry:

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

Can this abort() QEMU if a driver refuses mprotect on a shared PFN
mapping, for example by clearing VM_MAYWRITE? Would it also make a
read-only BAR mapping writable?

I could not confirm the driver behaviour from the repository, so this is
a question about the interaction.

[ ... ]

> @@ -427,6 +470,8 @@ void vfio_region_finalize(VFIORegion *region)
>  
>      for (i = 0; i < region->nr_mmaps; i++) {
>          if (region->mmaps[i].mmap) {
> +            g_autofree char *cpr_name = vfio_region_cpr_name(region, i);
> +            cpr_delete_ramblock(cpr_name);
>              munmap(region->mmaps[i].mmap, region->mmaps[i].size);
>          }
>      }

[Severity: Low]
Can the preserved entry for the lazily mapped display region be leaked
here? After cpr-exec, if new QEMU has not yet set up and mapped the
display region, vfio_region_setup() and vfio_region_mmap() are never
called for it. region->mem and region->mmaps[i].mmap stay NULL:

hw/vfio/display.c:vfio_display_region_exit() {
    if (!dpy->region.buffer.size) {
        return;
    }

    vfio_region_exit(&dpy->region.buffer);
    vfio_region_finalize(&dpy->region.buffer);
}

Here the early return, and the early return in vfio_region_finalize() when
!region->mem, skip the cpr_delete_ramblock() call. The entry then stays
in the list, so cpr_exec_cb() marks the VMA with MADV_DOEXEC again on the
next cpr-exec. The VMA also keeps a reference on the device file.

A re-added device with the same name could also pick the stale mapping up
through vfio_region_cpr_find(). Should the preserved entry be released
when the region is never remapped?

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261020-vfio_v1-v4-0-83a5668230e5@virtuozzo.com?part=29

  reply	other threads:[~2026-10-20 17:08 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-20 16:30 [PATCH QEMU HCI-8.1 v4 00/31] vfio: support qemu-update with passed through GPU's and vGPU's #VSTOR-103860 Andrey Drobyshev
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 01/31] VZ: migration/cpr-exec: fix Error leak in preserve_ram() Andrey Drobyshev
2026-10-20 16:34   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 02/31] migration/cpr-exec: restore RAM write access if exec fails Andrey Drobyshev
2026-10-20 16:34   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 03/31] vfio/region: create BAR dma-bufs with O_CLOEXEC Andrey Drobyshev
2026-10-20 16:35   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 04/31] migration/cpr-exec: require a file or exec migration URI Andrey Drobyshev
2026-10-20 16:37   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 05/31] migration: close the CPR state if the outgoing channel fails to open Andrey Drobyshev
2026-10-20 16:38   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 06/31] migration: Plug memory leaks after migrate_set_error() Andrey Drobyshev
2026-10-20 16:38   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 07/31] hw/vfio: Fix liveness check in vfio_connect_kvm_msi_virq() Andrey Drobyshev
2026-10-20 16:38   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 08/31] vfio/pci: Reject invalid MSI-X Table and PBA BIR values Andrey Drobyshev
2026-10-20 16:38   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 09/31] vfio/pci: Fix information leak in vfio_rom_read() Andrey Drobyshev
2026-10-20 16:39   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 10/31] vfio/pci: Initialize rom_read_failed in vfio_pci_load_rom() Andrey Drobyshev
2026-10-20 16:40   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 11/31] vfio/pci: Grow buffer in vfio_pci_host_match() Andrey Drobyshev
2026-10-20 16:39   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 12/31] q35: Fix migration of SMRAM state Andrey Drobyshev
2026-10-20 16:41   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 13/31] migration: ensure APIC is loaded prior to VFIO PCI devices Andrey Drobyshev
2026-10-20 16:40   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 14/31] migration: Fix regression of passing error_fatal into vmstate_load_state() Andrey Drobyshev
2026-10-20 16:43   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 15/31] migration: vmstate_save_state_v: fix double error_setg Andrey Drobyshev
2026-10-20 16:45   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 16/31] migration: yank: Move register instance earlier Andrey Drobyshev
2026-10-20 16:47   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 17/31] migration: Free cpr-transfer MigrationAddress along with gsource Andrey Drobyshev
2026-10-20 16:47   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 18/31] migration: Move CPR HUP watch to cpr-transfer.c Andrey Drobyshev
2026-10-20 16:48   ` no-reply
2026-10-20 16:30 ` [PATCH QEMU HCI-8.1 v4 19/31] migration: Fix crash on second migration when cancel early Andrey Drobyshev
2026-10-20 16:52   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 20/31] kvm: tolerate ioctls after kvm_close() Andrey Drobyshev
2026-10-20 16:52   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 21/31] kvm: fix coalesced MMIO flush racing with kvm_close() Andrey Drobyshev
2026-10-20 16:54   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 22/31] migration/cpr: add cpr_is_in_progress() Andrey Drobyshev
2026-10-20 16:54   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 23/31] vfio/migration: don't migrate device state during CPR Andrey Drobyshev
2026-10-20 17:00   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 24/31] vfio/listener: skip dirty page tracking " Andrey Drobyshev
2026-10-20 16:59   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 25/31] VZ: vfio/cpr: don't close KVM on cpr-exec Andrey Drobyshev
2026-10-20 17:01   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 26/31] VZ: migration/cpr-exec: abort cpr-exec if memory can't be preserved Andrey Drobyshev
2026-10-20 17:02   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 27/31] VZ: migration/cpr-exec: take the vhost-net devices back if exec fails Andrey Drobyshev
2026-10-20 17:03   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 28/31] VZ: migration/cpr-exec: don't exec if a vhost-net device can't be released Andrey Drobyshev
2026-10-20 17:03   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 29/31] VZ: vfio/region: preserve BAR mappings across cpr-exec #VSTOR-103860 Andrey Drobyshev
2026-10-20 17:08   ` no-reply [this message]
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 30/31] VZ: migration/cpr-exec: allow cpr-exec with VFIO devices #VSTOR-103860 Andrey Drobyshev
2026-10-20 17:04   ` no-reply
2026-10-20 16:31 ` [PATCH QEMU HCI-8.1 v4 31/31] VZ: vfio/container: lift the CPR blocker for mdev " Andrey Drobyshev
2026-10-20 17:06   ` 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=010701a15a497e88-17499b09-190a-4242-a21f-73d0a45590b7-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.