aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-01-08 10:28:42 +0000
committerPeter Maydell <peter.maydell@linaro.org>2024-01-08 10:28:42 +0000
commitffd454c67e38cc6df792733ebc5d967eee28ac0d (patch)
treeaff8d2ad7466ff6934fe3f7067fda272166c9f52 /hw
parent33252ebde15a238a1dbf07104aa0e5d5d487143c (diff)
parent19368b1905b4b917e915526fcbd5bfa3f7439451 (diff)
Merge tag 'pull-vfio-20240107' of https://github.com/legoater/qemu into staging
vfio queue: * Minor cleanups * Fix for a regression in device reset introduced in 8.2 * Coverity fixes, including the removal of the iommufd backend mutex * Introduced VFIOIOMMUClass, to avoid compiling spapr when !CONFIG_PSERIES # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmWbIrcACgkQUaNDx8/7 # 7KFtPRAAxWcH9uh4tjJe4CgL+wXC+JOgviiNaI3AS6KmxdTHXcAvXMNAiGJfTBo4 # y/lJg+PYNgcDWrOqZqp1jj6ulWpO8ekLD9Nxv03e6o3kaArX/o2MtsrndOtWYnG/ # CUrr+/kTNeEw9008OaOca9vuh03xh3AnSwb3DzjHTvpMkj5LTXzuE1mU50DTUkn9 # GZjuN3rqHcdjJ/fXpiS6IgJbxcxLdo2aSykmyuq+TZmGf02lTES94PRef3Btr7Q6 # sKQZpv+A+gcZ8DHDJqfOEzEgu1OSa257q4ic47O1X3CeSyiGTGQ7rVKHtX6bK7xP # mB9WOVqzzdH/g+kHNG+kVXMCQXZ0qo7VlIkHabYD220RryZBCqMecQ4aKPLFULQE # e7C5ZaEvb7TLe/EaEQUSFrLCns7Nq6ciurcoAmP0cn2Ef1Sr1luNQVAR9LWRH1pc # 1TeNmHy4nQygT0dQtFBXwNUZfnTuGcKdr43twReiCjX1ViPBU4lrcajVQH4rAuoe # K/bBak2Kyi1LsFn8AzIwKXZZl83L57EyL+XEW8i5GN1jFSAHFx4ocUq8NQBa//kS # xei9LV3HEJbAMOQsPO8HEK40mg5WR17s22AUClMqtD2DAQbPUrmcLbZ6Ttq6hTuV # BqL56JFjbfML5RGjxwF9G8v5mdLmLlNRCGF2KI3NsT7dkMbVh24= # =zvPi # -----END PGP SIGNATURE----- # gpg: Signature made Sun 07 Jan 2024 22:16:23 GMT # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-vfio-20240107' of https://github.com/legoater/qemu: backends/iommufd: Remove mutex backends/iommufd: Remove check on number of backend users vfio/migration: Add helper function to set state or reset device vfio/container: Rename vfio_init_container to vfio_set_iommu vfio/iommufd: Remove the use of stat() to check file existence hw/vfio: fix iteration over global VFIODevice list vfio/container: Replace basename with g_path_get_basename vfio/iommufd: Remove CONFIG_IOMMUFD usage vfio/spapr: Only compile sPAPR IOMMU support when needed vfio/iommufd: Introduce a VFIOIOMMU iommufd QOM interface vfio/spapr: Introduce a sPAPR VFIOIOMMU QOM interface vfio/container: Intoduce a new VFIOIOMMUClass::setup handler vfio/container: Introduce a VFIOIOMMU legacy QOM interface vfio/container: Introduce a VFIOIOMMU QOM interface vfio/container: Initialize VFIOIOMMUOps under vfio_init_container() vfio/container: Introduce vfio_legacy_setup() for further cleanups vfio/spapr: Extend VFIOIOMMUOps with a release handler Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/vfio/common.c19
-rw-r--r--hw/vfio/container-base.c12
-rw-r--r--hw/vfio/container.c153
-rw-r--r--hw/vfio/iommufd.c41
-rw-r--r--hw/vfio/meson.build2
-rw-r--r--hw/vfio/migration.c41
-rw-r--r--hw/vfio/pci.c2
-rw-r--r--hw/vfio/spapr.c60
8 files changed, 199 insertions, 131 deletions
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 08a3e57672..0b3352f2a9 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -19,7 +19,6 @@
*/
#include "qemu/osdep.h"
-#include CONFIG_DEVICES /* CONFIG_IOMMUFD */
#include <sys/ioctl.h>
#ifdef CONFIG_KVM
#include <linux/kvm.h>
@@ -74,7 +73,7 @@ bool vfio_mig_active(void)
return false;
}
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
if (vbasedev->migration_blocker) {
return false;
}
@@ -95,7 +94,7 @@ static bool vfio_multiple_devices_migration_is_supported(void)
unsigned int device_num = 0;
bool all_support_p2p = true;
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
if (vbasedev->migration) {
device_num++;
@@ -1367,13 +1366,13 @@ void vfio_reset_handler(void *opaque)
{
VFIODevice *vbasedev;
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
if (vbasedev->dev->realized) {
vbasedev->ops->vfio_compute_needs_reset(vbasedev);
}
}
- QLIST_FOREACH(vbasedev, &vfio_device_list, next) {
+ QLIST_FOREACH(vbasedev, &vfio_device_list, global_next) {
if (vbasedev->dev->realized && vbasedev->needs_reset) {
vbasedev->ops->vfio_hot_reset_multi(vbasedev);
}
@@ -1503,13 +1502,15 @@ retry:
int vfio_attach_device(char *name, VFIODevice *vbasedev,
AddressSpace *as, Error **errp)
{
- const VFIOIOMMUOps *ops = &vfio_legacy_ops;
+ const VFIOIOMMUClass *ops =
+ VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_LEGACY));
-#ifdef CONFIG_IOMMUFD
if (vbasedev->iommufd) {
- ops = &vfio_iommufd_ops;
+ ops = VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_IOMMUFD));
}
-#endif
+
+ assert(ops);
+
return ops->attach_device(name, vbasedev, as, errp);
}
diff --git a/hw/vfio/container-base.c b/hw/vfio/container-base.c
index 1ffd25bbfa..913ae49077 100644
--- a/hw/vfio/container-base.c
+++ b/hw/vfio/container-base.c
@@ -72,7 +72,7 @@ int vfio_container_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
}
void vfio_container_init(VFIOContainerBase *bcontainer, VFIOAddressSpace *space,
- const VFIOIOMMUOps *ops)
+ const VFIOIOMMUClass *ops)
{
bcontainer->ops = ops;
bcontainer->space = space;
@@ -99,3 +99,13 @@ void vfio_container_destroy(VFIOContainerBase *bcontainer)
g_list_free_full(bcontainer->iova_ranges, g_free);
}
+
+static const TypeInfo types[] = {
+ {
+ .name = TYPE_VFIO_IOMMU,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(VFIOIOMMUClass),
+ },
+};
+
+DEFINE_TYPES(types)
diff --git a/hw/vfio/container.c b/hw/vfio/container.c
index b22feb8ded..bd25b9fbad 100644
--- a/hw/vfio/container.c
+++ b/hw/vfio/container.c
@@ -369,10 +369,34 @@ static int vfio_get_iommu_type(VFIOContainer *container,
return -EINVAL;
}
-static int vfio_init_container(VFIOContainer *container, int group_fd,
- Error **errp)
+/*
+ * vfio_get_iommu_ops - get a VFIOIOMMUClass associated with a type
+ */
+static const VFIOIOMMUClass *vfio_get_iommu_class(int iommu_type, Error **errp)
+{
+ ObjectClass *klass = NULL;
+
+ switch (iommu_type) {
+ case VFIO_TYPE1v2_IOMMU:
+ case VFIO_TYPE1_IOMMU:
+ klass = object_class_by_name(TYPE_VFIO_IOMMU_LEGACY);
+ break;
+ case VFIO_SPAPR_TCE_v2_IOMMU:
+ case VFIO_SPAPR_TCE_IOMMU:
+ klass = object_class_by_name(TYPE_VFIO_IOMMU_SPAPR);
+ break;
+ default:
+ g_assert_not_reached();
+ };
+
+ return VFIO_IOMMU_CLASS(klass);
+}
+
+static int vfio_set_iommu(VFIOContainer *container, int group_fd,
+ VFIOAddressSpace *space, Error **errp)
{
int iommu_type, ret;
+ const VFIOIOMMUClass *vioc;
iommu_type = vfio_get_iommu_type(container, errp);
if (iommu_type < 0) {
@@ -401,6 +425,14 @@ static int vfio_init_container(VFIOContainer *container, int group_fd,
}
container->iommu_type = iommu_type;
+
+ vioc = vfio_get_iommu_class(iommu_type, errp);
+ if (!vioc) {
+ error_setg(errp, "No available IOMMU models");
+ return -EINVAL;
+ }
+
+ vfio_container_init(&container->bcontainer, space, vioc);
return 0;
}
@@ -474,6 +506,35 @@ static void vfio_get_iommu_info_migration(VFIOContainer *container,
}
}
+static int vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp)
+{
+ VFIOContainer *container = container_of(bcontainer, VFIOContainer,
+ bcontainer);
+ g_autofree struct vfio_iommu_type1_info *info = NULL;
+ int ret;
+
+ ret = vfio_get_iommu_info(container, &info);
+ if (ret) {
+ error_setg_errno(errp, -ret, "Failed to get VFIO IOMMU info");
+ return ret;
+ }
+
+ if (info->flags & VFIO_IOMMU_INFO_PGSIZES) {
+ bcontainer->pgsizes = info->iova_pgsizes;
+ } else {
+ bcontainer->pgsizes = qemu_real_host_page_size();
+ }
+
+ if (!vfio_get_info_dma_avail(info, &bcontainer->dma_max_mappings)) {
+ bcontainer->dma_max_mappings = 65535;
+ }
+
+ vfio_get_info_iova_range(info, bcontainer);
+
+ vfio_get_iommu_info_migration(container, info);
+ return 0;
+}
+
static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
Error **errp)
{
@@ -554,9 +615,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
container = g_malloc0(sizeof(*container));
container->fd = fd;
bcontainer = &container->bcontainer;
- vfio_container_init(bcontainer, space, &vfio_legacy_ops);
- ret = vfio_init_container(container, group->fd, errp);
+ ret = vfio_set_iommu(container, group->fd, space, errp);
if (ret) {
goto free_container_exit;
}
@@ -567,43 +627,11 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
goto free_container_exit;
}
- switch (container->iommu_type) {
- case VFIO_TYPE1v2_IOMMU:
- case VFIO_TYPE1_IOMMU:
- {
- struct vfio_iommu_type1_info *info;
-
- ret = vfio_get_iommu_info(container, &info);
- if (ret) {
- error_setg_errno(errp, -ret, "Failed to get VFIO IOMMU info");
- goto enable_discards_exit;
- }
-
- if (info->flags & VFIO_IOMMU_INFO_PGSIZES) {
- bcontainer->pgsizes = info->iova_pgsizes;
- } else {
- bcontainer->pgsizes = qemu_real_host_page_size();
- }
-
- if (!vfio_get_info_dma_avail(info, &bcontainer->dma_max_mappings)) {
- bcontainer->dma_max_mappings = 65535;
- }
-
- vfio_get_info_iova_range(info, bcontainer);
+ assert(bcontainer->ops->setup);
- vfio_get_iommu_info_migration(container, info);
- g_free(info);
- break;
- }
- case VFIO_SPAPR_TCE_v2_IOMMU:
- case VFIO_SPAPR_TCE_IOMMU:
- {
- ret = vfio_spapr_container_init(container, errp);
- if (ret) {
- goto enable_discards_exit;
- }
- break;
- }
+ ret = bcontainer->ops->setup(bcontainer, errp);
+ if (ret) {
+ goto enable_discards_exit;
}
vfio_kvm_device_add_group(group);
@@ -632,9 +660,8 @@ listener_release_exit:
QLIST_REMOVE(bcontainer, next);
vfio_kvm_device_del_group(group);
memory_listener_unregister(&bcontainer->listener);
- if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU ||
- container->iommu_type == VFIO_SPAPR_TCE_IOMMU) {
- vfio_spapr_container_deinit(container);
+ if (bcontainer->ops->release) {
+ bcontainer->ops->release(bcontainer);
}
enable_discards_exit:
@@ -667,9 +694,8 @@ static void vfio_disconnect_container(VFIOGroup *group)
*/
if (QLIST_EMPTY(&container->group_list)) {
memory_listener_unregister(&bcontainer->listener);
- if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU ||
- container->iommu_type == VFIO_SPAPR_TCE_IOMMU) {
- vfio_spapr_container_deinit(container);
+ if (bcontainer->ops->release) {
+ bcontainer->ops->release(bcontainer);
}
}
@@ -843,7 +869,8 @@ static void vfio_put_base_device(VFIODevice *vbasedev)
static int vfio_device_groupid(VFIODevice *vbasedev, Error **errp)
{
- char *tmp, group_path[PATH_MAX], *group_name;
+ char *tmp, group_path[PATH_MAX];
+ g_autofree char *group_name = NULL;
int ret, groupid;
ssize_t len;
@@ -859,7 +886,7 @@ static int vfio_device_groupid(VFIODevice *vbasedev, Error **errp)
group_path[len] = 0;
- group_name = basename(group_path);
+ group_name = g_path_get_basename(group_path);
if (sscanf(group_name, "%d", &groupid) != 1) {
error_setg_errno(errp, errno, "failed to read %s", group_path);
return -errno;
@@ -1093,12 +1120,26 @@ out_single:
return ret;
}
-const VFIOIOMMUOps vfio_legacy_ops = {
- .dma_map = vfio_legacy_dma_map,
- .dma_unmap = vfio_legacy_dma_unmap,
- .attach_device = vfio_legacy_attach_device,
- .detach_device = vfio_legacy_detach_device,
- .set_dirty_page_tracking = vfio_legacy_set_dirty_page_tracking,
- .query_dirty_bitmap = vfio_legacy_query_dirty_bitmap,
- .pci_hot_reset = vfio_legacy_pci_hot_reset,
+static void vfio_iommu_legacy_class_init(ObjectClass *klass, void *data)
+{
+ VFIOIOMMUClass *vioc = VFIO_IOMMU_CLASS(klass);
+
+ vioc->setup = vfio_legacy_setup;
+ vioc->dma_map = vfio_legacy_dma_map;
+ vioc->dma_unmap = vfio_legacy_dma_unmap;
+ vioc->attach_device = vfio_legacy_attach_device;
+ vioc->detach_device = vfio_legacy_detach_device;
+ vioc->set_dirty_page_tracking = vfio_legacy_set_dirty_page_tracking;
+ vioc->query_dirty_bitmap = vfio_legacy_query_dirty_bitmap;
+ vioc->pci_hot_reset = vfio_legacy_pci_hot_reset;
};
+
+static const TypeInfo types[] = {
+ {
+ .name = TYPE_VFIO_IOMMU_LEGACY,
+ .parent = TYPE_VFIO_IOMMU,
+ .class_init = vfio_iommu_legacy_class_init,
+ },
+};
+
+DEFINE_TYPES(types)
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 87a561c545..9bfddc1360 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -121,17 +121,11 @@ static int iommufd_cdev_getfd(const char *sysfs_path, Error **errp)
DIR *dir = NULL;
struct dirent *dent;
gchar *contents;
- struct stat st;
gsize length;
int major, minor;
dev_t vfio_devt;
path = g_strdup_printf("%s/vfio-dev", sysfs_path);
- if (stat(path, &st) < 0) {
- error_setg_errno(errp, errno, "no such host device");
- goto out_free_path;
- }
-
dir = opendir(path);
if (!dir) {
error_setg_errno(errp, errno, "couldn't open directory %s", path);
@@ -319,6 +313,8 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
int ret, devfd;
uint32_t ioas_id;
Error *err = NULL;
+ const VFIOIOMMUClass *iommufd_vioc =
+ VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_IOMMUFD));
if (vbasedev->fd < 0) {
devfd = iommufd_cdev_getfd(vbasedev->sysfsdev, errp);
@@ -340,7 +336,7 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
/* try to attach to an existing container in this space */
QLIST_FOREACH(bcontainer, &space->containers, next) {
container = container_of(bcontainer, VFIOIOMMUFDContainer, bcontainer);
- if (bcontainer->ops != &vfio_iommufd_ops ||
+ if (bcontainer->ops != iommufd_vioc ||
vbasedev->iommufd != container->be) {
continue;
}
@@ -374,7 +370,7 @@ static int iommufd_cdev_attach(const char *name, VFIODevice *vbasedev,
container->ioas_id = ioas_id;
bcontainer = &container->bcontainer;
- vfio_container_init(bcontainer, space, &vfio_iommufd_ops);
+ vfio_container_init(bcontainer, space, iommufd_vioc);
QLIST_INSERT_HEAD(&space->containers, bcontainer, next);
ret = iommufd_cdev_attach_container(vbasedev, container, errp);
@@ -476,9 +472,11 @@ static void iommufd_cdev_detach(VFIODevice *vbasedev)
static VFIODevice *iommufd_cdev_pci_find_by_devid(__u32 devid)
{
VFIODevice *vbasedev_iter;
+ const VFIOIOMMUClass *iommufd_vioc =
+ VFIO_IOMMU_CLASS(object_class_by_name(TYPE_VFIO_IOMMU_IOMMUFD));
QLIST_FOREACH(vbasedev_iter, &vfio_device_list, global_next) {
- if (vbasedev_iter->bcontainer->ops != &vfio_iommufd_ops) {
+ if (vbasedev_iter->bcontainer->ops != iommufd_vioc) {
continue;
}
if (devid == vbasedev_iter->devid) {
@@ -621,10 +619,23 @@ out_single:
return ret;
}
-const VFIOIOMMUOps vfio_iommufd_ops = {
- .dma_map = iommufd_cdev_map,
- .dma_unmap = iommufd_cdev_unmap,
- .attach_device = iommufd_cdev_attach,
- .detach_device = iommufd_cdev_detach,
- .pci_hot_reset = iommufd_cdev_pci_hot_reset,
+static void vfio_iommu_iommufd_class_init(ObjectClass *klass, void *data)
+{
+ VFIOIOMMUClass *vioc = VFIO_IOMMU_CLASS(klass);
+
+ vioc->dma_map = iommufd_cdev_map;
+ vioc->dma_unmap = iommufd_cdev_unmap;
+ vioc->attach_device = iommufd_cdev_attach;
+ vioc->detach_device = iommufd_cdev_detach;
+ vioc->pci_hot_reset = iommufd_cdev_pci_hot_reset;
+};
+
+static const TypeInfo types[] = {
+ {
+ .name = TYPE_VFIO_IOMMU_IOMMUFD,
+ .parent = TYPE_VFIO_IOMMU,
+ .class_init = vfio_iommu_iommufd_class_init,
+ },
};
+
+DEFINE_TYPES(types)
diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
index e5d98b6adc..bb98493b53 100644
--- a/hw/vfio/meson.build
+++ b/hw/vfio/meson.build
@@ -4,9 +4,9 @@ vfio_ss.add(files(
'common.c',
'container-base.c',
'container.c',
- 'spapr.c',
'migration.c',
))
+vfio_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr.c'))
vfio_ss.add(when: 'CONFIG_IOMMUFD', if_true: files(
'iommufd.c',
))
diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c
index 28d422b39f..70e6b1a709 100644
--- a/hw/vfio/migration.c
+++ b/hw/vfio/migration.c
@@ -163,6 +163,19 @@ reset_device:
return ret;
}
+/*
+ * Some device state transitions require resetting the device if they fail.
+ * This function sets the device in new_state and resets the device if that
+ * fails. Reset is done by using ERROR as the recover state.
+ */
+static int
+vfio_migration_set_state_or_reset(VFIODevice *vbasedev,
+ enum vfio_device_mig_state new_state)
+{
+ return vfio_migration_set_state(vbasedev, new_state,
+ VFIO_DEVICE_STATE_ERROR);
+}
+
static int vfio_load_buffer(QEMUFile *f, VFIODevice *vbasedev,
uint64_t data_size)
{
@@ -422,12 +435,7 @@ static void vfio_save_cleanup(void *opaque)
* after migration has completed, so it won't increase downtime.
*/
if (migration->device_state == VFIO_DEVICE_STATE_STOP_COPY) {
- /*
- * If setting the device in STOP state fails, the device should be
- * reset. To do so, use ERROR state as a recover state.
- */
- vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_STOP,
- VFIO_DEVICE_STATE_ERROR);
+ vfio_migration_set_state_or_reset(vbasedev, VFIO_DEVICE_STATE_STOP);
}
g_free(migration->data_buffer);
@@ -699,12 +707,7 @@ static void vfio_vmstate_change_prepare(void *opaque, bool running,
VFIO_DEVICE_STATE_PRE_COPY_P2P :
VFIO_DEVICE_STATE_RUNNING_P2P;
- /*
- * If setting the device in new_state fails, the device should be reset.
- * To do so, use ERROR state as a recover state.
- */
- ret = vfio_migration_set_state(vbasedev, new_state,
- VFIO_DEVICE_STATE_ERROR);
+ ret = vfio_migration_set_state_or_reset(vbasedev, new_state);
if (ret) {
/*
* Migration should be aborted in this case, but vm_state_notify()
@@ -736,12 +739,7 @@ static void vfio_vmstate_change(void *opaque, bool running, RunState state)
VFIO_DEVICE_STATE_STOP;
}
- /*
- * If setting the device in new_state fails, the device should be reset.
- * To do so, use ERROR state as a recover state.
- */
- ret = vfio_migration_set_state(vbasedev, new_state,
- VFIO_DEVICE_STATE_ERROR);
+ ret = vfio_migration_set_state_or_reset(vbasedev, new_state);
if (ret) {
/*
* Migration should be aborted in this case, but vm_state_notify()
@@ -770,12 +768,7 @@ static void vfio_migration_state_notifier(Notifier *notifier, void *data)
case MIGRATION_STATUS_CANCELLING:
case MIGRATION_STATUS_CANCELLED:
case MIGRATION_STATUS_FAILED:
- /*
- * If setting the device in RUNNING state fails, the device should
- * be reset. To do so, use ERROR state as a recover state.
- */
- vfio_migration_set_state(vbasedev, VFIO_DEVICE_STATE_RUNNING,
- VFIO_DEVICE_STATE_ERROR);
+ vfio_migration_set_state_or_reset(vbasedev, VFIO_DEVICE_STATE_RUNNING);
}
}
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 9f838978be..d7fe06715c 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2488,7 +2488,7 @@ int vfio_pci_get_pci_hot_reset_info(VFIOPCIDevice *vdev,
static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
{
VFIODevice *vbasedev = &vdev->vbasedev;
- const VFIOIOMMUOps *ops = vbasedev->bcontainer->ops;
+ const VFIOIOMMUClass *ops = vbasedev->bcontainer->ops;
return ops->pci_hot_reset(vbasedev, single);
}
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 5c6426e697..0d949bb728 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -440,19 +440,29 @@ vfio_spapr_container_del_section_window(VFIOContainerBase *bcontainer,
}
}
-static VFIOIOMMUOps vfio_iommu_spapr_ops;
-
-static void setup_spapr_ops(VFIOContainerBase *bcontainer)
+static void vfio_spapr_container_release(VFIOContainerBase *bcontainer)
{
- vfio_iommu_spapr_ops = *bcontainer->ops;
- vfio_iommu_spapr_ops.add_window = vfio_spapr_container_add_section_window;
- vfio_iommu_spapr_ops.del_window = vfio_spapr_container_del_section_window;
- bcontainer->ops = &vfio_iommu_spapr_ops;
+ VFIOContainer *container = container_of(bcontainer, VFIOContainer,
+ bcontainer);
+ VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
+ container);
+ VFIOHostDMAWindow *hostwin, *next;
+
+ if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
+ memory_listener_unregister(&scontainer->prereg_listener);
+ }
+ QLIST_FOREACH_SAFE(hostwin, &scontainer->hostwin_list, hostwin_next,
+ next) {
+ QLIST_REMOVE(hostwin, hostwin_next);
+ g_free(hostwin);
+ }
}
-int vfio_spapr_container_init(VFIOContainer *container, Error **errp)
+static int vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
+ Error **errp)
{
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainer *container = container_of(bcontainer, VFIOContainer,
+ bcontainer);
VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
container);
struct vfio_iommu_spapr_tce_info info;
@@ -517,8 +527,6 @@ int vfio_spapr_container_init(VFIOContainer *container, Error **errp)
0x1000);
}
- setup_spapr_ops(bcontainer);
-
return 0;
listener_unregister_exit:
@@ -528,18 +536,22 @@ listener_unregister_exit:
return ret;
}
-void vfio_spapr_container_deinit(VFIOContainer *container)
+static void vfio_iommu_spapr_class_init(ObjectClass *klass, void *data)
{
- VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
- container);
- VFIOHostDMAWindow *hostwin, *next;
+ VFIOIOMMUClass *vioc = VFIO_IOMMU_CLASS(klass);
- if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU) {
- memory_listener_unregister(&scontainer->prereg_listener);
- }
- QLIST_FOREACH_SAFE(hostwin, &scontainer->hostwin_list, hostwin_next,
- next) {
- QLIST_REMOVE(hostwin, hostwin_next);
- g_free(hostwin);
- }
-}
+ vioc->add_window = vfio_spapr_container_add_section_window;
+ vioc->del_window = vfio_spapr_container_del_section_window;
+ vioc->release = vfio_spapr_container_release;
+ vioc->setup = vfio_spapr_container_setup;
+};
+
+static const TypeInfo types[] = {
+ {
+ .name = TYPE_VFIO_IOMMU_SPAPR,
+ .parent = TYPE_VFIO_IOMMU_LEGACY,
+ .class_init = vfio_iommu_spapr_class_init,
+ },
+};
+
+DEFINE_TYPES(types)