Save the iommu and vfio device fd in CPR state when it is created. After CPR, the fd number is found in CPR state and reused. Remember the reused status for subsequent patches. The reused status is cleared when vmstate load finishes.
Signed-off-by: Steve Sistare <steven.sist...@oracle.com> --- backends/iommufd.c | 19 ++++++++++--------- hw/vfio/cpr-iommufd.c | 16 ++++++++++++++++ hw/vfio/device.c | 10 ++-------- hw/vfio/iommufd.c | 13 +++++++++++-- include/system/iommufd.h | 1 + 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/backends/iommufd.c b/backends/iommufd.c index 6fed1c1..492747c 100644 --- a/backends/iommufd.c +++ b/backends/iommufd.c @@ -16,12 +16,18 @@ #include "qemu/module.h" #include "qom/object_interfaces.h" #include "qemu/error-report.h" +#include "migration/cpr.h" #include "monitor/monitor.h" #include "trace.h" #include "hw/vfio/vfio-device.h" #include <sys/ioctl.h> #include <linux/iommufd.h> +static const char *iommufd_fd_name(IOMMUFDBackend *be) +{ + return object_get_canonical_path_component(OBJECT(be)); +} + static void iommufd_backend_init(Object *obj) { IOMMUFDBackend *be = IOMMUFD_BACKEND(obj); @@ -47,9 +53,8 @@ static void iommufd_backend_set_fd(Object *obj, const char *str, Error **errp) IOMMUFDBackend *be = IOMMUFD_BACKEND(obj); int fd = -1; - fd = monitor_fd_param(monitor_cur(), str, errp); + fd = cpr_get_fd_param(iommufd_fd_name(be), str, 0, &be->cpr_reused, errp); if (fd == -1) { - error_prepend(errp, "Could not parse remote object fd %s:", str); return; } be->fd = fd; @@ -95,14 +100,9 @@ bool iommufd_change_process(IOMMUFDBackend *be, Error **errp) bool iommufd_backend_connect(IOMMUFDBackend *be, Error **errp) { - int fd; - if (be->owned && !be->users) { - fd = qemu_open("/dev/iommu", O_RDWR, errp); - if (fd < 0) { - return false; - } - be->fd = fd; + be->fd = cpr_open_fd("/dev/iommu", O_RDWR, iommufd_fd_name(be), 0, + &be->cpr_reused, errp); } be->users++; @@ -121,6 +121,7 @@ void iommufd_backend_disconnect(IOMMUFDBackend *be) be->fd = -1; } out: + cpr_delete_fd(iommufd_fd_name(be), 0); trace_iommufd_backend_disconnect(be->fd, be->users); } diff --git a/hw/vfio/cpr-iommufd.c b/hw/vfio/cpr-iommufd.c index 46f2006..b760bd3 100644 --- a/hw/vfio/cpr-iommufd.c +++ b/hw/vfio/cpr-iommufd.c @@ -8,6 +8,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/vfio/vfio-cpr.h" +#include "hw/vfio/vfio-device.h" #include "migration/blocker.h" #include "migration/cpr.h" #include "migration/migration.h" @@ -25,10 +26,25 @@ static bool vfio_cpr_supported(VFIOIOMMUFDContainer *container, Error **errp) return true; } +static int vfio_container_post_load(void *opaque, int version_id) +{ + VFIOIOMMUFDContainer *container = opaque; + VFIOContainerBase *bcontainer = &container->bcontainer; + VFIODevice *vbasedev; + + QLIST_FOREACH(vbasedev, &bcontainer->device_list, container_next) { + vbasedev->cpr.reused = false; + } + container->be->cpr_reused = false; + + return 0; +} + static const VMStateDescription vfio_container_vmstate = { .name = "vfio-iommufd-container", .version_id = 0, .minimum_version_id = 0, + .post_load = vfio_container_post_load, .needed = cpr_needed_for_reuse, .fields = (VMStateField[]) { VMSTATE_END_OF_LIST() diff --git a/hw/vfio/device.c b/hw/vfio/device.c index 8e9de68..02f384e 100644 --- a/hw/vfio/device.c +++ b/hw/vfio/device.c @@ -312,14 +312,8 @@ bool vfio_device_get_name(VFIODevice *vbasedev, Error **errp) void vfio_device_set_fd(VFIODevice *vbasedev, const char *str, Error **errp) { - ERRP_GUARD(); - int fd = monitor_fd_param(monitor_cur(), str, errp); - - if (fd < 0) { - error_prepend(errp, "Could not parse remote object fd %s:", str); - return; - } - vbasedev->fd = fd; + vbasedev->fd = cpr_get_fd_param(vbasedev->dev->id, str, 0, + &vbasedev->cpr.reused, errp); } static VFIODeviceIOOps vfio_device_io_ops_ioctl; diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c index dabb948..046f601 100644 --- a/hw/vfio/iommufd.c +++ b/hw/vfio/iommufd.c @@ -26,6 +26,7 @@ #include "qemu/cutils.h" #include "qemu/chardev_open.h" #include "migration/blocker.h" +#include "migration/cpr.h" #include "pci.h" #include "vfio-iommufd.h" #include "vfio-helpers.h" @@ -530,13 +531,18 @@ static bool iommufd_cdev_attach(const char *name, VFIODevice *vbasedev, VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_IOMMUFD)); if (vbasedev->fd < 0) { - devfd = iommufd_cdev_getfd(vbasedev->sysfsdev, errp); + devfd = cpr_find_fd(vbasedev->name, 0); + vbasedev->cpr.reused = (devfd >= 0); + if (!vbasedev->cpr.reused) { + devfd = iommufd_cdev_getfd(vbasedev->sysfsdev, errp); + } if (devfd < 0) { return false; } vbasedev->fd = devfd; } else { devfd = vbasedev->fd; + /* reused was set in iommufd_backend_set_fd */ } if (!iommufd_cdev_connect_and_bind(vbasedev, errp)) { @@ -634,7 +640,9 @@ found_container: vfio_device_prepare(vbasedev, bcontainer, &dev_info); vfio_iommufd_cpr_register_device(vbasedev); - + if (!vbasedev->cpr.reused) { + cpr_save_fd(vbasedev->name, 0, vbasedev->fd); + } trace_iommufd_cdev_device_info(vbasedev->name, devfd, vbasedev->num_irqs, vbasedev->num_regions, vbasedev->flags); return true; @@ -673,6 +681,7 @@ static void iommufd_cdev_detach(VFIODevice *vbasedev) migrate_del_blocker(&vbasedev->cpr.id_blocker); vfio_iommufd_cpr_unregister_device(vbasedev); + cpr_delete_fd(vbasedev->name, 0); iommufd_cdev_unbind_and_disconnect(vbasedev); close(vbasedev->fd); } diff --git a/include/system/iommufd.h b/include/system/iommufd.h index db9ed53..5c17abd 100644 --- a/include/system/iommufd.h +++ b/include/system/iommufd.h @@ -32,6 +32,7 @@ struct IOMMUFDBackend { /*< protected >*/ int fd; /* /dev/iommu file descriptor */ bool owned; /* is the /dev/iommu opened internally */ + bool cpr_reused; /* fd is reused after CPR */ uint32_t users; /*< public >*/ -- 1.8.3.1