summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-04-16 21:21:55 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-04-16 21:21:55 -0700
commit43cfbdda5af60ffc6272a7b8c5c37d1d0a181ca9 (patch)
tree31a383b5a33abead3f5115965d296a217d633c28
parent87fe97a184c000a3941e2b53671742993abb1ddc (diff)
parent8602018b1f17fbdaa5e5d79f4c8603ad20640c12 (diff)
Merge tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd
Pull iommufd updates from Jason Gunthorpe: "Several fixes: - Add missing static const - Correct type 1 emulation for VFIO_CHECK_EXTENSION when no-iommu is turned on - Fix selftest memory leak and syzkaller splat - Fix missed -EFAULT in fault reporting write() fops - Fix a race where map/unmap with the internal IOVA allocator can unmap things it should not" * tag 'for-linus-iommufd' of git://git.kernel.org/pub/scm/linux/kernel/git/jgg/iommufd: iommufd: Fix a race with concurrent allocation and unmap iommufd/selftest: Remove MOCK_IOMMUPT_AMDV1 format iommufd: Fix return value of iommufd_fault_fops_write() iommufd: update outdated comment for renamed iommufd_hw_pagetable_alloc() iommufd/selftest: Fix page leaks in mock_viommu_{init,destroy} iommufd: vfio compatibility extension check for noiommu mode iommufd: Constify struct dma_buf_attach_ops
-rw-r--r--drivers/iommu/iommufd/device.c2
-rw-r--r--drivers/iommu/iommufd/eventq.c5
-rw-r--r--drivers/iommu/iommufd/io_pagetable.c10
-rw-r--r--drivers/iommu/iommufd/iommufd_test.h1
-rw-r--r--drivers/iommu/iommufd/pages.c2
-rw-r--r--drivers/iommu/iommufd/selftest.c35
-rw-r--r--drivers/iommu/iommufd/vfio_compat.c2
7 files changed, 18 insertions, 39 deletions
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 92c5d5ef8d00..170a7005f0bc 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -866,7 +866,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, ioasid_t pasid,
{
/*
* iommufd_hw_pagetable_attach() is called by
- * iommufd_hw_pagetable_alloc() in immediate attachment mode, same as
+ * iommufd_hwpt_paging_alloc() in immediate attachment mode, same as
* iommufd_device_do_attach(). So if we are in this mode then we prefer
* to use the immediate_attach path as it supports drivers that can't
* directly allocate a domain.
diff --git a/drivers/iommu/iommufd/eventq.c b/drivers/iommu/iommufd/eventq.c
index f1e686b3a265..710eef0b6004 100644
--- a/drivers/iommu/iommufd/eventq.c
+++ b/drivers/iommu/iommufd/eventq.c
@@ -187,9 +187,10 @@ static ssize_t iommufd_fault_fops_write(struct file *filep, const char __user *b
mutex_lock(&fault->mutex);
while (count > done) {
- rc = copy_from_user(&response, buf + done, response_size);
- if (rc)
+ if (copy_from_user(&response, buf + done, response_size)) {
+ rc = -EFAULT;
break;
+ }
static_assert((int)IOMMUFD_PAGE_RESP_SUCCESS ==
(int)IOMMU_PAGE_RESP_SUCCESS);
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c
index ee003bb2f647..24d4917105d9 100644
--- a/drivers/iommu/iommufd/io_pagetable.c
+++ b/drivers/iommu/iommufd/io_pagetable.c
@@ -814,6 +814,16 @@ again:
unmapped_bytes += area_last - area_first + 1;
down_write(&iopt->iova_rwsem);
+
+ /*
+ * After releasing the iova_rwsem concurrent allocation could
+ * place new areas at IOVAs we have already unmapped. Keep
+ * moving the start of the search forward to ignore the area
+ * already unmapped.
+ */
+ if (area_last >= last)
+ break;
+ start = area_last + 1;
}
out_unlock_iova:
diff --git a/drivers/iommu/iommufd/iommufd_test.h b/drivers/iommu/iommufd/iommufd_test.h
index 73e73e1ec158..52b78cbcc920 100644
--- a/drivers/iommu/iommufd/iommufd_test.h
+++ b/drivers/iommu/iommufd/iommufd_test.h
@@ -36,7 +36,6 @@ enum {
enum {
MOCK_IOMMUPT_DEFAULT = 0,
MOCK_IOMMUPT_HUGE,
- MOCK_IOMMUPT_AMDV1,
};
/* These values are true for MOCK_IOMMUPT_DEFAULT */
diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index 8124c554f2cc..9bdb2945afe1 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -1450,7 +1450,7 @@ static void iopt_revoke_notify(struct dma_buf_attachment *attach)
pages->dmabuf.phys.len = 0;
}
-static struct dma_buf_attach_ops iopt_dmabuf_attach_revoke_ops = {
+static const struct dma_buf_attach_ops iopt_dmabuf_attach_revoke_ops = {
.allow_peer2peer = true,
.invalidate_mappings = iopt_revoke_notify,
};
diff --git a/drivers/iommu/iommufd/selftest.c b/drivers/iommu/iommufd/selftest.c
index 2a82cee7921b..af07c642a526 100644
--- a/drivers/iommu/iommufd/selftest.c
+++ b/drivers/iommu/iommufd/selftest.c
@@ -421,19 +421,6 @@ static const struct iommu_dirty_ops amdv1_mock_dirty_ops = {
.set_dirty_tracking = mock_domain_set_dirty_tracking,
};
-static const struct iommu_domain_ops amdv1_ops = {
- IOMMU_PT_DOMAIN_OPS(amdv1),
- .free = mock_domain_free,
- .attach_dev = mock_domain_nop_attach,
- .set_dev_pasid = mock_domain_set_dev_pasid_nop,
- .iotlb_sync = &mock_iotlb_sync,
-};
-
-static const struct iommu_dirty_ops amdv1_dirty_ops = {
- IOMMU_PT_DIRTY_OPS(amdv1),
- .set_dirty_tracking = mock_domain_set_dirty_tracking,
-};
-
static struct mock_iommu_domain *
mock_domain_alloc_pgtable(struct device *dev,
const struct iommu_hwpt_selftest *user_cfg, u32 flags)
@@ -477,24 +464,6 @@ mock_domain_alloc_pgtable(struct device *dev,
mock->domain.dirty_ops = &amdv1_mock_dirty_ops;
break;
}
-
- case MOCK_IOMMUPT_AMDV1: {
- struct pt_iommu_amdv1_cfg cfg = {};
-
- cfg.common.hw_max_vasz_lg2 = 64;
- cfg.common.hw_max_oasz_lg2 = 52;
- cfg.common.features = BIT(PT_FEAT_DYNAMIC_TOP) |
- BIT(PT_FEAT_AMDV1_ENCRYPT_TABLES) |
- BIT(PT_FEAT_AMDV1_FORCE_COHERENCE);
- cfg.starting_level = 2;
- mock->domain.ops = &amdv1_ops;
- rc = pt_iommu_amdv1_init(&mock->amdv1, &cfg, GFP_KERNEL);
- if (rc)
- goto err_free;
- if (flags & IOMMU_HWPT_ALLOC_DIRTY_TRACKING)
- mock->domain.dirty_ops = &amdv1_dirty_ops;
- break;
- }
default:
rc = -EOPNOTSUPP;
goto err_free;
@@ -636,7 +605,7 @@ static void mock_viommu_destroy(struct iommufd_viommu *viommu)
if (mock_viommu->mmap_offset)
iommufd_viommu_destroy_mmap(&mock_viommu->core,
mock_viommu->mmap_offset);
- free_page((unsigned long)mock_viommu->page);
+ free_pages((unsigned long)mock_viommu->page, 1);
mutex_destroy(&mock_viommu->queue_mutex);
/* iommufd core frees mock_viommu and viommu */
@@ -870,7 +839,7 @@ err_destroy_mmap:
iommufd_viommu_destroy_mmap(&mock_viommu->core,
mock_viommu->mmap_offset);
err_free_page:
- free_page((unsigned long)mock_viommu->page);
+ free_pages((unsigned long)mock_viommu->page, 1);
return rc;
}
diff --git a/drivers/iommu/iommufd/vfio_compat.c b/drivers/iommu/iommufd/vfio_compat.c
index a258ee2f4579..acb48cdd3b00 100644
--- a/drivers/iommu/iommufd/vfio_compat.c
+++ b/drivers/iommu/iommufd/vfio_compat.c
@@ -283,7 +283,7 @@ static int iommufd_vfio_check_extension(struct iommufd_ctx *ictx,
case VFIO_TYPE1_IOMMU:
case VFIO_TYPE1v2_IOMMU:
case VFIO_UNMAP_ALL:
- return 1;
+ return !ictx->no_iommu_mode;
case VFIO_NOIOMMU_IOMMU:
return IS_ENABLED(CONFIG_VFIO_NOIOMMU);