Skip to content

Commit

Permalink
Merge tag 'pull-vfio-20240107' of https://github.com/legoater/qemu in…
Browse files Browse the repository at this point in the history
…to 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>
  • Loading branch information
pm215 committed Jan 8, 2024
2 parents 33252eb + 19368b1 commit ffd454c
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 151 deletions.
12 changes: 0 additions & 12 deletions backends/iommufd.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ static void iommufd_backend_init(Object *obj)
be->fd = -1;
be->users = 0;
be->owned = true;
qemu_mutex_init(&be->lock);
}

static void iommufd_backend_finalize(Object *obj)
Expand All @@ -52,10 +51,8 @@ static void iommufd_backend_set_fd(Object *obj, const char *str, Error **errp)
error_prepend(errp, "Could not parse remote object fd %s:", str);
return;
}
qemu_mutex_lock(&be->lock);
be->fd = fd;
be->owned = false;
qemu_mutex_unlock(&be->lock);
trace_iommu_backend_set_fd(be->fd);
}

Expand All @@ -79,12 +76,6 @@ int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
{
int fd, ret = 0;

qemu_mutex_lock(&be->lock);
if (be->users == UINT32_MAX) {
error_setg(errp, "too many connections");
ret = -E2BIG;
goto out;
}
if (be->owned && !be->users) {
fd = qemu_open_old("/dev/iommu", O_RDWR);
if (fd < 0) {
Expand All @@ -98,13 +89,11 @@ int iommufd_backend_connect(IOMMUFDBackend *be, Error **errp)
out:
trace_iommufd_backend_connect(be->fd, be->owned,
be->users, ret);
qemu_mutex_unlock(&be->lock);
return ret;
}

void iommufd_backend_disconnect(IOMMUFDBackend *be)
{
qemu_mutex_lock(&be->lock);
if (!be->users) {
goto out;
}
Expand All @@ -115,7 +104,6 @@ void iommufd_backend_disconnect(IOMMUFDBackend *be)
}
out:
trace_iommufd_backend_disconnect(be->fd, be->users);
qemu_mutex_unlock(&be->lock);
}

int iommufd_backend_alloc_ioas(IOMMUFDBackend *be, uint32_t *ioas_id,
Expand Down
19 changes: 10 additions & 9 deletions hw/vfio/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
*/

#include "qemu/osdep.h"
#include CONFIG_DEVICES /* CONFIG_IOMMUFD */
#include <sys/ioctl.h>
#ifdef CONFIG_KVM
#include <linux/kvm.h>
Expand Down Expand Up @@ -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;
}
Expand All @@ -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++;

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -1503,13 +1502,15 @@ struct vfio_device_info *vfio_get_device_info(int fd)
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);
}

Expand Down
12 changes: 11 additions & 1 deletion hw/vfio/container-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
153 changes: 97 additions & 56 deletions hw/vfio/container.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -632,9 +660,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as,
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:
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -1093,12 +1120,26 @@ static int vfio_legacy_pci_hot_reset(VFIODevice *vbasedev, bool 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)

0 comments on commit ffd454c

Please sign in to comment.