Linux IOMMU Development
 help / color / mirror / Atom feed
From: Yi Liu <yi.l.liu@intel.com>
To: kevin.tian@intel.com, jgg@nvidia.com
Cc: joro@8bytes.org, baolu.lu@linux.intel.com, yi.l.liu@intel.com,
	iommu@lists.linux.dev, nicolinc@nvidia.com
Subject: [PATCH v9 02/21] iommu: Wrap pasid_array entry creation and setting
Date: Thu, 13 Mar 2025 05:35:13 -0700	[thread overview]
Message-ID: <20250313123532.103522-3-yi.l.liu@intel.com> (raw)
In-Reply-To: <20250313123532.103522-1-yi.l.liu@intel.com>

The IOMMU core does not mandate that callers must always provide a new
handle, allowing for the possibility of handle reuse. In the replace
path, the existing handle can be reused. To facilitate this, the core
must ensure that the pasid_array entry is made or updated under xa_lock
to prevent race conditions with callers of iommu_attach_handle_get().
Additionally, this operation should be performed only after the underlying
IOMMU driver has successfully set the domain. This precaution is necessary
to prevent forwarding PRIs to the new domain before it is fully prepared.

To streamline this process, the creation of the pasid_array entry and the
__xa_store() operation are encapsulated into a helper, which is invoked at
the end of the replace operation.

Signed-off-by: Yi Liu <yi.l.liu@intel.com>
---
 drivers/iommu/iommu.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 332ecb20c385..6a314122a9da 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2168,6 +2168,22 @@ static void iommu_pasid_array_entry_clear_handle(void *entry)
 		 xa_untag_pointer(entry))->domain = NULL;
 }
 
+/* Caller should have reserved memory for __xa_store() */
+static void iommu_group_pasid_store(struct iommu_group *group, ioasid_t pasid,
+				    struct iommu_domain *domain,
+				    struct iommu_attach_handle *handle)
+{
+	void *entry;
+
+	lockdep_assert_held(&group->mutex);
+
+	xa_lock(&group->pasid_array);
+	entry = iommu_make_pasid_array_entry(domain, handle);
+	WARN_ON(xa_is_err(__xa_store(&group->pasid_array, pasid, entry,
+				     GFP_KERNEL)));
+	xa_unlock(&group->pasid_array);
+}
+
 static int __iommu_attach_group(struct iommu_domain *domain,
 				struct iommu_group *group)
 {
@@ -3369,7 +3385,6 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
 	struct iommu_group *group = dev->iommu_group;
 	struct group_device *device;
 	const struct iommu_ops *ops;
-	void *entry;
 	int ret;
 
 	if (!group)
@@ -3393,8 +3408,6 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
 		}
 	}
 
-	entry = iommu_make_pasid_array_entry(domain, handle);
-
 	/*
 	 * Entry present is a failure case. Use xa_insert() instead of
 	 * xa_reserve().
@@ -3415,8 +3428,7 @@ int iommu_attach_device_pasid(struct iommu_domain *domain,
 	 * operation succeeds as we cannot tolerate PRIs becoming concurrently
 	 * queued and then failing attach.
 	 */
-	WARN_ON(xa_is_err(xa_store(&group->pasid_array,
-				   pasid, entry, GFP_KERNEL)));
+	iommu_group_pasid_store(group, pasid, domain, handle);
 
 out_unlock:
 	mutex_unlock(&group->mutex);
@@ -3527,14 +3539,12 @@ int iommu_attach_group_handle(struct iommu_domain *domain,
 			      struct iommu_group *group,
 			      struct iommu_attach_handle *handle)
 {
-	void *entry;
 	int ret;
 
 	if (!handle)
 		return -EINVAL;
 
 	mutex_lock(&group->mutex);
-	entry = iommu_make_pasid_array_entry(domain, handle);
 	ret = xa_insert(&group->pasid_array,
 			IOMMU_NO_PASID, XA_ZERO_ENTRY, GFP_KERNEL);
 	if (ret)
@@ -3552,8 +3562,7 @@ int iommu_attach_group_handle(struct iommu_domain *domain,
 	 * operation succeeds as we cannot tolerate PRIs becoming concurrently
 	 * queued and then failing attach.
 	 */
-	WARN_ON(xa_is_err(xa_store(&group->pasid_array,
-				   IOMMU_NO_PASID, entry, GFP_KERNEL)));
+	iommu_group_pasid_store(group, IOMMU_NO_PASID, domain, handle);
 
 out_unlock:
 	mutex_unlock(&group->mutex);
@@ -3600,14 +3609,12 @@ int iommu_replace_group_handle(struct iommu_group *group,
 			       struct iommu_domain *new_domain,
 			       struct iommu_attach_handle *handle)
 {
-	void *curr, *entry;
 	int ret;
 
 	if (!new_domain || !handle)
 		return -EINVAL;
 
 	mutex_lock(&group->mutex);
-	entry = iommu_make_pasid_array_entry(new_domain, handle);
 	ret = xa_reserve(&group->pasid_array, IOMMU_NO_PASID, GFP_KERNEL);
 	if (ret)
 		goto err_unlock;
@@ -3616,8 +3623,7 @@ int iommu_replace_group_handle(struct iommu_group *group,
 	if (ret)
 		goto err_release;
 
-	curr = xa_store(&group->pasid_array, IOMMU_NO_PASID, entry, GFP_KERNEL);
-	WARN_ON(xa_is_err(curr));
+	iommu_group_pasid_store(group, IOMMU_NO_PASID, new_domain, handle);
 
 	mutex_unlock(&group->mutex);
 
-- 
2.34.1


  parent reply	other threads:[~2025-03-13 12:35 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-13 12:35 [PATCH v9 00/21] iommufd support pasid attach/replace Yi Liu
2025-03-13 12:35 ` [PATCH v9 01/21] iommu: Clear handle->domain in detach Yi Liu
2025-03-18 11:46   ` Jason Gunthorpe
2025-03-18 13:30     ` Yi Liu
2025-03-13 12:35 ` Yi Liu [this message]
2025-03-18 12:04   ` [PATCH v9 02/21] iommu: Wrap pasid_array entry creation and setting Jason Gunthorpe
2025-03-18 14:40     ` Yi Liu
2025-03-13 12:35 ` [PATCH v9 03/21] iommu: Introduce a replace API for device pasid Yi Liu
2025-03-18 12:19   ` Jason Gunthorpe
2025-03-18 13:50     ` Baolu Lu
2025-03-18 13:57       ` Jason Gunthorpe
2025-03-13 12:35 ` [PATCH v9 04/21] iommufd: Pass @pasid through the device attach/replace path Yi Liu
2025-03-13 12:35 ` [PATCH v9 05/21] iommufd/device: Only add reserved_iova in non-pasid path Yi Liu
2025-03-18 19:22   ` Nicolin Chen
2025-03-13 12:35 ` [PATCH v9 06/21] iommufd/device: Replace idev->igroup with local variable Yi Liu
2025-03-18 12:25   ` Jason Gunthorpe
2025-03-18 19:24   ` Nicolin Chen
2025-03-13 12:35 ` [PATCH v9 07/21] iommufd/device: Check !igroup->hwpt in iommufd_device_attach_reserved_iova() Yi Liu
2025-03-18 12:27   ` Jason Gunthorpe
2025-03-13 12:35 ` [PATCH v9 08/21] iommufd/device: Lift iommufd_attach_handle handling to upper level helpers Yi Liu
2025-03-18 12:30   ` Jason Gunthorpe
2025-03-13 12:35 ` [PATCH v9 09/21] iommufd/device: Use iommufd_attach_handle track attachment Yi Liu
2025-03-13 12:35 ` [PATCH v9 10/21] iommufd/device: Replace device_list with device_array Yi Liu
2025-03-13 12:35 ` [PATCH v9 11/21] iommufd/device: Move attached device tracking to handle Yi Liu
2025-03-18 12:34   ` Jason Gunthorpe
2025-03-18 13:25     ` Yi Liu
2025-03-18 13:26       ` Jason Gunthorpe
2025-03-18 13:50         ` Yi Liu
2025-03-18 13:56           ` Jason Gunthorpe
2025-03-18 14:13             ` Yi Liu
2025-03-18 14:32               ` Jason Gunthorpe
2025-03-13 12:35 ` [PATCH v9 12/21] iommufd/device: Add pasid_attach array to track per-PASID attach Yi Liu
2025-03-17  7:07   ` Yi Liu
2025-03-13 12:35 ` [PATCH v9 13/21] iommufd: Enforce PASID-compatible domain in PASID path Yi Liu
2025-03-13 12:35 ` [PATCH v9 14/21] iommufd: Support pasid attach/replace Yi Liu
2025-03-18 12:35   ` Jason Gunthorpe
2025-03-13 12:35 ` [PATCH v9 15/21] iommufd: Enforce PASID-compatible domain for RID Yi Liu
2025-03-18 12:38   ` Jason Gunthorpe
2025-03-18 14:09     ` Yi Liu
2025-03-13 12:35 ` [PATCH v9 16/21] iommu/vt-d: Add IOMMU_HWPT_ALLOC_PASID support Yi Liu
2025-03-13 12:35 ` [PATCH v9 17/21] iommufd: Allow allocating PASID-compatible domain Yi Liu
2025-03-18 12:39   ` Jason Gunthorpe
2025-03-13 12:35 ` [PATCH v9 18/21] iommufd/selftest: Add set_dev_pasid in mock iommu Yi Liu
2025-03-13 12:35 ` [PATCH v9 19/21] iommufd/selftest: Add a helper to get test device Yi Liu
2025-03-13 12:35 ` [PATCH v9 20/21] iommufd/selftest: Add test ops to test pasid attach/detach Yi Liu
2025-03-13 12:35 ` [PATCH v9 21/21] iommufd/selftest: Add coverage for iommufd " Yi Liu
2025-03-18 12:41 ` [PATCH v9 00/21] iommufd support pasid attach/replace Jason Gunthorpe
2025-03-18 14:37   ` Yi Liu

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=20250313123532.103522-3-yi.l.liu@intel.com \
    --to=yi.l.liu@intel.com \
    --cc=baolu.lu@linux.intel.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@nvidia.com \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=nicolinc@nvidia.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