@@ -16,6 +16,7 @@
#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 <sys/ioctl.h>
@@ -77,11 +78,17 @@ bool iommufd_backend_connect(IOMMUFDBackend *be, const char *name, Error **errp)
int fd;
if (be->owned && !be->users) {
- fd = qemu_open_old("/dev/iommu", O_RDWR);
+ g_autofree char *iname = g_strdup_printf("%s_iommu", name);
+ fd = cpr_find_fd(iname, 0);
+ be->reused = (fd >= 0);
+ if (!be->reused) {
+ fd = qemu_open_old("/dev/iommu", O_RDWR);
+ }
if (fd < 0) {
error_setg_errno(errp, errno, "/dev/iommu opening failed");
return false;
}
+ cpr_resave_fd(iname, 0, fd);
be->fd = fd;
}
be->users++;
@@ -92,6 +99,8 @@ bool iommufd_backend_connect(IOMMUFDBackend *be, const char *name, Error **errp)
void iommufd_backend_disconnect(IOMMUFDBackend *be, const char *name)
{
+ g_autofree char *iname = g_strdup_printf("%s_iommu", name);
+
if (!be->users) {
goto out;
}
@@ -101,6 +110,7 @@ void iommufd_backend_disconnect(IOMMUFDBackend *be, const char *name)
be->fd = -1;
}
out:
+ cpr_delete_fd(iname, 0);
trace_iommufd_backend_disconnect(be->fd, be->users);
}
@@ -24,6 +24,7 @@
#include "sysemu/reset.h"
#include "qemu/cutils.h"
#include "qemu/chardev_open.h"
+#include "migration/cpr.h"
#include "pci.h"
static int iommufd_cdev_map(const VFIOContainerBase *bcontainer, hwaddr iova,
@@ -84,6 +85,11 @@ static bool iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
goto err_kvm_device_add;
}
+ if (vbasedev->reused) {
+ /* Already bound, and devid was set in iommufd_cdev_attach */
+ goto skip_bind;
+ }
+
/* Bind device to iommufd */
bind.iommufd = iommufd->fd;
if (ioctl(vbasedev->fd, VFIO_DEVICE_BIND_IOMMUFD, &bind)) {
@@ -95,6 +101,8 @@ static bool iommufd_cdev_connect_and_bind(VFIODevice *vbasedev, Error **errp)
vbasedev->devid = bind.out_devid;
trace_iommufd_cdev_connect_and_bind(bind.iommufd, vbasedev->name,
vbasedev->fd, vbasedev->devid);
+
+skip_bind:
return true;
err_bind:
iommufd_cdev_kvm_device_del(vbasedev);
@@ -305,13 +313,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_any(vbasedev->name, (int *)&vbasedev->devid);
+ vbasedev->reused = (devfd >= 0);
+ if (!vbasedev->reused) {
+ devfd = iommufd_cdev_getfd(vbasedev->sysfsdev, errp);
+ }
if (devfd < 0) {
return false;
}
vbasedev->fd = devfd;
} else {
devfd = vbasedev->fd;
+ vbasedev->reused = false;
}
if (!iommufd_cdev_connect_and_bind(vbasedev, errp)) {
@@ -413,6 +426,7 @@ found_container:
vbasedev->bcontainer = bcontainer;
QLIST_INSERT_HEAD(&bcontainer->device_list, vbasedev, container_next);
QLIST_INSERT_HEAD(&vfio_device_list, vbasedev, global_next);
+ cpr_resave_fd(vbasedev->name, vbasedev->devid, devfd);
trace_iommufd_cdev_device_info(vbasedev->name, devfd, vbasedev->num_irqs,
vbasedev->num_regions, vbasedev->flags);
@@ -452,6 +466,7 @@ static void iommufd_cdev_detach(VFIODevice *vbasedev)
iommufd_cdev_container_destroy(container);
vfio_put_address_space(space);
+ cpr_delete_fd(vbasedev->name, vbasedev->devid);
iommufd_cdev_unbind_and_disconnect(vbasedev);
close(vbasedev->fd);
}
@@ -32,6 +32,7 @@ struct IOMMUFDBackend {
/*< protected >*/
int fd; /* /dev/iommu file descriptor */
bool owned; /* is the /dev/iommu opened internally */
+ bool reused; /* fd is reused after CPR */
uint32_t users;
/*< public >*/
Save the iommu and vfio device fd in CPR state when it is created, and fetch the fd from that state after CPR. Save the devid as the fd id. Remember that the fd was reused, for subsequent patches. Signed-off-by: Steve Sistare <steven.sistare@oracle.com> --- backends/iommufd.c | 12 +++++++++++- hw/vfio/iommufd.c | 17 ++++++++++++++++- include/sysemu/iommufd.h | 1 + 3 files changed, 28 insertions(+), 2 deletions(-)