vfio queue:

* Fix CPR transfer
 * Add support for VFIO_DMA_UNMAP_FLAG_ALL
 * Fix vfio-user documentation
 * Update Alex Williamson's email address
 * Fix for vfio-region cache for the vGPU use case
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmj4y4QACgkQUaNDx8/7
 7KFGOw/8DRo/tRCW5q5uQj8T5DPQqL7QSBsZ50Zbtxn31xAstx8d30waxNCYGyMz
 /LzKHATb/MFKtM4pZnQS9fVQRXsHaiFyokIx58u+xZpbxrAs8WeBsBgepftkid9+
 Mv88plvFdMRZuIiEmAZOvuIcCWjAMjDwJ60o/InykQR6Y2a+LawAy2Jp30wAp5q4
 7RH4+CkjKP4G00WAjhi1cRZjjBOa8xA+BvD5CDMlZKpURnSivjK0K5XQARWpj3aG
 X0Ggg8LVsE98iJtq7g/+233QfCiuHe+c7FvVd+c6svg18n0uEYzfUUI0MGJPUtWS
 zxUlhDcNoy0XCVIb5Dd3QG+8NfetMV5T4oNrhZADRBjKHBk+OuJfI9yZFwAzXlKl
 n9hVRk/HVIsdi2f5OtRgUNJYhuph0gkryNPQQRDgPb8XLip/OeLRQJ4qUyZ4XuYA
 nfU3vZWFwfPdhfbqU6koa49VTIJTx2TGj/naFAeqLhJolGVTdjgXoJTIS62y58gd
 eKxJwkB0sVv7em8VvjhdsOPMdeosU/ZS82aM6B0u5PB/DepsG1tq5RSSkbmozgYJ
 6muXwOsSwMQbvsf2KVy70kQCuTb5sKyWr2BlS8tvya5LV7BPbNNlOqtnapekCh+B
 C2cP1MAVs2LcKNQwI2avrDrb7mun6uupFtA3Ci7gxxbBulMQZTA=
 =O4HA
 -----END PGP SIGNATURE-----

Merge tag 'pull-vfio-20251022' of https://github.com/legoater/qemu into staging

vfio queue:

* Fix CPR transfer
* Add support for VFIO_DMA_UNMAP_FLAG_ALL
* Fix vfio-user documentation
* Update Alex Williamson's email address
* Fix for vfio-region cache for the vGPU use case

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmj4y4QACgkQUaNDx8/7
# 7KFGOw/8DRo/tRCW5q5uQj8T5DPQqL7QSBsZ50Zbtxn31xAstx8d30waxNCYGyMz
# /LzKHATb/MFKtM4pZnQS9fVQRXsHaiFyokIx58u+xZpbxrAs8WeBsBgepftkid9+
# Mv88plvFdMRZuIiEmAZOvuIcCWjAMjDwJ60o/InykQR6Y2a+LawAy2Jp30wAp5q4
# 7RH4+CkjKP4G00WAjhi1cRZjjBOa8xA+BvD5CDMlZKpURnSivjK0K5XQARWpj3aG
# X0Ggg8LVsE98iJtq7g/+233QfCiuHe+c7FvVd+c6svg18n0uEYzfUUI0MGJPUtWS
# zxUlhDcNoy0XCVIb5Dd3QG+8NfetMV5T4oNrhZADRBjKHBk+OuJfI9yZFwAzXlKl
# n9hVRk/HVIsdi2f5OtRgUNJYhuph0gkryNPQQRDgPb8XLip/OeLRQJ4qUyZ4XuYA
# nfU3vZWFwfPdhfbqU6koa49VTIJTx2TGj/naFAeqLhJolGVTdjgXoJTIS62y58gd
# eKxJwkB0sVv7em8VvjhdsOPMdeosU/ZS82aM6B0u5PB/DepsG1tq5RSSkbmozgYJ
# 6muXwOsSwMQbvsf2KVy70kQCuTb5sKyWr2BlS8tvya5LV7BPbNNlOqtnapekCh+B
# C2cP1MAVs2LcKNQwI2avrDrb7mun6uupFtA3Ci7gxxbBulMQZTA=
# =O4HA
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 22 Oct 2025 07:18:12 AM CDT
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full]
# gpg:                 aka "Cédric Le Goater <clg@kaod.org>" [full]

* tag 'pull-vfio-20251022' of https://github.com/legoater/qemu:
  vfio: only check region info cache for initial regions
  vfio: rename field to "num_initial_regions"
  MAINTAINERS: Update Alex Williamson's email address
  docs/system/devices/vfio-user: fix formatting
  vfio/listener: Add an assertion for unmap_all
  vfio/iommufd: Support unmap all in one ioctl()
  vfio/container: Support unmap all in one ioctl()
  accel/kvm: Fix an erroneous check on coalesced_mmio_ring
  vfio/iommufd: Restore vbasedev's reference to hwpt after CPR transfer
  vfio/iommufd: Set cpr.ioas_id on source side for CPR transfer
  vfio/cpr-legacy: drop an erroneous assert
  vfio/container: Remap only populated parts in a section

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2025-10-22 08:01:21 -05:00
commit c0e80879c8
15 changed files with 85 additions and 68 deletions

View file

@ -74,6 +74,7 @@ Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <aleksandar.markovic@imgte
Aleksandar Markovic <aleksandar.qemu.devel@gmail.com> <amarkovic@wavecomp.com>
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <arikalo@wavecomp.com>
Aleksandar Rikalo <aleksandar.rikalo@syrmia.com> <aleksandar.rikalo@rt-rk.com>
Alex Williamson <alex@shazbot.org> <alex.williamson@redhat.com>
Alexander Graf <agraf@csgraf.de> <agraf@suse.de>
Ani Sinha <anisinha@redhat.com> <ani@anisinha.ca>
Anthony Liguori <anthony@codemonkey.ws> Anthony Liguori <aliguori@us.ibm.com>

View file

@ -2286,7 +2286,7 @@ S: Maintained
F: hw/usb/dev-serial.c
VFIO
M: Alex Williamson <alex.williamson@redhat.com>
M: Alex Williamson <alex@shazbot.org>
M: Cédric Le Goater <clg@redhat.com>
S: Supported
F: hw/vfio/*
@ -2298,7 +2298,7 @@ F: migration/vfio-stub.c
F: tests/functional/aarch64/test_device_passthrough.py
vfio-igd
M: Alex Williamson <alex.williamson@redhat.com>
M: Alex Williamson <alex@shazbot.org>
M: Cédric Le Goater <clg@redhat.com>
M: Tomita Moeko <tomitamoeko@gmail.com>
S: Supported

View file

@ -525,7 +525,8 @@ static int do_kvm_destroy_vcpu(CPUState *cpu)
}
/* If I am the CPU that created coalesced_mmio_ring, then discard it */
if (s->coalesced_mmio_ring == (void *)cpu->kvm_run + PAGE_SIZE) {
if (s->coalesced_mmio_ring ==
(void *)cpu->kvm_run + s->coalesced_mmio * PAGE_SIZE) {
s->coalesced_mmio_ring = NULL;
}

View file

@ -20,7 +20,7 @@ Presuming a suitable ``vfio-user`` server has opened a socket at
.. code-block:: console
-device '{"driver": "vfio-user-pci","socket": {"path": "/tmp/vfio-user.sock", "type": "unix"}}'
--device '{"driver": "vfio-user-pci","socket": {"path": "/tmp/vfio-user.sock", "type": "unix"}}'
See `libvfio-user <https://github.com/nutanix/libvfio-user/>`_ for further
information.

View file

@ -134,7 +134,7 @@ static int vfio_user_device_io_get_region_info(VFIODevice *vbasedev,
VFIOUserFDs fds = { 0, 1, fd};
int ret;
if (info->index > vbasedev->num_regions) {
if (info->index > vbasedev->num_initial_regions) {
return -EINVAL;
}

View file

@ -484,9 +484,9 @@ static bool vfio_ccw_get_region(VFIOCCWDevice *vcdev, Error **errp)
* We always expect at least the I/O region to be present. We also
* may have a variable number of regions governed by capabilities.
*/
if (vdev->num_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) {
if (vdev->num_initial_regions < VFIO_CCW_CONFIG_REGION_INDEX + 1) {
error_setg(errp, "vfio: too few regions (%u), expected at least %u",
vdev->num_regions, VFIO_CCW_CONFIG_REGION_INDEX + 1);
vdev->num_initial_regions, VFIO_CCW_CONFIG_REGION_INDEX + 1);
return false;
}

View file

@ -121,14 +121,14 @@ unmap_exit:
return ret;
}
static int vfio_legacy_dma_unmap_one(const VFIOContainer *bcontainer,
static int vfio_legacy_dma_unmap_one(const VFIOLegacyContainer *container,
hwaddr iova, uint64_t size,
IOMMUTLBEntry *iotlb)
uint32_t flags, IOMMUTLBEntry *iotlb)
{
const VFIOLegacyContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
const VFIOContainer *bcontainer = VFIO_IOMMU(container);
struct vfio_iommu_type1_dma_unmap unmap = {
.argsz = sizeof(unmap),
.flags = 0,
.flags = flags,
.iova = iova,
.size = size,
};
@ -170,25 +170,28 @@ static int vfio_legacy_dma_unmap(const VFIOContainer *bcontainer,
hwaddr iova, uint64_t size,
IOMMUTLBEntry *iotlb, bool unmap_all)
{
const VFIOLegacyContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
uint32_t flags = 0;
int ret;
if (unmap_all) {
/* The unmap ioctl doesn't accept a full 64-bit span. */
Int128 llsize = int128_rshift(int128_2_64(), 1);
if (container->unmap_all_supported) {
flags = VFIO_DMA_UNMAP_FLAG_ALL;
} else {
/* The unmap ioctl doesn't accept a full 64-bit span. */
Int128 llsize = int128_rshift(int128_2_64(), 1);
size = int128_get64(llsize);
ret = vfio_legacy_dma_unmap_one(bcontainer, 0, int128_get64(llsize),
iotlb);
ret = vfio_legacy_dma_unmap_one(container, 0, size, flags, iotlb);
if (ret) {
return ret;
}
if (ret == 0) {
ret = vfio_legacy_dma_unmap_one(bcontainer, int128_get64(llsize),
int128_get64(llsize), iotlb);
iova = size;
}
} else {
ret = vfio_legacy_dma_unmap_one(bcontainer, iova, size, iotlb);
}
return ret;
return vfio_legacy_dma_unmap_one(container, iova, size, flags, iotlb);
}
static int vfio_legacy_dma_map(const VFIOContainer *bcontainer, hwaddr iova,
@ -519,6 +522,9 @@ static bool vfio_legacy_setup(VFIOContainer *bcontainer, Error **errp)
vfio_get_info_iova_range(info, bcontainer);
ret = ioctl(container->fd, VFIO_CHECK_EXTENSION, VFIO_UNMAP_ALL);
container->unmap_all_supported = !!ret;
vfio_get_iommu_info_migration(container, info);
return true;
}

View file

@ -52,8 +52,6 @@ static int vfio_legacy_cpr_dma_map(const VFIOContainer *bcontainer,
.size = size,
};
g_assert(cpr_is_incoming());
if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) {
return -errno;
}
@ -228,22 +226,32 @@ void vfio_cpr_giommu_remap(VFIOContainer *bcontainer,
memory_region_iommu_replay(giommu->iommu_mr, &giommu->n);
}
static int vfio_cpr_rdm_remap(MemoryRegionSection *section, void *opaque)
{
RamDiscardListener *rdl = opaque;
return rdl->notify_populate(rdl, section);
}
/*
* In old QEMU, VFIO_DMA_UNMAP_FLAG_VADDR may fail on some mapping after
* succeeding for others, so the latter have lost their vaddr. Call this
* to restore vaddr for a section with a RamDiscardManager.
* to restore vaddr for populated parts in a section with a RamDiscardManager.
*
* The ram discard listener already exists. Call its populate function
* The ram discard listener already exists. Call its replay_populated function
* directly, which calls vfio_legacy_cpr_dma_map.
*/
bool vfio_cpr_ram_discard_register_listener(VFIOContainer *bcontainer,
MemoryRegionSection *section)
bool vfio_cpr_ram_discard_replay_populated(VFIOContainer *bcontainer,
MemoryRegionSection *section)
{
RamDiscardManager *rdm = memory_region_get_ram_discard_manager(section->mr);
VFIORamDiscardListener *vrdl =
vfio_find_ram_discard_listener(bcontainer, section);
g_assert(vrdl);
return vrdl->listener.notify_populate(&vrdl->listener, section) == 0;
return ram_discard_manager_replay_populated(rdm, section,
vfio_cpr_rdm_remap,
&vrdl->listener) == 0;
}
int vfio_cpr_group_get_device_fd(int d, const char *name)

View file

@ -205,10 +205,19 @@ int vfio_device_get_region_info(VFIODevice *vbasedev, int index,
int fd = -1;
int ret;
/* check cache */
if (vbasedev->reginfo[index] != NULL) {
*info = vbasedev->reginfo[index];
return 0;
/*
* We only set up the region info cache for the initial number of regions.
*
* Since a VFIO device may later increase the number of regions then use
* such regions with an index past ->num_initial_regions, don't attempt to
* use the info cache in those cases.
*/
if (index < vbasedev->num_initial_regions) {
/* check cache */
if (vbasedev->reginfo[index] != NULL) {
*info = vbasedev->reginfo[index];
return 0;
}
}
*info = g_malloc0(argsz);
@ -236,10 +245,12 @@ retry:
goto retry;
}
/* fill cache */
vbasedev->reginfo[index] = *info;
if (vbasedev->region_fds != NULL) {
vbasedev->region_fds[index] = fd;
if (index < vbasedev->num_initial_regions) {
/* fill cache */
vbasedev->reginfo[index] = *info;
if (vbasedev->region_fds != NULL) {
vbasedev->region_fds[index] = fd;
}
}
return 0;
@ -257,7 +268,7 @@ int vfio_device_get_region_info_type(VFIODevice *vbasedev, uint32_t type,
{
int i;
for (i = 0; i < vbasedev->num_regions; i++) {
for (i = 0; i < vbasedev->num_initial_regions; i++) {
struct vfio_info_cap_header *hdr;
struct vfio_region_info_cap_type *cap_type;
@ -466,7 +477,7 @@ void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainer *bcontainer,
int i;
vbasedev->num_irqs = info->num_irqs;
vbasedev->num_regions = info->num_regions;
vbasedev->num_initial_regions = info->num_regions;
vbasedev->flags = info->flags;
vbasedev->reset_works = !!(info->flags & VFIO_DEVICE_FLAGS_RESET);
@ -476,10 +487,10 @@ void vfio_device_prepare(VFIODevice *vbasedev, VFIOContainer *bcontainer,
QLIST_INSERT_HEAD(&vfio_device_list, vbasedev, global_next);
vbasedev->reginfo = g_new0(struct vfio_region_info *,
vbasedev->num_regions);
vbasedev->num_initial_regions);
if (vbasedev->use_region_fds) {
vbasedev->region_fds = g_new0(int, vbasedev->num_regions);
for (i = 0; i < vbasedev->num_regions; i++) {
vbasedev->region_fds = g_new0(int, vbasedev->num_initial_regions);
for (i = 0; i < vbasedev->num_initial_regions; i++) {
vbasedev->region_fds[i] = -1;
}
}
@ -489,7 +500,7 @@ void vfio_device_unprepare(VFIODevice *vbasedev)
{
int i;
for (i = 0; i < vbasedev->num_regions; i++) {
for (i = 0; i < vbasedev->num_initial_regions; i++) {
g_free(vbasedev->reginfo[i]);
if (vbasedev->region_fds != NULL && vbasedev->region_fds[i] != -1) {
close(vbasedev->region_fds[i]);

View file

@ -62,21 +62,8 @@ static int iommufd_cdev_unmap(const VFIOContainer *bcontainer,
{
const VFIOIOMMUFDContainer *container = VFIO_IOMMU_IOMMUFD(bcontainer);
/* unmap in halves */
if (unmap_all) {
Int128 llsize = int128_rshift(int128_2_64(), 1);
int ret;
ret = iommufd_backend_unmap_dma(container->be, container->ioas_id,
0, int128_get64(llsize));
if (ret == 0) {
ret = iommufd_backend_unmap_dma(container->be, container->ioas_id,
int128_get64(llsize),
int128_get64(llsize));
}
return ret;
size = UINT64_MAX;
}
/* TODO: Handle dma_unmap_bitmap with iotlb args (migration) */
@ -560,10 +547,9 @@ static bool iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
continue;
}
if (!cpr_is_incoming()) {
if (!cpr_is_incoming() ||
(vbasedev->cpr.ioas_id == container->ioas_id)) {
res = iommufd_cdev_attach_container(vbasedev, container, &err);
} else if (vbasedev->cpr.ioas_id == container->ioas_id) {
res = true;
} else {
continue;
}
@ -602,7 +588,6 @@ skip_ioas_alloc:
container->be = vbasedev->iommufd;
container->ioas_id = ioas_id;
QLIST_INIT(&container->hwpt_list);
vbasedev->cpr.ioas_id = ioas_id;
bcontainer = VFIO_IOMMU(container);
vfio_address_space_insert(space, bcontainer);
@ -636,6 +621,8 @@ skip_ioas_alloc:
bcontainer->initialized = true;
found_container:
vbasedev->cpr.ioas_id = container->ioas_id;
ret = ioctl(devfd, VFIO_DEVICE_GET_INFO, &dev_info);
if (ret) {
error_setg_errno(errp, errno, "error getting device info");
@ -663,7 +650,8 @@ found_container:
vfio_iommufd_cpr_register_device(vbasedev);
trace_iommufd_cdev_device_info(vbasedev->name, devfd, vbasedev->num_irqs,
vbasedev->num_regions, vbasedev->flags);
vbasedev->num_initial_regions,
vbasedev->flags);
return true;
err_listener_register:

View file

@ -577,8 +577,8 @@ void vfio_container_region_add(VFIOContainer *bcontainer,
if (!vfio_ram_discard_register_listener(bcontainer, section, &err)) {
goto fail;
}
} else if (!vfio_cpr_ram_discard_register_listener(bcontainer,
section)) {
} else if (!vfio_cpr_ram_discard_replay_populated(bcontainer,
section)) {
error_setg(&err,
"vfio_cpr_ram_discard_register_listener for %s failed",
memory_region_name(section->mr));
@ -715,6 +715,7 @@ static void vfio_listener_region_del(MemoryListener *listener,
bool unmap_all = false;
if (int128_eq(llsize, int128_2_64())) {
assert(!iova);
unmap_all = true;
llsize = int128_zero();
}

View file

@ -2975,9 +2975,9 @@ bool vfio_pci_populate_device(VFIOPCIDevice *vdev, Error **errp)
return false;
}
if (vbasedev->num_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) {
if (vbasedev->num_initial_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) {
error_setg(errp, "unexpected number of io regions %u",
vbasedev->num_regions);
vbasedev->num_initial_regions);
return false;
}

View file

@ -30,6 +30,7 @@ struct VFIOLegacyContainer {
int fd; /* /dev/vfio/vfio, empowered by the attached groups */
unsigned iommu_type;
bool unmap_all_supported;
QLIST_HEAD(, VFIOGroup) group_list;
VFIOContainerCPR cpr;
};

View file

@ -68,7 +68,7 @@ bool vfio_cpr_container_match(struct VFIOLegacyContainer *container,
void vfio_cpr_giommu_remap(struct VFIOContainer *bcontainer,
MemoryRegionSection *section);
bool vfio_cpr_ram_discard_register_listener(
bool vfio_cpr_ram_discard_replay_populated(
struct VFIOContainer *bcontainer, MemoryRegionSection *section);
void vfio_cpr_save_vector_fd(struct VFIOPCIDevice *vdev, const char *name,

View file

@ -74,7 +74,7 @@ typedef struct VFIODevice {
VFIODeviceOps *ops;
VFIODeviceIOOps *io_ops;
unsigned int num_irqs;
unsigned int num_regions;
unsigned int num_initial_regions;
unsigned int flags;
VFIOMigration *migration;
Error *migration_blocker;