[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3 12/15] vfio/common: Support device dirty page tracking with vI
|
From: |
Joao Martins |
|
Subject: |
[PATCH v3 12/15] vfio/common: Support device dirty page tracking with vIOMMU |
|
Date: |
Tue, 30 May 2023 18:59:34 +0100 |
Currently, device dirty page tracking with vIOMMU is not supported,
and a blocker is added and the migration is prevented.
When vIOMMU is used, IOVA ranges are DMA mapped/unmapped on the fly as
requesting by the vIOMMU. These IOVA ranges can potentially be mapped
anywhere in the vIOMMU IOVA space as advertised by the VMM.
To support device dirty tracking when vIOMMU enabled instead create the
dirty ranges based on the vIOMMU provided limits, which leads to the
tracking of the whole IOVA space regardless of what devices use.
Signed-off-by: Avihai Horon <avihaih@nvidia.com>
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
---
hw/vfio/common.c | 64 ++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 54 insertions(+), 10 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b8d97577f856..d2897aceedae 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -447,6 +447,31 @@ static bool vfio_viommu_preset(void)
return false;
}
+static int vfio_viommu_get_max_iova(hwaddr *max_iova)
+{
+ VFIOAddressSpace *space;
+ int ret = -EINVAL;
+
+ QLIST_FOREACH(space, &vfio_address_spaces, list) {
+ if (space->as == &address_space_memory) {
+ continue;
+ }
+
+ if (!space->iommu_mr) {
+ break;
+ }
+
+ ret = memory_region_iommu_get_attr(space->iommu_mr,
+ IOMMU_ATTR_MAX_IOVA,
+ max_iova);
+ if (ret) {
+ break;
+ }
+ }
+
+ return ret;
+}
+
int vfio_block_giommu_migration(Error **errp)
{
int ret;
@@ -1483,10 +1508,11 @@ static const MemoryListener
vfio_dirty_tracking_listener = {
.region_add = vfio_listener_dirty_tracking_update,
};
-static void vfio_dirty_tracking_init(VFIOContainer *container,
+static int vfio_dirty_tracking_init(VFIOContainer *container,
VFIODirtyRanges *ranges)
{
VFIODirtyRangesListener dirty;
+ int ret;
memset(&dirty, 0, sizeof(dirty));
dirty.ranges.min32 = UINT32_MAX;
@@ -1494,17 +1520,29 @@ static void vfio_dirty_tracking_init(VFIOContainer
*container,
dirty.listener = vfio_dirty_tracking_listener;
dirty.container = container;
- memory_listener_register(&dirty.listener,
- container->space->as);
+ if (vfio_viommu_preset()) {
+ hwaddr iommu_max_iova;
+
+ ret = vfio_viommu_get_max_iova(&iommu_max_iova);
+ if (ret) {
+ return ret;
+ }
+
+ vfio_dirty_tracking_update(0, iommu_max_iova, &dirty.ranges);
+ } else {
+ memory_listener_register(&dirty.listener,
+ container->space->as);
+ /*
+ * The memory listener is synchronous, and used to calculate the range
+ * to dirty tracking. Unregister it after we are done as we are not
+ * interested in any follow-up updates.
+ */
+ memory_listener_unregister(&dirty.listener);
+ }
*ranges = dirty.ranges;
- /*
- * The memory listener is synchronous, and used to calculate the range
- * to dirty tracking. Unregister it after we are done as we are not
- * interested in any follow-up updates.
- */
- memory_listener_unregister(&dirty.listener);
+ return 0;
}
static void vfio_devices_dma_logging_stop(VFIOContainer *container)
@@ -1609,7 +1647,13 @@ static int vfio_devices_dma_logging_start(VFIOContainer
*container)
VFIOGroup *group;
int ret = 0;
- vfio_dirty_tracking_init(container, &ranges);
+ ret = vfio_dirty_tracking_init(container, &ranges);
+ if (ret) {
+ error_report("Failed to init DMA logging ranges, err %d",
+ ret);
+ return -EOPNOTSUPP;
+ }
+
feature = vfio_device_feature_dma_logging_start_create(container,
&ranges);
if (!feature) {
--
2.39.3
- [PATCH v3 01/15] hw/pci: Refactor pci_device_iommu_address_space(), (continued)
- [PATCH v3 01/15] hw/pci: Refactor pci_device_iommu_address_space(), Joao Martins, 2023/05/30
- [PATCH v3 03/15] hw/pci: Add a pci_device_iommu_memory_region() helper, Joao Martins, 2023/05/30
- [PATCH v3 04/15] intel-iommu: Switch to pci_setup_iommu_info(), Joao Martins, 2023/05/30
- [PATCH v3 05/15] vfio/common: Track the IOMMU MR behind the device in addition to the AS, Joao Martins, 2023/05/30
- [PATCH v3 06/15] memory/iommu: Add IOMMU_ATTR_DMA_TRANSLATION attribute, Joao Martins, 2023/05/30
- [PATCH v3 07/15] intel-iommu: Implement get_attr() method, Joao Martins, 2023/05/30
- [PATCH v3 08/15] vfio/common: Relax vIOMMU detection when DMA translation is off, Joao Martins, 2023/05/30
- [PATCH v3 09/15] memory/iommu: Add IOMMU_ATTR_MAX_IOVA attribute, Joao Martins, 2023/05/30
- [PATCH v3 10/15] intel-iommu: Implement IOMMU_ATTR_MAX_IOVA get_attr() attribute, Joao Martins, 2023/05/30
- [PATCH v3 11/15] vfio/common: Move dirty tracking ranges update to helper, Joao Martins, 2023/05/30
- [PATCH v3 12/15] vfio/common: Support device dirty page tracking with vIOMMU,
Joao Martins <=
- [PATCH v3 13/15] vfio/common: Extract vIOMMU code from vfio_sync_dirty_bitmap(), Joao Martins, 2023/05/30
- [PATCH v3 14/15] vfio/common: Optimize device dirty page tracking with vIOMMU, Joao Martins, 2023/05/30
- [PATCH v3 15/15] vfio/common: Block migration with vIOMMUs without address width limits, Joao Martins, 2023/05/30