From: Nicolin Chen <nicolinc@nvidia.com>
To: Will Deacon <will@kernel.org>, Jason Gunthorpe <jgg@nvidia.com>,
"Kevin Tian" <kevin.tian@intel.com>,
Lu Baolu <baolu.lu@linux.intel.com>
Cc: Robin Murphy <robin.murphy@arm.com>, <joro@8bytes.org>,
David Woodhouse <dwmw2@infradead.org>,
<linux-arm-kernel@lists.infradead.org>, <iommu@lists.linux.dev>,
<linux-kernel@vger.kernel.org>
Subject: [PATCH v3 2/5] iommufd: Iterate the cache invalidation array in the core
Date: Wed, 8 Jul 2026 12:44:17 -0700 [thread overview]
Message-ID: <c19b7508428e9f14d6997ff9f5a41d9d5ba6cde5.1783539724.git.nicolinc@nvidia.com> (raw)
In-Reply-To: <cover.1783539724.git.nicolinc@nvidia.com>
The cache invalidation ops, cache_invalidate_user() for a nested HWPT and
the cache_invalidate() for a vIOMMU, are each handed the full user request
array and report how many of the array entries they handled by setting the
array->entry_num. Every driver therefore implements its own loop over the
array, and a driver wanting to process that array in fixed-size chunks
(e.g. to issue commands out of a fixed-size on-stack buffer) has to carry
the loop and its sub-array bookkeeping all on its own.
Move the iteration into the iommufd core instead. Invoke the op with a
sub-array that starts at the first not-yet-handled entry, let it handle a
prefix of that sub-array and report the count via array->entry_num, then
advance the base pointer and re-invoke the op until the entire array has
been consumed or until the op returns an error along the way.
A driver that handles the entire window in one single call, as all of the
current drivers happen to do, finishes the loop in just one pass, so this
does not change any of the existing behavior. It instead lets each of the
drivers convert to bounded chunk processing on its own, done by each of the
subsequent changes.
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
include/linux/iommu.h | 6 ++++--
include/linux/iommufd.h | 2 ++
drivers/iommu/iommufd/hw_pagetable.c | 25 +++++++++++++++----------
3 files changed, 21 insertions(+), 12 deletions(-)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index d20aa6f6863ab..969758f87e445 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -773,8 +773,10 @@ struct iommu_ops {
* passes in the cache invalidation requests, in form
* of a driver data structure. The driver must update
* array->entry_num to report the number of handled
- * invalidation requests. The driver data structure
- * must be defined in include/uapi/linux/iommufd.h
+ * invalidation requests. A driver may handle fewer than
+ * the requested, in which case the core re-invokes the
+ * op for the remainder. The driver data structure must
+ * be defined in include/uapi/linux/iommufd.h
* @iova_to_phys: translate iova to physical address
* @enforce_cache_coherency: Prevent any kind of DMA from bypassing IOMMU_CACHE,
* including no-snoop TLPs on PCIe or other platform
diff --git a/include/linux/iommufd.h b/include/linux/iommufd.h
index 6e7efe83bc5d8..3087f5b2def84 100644
--- a/include/linux/iommufd.h
+++ b/include/linux/iommufd.h
@@ -154,6 +154,8 @@ struct iommufd_hw_queue {
* The @array passes in the cache invalidation requests, in
* form of a driver data structure. A driver must update the
* array->entry_num to report the number of handled requests.
+ * A driver may handle fewer than the requested entry_num, in
+ * which case the core re-invokes the op for the remainder.
* The data structure of the array entry must be defined in
* include/uapi/linux/iommufd.h
* @vdevice_size: Size of the driver-defined vDEVICE structure per this vIOMMU
diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index 623cc608ca0cd..644daf18849f4 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -501,6 +501,8 @@ int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd)
.entry_len = cmd->entry_len,
.entry_num = cmd->entry_num,
};
+ struct iommufd_hw_pagetable *hwpt = NULL;
+ struct iommufd_viommu *viommu = NULL;
struct iommufd_object *pt_obj;
u32 done_num = 0;
int rc;
@@ -527,31 +529,34 @@ int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd)
goto out;
}
if (pt_obj->type == IOMMUFD_OBJ_HWPT_NESTED) {
- struct iommufd_hw_pagetable *hwpt =
- container_of(pt_obj, struct iommufd_hw_pagetable, obj);
-
+ hwpt = container_of(pt_obj, struct iommufd_hw_pagetable, obj);
if (!hwpt->domain->ops ||
!hwpt->domain->ops->cache_invalidate_user) {
rc = -EOPNOTSUPP;
goto out_put_pt;
}
- rc = hwpt->domain->ops->cache_invalidate_user(hwpt->domain,
- &data_array);
} else if (pt_obj->type == IOMMUFD_OBJ_VIOMMU) {
- struct iommufd_viommu *viommu =
- container_of(pt_obj, struct iommufd_viommu, obj);
-
+ viommu = container_of(pt_obj, struct iommufd_viommu, obj);
if (!viommu->ops || !viommu->ops->cache_invalidate) {
rc = -EOPNOTSUPP;
goto out_put_pt;
}
- rc = viommu->ops->cache_invalidate(viommu, &data_array);
} else {
rc = -EINVAL;
goto out_put_pt;
}
- done_num = data_array.entry_num;
+ do {
+ if (viommu)
+ rc = viommu->ops->cache_invalidate(viommu, &data_array);
+ else
+ rc = hwpt->domain->ops->cache_invalidate_user(
+ hwpt->domain, &data_array);
+
+ done_num += data_array.entry_num;
+ data_array.uptr += data_array.entry_num * data_array.entry_len;
+ data_array.entry_num = cmd->entry_num - done_num;
+ } while (!rc && done_num != cmd->entry_num);
out_put_pt:
iommufd_put_object(ucmd->ictx, pt_obj);
--
2.43.0
next prev parent reply other threads:[~2026-07-08 19:45 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 19:44 [PATCH v3 0/5] iommufd: Iterate the cache invalidation array in the core Nicolin Chen
2026-07-08 19:44 ` [PATCH v3 1/5] iommu/arm-smmu-v3-iommufd: Reject unsupported bits in invalidation commands Nicolin Chen
2026-07-08 19:44 ` Nicolin Chen [this message]
2026-07-08 19:44 ` [PATCH v3 3/5] iommufd/selftest: Convert cache invalidation mocks to the core array loop Nicolin Chen
2026-07-08 19:44 ` [PATCH v3 4/5] iommu/arm-smmu-v3-iommufd: Convert cache invalidation " Nicolin Chen
2026-07-08 19:44 ` [PATCH v3 5/5] iommu/vt-d: Convert nested " Nicolin Chen
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=c19b7508428e9f14d6997ff9f5a41d9d5ba6cde5.1783539724.git.nicolinc@nvidia.com \
--to=nicolinc@nvidia.com \
--cc=baolu.lu@linux.intel.com \
--cc=dwmw2@infradead.org \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robin.murphy@arm.com \
--cc=will@kernel.org \
/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