diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-24 14:34:12 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-02-24 14:34:12 -0800 |
commit | 143c7bc6496c886ce5db2a2f9cec580494690170 (patch) | |
tree | 4d913577dcc79178eaea528cefb3e693c761be7f /drivers/vfio | |
parent | a13de74e476532e32efb06e96acae84c634f0159 (diff) | |
parent | 939204e4df962982cbc84acc26b29b421dd530a8 (diff) |
Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd
Pull iommufd updates from Jason Gunthorpe:
"Some polishing and small fixes for iommufd:
- Remove IOMMU_CAP_INTR_REMAP, instead rely on the interrupt
subsystem
- Use GFP_KERNEL_ACCOUNT inside the iommu_domains
- Support VFIO_NOIOMMU mode with iommufd
- Various typos
- A list corruption bug if HWPTs are used for attach"
* tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd:
iommufd: Do not add the same hwpt to the ioas->hwpt_list twice
iommufd: Make sure to zero vfio_iommu_type1_info before copying to user
vfio: Support VFIO_NOIOMMU with iommufd
iommufd: Add three missing structures in ucmd_buffer
selftests: iommu: Fix test_cmd_destroy_access() call in user_copy
iommu: Remove IOMMU_CAP_INTR_REMAP
irq/s390: Add arch_is_isolated_msi() for s390
iommu/x86: Replace IOMMU_CAP_INTR_REMAP with IRQ_DOMAIN_FLAG_ISOLATED_MSI
genirq/msi: Rename IRQ_DOMAIN_MSI_REMAP to IRQ_DOMAIN_ISOLATED_MSI
genirq/irqdomain: Remove unused irq_domain_check_msi_remap() code
iommufd: Convert to msi_device_has_isolated_msi()
vfio/type1: Convert to iommu_group_has_isolated_msi()
iommu: Add iommu_group_has_isolated_msi()
genirq/msi: Add msi_device_has_isolated_msi()
Diffstat (limited to 'drivers/vfio')
-rw-r--r-- | drivers/vfio/Kconfig | 2 | ||||
-rw-r--r-- | drivers/vfio/container.c | 7 | ||||
-rw-r--r-- | drivers/vfio/group.c | 7 | ||||
-rw-r--r-- | drivers/vfio/iommufd.c | 19 | ||||
-rw-r--r-- | drivers/vfio/vfio.h | 8 | ||||
-rw-r--r-- | drivers/vfio/vfio_iommu_type1.c | 16 | ||||
-rw-r--r-- | drivers/vfio/vfio_main.c | 7 |
7 files changed, 41 insertions, 25 deletions
diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig index a8f544629467..89e06c981e43 100644 --- a/drivers/vfio/Kconfig +++ b/drivers/vfio/Kconfig @@ -32,6 +32,7 @@ config VFIO_IOMMU_SPAPR_TCE tristate depends on SPAPR_TCE_IOMMU default VFIO +endif config VFIO_NOIOMMU bool "VFIO No-IOMMU support" @@ -46,7 +47,6 @@ config VFIO_NOIOMMU this mode since there is no IOMMU to provide DMA translation. If you don't know what to do here, say N. -endif config VFIO_VIRQFD bool diff --git a/drivers/vfio/container.c b/drivers/vfio/container.c index b7a9560ab25e..89f10becf962 100644 --- a/drivers/vfio/container.c +++ b/drivers/vfio/container.c @@ -29,13 +29,6 @@ static struct vfio { struct mutex iommu_drivers_lock; } vfio; -#ifdef CONFIG_VFIO_NOIOMMU -bool vfio_noiommu __read_mostly; -module_param_named(enable_unsafe_noiommu_mode, - vfio_noiommu, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel. If you do not know what this is for, step away. (default: false)"); -#endif - static void *vfio_noiommu_open(unsigned long arg) { if (arg != VFIO_NOIOMMU_IOMMU) diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c index bb24b2f0271e..e166ad7ce6e7 100644 --- a/drivers/vfio/group.c +++ b/drivers/vfio/group.c @@ -133,9 +133,12 @@ static int vfio_group_ioctl_set_container(struct vfio_group *group, iommufd = iommufd_ctx_from_file(f.file); if (!IS_ERR(iommufd)) { - u32 ioas_id; + if (IS_ENABLED(CONFIG_VFIO_NOIOMMU) && + group->type == VFIO_NO_IOMMU) + ret = iommufd_vfio_compat_set_no_iommu(iommufd); + else + ret = iommufd_vfio_compat_ioas_create(iommufd); - ret = iommufd_vfio_compat_ioas_id(iommufd, &ioas_id); if (ret) { iommufd_ctx_put(group->iommufd); goto out_unlock; diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c index 4f82a6fa7c6c..db4efbd56042 100644 --- a/drivers/vfio/iommufd.c +++ b/drivers/vfio/iommufd.c @@ -18,6 +18,20 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx) lockdep_assert_held(&vdev->dev_set->lock); + if (vfio_device_is_noiommu(vdev)) { + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + + /* + * Require no compat ioas to be assigned to proceed. The basic + * statement is that the user cannot have done something that + * implies they expected translation to exist + */ + if (!iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id)) + return -EPERM; + return 0; + } + /* * If the driver doesn't provide this op then it means the device does * not do DMA at all. So nothing to do. @@ -29,7 +43,7 @@ int vfio_iommufd_bind(struct vfio_device *vdev, struct iommufd_ctx *ictx) if (ret) return ret; - ret = iommufd_vfio_compat_ioas_id(ictx, &ioas_id); + ret = iommufd_vfio_compat_ioas_get_id(ictx, &ioas_id); if (ret) goto err_unbind; ret = vdev->ops->attach_ioas(vdev, &ioas_id); @@ -52,6 +66,9 @@ void vfio_iommufd_unbind(struct vfio_device *vdev) { lockdep_assert_held(&vdev->dev_set->lock); + if (vfio_device_is_noiommu(vdev)) + return; + if (vdev->ops->unbind_iommufd) vdev->ops->unbind_iommufd(vdev); } diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h index f8219a438bfb..9e94abcf8ee1 100644 --- a/drivers/vfio/vfio.h +++ b/drivers/vfio/vfio.h @@ -10,10 +10,10 @@ #include <linux/device.h> #include <linux/cdev.h> #include <linux/module.h> +#include <linux/vfio.h> struct iommufd_ctx; struct iommu_group; -struct vfio_device; struct vfio_container; void vfio_device_put_registration(struct vfio_device *device); @@ -88,6 +88,12 @@ bool vfio_device_has_container(struct vfio_device *device); int __init vfio_group_init(void); void vfio_group_cleanup(void); +static inline bool vfio_device_is_noiommu(struct vfio_device *vdev) +{ + return IS_ENABLED(CONFIG_VFIO_NOIOMMU) && + vdev->group->type == VFIO_NO_IOMMU; +} + #if IS_ENABLED(CONFIG_VFIO_CONTAINER) /* events for the backend driver notify callback */ enum vfio_iommu_notify_type { diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 5600eb67ca30..a44ac3fe657c 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -37,7 +37,6 @@ #include <linux/vfio.h> #include <linux/workqueue.h> #include <linux/notifier.h> -#include <linux/irqdomain.h> #include "vfio.h" #define DRIVER_VERSION "0.2" @@ -2170,12 +2169,6 @@ static void vfio_iommu_iova_insert_copy(struct vfio_iommu *iommu, list_splice_tail(iova_copy, iova); } -/* Redundantly walks non-present capabilities to simplify caller */ -static int vfio_iommu_device_capable(struct device *dev, void *data) -{ - return device_iommu_capable(dev, (enum iommu_cap)data); -} - static int vfio_iommu_domain_alloc(struct device *dev, void *data) { struct iommu_domain **domain = data; @@ -2190,7 +2183,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, struct vfio_iommu *iommu = iommu_data; struct vfio_iommu_group *group; struct vfio_domain *domain, *d; - bool resv_msi, msi_remap; + bool resv_msi; phys_addr_t resv_msi_base = 0; struct iommu_domain_geometry *geo; LIST_HEAD(iova_copy); @@ -2288,11 +2281,8 @@ static int vfio_iommu_type1_attach_group(void *iommu_data, INIT_LIST_HEAD(&domain->group_list); list_add(&group->next, &domain->group_list); - msi_remap = irq_domain_check_msi_remap() || - iommu_group_for_each_dev(iommu_group, (void *)IOMMU_CAP_INTR_REMAP, - vfio_iommu_device_capable); - - if (!allow_unsafe_interrupts && !msi_remap) { + if (!allow_unsafe_interrupts && + !iommu_group_has_isolated_msi(iommu_group)) { pr_warn("%s: No interrupt remapping support. Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n", __func__); ret = -EPERM; diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c index 5177bb061b17..90541fc94988 100644 --- a/drivers/vfio/vfio_main.c +++ b/drivers/vfio/vfio_main.c @@ -45,6 +45,13 @@ static struct vfio { struct ida device_ida; } vfio; +#ifdef CONFIG_VFIO_NOIOMMU +bool vfio_noiommu __read_mostly; +module_param_named(enable_unsafe_noiommu_mode, + vfio_noiommu, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode. This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel. If you do not know what this is for, step away. (default: false)"); +#endif + static DEFINE_XARRAY(vfio_device_set_xa); int vfio_assign_device_set(struct vfio_device *device, void *set_id) |