[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 15/27] vfio/container: restore DMA vaddr
From: |
Cédric Le Goater |
Subject: |
[PULL 15/27] vfio/container: restore DMA vaddr |
Date: |
Wed, 11 Jun 2025 17:06:07 +0200 |
From: Steve Sistare <steven.sistare@oracle.com>
In new QEMU, do not register the memory listener at device creation time.
Register it later, in the container post_load handler, after all vmstate
that may affect regions and mapping boundaries has been loaded. The
post_load registration will cause the listener to invoke its callback on
each flat section, and the calls will match the mappings remembered by the
kernel.
The listener calls a special dma_map handler that passes the new VA of each
section to the kernel using VFIO_DMA_MAP_FLAG_VADDR. Restore the normal
handler at the end.
Signed-off-by: Steve Sistare <steven.sistare@oracle.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Link:
1749569991-25171-7-git-send-email-steven.sistare@oracle.com">https://lore.kernel.org/qemu-devel/1749569991-25171-7-git-send-email-steven.sistare@oracle.com
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
include/hw/vfio/vfio-cpr.h | 3 ++
hw/vfio/container.c | 15 ++++++++--
hw/vfio/cpr-legacy.c | 57 ++++++++++++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 2 deletions(-)
diff --git a/include/hw/vfio/vfio-cpr.h b/include/hw/vfio/vfio-cpr.h
index
5a2e5f6b21e690cf91fd731ff9aa21a569f92f61..04624475f87361954a09ba3c9a47cf1d8e7cc5b3
100644
--- a/include/hw/vfio/vfio-cpr.h
+++ b/include/hw/vfio/vfio-cpr.h
@@ -17,6 +17,9 @@ struct VFIOGroup;
typedef struct VFIOContainerCPR {
Error *blocker;
+ int (*saved_dma_map)(const struct VFIOContainerBase *bcontainer,
+ hwaddr iova, ram_addr_t size,
+ void *vaddr, bool readonly, MemoryRegion *mr);
} VFIOContainerCPR;
diff --git a/hw/vfio/container.c b/hw/vfio/container.c
index
5caae4ccae59bf114f37a49019c40bb125ed4ba1..936ce37f190686b0875ed934ee277d9e4ff8cb2f
100644
--- a/hw/vfio/container.c
+++ b/hw/vfio/container.c
@@ -136,6 +136,8 @@ static int vfio_legacy_dma_unmap_one(const
VFIOContainerBase *bcontainer,
int ret;
Error *local_err = NULL;
+ g_assert(!cpr_is_incoming());
+
if (iotlb && vfio_container_dirty_tracking_is_started(bcontainer)) {
if (!vfio_container_devices_dirty_tracking_is_supported(bcontainer) &&
bcontainer->dirty_pages_supported) {
@@ -690,8 +692,17 @@ static bool vfio_container_connect(VFIOGroup *group,
AddressSpace *as,
}
group_was_added = true;
- if (!vfio_listener_register(bcontainer, errp)) {
- goto fail;
+ /*
+ * If CPR, register the listener later, after all state that may
+ * affect regions and mapping boundaries has been cpr load'ed. Later,
+ * the listener will invoke its callback on each flat section and call
+ * dma_map to supply the new vaddr, and the calls will match the mappings
+ * remembered by the kernel.
+ */
+ if (!cpr_is_incoming()) {
+ if (!vfio_listener_register(bcontainer, errp)) {
+ goto fail;
+ }
}
bcontainer->initialized = true;
diff --git a/hw/vfio/cpr-legacy.c b/hw/vfio/cpr-legacy.c
index
ef106d0ea865e86e3fdce86928e987e812724a0e..2fd8348c7cd37964af87ef04e32ce3dcd2bfde1a
100644
--- a/hw/vfio/cpr-legacy.c
+++ b/hw/vfio/cpr-legacy.c
@@ -9,11 +9,13 @@
#include "qemu/osdep.h"
#include "hw/vfio/vfio-container.h"
#include "hw/vfio/vfio-device.h"
+#include "hw/vfio/vfio-listener.h"
#include "migration/blocker.h"
#include "migration/cpr.h"
#include "migration/migration.h"
#include "migration/vmstate.h"
#include "qapi/error.h"
+#include "qemu/error-report.h"
static bool vfio_dma_unmap_vaddr_all(VFIOContainer *container, Error **errp)
{
@@ -30,6 +32,32 @@ static bool vfio_dma_unmap_vaddr_all(VFIOContainer
*container, Error **errp)
return true;
}
+/*
+ * Set the new @vaddr for any mappings registered during cpr load.
+ * The incoming state is cleared thereafter.
+ */
+static int vfio_legacy_cpr_dma_map(const VFIOContainerBase *bcontainer,
+ hwaddr iova, ram_addr_t size, void *vaddr,
+ bool readonly, MemoryRegion *mr)
+{
+ const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
+ bcontainer);
+ struct vfio_iommu_type1_dma_map map = {
+ .argsz = sizeof(map),
+ .flags = VFIO_DMA_MAP_FLAG_VADDR,
+ .vaddr = (__u64)(uintptr_t)vaddr,
+ .iova = iova,
+ .size = size,
+ };
+
+ g_assert(cpr_is_incoming());
+
+ if (ioctl(container->fd, VFIO_IOMMU_MAP_DMA, &map)) {
+ return -errno;
+ }
+
+ return 0;
+}
static bool vfio_cpr_supported(VFIOContainer *container, Error **errp)
{
@@ -58,11 +86,34 @@ static int vfio_container_pre_save(void *opaque)
return 0;
}
+static int vfio_container_post_load(void *opaque, int version_id)
+{
+ VFIOContainer *container = opaque;
+ VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOGroup *group;
+ Error *local_err = NULL;
+
+ if (!vfio_listener_register(bcontainer, &local_err)) {
+ error_report_err(local_err);
+ return -1;
+ }
+
+ QLIST_FOREACH(group, &container->group_list, container_next) {
+ VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
+
+ /* Restore original dma_map function */
+ vioc->dma_map = container->cpr.saved_dma_map;
+ }
+ return 0;
+}
+
static const VMStateDescription vfio_container_vmstate = {
.name = "vfio-container",
.version_id = 0,
.minimum_version_id = 0,
+ .priority = MIG_PRI_LOW, /* Must happen after devices and groups */
.pre_save = vfio_container_pre_save,
+ .post_load = vfio_container_post_load,
.needed = cpr_incoming_needed,
.fields = (VMStateField[]) {
VMSTATE_END_OF_LIST()
@@ -85,6 +136,12 @@ bool vfio_legacy_cpr_register_container(VFIOContainer
*container, Error **errp)
vmstate_register(NULL, -1, &vfio_container_vmstate, container);
+ /* During incoming CPR, divert calls to dma_map. */
+ if (cpr_is_incoming()) {
+ VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
+ container->cpr.saved_dma_map = vioc->dma_map;
+ vioc->dma_map = vfio_legacy_cpr_dma_map;
+ }
return true;
}
--
2.49.0
- [PULL 06/27] s390: implementing CHSC SEI for AP config change, (continued)
- [PULL 06/27] s390: implementing CHSC SEI for AP config change, Cédric Le Goater, 2025/06/11
- [PULL 05/27] hw/vfio/ap: Storing event information for an AP configuration change event, Cédric Le Goater, 2025/06/11
- [PULL 09/27] vfio: mark posted writes in region write callbacks, Cédric Le Goater, 2025/06/11
- [PULL 07/27] vfio: export PCI helpers needed for vfio-user, Cédric Le Goater, 2025/06/11
- [PULL 08/27] vfio: add per-region fd support, Cédric Le Goater, 2025/06/11
- [PULL 10/27] migration: cpr helpers, Cédric Le Goater, 2025/06/11
- [PULL 11/27] migration: lower handler priority, Cédric Le Goater, 2025/06/11
- [PULL 12/27] vfio/container: register container for cpr, Cédric Le Goater, 2025/06/11
- [PULL 14/27] vfio/container: discard old DMA vaddr, Cédric Le Goater, 2025/06/11
- [PULL 13/27] vfio/container: preserve descriptors, Cédric Le Goater, 2025/06/11
- [PULL 15/27] vfio/container: restore DMA vaddr,
Cédric Le Goater <=
- [PULL 16/27] vfio/container: mdev cpr blocker, Cédric Le Goater, 2025/06/11
- [PULL 17/27] vfio/container: recover from unmap-all-vaddr failure, Cédric Le Goater, 2025/06/11
- [PULL 18/27] pci: export msix_is_pending, Cédric Le Goater, 2025/06/11
- [PULL 19/27] pci: skip reset during cpr, Cédric Le Goater, 2025/06/11
- [PULL 20/27] vfio-pci: skip reset during cpr, Cédric Le Goater, 2025/06/11
- [PULL 21/27] vfio/pci: vfio_pci_vector_init, Cédric Le Goater, 2025/06/11
- [PULL 24/27] vfio/pci: vfio_notifier_init cpr parameters, Cédric Le Goater, 2025/06/11
- [PULL 22/27] vfio/pci: vfio_notifier_init, Cédric Le Goater, 2025/06/11
- [PULL 25/27] vfio/pci: vfio_notifier_cleanup, Cédric Le Goater, 2025/06/11
- [PULL 23/27] vfio/pci: pass vector to virq functions, Cédric Le Goater, 2025/06/11