All of lore.kernel.org
 help / color / mirror / Atom feed
From: Joao Martins <joao.m.martins@oracle.com>
To: qemu-devel@nongnu.org
Cc: "Joao Martins" <joao.m.martins@oracle.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Eduardo Habkost" <eduardo@habkost.net>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
	"Peter Xu" <peterx@redhat.com>,
	"Jason Wang" <jasowang@redhat.com>,
	"Alex Williamson" <alex.williamson@redhat.com>,
	"David Hildenbrand" <david@redhat.com>,
	"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
	"Cornelia Huck" <cohuck@redhat.com>,
	"Juan Quintela" <quintela@redhat.com>,
	"Eric Blake" <eblake@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Jason Gunthorpe" <jgg@nvidia.com>,
	"Nicolin Chen" <nicolinc@nvidia.com>,
	"Yishai Hadas" <yishaih@nvidia.com>,
	"Kevin Tian" <kevin.tian@intel.com>,
	"Yi Liu" <yi.l.liu@intel.com>,
	"Eric Auger" <eric.auger@redhat.com>,
	"Thanos Makatos" <thanos.makatos@nutanix.com>,
	"John G . Johnson" <john.g.johnson@oracle.com>,
	kvm@vger.kernel.org
Subject: [PATCH RFC 07/10] vfio/iommufd: Add HWPT_GET_DIRTY_IOVA support
Date: Thu, 28 Apr 2022 22:13:48 +0100	[thread overview]
Message-ID: <20220428211351.3897-8-joao.m.martins@oracle.com> (raw)
In-Reply-To: <20220428211351.3897-1-joao.m.martins@oracle.com>

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


WARNING: multiple messages have this Message-ID (diff)
From: Joao Martins <joao.m.martins@oracle.com>
To: qemu-devel@nongnu.org
Cc: "John G . Johnson" <john.g.johnson@oracle.com>,
	kvm@vger.kernel.org, "Michael S. Tsirkin" <mst@redhat.com>,
	"Jason Wang" <jasowang@redhat.com>,
	"Peter Xu" <peterx@redhat.com>,
	"Joao Martins" <joao.m.martins@oracle.com>,
	"Eric Blake" <eblake@redhat.com>, "Yi Liu" <yi.l.liu@intel.com>,
	"Juan Quintela" <quintela@redhat.com>,
	"David Hildenbrand" <david@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Nicolin Chen" <nicolinc@nvidia.com>,
	"Jason Gunthorpe" <jgg@nvidia.com>,
	"Kevin Tian" <kevin.tian@intel.com>,
	"Richard Henderson" <richard.henderson@linaro.org>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	"Eric Auger" <eric.auger@redhat.com>,
	"Alex Williamson" <alex.williamson@redhat.com>,
	"Thanos Makatos" <thanos.makatos@nutanix.com>,
	"Eduardo Habkost" <eduardo@habkost.net>,
	"Yishai Hadas" <yishaih@nvidia.com>,
	"Cornelia Huck" <cohuck@redhat.com>,
	"Philippe Mathieu-Daudé" <f4bug@amsat.org>,
	"Paolo Bonzini" <pbonzini@redhat.com>
Subject: [PATCH RFC 07/10] vfio/iommufd: Add HWPT_GET_DIRTY_IOVA support
Date: Thu, 28 Apr 2022 22:13:48 +0100	[thread overview]
Message-ID: <20220428211351.3897-8-joao.m.martins@oracle.com> (raw)
In-Reply-To: <20220428211351.3897-1-joao.m.martins@oracle.com>

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



  parent reply	other threads:[~2022-04-28 21:15 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-28 21:13 [PATCH RFC 00/10] hw/vfio, x86/iommu: IOMMUFD Dirty Tracking Joao Martins
2022-04-28 21:13 ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 01/10] amd-iommu: Cache PTE/DTE info in IOTLB Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 02/10] amd-iommu: Access/Dirty bit support Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 03/10] intel-iommu: Cache PASID entry flags Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 04/10] intel_iommu: Second Stage Access Dirty bit support Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-04-29  2:26   ` Jason Wang
2022-04-29  2:26     ` Jason Wang
2022-04-29  9:12     ` Joao Martins
2022-04-29  9:12       ` Joao Martins
2022-04-29 18:21       ` Peter Xu
2022-04-29 18:21         ` Peter Xu
2022-05-03 11:54         ` Joao Martins
2022-05-05  7:41           ` Jason Wang
2022-05-05  9:57             ` Joao Martins
2022-05-04 20:11   ` Peter Xu
2022-05-05  9:54     ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 05/10] linux-headers: import iommufd.h hwpt extensions Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 06/10] vfio/iommufd: Add HWPT_SET_DIRTY support Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-04-28 21:13 ` Joao Martins [this message]
2022-04-28 21:13   ` [PATCH RFC 07/10] vfio/iommufd: Add HWPT_GET_DIRTY_IOVA support Joao Martins
2022-04-28 21:13 ` [PATCH RFC 08/10] vfio/iommufd: Add IOAS_UNMAP_DIRTY support Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 09/10] migration/dirtyrate: Expand dirty_bitmap to be tracked separately for devices Joao Martins
2022-04-28 21:13   ` Joao Martins
2022-05-02 12:54   ` Markus Armbruster
2022-05-02 12:54     ` Markus Armbruster
2022-05-02 14:35     ` Joao Martins
2022-05-02 14:35       ` Joao Martins
2022-04-28 21:13 ` [PATCH RFC 10/10] hw/vfio: Add nr of dirty pages to tracepoints Joao Martins
2022-04-28 21:13   ` Joao Martins

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=20220428211351.3897-8-joao.m.martins@oracle.com \
    --to=joao.m.martins@oracle.com \
    --cc=alex.williamson@redhat.com \
    --cc=armbru@redhat.com \
    --cc=cohuck@redhat.com \
    --cc=david@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=eblake@redhat.com \
    --cc=eduardo@habkost.net \
    --cc=eric.auger@redhat.com \
    --cc=f4bug@amsat.org \
    --cc=jasowang@redhat.com \
    --cc=jgg@nvidia.com \
    --cc=john.g.johnson@oracle.com \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=marcel.apfelbaum@gmail.com \
    --cc=mst@redhat.com \
    --cc=nicolinc@nvidia.com \
    --cc=pbonzini@redhat.com \
    --cc=peterx@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=richard.henderson@linaro.org \
    --cc=thanos.makatos@nutanix.com \
    --cc=yi.l.liu@intel.com \
    --cc=yishaih@nvidia.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.