From: Lu Baolu <baolu.lu@linux.intel.com>
To: Joerg Roedel <joro@8bytes.org>, Will Deacon <will@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Jason Gunthorpe <jgg@ziepe.ca>, Kevin Tian <kevin.tian@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>,
Dave Jiang <dave.jiang@intel.com>, Vinod Koul <vkoul@kernel.org>,
Zhangfei Gao <zhangfei.gao@linaro.org>,
Zhou Wang <wangzhou1@hisilicon.com>,
iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
Lu Baolu <baolu.lu@linux.intel.com>
Subject: [PATCH 07/12] iommu/vt-d: Put iopf enablement in domain attach path
Date: Fri, 14 Feb 2025 14:10:59 +0800 [thread overview]
Message-ID: <20250214061104.1959525-8-baolu.lu@linux.intel.com> (raw)
In-Reply-To: <20250214061104.1959525-1-baolu.lu@linux.intel.com>
Update iopf enablement in the driver to use the new method, similar to
the arm-smmu-v3 driver. Enable iopf support when any domain with an
iopf_handler is attached, and disable it when the domain is removed.
Place all the logic for controlling the PRI and iopf queue in the domain
set/remove/replace paths. Keep track of the number of domains set to the
device and PASIDs that require iopf. When the first domain requiring iopf
is attached, add the device to the iopf queue and enable PRI. When the
last domain is removed, remove it from the iopf queue and disable PRI.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.c | 42 ++++++++++++++++++++++++++++++-----
drivers/iommu/intel/iommu.h | 43 ++++++++++++++++++++++++++++++++++++
drivers/iommu/intel/nested.c | 16 ++++++++++++--
drivers/iommu/intel/svm.c | 9 ++++++--
4 files changed, 100 insertions(+), 10 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 1d564240c977..20d07f5fea85 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -3223,6 +3223,9 @@ void device_block_translation(struct device *dev)
static int blocking_domain_attach_dev(struct iommu_domain *domain,
struct device *dev)
{
+ struct device_domain_info *info = dev_iommu_priv_get(dev);
+
+ iopf_for_domain_remove(info->domain ? &info->domain->domain : NULL, dev);
device_block_translation(dev);
return 0;
}
@@ -3432,7 +3435,15 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
if (ret)
return ret;
- return dmar_domain_attach_device(to_dmar_domain(domain), dev);
+ ret = iopf_for_domain_set(domain, dev);
+ if (ret)
+ return ret;
+
+ ret = dmar_domain_attach_device(to_dmar_domain(domain), dev);
+ if (ret)
+ iopf_for_domain_remove(domain, dev);
+
+ return ret;
}
static int intel_iommu_map(struct iommu_domain *domain,
@@ -3878,6 +3889,8 @@ int intel_iommu_enable_iopf(struct device *dev)
if (!info->pri_enabled)
return -ENODEV;
+ /* pri_enabled is protected by the group mutex. */
+ iommu_group_mutex_assert(dev);
if (info->iopf_refcount) {
info->iopf_refcount++;
return 0;
@@ -3900,6 +3913,7 @@ void intel_iommu_disable_iopf(struct device *dev)
if (WARN_ON(!info->pri_enabled))
return;
+ iommu_group_mutex_assert(dev);
if (--info->iopf_refcount)
return;
@@ -3911,8 +3925,7 @@ intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat)
{
switch (feat) {
case IOMMU_DEV_FEAT_IOPF:
- return intel_iommu_enable_iopf(dev);
-
+ return 0;
default:
return -ENODEV;
}
@@ -3923,7 +3936,6 @@ intel_iommu_dev_disable_feat(struct device *dev, enum iommu_dev_features feat)
{
switch (feat) {
case IOMMU_DEV_FEAT_IOPF:
- intel_iommu_disable_iopf(dev);
return 0;
default:
@@ -4004,6 +4016,7 @@ static int blocking_domain_set_dev_pasid(struct iommu_domain *domain,
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
+ iopf_for_domain_remove(old, dev);
intel_pasid_tear_down_entry(info->iommu, dev, pasid, false);
domain_remove_dev_pasid(old, dev, pasid);
@@ -4077,6 +4090,10 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
if (IS_ERR(dev_pasid))
return PTR_ERR(dev_pasid);
+ ret = iopf_for_domain_replace(domain, old, dev);
+ if (ret)
+ goto out_remove_dev_pasid;
+
if (dmar_domain->use_first_level)
ret = domain_setup_first_level(iommu, dmar_domain,
dev, pasid, old);
@@ -4084,7 +4101,7 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
ret = domain_setup_second_level(iommu, dmar_domain,
dev, pasid, old);
if (ret)
- goto out_remove_dev_pasid;
+ goto out_unwind_iopf;
domain_remove_dev_pasid(old, dev, pasid);
@@ -4092,6 +4109,8 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
return 0;
+out_unwind_iopf:
+ iopf_for_domain_replace(old, domain, dev);
out_remove_dev_pasid:
domain_remove_dev_pasid(domain, dev, pasid);
return ret;
@@ -4309,6 +4328,11 @@ static int identity_domain_attach_dev(struct iommu_domain *domain, struct device
if (dev_is_real_dma_subdevice(dev))
return 0;
+ /*
+ * No PRI support with the global identity domain. No need to enable or
+ * disable PRI in this path as the iommu has been put in the blocking
+ * state.
+ */
if (sm_supported(iommu))
ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID);
else
@@ -4328,9 +4352,15 @@ static int identity_domain_set_dev_pasid(struct iommu_domain *domain,
if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
return -EOPNOTSUPP;
+ ret = iopf_for_domain_replace(domain, old, dev);
+ if (ret)
+ return ret;
+
ret = domain_setup_passthrough(iommu, dev, pasid, old);
- if (ret)
+ if (ret) {
+ iopf_for_domain_replace(old, domain, dev);
return ret;
+ }
domain_remove_dev_pasid(old, dev, pasid);
return 0;
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 754f6d7ade26..dfb0628fabf8 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1317,6 +1317,49 @@ void intel_iommu_drain_pasid_prq(struct device *dev, u32 pasid);
int intel_iommu_enable_iopf(struct device *dev);
void intel_iommu_disable_iopf(struct device *dev);
+static inline int iopf_for_domain_set(struct iommu_domain *domain,
+ struct device *dev)
+{
+ if (!domain || !domain->iopf_handler)
+ return 0;
+
+ return intel_iommu_enable_iopf(dev);
+}
+
+static inline void iopf_for_domain_remove(struct iommu_domain *domain,
+ struct device *dev)
+{
+ if (!domain || !domain->iopf_handler)
+ return;
+
+ intel_iommu_disable_iopf(dev);
+}
+
+static inline int iopf_for_domain_replace(struct iommu_domain *new,
+ struct iommu_domain *old,
+ struct device *dev)
+{
+ if (!old)
+ return iopf_for_domain_set(new, dev);
+
+ if (!new) {
+ iopf_for_domain_remove(old, dev);
+ return 0;
+ }
+
+ /*
+ * Replace a non-iopf-capable domain with an iopf-capable one requires
+ * to enable PRI on the device. On the contrary, disable it.
+ */
+ if (new->iopf_handler && !old->iopf_handler)
+ return intel_iommu_enable_iopf(dev);
+
+ if (!new->iopf_handler && old->iopf_handler)
+ intel_iommu_disable_iopf(dev);
+
+ return 0;
+}
+
#ifdef CONFIG_INTEL_IOMMU_SVM
void intel_svm_check(struct intel_iommu *iommu);
struct iommu_domain *intel_svm_domain_alloc(struct device *dev,
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index aba92c00b427..ad307248bcae 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -56,10 +56,14 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
if (ret)
goto detach_iommu;
+ ret = iopf_for_domain_set(domain, dev);
+ if (ret)
+ goto unassign_tag;
+
ret = intel_pasid_setup_nested(iommu, dev,
IOMMU_NO_PASID, dmar_domain);
if (ret)
- goto unassign_tag;
+ goto disable_iopf;
info->domain = dmar_domain;
spin_lock_irqsave(&dmar_domain->lock, flags);
@@ -67,6 +71,8 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
spin_unlock_irqrestore(&dmar_domain->lock, flags);
return 0;
+disable_iopf:
+ iopf_for_domain_remove(domain, dev);
unassign_tag:
cache_tag_unassign_domain(dmar_domain, dev, IOMMU_NO_PASID);
detach_iommu:
@@ -166,14 +172,20 @@ static int intel_nested_set_dev_pasid(struct iommu_domain *domain,
if (IS_ERR(dev_pasid))
return PTR_ERR(dev_pasid);
- ret = domain_setup_nested(iommu, dmar_domain, dev, pasid, old);
+ ret = iopf_for_domain_replace(domain, old, dev);
if (ret)
goto out_remove_dev_pasid;
+ ret = domain_setup_nested(iommu, dmar_domain, dev, pasid, old);
+ if (ret)
+ goto out_unwind_iopf;
+
domain_remove_dev_pasid(old, dev, pasid);
return 0;
+out_unwind_iopf:
+ iopf_for_domain_replace(old, domain, dev);
out_remove_dev_pasid:
domain_remove_dev_pasid(domain, dev, pasid);
return ret;
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index ba93123cb4eb..f3da596410b5 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -164,18 +164,23 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
if (IS_ERR(dev_pasid))
return PTR_ERR(dev_pasid);
+ ret = iopf_for_domain_replace(domain, old, dev);
+ if (ret)
+ goto out_remove_dev_pasid;
+
/* Setup the pasid table: */
sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
ret = __domain_setup_first_level(iommu, dev, pasid,
FLPT_DEFAULT_DID, mm->pgd,
sflags, old);
if (ret)
- goto out_remove_dev_pasid;
+ goto out_unwind_iopf;
domain_remove_dev_pasid(old, dev, pasid);
return 0;
-
+out_unwind_iopf:
+ iopf_for_domain_replace(old, domain, dev);
out_remove_dev_pasid:
domain_remove_dev_pasid(domain, dev, pasid);
return ret;
--
2.43.0
next prev parent reply other threads:[~2025-02-14 6:11 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-02-14 6:10 [PATCH 00/12] iommu: Remove IOMMU_DEV_FEAT_SVA/_IOPF Lu Baolu
2025-02-14 6:10 ` [PATCH 01/12] iommu/arm-smmu-v3: Put iopf enablement in the domain attach path Lu Baolu
2025-02-14 6:10 ` [PATCH 02/12] iommu/vt-d: Check if SVA is supported when attaching the SVA domain Lu Baolu
2025-02-14 6:10 ` [PATCH 03/12] iommu: Remove IOMMU_DEV_FEAT_SVA Lu Baolu
2025-02-14 6:10 ` [PATCH 04/12] iommu/vt-d: Move scalable mode ATS enablement to probe path Lu Baolu
2025-02-14 6:10 ` [PATCH 05/12] iommu/vt-d: Move PRI enablement in " Lu Baolu
2025-02-14 6:10 ` [PATCH 06/12] iommu/vt-d: Cleanup intel_context_flush_present() Lu Baolu
2025-02-14 6:10 ` Lu Baolu [this message]
2025-02-14 6:11 ` [PATCH 08/12] iommufd/selftest: Put iopf enablement in domain attach path Lu Baolu
2025-02-20 1:02 ` Jason Gunthorpe
2025-02-20 7:03 ` Baolu Lu
2025-02-20 18:00 ` Jason Gunthorpe
2025-02-21 1:31 ` Baolu Lu
2025-02-21 15:04 ` Jason Gunthorpe
2025-02-22 7:25 ` Baolu Lu
2025-02-24 19:23 ` Jason Gunthorpe
2025-02-14 6:11 ` [PATCH 09/12] dmaengine: idxd: Remove unnecessary IOMMU_DEV_FEAT_IOPF Lu Baolu
2025-02-14 11:22 ` Vinod Koul
2025-02-14 16:25 ` Dave Jiang
2025-02-18 22:55 ` Fenghua Yu
2025-02-19 6:02 ` Baolu Lu
2025-02-20 1:03 ` Jason Gunthorpe
2025-02-14 6:11 ` [PATCH 10/12] uacce: " Lu Baolu
2025-02-20 1:03 ` Jason Gunthorpe
2025-02-14 6:11 ` [PATCH 11/12] iommufd: " Lu Baolu
2025-02-14 7:06 ` Nicolin Chen
2025-02-15 6:32 ` Baolu Lu
2025-02-18 13:06 ` Jason Gunthorpe
2025-02-19 5:59 ` Baolu Lu
2025-02-20 1:04 ` Jason Gunthorpe
2025-02-14 6:11 ` [PATCH 12/12] iommu: Remove iommu_dev_enable/disable_feature() Lu Baolu
2025-02-20 1:04 ` Jason Gunthorpe
2025-02-14 8:43 ` [PATCH 00/12] iommu: Remove IOMMU_DEV_FEAT_SVA/_IOPF Zhangfei Gao
2025-02-14 9:24 ` Zhangfei Gao
2025-02-14 12:56 ` Jason Gunthorpe
2025-02-15 8:11 ` Zhangfei Gao
2025-02-15 10:06 ` Baolu Lu
2025-02-15 11:35 ` Zhangfei Gao
2025-02-18 2:57 ` Baolu Lu
2025-02-18 6:13 ` Zhangfei Gao
2025-02-18 13:57 ` Jason Gunthorpe
2025-02-18 15:25 ` Zhangfei Gao
2025-02-18 16:53 ` Jason Gunthorpe
2025-02-19 6:06 ` Baolu Lu
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=20250214061104.1959525-8-baolu.lu@linux.intel.com \
--to=baolu.lu@linux.intel.com \
--cc=dave.jiang@intel.com \
--cc=fenghua.yu@intel.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=robin.murphy@arm.com \
--cc=vkoul@kernel.org \
--cc=wangzhou1@hisilicon.com \
--cc=will@kernel.org \
--cc=zhangfei.gao@linaro.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