From: Jason Gunthorpe <jgg@nvidia.com>
To: "Alex Williamson" <alex@shazbot.org>,
"Christian König" <christian.koenig@amd.com>,
dri-devel@lists.freedesktop.org, iommu@lists.linux.dev,
"Joerg Roedel" <joro@8bytes.org>,
"Kevin Tian" <kevin.tian@intel.com>,
kvm@vger.kernel.org, linaro-mm-sig@lists.linaro.org,
linux-kselftest@vger.kernel.org, linux-media@vger.kernel.org,
"Robin Murphy" <robin.murphy@arm.com>,
"Shuah Khan" <shuah@kernel.org>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Will Deacon" <will@kernel.org>
Cc: Krishnakant Jaju <kjaju@nvidia.com>,
Leon Romanovsky <leon@kernel.org>, Matt Ochs <mochs@nvidia.com>,
Nicolin Chen <nicolinc@nvidia.com>,
patches@lists.linux.dev, Simona Vetter <simona.vetter@ffwll.ch>,
Vivek Kasireddy <vivek.kasireddy@intel.com>,
Xu Yilun <yilun.xu@linux.intel.com>
Subject: [PATCH 3/9] iommufd: Do not map/unmap revoked DMABUFs
Date: Fri, 7 Nov 2025 12:49:35 -0400 [thread overview]
Message-ID: <3-v1-af84a3ab44f5+f68-iommufd_buf_jgg@nvidia.com> (raw)
In-Reply-To: <0-v1-af84a3ab44f5+f68-iommufd_buf_jgg@nvidia.com>
Once a DMABUF is revoked the domain will be unmapped under the pages
mutex. Double unmapping will trigger a WARN, and mapping while revoked
will fail.
Check for revoked DMABUFs along all the map and unmap paths to resolve
this. Ensure that map/unmap is always done under the pages mutex so it is
synchronized with the revoke notifier.
If a revoke happens between allocating the iopt_pages and the population
to a domain then the population will succeed, and leave things unmapped as
though revoke had happened immediately after.
Currently there is no way to repopulate the domains. Userspace is expected
to know if it is going to do something that would trigger revoke (eg if it
is about to do a FLR) then it should go and remove the DMABUF mappings
before and put the back after. The revoke is only to protect the kernel
from mis-behaving userspace.
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
drivers/iommu/iommufd/io_pagetable.c | 11 +++++-
drivers/iommu/iommufd/io_pagetable.h | 8 +++++
drivers/iommu/iommufd/pages.c | 54 +++++++++++++++++-----------
3 files changed, 52 insertions(+), 21 deletions(-)
diff --git a/drivers/iommu/iommufd/io_pagetable.c b/drivers/iommu/iommufd/io_pagetable.c
index b3cf3825a88c7f..38c5fdc6c82128 100644
--- a/drivers/iommu/iommufd/io_pagetable.c
+++ b/drivers/iommu/iommufd/io_pagetable.c
@@ -970,9 +970,14 @@ static void iopt_unfill_domain(struct io_pagetable *iopt,
WARN_ON(!area->storage_domain);
if (area->storage_domain == domain)
area->storage_domain = storage_domain;
+ if (iopt_is_dmabuf(pages)) {
+ if (!iopt_dmabuf_revoked(pages))
+ iopt_area_unmap_domain(area, domain);
+ }
mutex_unlock(&pages->mutex);
- iopt_area_unmap_domain(area, domain);
+ if (!iopt_is_dmabuf(pages))
+ iopt_area_unmap_domain(area, domain);
}
return;
}
@@ -1261,6 +1266,10 @@ static int iopt_area_split(struct iopt_area *area, unsigned long iova)
if (!pages || area->prevent_access)
return -EBUSY;
+ /* Maintaining the domains_itree below is a bit complicated */
+ if (iopt_is_dmabuf(pages))
+ return -EOPNOTSUPP;
+
if (new_start & (alignment - 1) ||
iopt_area_start_byte(area, new_start) & (alignment - 1))
return -EINVAL;
diff --git a/drivers/iommu/iommufd/io_pagetable.h b/drivers/iommu/iommufd/io_pagetable.h
index 389e3c3c80f335..00fe06bf533d62 100644
--- a/drivers/iommu/iommufd/io_pagetable.h
+++ b/drivers/iommu/iommufd/io_pagetable.h
@@ -237,6 +237,14 @@ static inline bool iopt_is_dmabuf(struct iopt_pages *pages)
return pages->type == IOPT_ADDRESS_DMABUF;
}
+static inline bool iopt_dmabuf_revoked(struct iopt_pages *pages)
+{
+ lockdep_assert_held(&pages->mutex);
+ if (iopt_is_dmabuf(pages))
+ return pages->dmabuf.phys.len == 0;
+ return false;
+}
+
struct iopt_pages *iopt_alloc_user_pages(void __user *uptr,
unsigned long length, bool writable);
struct iopt_pages *iopt_alloc_file_pages(struct file *file, unsigned long start,
diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index 7bc4731501cc21..2c1a59ab1cc123 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -1650,6 +1650,9 @@ void iopt_area_unmap_domain(struct iopt_area *area, struct iommu_domain *domain)
void iopt_area_unfill_domain(struct iopt_area *area, struct iopt_pages *pages,
struct iommu_domain *domain)
{
+ if (iopt_dmabuf_revoked(pages))
+ return;
+
__iopt_area_unfill_domain(area, pages, domain,
iopt_area_last_index(area));
}
@@ -1670,6 +1673,9 @@ int iopt_area_fill_domain(struct iopt_area *area, struct iommu_domain *domain)
lockdep_assert_held(&area->pages->mutex);
+ if (iopt_dmabuf_revoked(area->pages))
+ return 0;
+
rc = pfn_reader_first(&pfns, area->pages, iopt_area_index(area),
iopt_area_last_index(area));
if (rc)
@@ -1729,33 +1735,38 @@ int iopt_area_fill_domains(struct iopt_area *area, struct iopt_pages *pages)
return 0;
mutex_lock(&pages->mutex);
- rc = pfn_reader_first(&pfns, pages, iopt_area_index(area),
- iopt_area_last_index(area));
- if (rc)
- goto out_unlock;
+ if (!iopt_dmabuf_revoked(pages)) {
+ rc = pfn_reader_first(&pfns, pages, iopt_area_index(area),
+ iopt_area_last_index(area));
+ if (rc)
+ goto out_unlock;
- while (!pfn_reader_done(&pfns)) {
- done_first_end_index = pfns.batch_end_index;
- done_all_end_index = pfns.batch_start_index;
- xa_for_each(&area->iopt->domains, index, domain) {
- rc = batch_to_domain(&pfns.batch, domain, area,
- pfns.batch_start_index);
+ while (!pfn_reader_done(&pfns)) {
+ done_first_end_index = pfns.batch_end_index;
+ done_all_end_index = pfns.batch_start_index;
+ xa_for_each(&area->iopt->domains, index, domain) {
+ rc = batch_to_domain(&pfns.batch, domain, area,
+ pfns.batch_start_index);
+ if (rc)
+ goto out_unmap;
+ }
+ done_all_end_index = done_first_end_index;
+
+ rc = pfn_reader_next(&pfns);
if (rc)
goto out_unmap;
}
- done_all_end_index = done_first_end_index;
-
- rc = pfn_reader_next(&pfns);
+ rc = pfn_reader_update_pinned(&pfns);
if (rc)
goto out_unmap;
+
+ pfn_reader_destroy(&pfns);
}
- rc = pfn_reader_update_pinned(&pfns);
- if (rc)
- goto out_unmap;
area->storage_domain = xa_load(&area->iopt->domains, 0);
interval_tree_insert(&area->pages_node, &pages->domains_itree);
- goto out_destroy;
+ mutex_unlock(&pages->mutex);
+ return 0;
out_unmap:
pfn_reader_release_pins(&pfns);
@@ -1782,7 +1793,6 @@ int iopt_area_fill_domains(struct iopt_area *area, struct iopt_pages *pages)
end_index);
}
}
-out_destroy:
pfn_reader_destroy(&pfns);
out_unlock:
mutex_unlock(&pages->mutex);
@@ -1809,11 +1819,15 @@ void iopt_area_unfill_domains(struct iopt_area *area, struct iopt_pages *pages)
if (!area->storage_domain)
goto out_unlock;
- xa_for_each(&iopt->domains, index, domain)
- if (domain != area->storage_domain)
+ xa_for_each(&iopt->domains, index, domain) {
+ if (domain == area->storage_domain)
+ continue;
+
+ if (!iopt_dmabuf_revoked(pages))
iopt_area_unmap_domain_range(
area, domain, iopt_area_index(area),
iopt_area_last_index(area));
+ }
if (IS_ENABLED(CONFIG_IOMMUFD_TEST))
WARN_ON(RB_EMPTY_NODE(&area->pages_node.rb));
--
2.43.0
next prev parent reply other threads:[~2025-11-07 16:49 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-07 16:49 [PATCH 0/9] Initial DMABUF support for iommufd Jason Gunthorpe
2025-11-07 16:49 ` [PATCH 1/9] vfio/pci: Add vfio_pci_dma_buf_iommufd_map() Jason Gunthorpe
2025-11-20 7:49 ` Tian, Kevin
2025-11-20 17:34 ` Nicolin Chen
2025-11-07 16:49 ` [PATCH 2/9] iommufd: Add DMABUF to iopt_pages Jason Gunthorpe
2025-11-07 18:02 ` Nicolin Chen
2025-11-20 7:55 ` Tian, Kevin
2025-11-21 14:27 ` Jason Gunthorpe
2025-11-07 16:49 ` Jason Gunthorpe [this message]
2025-11-07 18:30 ` [PATCH 3/9] iommufd: Do not map/unmap revoked DMABUFs Nicolin Chen
2025-11-20 7:56 ` Tian, Kevin
2025-11-07 16:49 ` [PATCH 4/9] iommufd: Allow a DMABUF to be revoked Jason Gunthorpe
2025-11-13 23:26 ` Nicolin Chen
2025-11-20 7:58 ` Tian, Kevin
2025-11-07 16:49 ` [PATCH 5/9] iommufd: Allow MMIO pages in a batch Jason Gunthorpe
2025-11-13 23:28 ` Nicolin Chen
2025-11-20 7:59 ` Tian, Kevin
2025-11-20 14:59 ` Jason Gunthorpe
2025-11-07 16:49 ` [PATCH 6/9] iommufd: Have pfn_reader process DMABUF iopt_pages Jason Gunthorpe
2025-11-13 23:39 ` Nicolin Chen
2025-11-18 19:38 ` Jason Gunthorpe
2025-11-20 8:04 ` Tian, Kevin
2025-11-21 0:47 ` Jason Gunthorpe
2025-11-21 14:33 ` Jason Gunthorpe
2025-11-07 16:49 ` [PATCH 7/9] iommufd: Have iopt_map_file_pages convert the fd to a file Jason Gunthorpe
2025-11-13 23:43 ` Nicolin Chen
2025-11-20 8:05 ` Tian, Kevin
2025-11-07 16:49 ` [PATCH 8/9] iommufd: Accept a DMABUF through IOMMU_IOAS_MAP_FILE Jason Gunthorpe
2025-11-14 0:05 ` Nicolin Chen
2025-11-18 19:44 ` Jason Gunthorpe
2025-11-18 19:57 ` Nicolin Chen
2025-11-20 8:06 ` Tian, Kevin
2025-11-07 16:49 ` [PATCH 9/9] iommufd/selftest: Add some tests for the dmabuf flow Jason Gunthorpe
2025-11-07 19:43 ` Nicolin Chen
2025-11-18 19:25 ` Jason Gunthorpe
2025-11-20 8:06 ` Tian, Kevin
2025-11-07 17:52 ` [PATCH 0/9] Initial DMABUF support for iommufd Nicolin Chen
2025-11-13 6:33 ` Shuai Xue
2025-11-13 7:34 ` Nicolin Chen
2025-11-13 11:32 ` Shuai Xue
2025-11-13 17:44 ` Nicolin Chen
2025-11-13 18:37 ` Alex Williamson
2025-11-17 15:50 ` Jason Gunthorpe
2025-11-18 5:37 ` Kasireddy, Vivek
2025-11-18 14:59 ` Jason Gunthorpe
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3-v1-af84a3ab44f5+f68-iommufd_buf_jgg@nvidia.com \
--to=jgg@nvidia.com \
--cc=alex@shazbot.org \
--cc=christian.koenig@amd.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=iommu@lists.linux.dev \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=kjaju@nvidia.com \
--cc=kvm@vger.kernel.org \
--cc=leon@kernel.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=mochs@nvidia.com \
--cc=nicolinc@nvidia.com \
--cc=patches@lists.linux.dev \
--cc=robin.murphy@arm.com \
--cc=shuah@kernel.org \
--cc=simona.vetter@ffwll.ch \
--cc=sumit.semwal@linaro.org \
--cc=vivek.kasireddy@intel.com \
--cc=will@kernel.org \
--cc=yilun.xu@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox