From a7d1827d76767fe3e5366ef50efd50ebea0ed089 Mon Sep 17 00:00:00 2001 From: Nicolin Chen Date: Wed, 22 Dec 2021 21:48:18 -0800 Subject: [PATCH] vfio: Add iommufd VFIO compat support to group_fd IOMMUFD has VFIO compatibility so user space can open /dev/iommu to reuse existing VFIO IOMMU ioctls. However, the group_fd used for VFIO_GROUP_SET/UNSET_CONTAINER is still a VFIO thing and is not supported using new IOMMUFD ioctls, which go for an approach of attaching and dettaching a VFIO device directly instead of a VFIO group. In order to fill this gap, IOMMUFD provides a pair of helpers to VFIO to call, so as to bind/unbind all devices in the VFIO group to/from the iommufd and to attach/detach them to/from the ioas. So this patch simply calls those two helpers in cases where user space uses VFIO ioctls on top of /dev/iommu and wants to connect group_fd to that. Signed-off-by: Nicolin Chen Signed-off-by: Yi Liu --- drivers/iommu/iommufd/vfio_compat.c | 3 ++- drivers/vfio/Kconfig | 1 + drivers/vfio/vfio.c | 22 ++++++++++++++++++++-- include/linux/iommufd.h | 6 ++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/iommufd/vfio_compat.c b/drivers/iommu/iommufd/vfio_compat.c index e0e80fdb4ddfb..134e4ef493fa3 100644 --- a/drivers/iommu/iommufd/vfio_compat.c +++ b/drivers/iommu/iommufd/vfio_compat.c @@ -153,7 +153,7 @@ static int iommufd_vfio_unmap_dma(struct iommufd_ctx *ictx, unsigned int cmd, return rc; } -static int iommufd_vfio_check_extension(unsigned long type) +int iommufd_vfio_check_extension(unsigned long type) { switch (type) { case VFIO_TYPE1v2_IOMMU: @@ -205,6 +205,7 @@ static int iommufd_vfio_check_extension(unsigned long type) * review along side HW drivers implementing it. */ } +EXPORT_SYMBOL_GPL(iommufd_vfio_check_extension); static int iommufd_vfio_set_iommu(struct iommufd_ctx *ictx, unsigned long type) { diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index 6130d00252ed7..c440ee311bd35 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -2,6 +2,7 @@ menuconfig VFIO tristate "VFIO Non-Privileged userspace driver framework" select IOMMU_API + select IOMMUFD if MMU && (X86 || S390 || ARM || ARM64) select VFIO_IOMMU_TYPE1 if MMU && (X86 || S390 || ARM || ARM64) help VFIO provides a framework for secure userspace device drivers. diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 3b2e87df2e427..cf5f5a4f057e4 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -84,6 +84,7 @@ struct vfio_group { unsigned int dev_counter; struct kvm *kvm; struct blocking_notifier_head notifier; + void *iommufd; }; #ifdef CONFIG_VFIO_NOIOMMU @@ -1079,6 +1080,12 @@ static void __vfio_group_unset_container(struct vfio_group *group) struct vfio_container *container = group->container; struct vfio_iommu_driver *driver; + if (group->iommufd) { + vfio_group_unset_iommufd(group->iommufd, &group->device_list); + group->iommufd = NULL; + return; + } + down_write(&container->group_lock); driver = container->iommu_driver; @@ -1150,6 +1157,13 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd) if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) return -EPERM; + group->iommufd = vfio_group_set_iommufd(container_fd, + &group->device_list); + if (group->iommufd) { + atomic_inc(&group->container_users); + return ret; + } + f = fdget(container_fd); if (!f.file) return -EBADF; @@ -1210,7 +1224,7 @@ static int vfio_group_add_container_user(struct vfio_group *group) atomic_dec(&group->container_users); return -EPERM; } - if (!group->container->iommu_driver) { + if ((group->container && !group->container->iommu_driver) || !group->iommufd) { atomic_dec(&group->container_users); return -EINVAL; } @@ -1261,7 +1275,8 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf) int ret = 0; if (0 == atomic_read(&group->container_users) || - !group->container->iommu_driver) + (group->container && !group->container->iommu_driver) || + (!group->container && !group->iommufd)) return -EINVAL; if (group->type == VFIO_NO_IOMMU && !capable(CAP_SYS_RAWIO)) @@ -1775,6 +1790,9 @@ EXPORT_SYMBOL_GPL(vfio_external_user_iommu_id); long vfio_external_check_extension(struct vfio_group *group, unsigned long arg) { + if (group->iommufd) + return iommufd_vfio_check_extension(arg); + return vfio_ioctl_check_extension(group->container, arg); } EXPORT_SYMBOL_GPL(vfio_external_check_extension); diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h index baf81da08fdb9..8899db02110e2 100644 --- a/include/linux/iommufd.h +++ b/include/linux/iommufd.h @@ -31,6 +31,7 @@ void iommufd_device_detach(struct iommufd_device *idev); struct iommufd_ctx *vfio_group_set_iommufd(int fd, struct list_head *device_list); void vfio_group_unset_iommufd(void *iommufd, struct list_head *device_list); +int iommufd_vfio_check_extension(unsigned long type); #else /* !CONFIG_IOMMUFD */ static inline struct iommufd_device * iommufd_bind_pci_device(int fd, struct pci_dev *pdev, u32 *id) @@ -62,5 +63,10 @@ static inline void vfio_group_unset_iommufd(void *iommufd, struct list_head *device_list) { } + +static int iommufd_vfio_check_extension(unsigned long type) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_IOMMUFD */ #endif