diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2024-01-08 10:28:42 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2024-01-08 10:28:42 +0000 |
commit | ffd454c67e38cc6df792733ebc5d967eee28ac0d (patch) | |
tree | aff8d2ad7466ff6934fe3f7067fda272166c9f52 /hw/vfio/container.c | |
parent | 33252ebde15a238a1dbf07104aa0e5d5d487143c (diff) | |
parent | 19368b1905b4b917e915526fcbd5bfa3f7439451 (diff) | |
download | qemu-ffd454c67e38cc6df792733ebc5d967eee28ac0d.zip qemu-ffd454c67e38cc6df792733ebc5d967eee28ac0d.tar.gz qemu-ffd454c67e38cc6df792733ebc5d967eee28ac0d.tar.bz2 |
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/vfio/container.c')
-rw-r--r-- | hw/vfio/container.c | 153 |
1 files changed, 97 insertions, 56 deletions
diff --git a/hw/vfio/container.c b/hw/vfio/container.c index b22feb8..bd25b9f 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) |