On 09/07/2024 08:05, Cédric Le Goater wrote: > On 7/8/24 4:34 PM, Joao Martins wrote: >> ioctl(iommufd, IOMMU_HWPT_GET_DIRTY_BITMAP, 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 hwpts >> sharing an IOAS which is then used in log_sync() to set Qemu >> global bitmaps. >> >> Signed-off-by: Joao Martins <joao.m.mart...@oracle.com> >> --- >> include/sysemu/iommufd.h | 3 +++ >> backends/iommufd.c | 26 ++++++++++++++++++++++++++ >> hw/vfio/iommufd.c | 34 ++++++++++++++++++++++++++++++++++ >> backends/trace-events | 1 + >> 4 files changed, 64 insertions(+) >> >> diff --git a/include/sysemu/iommufd.h b/include/sysemu/iommufd.h >> index 1470377f55ba..223f1ea14e84 100644 >> --- a/include/sysemu/iommufd.h >> +++ b/include/sysemu/iommufd.h >> @@ -56,6 +56,9 @@ int iommufd_backend_alloc_hwpt(IOMMUFDBackend *be, uint32_t >> dev_id, >> void *data_ptr, uint32_t *out_hwpt); >> int iommufd_backend_set_dirty_tracking(IOMMUFDBackend *be, uint32_t >> hwpt_id, >> bool start); >> +int iommufd_backend_get_dirty_bitmap(IOMMUFDBackend *be, uint32_t hwpt_id, >> + uint64_t iova, ram_addr_t size, >> + uint64_t page_size, uint64_t *data); >> #define TYPE_HOST_IOMMU_DEVICE_IOMMUFD TYPE_HOST_IOMMU_DEVICE "-iommufd" >> diff --git a/backends/iommufd.c b/backends/iommufd.c >> index 69daabc27473..b2d3bbd7c31b 100644 >> --- a/backends/iommufd.c >> +++ b/backends/iommufd.c >> @@ -257,6 +257,32 @@ int iommufd_backend_set_dirty_tracking(IOMMUFDBackend >> *be, uint32_t hwpt_id, >> return ret; >> } >> +int iommufd_backend_get_dirty_bitmap(IOMMUFDBackend *be, 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_bitmap get_dirty_bitmap = { >> + .size = sizeof(get_dirty_bitmap), >> + .hwpt_id = hwpt_id, >> + .iova = iova, >> + .length = size, >> + .page_size = page_size, >> + .data = (uintptr_t)data, >> + }; >> + >> + ret = ioctl(be->fd, IOMMU_HWPT_GET_DIRTY_BITMAP, &get_dirty_bitmap); >> + trace_iommufd_backend_get_dirty_bitmap(be->fd, hwpt_id, iova, size, >> + page_size, ret); >> + if (ret) { >> + error_report("IOMMU_HWPT_GET_DIRTY_BITMAP (iova: 0x%"PRIx64 >> + " size: 0x%"PRIx64") failed: %s", iova, >> + size, strerror(errno)); >> + } >> + >> + return !ret ? 0 : -errno; >> +} >> + >> bool iommufd_backend_get_device_info(IOMMUFDBackend *be, uint32_t devid, >> uint32_t *type, void *data, uint32_t >> len, >> uint64_t *caps, Error **errp) >> diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c >> index 158a98cb3b12..9fad47baed9e 100644 >> --- a/hw/vfio/iommufd.c >> +++ b/hw/vfio/iommufd.c >> @@ -25,6 +25,7 @@ >> #include "qemu/cutils.h" >> #include "qemu/chardev_open.h" >> #include "pci.h" >> +#include "exec/ram_addr.h" >> static int iommufd_cdev_map(const VFIOContainerBase *bcontainer, hwaddr >> iova, >> ram_addr_t size, void *vaddr, bool readonly) >> @@ -152,6 +153,38 @@ err: >> return ret; >> } >> +static int iommufd_query_dirty_bitmap(const VFIOContainerBase *bcontainer, >> + VFIOBitmap *vbmap, hwaddr iova, >> + hwaddr size, Error **errp) >> +{ >> + VFIOIOMMUFDContainer *container = container_of(bcontainer, >> + VFIOIOMMUFDContainer, >> + bcontainer); >> + int ret; >> + VFIOIOASHwpt *hwpt; >> + unsigned long page_size; >> + >> + page_size = qemu_real_host_page_size(); >> + QLIST_FOREACH(hwpt, &container->hwpt_list, next) { >> + if (!iommufd_hwpt_dirty_tracking(hwpt)) { >> + continue; >> + } >> + >> + ret = iommufd_backend_get_dirty_bitmap(container->be, hwpt->hwpt_id, >> + iova, size, page_size, >> + vbmap->bitmap); >> + if (ret) { >> + error_setg_errno(errp, ret, >> + "Failed to get dirty bitmap report, hwpt_id %u, >> iova: " >> + "0x%" HWADDR_PRIx ", size: 0x%" HWADDR_PRIx, >> + hwpt->hwpt_id, iova, size); > > This error looks redundant with the one printed out in > iommufd_backend_get_dirty_bitmap(). Couldn't we add an 'Error **' > parameter and simply return a bool ? >
I'll add it. Just as a sidebar: This is a odd pattern which seems somewhat spread, that somehow we only care about @errno as something to put on a message, rather then letting the user know what exact error code it had returned programmatically. Here in this series it is only important for the device attach so likely doesn't justify a Error structure enhancement, hence the rest of functions I introduced here can just adopt bool+errp.