From 2276a3a175576a63da6abd5ccb309dd1cdbc4021 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Mon, 22 Jul 2024 22:13:21 +0100 Subject: [PATCH] vfio/{iommufd, container}: Invoke HostIOMMUDevice::realize() during attach_device() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the HostIOMMUDevice::realize() to be invoked during the attach of the device before we allocate IOMMUFD hardware pagetable objects (HWPT). This allows the use of the hw_caps obtained by IOMMU_GET_HW_INFO that essentially tell if the IOMMU behind the device supports dirty tracking. Note: The HostIOMMUDevice data from legacy backend is static and doesn't need any information from the (type1-iommu) backend to be initialized. In contrast however, the IOMMUFD HostIOMMUDevice data requires the iommufd FD to be connected and having a devid to be able to successfully GET_HW_INFO. This means vfio_device_hiod_realize() is called in different places within the backend .attach_device() implementation. Suggested-by: Cédric Le Goater Signed-off-by: Joao Martins Reviewed-by: Zhenzhong Duan Reviewed-by: Cédric Le Goater [ clg: Fixed error handling in iommufd_cdev_attach() ] Signed-off-by: Cédric Le Goater Reviewed-by: Eric Auger --- hw/vfio/common.c | 19 +++++++------------ hw/vfio/container.c | 4 ++++ hw/vfio/helpers.c | 11 +++++++++++ hw/vfio/iommufd.c | 11 +++++++++++ include/hw/vfio/vfio-common.h | 1 + 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index ceb1da0b94..65e1c9f810 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -1659,22 +1659,17 @@ int vfio_attach_device(char *name, VFIODevice *vbasedev, assert(ops); - ret = ops->attach_device(name, vbasedev, as, errp); - if (ret) { - return ret; - } - - if (vbasedev->mdev) { - return true; + if (!vbasedev->mdev) { + hiod = HOST_IOMMU_DEVICE(object_new(ops->hiod_typename)); + vbasedev->hiod = hiod; } - hiod = HOST_IOMMU_DEVICE(object_new(ops->hiod_typename)); - if (!HOST_IOMMU_DEVICE_GET_CLASS(hiod)->realize(hiod, vbasedev, errp)) { + ret = ops->attach_device(name, vbasedev, as, errp); + if (ret) { object_unref(hiod); - ops->detach_device(vbasedev); - return -1; + vbasedev->hiod = NULL; + return ret; } - vbasedev->hiod = hiod; return 0; } diff --git a/hw/vfio/container.c b/hw/vfio/container.c index 30a62348d3..64eacfd912 100644 --- a/hw/vfio/container.c +++ b/hw/vfio/container.c @@ -1030,6 +1030,10 @@ static int vfio_legacy_attach_device(const char *name, VFIODevice *vbasedev, trace_vfio_attach_device(vbasedev->name, groupid); + if (!vfio_device_hiod_realize(vbasedev, errp)) { + return false; + } + group = vfio_get_group(groupid, as, errp); if (!group) { return -ENOENT; diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c index 37bc383c69..1f3bfed917 100644 --- a/hw/vfio/helpers.c +++ b/hw/vfio/helpers.c @@ -694,3 +694,14 @@ bool vfio_device_is_mdev(VFIODevice *vbasedev) subsys = realpath(tmp, NULL); return subsys && (strcmp(subsys, "/sys/bus/mdev") == 0); } + +bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp) +{ + HostIOMMUDevice *hiod = vbasedev->hiod; + + if (!hiod) { + return true; + } + + return HOST_IOMMU_DEVICE_GET_CLASS(hiod)->realize(hiod, vbasedev, errp); +} diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index d9088705de..8fd6826826 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -424,6 +424,17 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev, space = vfio_get_address_space(as); + /* + * The HostIOMMUDevice data from legacy backend is static and doesn't need + * any information from the (type1-iommu) backend to be initialized. In + * contrast however, the IOMMUFD HostIOMMUDevice data requires the iommufd + * FD to be connected and having a devid to be able to successfully call + * iommufd_backend_get_device_info(). + */ + if (!vfio_device_hiod_realize(vbasedev, errp)) { + goto err_alloc_ioas; + } + /* try to attach to an existing container in this space */ QLIST_FOREACH(bcontainer, &space->containers, next) { container = container_of(bcontainer, VFIOIOMMUFDContainer, bcontainer); diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h index 2093ed2e91..63da291456 100644 --- a/include/hw/vfio/vfio-common.h +++ b/include/hw/vfio/vfio-common.h @@ -230,6 +230,7 @@ void vfio_region_finalize(VFIORegion *region); void vfio_reset_handler(void *opaque); struct vfio_device_info *vfio_get_device_info(int fd); bool vfio_device_is_mdev(VFIODevice *vbasedev); +bool vfio_device_hiod_realize(VFIODevice *vbasedev, Error **errp); int vfio_attach_device(char *name, VFIODevice *vbasedev, AddressSpace *as, Error **errp); void vfio_detach_device(VFIODevice *vbasedev); -- 2.41.0.windows.1