[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH RFC 07/10] vfio/iommufd: Add HWPT_GET_DIRTY_IOVA support
From: |
Joao Martins |
Subject: |
[PATCH RFC 07/10] vfio/iommufd: Add HWPT_GET_DIRTY_IOVA support |
Date: |
Thu, 28 Apr 2022 22:13:48 +0100 |
ioctl(iommufd, IOMMU_HWPT_GET_DIRTY_IOVA, arg) is the UAPI
that fetches the bitmap that tells what was dirty in an IOVA
range.
A single bitmap is allocated and used across all the hw_pagetables
sharing an IOAS which is then used in log_sync() to set Qemu
global bitmaps.
There's no point of even attempting to fetch these bitmaps,
should the iommu tracker fail to start in a previous call
to HWPT_SET_DIRTY.
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
---
hw/iommufd/iommufd.c | 24 ++++++++++++++++++++
hw/iommufd/trace-events | 1 +
hw/vfio/iommufd.c | 44 ++++++++++++++++++++++++++++++++++++
include/hw/iommufd/iommufd.h | 2 ++
4 files changed, 71 insertions(+)
diff --git a/hw/iommufd/iommufd.c b/hw/iommufd/iommufd.c
index e5aff5deaf14..bc870b5e9b2f 100644
--- a/hw/iommufd/iommufd.c
+++ b/hw/iommufd/iommufd.c
@@ -219,6 +219,30 @@ int iommufd_set_dirty_tracking(int iommufd, uint32_t
hwpt_id, bool start)
return !ret ? 0 : -errno;
}
+int iommufd_get_dirty_iova(int iommufd, uint32_t hwpt_id, uint64_t iova,
+ ram_addr_t size, uint64_t page_size, uint64_t *data)
+{
+ int ret;
+ struct iommu_hwpt_get_dirty_iova get_dirty_iova = {
+ .size = sizeof(get_dirty_iova),
+ .hwpt_id = hwpt_id,
+ .bitmap = {
+ .iova = iova, .length = size,
+ .page_size = page_size, .data = (__u64 *)data,
+ },
+ };
+
+ ret = ioctl(iommufd, IOMMU_HWPT_GET_DIRTY_IOVA, &get_dirty_iova);
+ trace_iommufd_get_dirty_iova(iommufd, hwpt_id, iova, size, page_size, ret);
+ if (ret) {
+ error_report("IOMMU_HWPT_GET_DIRTY_IOVA (iova: 0x%"PRIx64
+ " size: 0x%"PRIx64") failed: %s", iova,
+ size, strerror(errno));
+ }
+
+ return !ret ? 0 : -errno;
+}
+
static void iommufd_register_types(void)
{
qemu_mutex_init(&iommufd_lock);
diff --git a/hw/iommufd/trace-events b/hw/iommufd/trace-events
index d3c2b5a0ab95..9fe2cc60c6fe 100644
--- a/hw/iommufd/trace-events
+++ b/hw/iommufd/trace-events
@@ -10,3 +10,4 @@ iommufd_unmap_dma(int iommufd, uint32_t ioas, uint64_t iova,
uint64_t size, int
iommufd_map_dma(int iommufd, uint32_t ioas, uint64_t iova, uint64_t size, void
*vaddr, bool readonly, int ret) " iommufd=%d ioas=%d iova=0x%"PRIx64"
size=0x%"PRIx64" addr=%p readonly=%d (%d)"
iommufd_copy_dma(int iommufd, uint32_t src_ioas, uint32_t dst_ioas, uint64_t
iova, uint64_t size, bool readonly, int ret) " iommufd=%d src_ioas=%d
dst_ioas=%d iova=0x%"PRIx64" size=0x%"PRIx64" readonly=%d (%d)"
iommufd_set_dirty(int iommufd, uint32_t hwpt_id, bool start, int ret) "
iommufd=%d hwpt=%d enable=%d (%d)"
+iommufd_get_dirty_iova(int iommufd, uint32_t hwpt_id, uint64_t iova, uint64_t
size, uint64_t page_size, int ret) " iommufd=%d hwpt=%d iova=0x%"PRIx64"
size=0x%"PRIx64" page_size=0x%"PRIx64" (%d)"
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 8146407feedd..6c12239a40ab 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -33,6 +33,7 @@
#include "hw/qdev-core.h"
#include "sysemu/reset.h"
#include "qemu/cutils.h"
+#include "exec/ram_addr.h"
#include "migration/migration.h"
static bool iommufd_check_extension(VFIOContainer *bcontainer,
@@ -102,6 +103,48 @@ static void iommufd_set_dirty_page_tracking(VFIOContainer
*bcontainer,
bcontainer->dirty_pages_supported = start;
}
+static int iommufd_get_dirty_bitmap(VFIOContainer *bcontainer, uint64_t iova,
+ uint64_t size, ram_addr_t ram_addr)
+{
+ VFIOIOMMUFDContainer *container = container_of(bcontainer,
+ VFIOIOMMUFDContainer, obj);
+ int ret;
+ VFIOIOASHwpt *hwpt;
+ unsigned long *data, page_size, bitmap_size, pages;
+
+ if (!bcontainer->dirty_pages_supported) {
+ return 0;
+ }
+
+ page_size = qemu_real_host_page_size;
+ pages = REAL_HOST_PAGE_ALIGN(size) / qemu_real_host_page_size;
+ bitmap_size = ROUND_UP(pages, sizeof(__u64) * BITS_PER_BYTE) /
+ BITS_PER_BYTE;
+ data = g_try_malloc0(bitmap_size);
+ if (!data) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ QLIST_FOREACH(hwpt, &container->hwpt_list, next) {
+ ret = iommufd_get_dirty_iova(container->iommufd, hwpt->hwpt_id,
+ iova, size, page_size, data);
+ if (ret) {
+ goto err_out;
+ }
+ }
+
+ cpu_physical_memory_set_dirty_lebitmap(data, ram_addr, pages);
+
+ trace_vfio_get_dirty_bitmap(container->iommufd, iova, size, bitmap_size,
+ ram_addr);
+
+err_out:
+ g_free(data);
+
+ return ret;
+}
+
static int vfio_get_devicefd(const char *sysfs_path, Error **errp)
{
long int vfio_id = -1, ret = -ENOTTY;
@@ -611,6 +654,7 @@ static void vfio_iommufd_class_init(ObjectClass *klass,
vccs->reset = vfio_iommufd_container_reset;
vccs->devices_all_dirty_tracking = vfio_iommufd_devices_all_dirty_tracking;
vccs->set_dirty_page_tracking = iommufd_set_dirty_page_tracking;
+ vccs->get_dirty_bitmap = iommufd_get_dirty_bitmap;
}
static const TypeInfo vfio_iommufd_info = {
diff --git a/include/hw/iommufd/iommufd.h b/include/hw/iommufd/iommufd.h
index 61fd83771099..9b467e57723b 100644
--- a/include/hw/iommufd/iommufd.h
+++ b/include/hw/iommufd/iommufd.h
@@ -34,5 +34,7 @@ int iommufd_map_dma(int iommufd, uint32_t ioas, hwaddr iova,
int iommufd_copy_dma(int iommufd, uint32_t src_ioas, uint32_t dst_ioas,
hwaddr iova, ram_addr_t size, bool readonly);
int iommufd_set_dirty_tracking(int iommufd, uint32_t hwpt_id, bool start);
+int iommufd_get_dirty_iova(int iommufd, uint32_t hwpt_id, uint64_t iova,
+ ram_addr_t size, uint64_t page_size, uint64_t
*data);
bool iommufd_supported(void);
#endif /* HW_IOMMUFD_IOMMUFD_H */
--
2.17.2
- [PATCH RFC 00/10] hw/vfio, x86/iommu: IOMMUFD Dirty Tracking, Joao Martins, 2022/04/28
- [PATCH RFC 01/10] amd-iommu: Cache PTE/DTE info in IOTLB, Joao Martins, 2022/04/28
- [PATCH RFC 04/10] intel_iommu: Second Stage Access Dirty bit support, Joao Martins, 2022/04/28
- [PATCH RFC 02/10] amd-iommu: Access/Dirty bit support, Joao Martins, 2022/04/28
- [PATCH RFC 03/10] intel-iommu: Cache PASID entry flags, Joao Martins, 2022/04/28
- [PATCH RFC 05/10] linux-headers: import iommufd.h hwpt extensions, Joao Martins, 2022/04/28
- [PATCH RFC 07/10] vfio/iommufd: Add HWPT_GET_DIRTY_IOVA support,
Joao Martins <=
- [PATCH RFC 08/10] vfio/iommufd: Add IOAS_UNMAP_DIRTY support, Joao Martins, 2022/04/28
- [PATCH RFC 06/10] vfio/iommufd: Add HWPT_SET_DIRTY support, Joao Martins, 2022/04/28
- [PATCH RFC 09/10] migration/dirtyrate: Expand dirty_bitmap to be tracked separately for devices, Joao Martins, 2022/04/28
- [PATCH RFC 10/10] hw/vfio: Add nr of dirty pages to tracepoints, Joao Martins, 2022/04/28