summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenzhong Duan <zhenzhong.duan@intel.com>2026-04-02 14:57:26 +0800
committerJoerg Roedel <joerg.roedel@amd.com>2026-04-02 09:26:05 +0200
commitae2fafc19e7bfcdd00920888468546f35286e715 (patch)
tree2d1bfcd04b3d221d1ace4a32ee87bb811bfb2af4
parent922e2598a40f1851620144b3997aeefe066bd4de (diff)
iommu/vt-d: Support dirty tracking on PASID
In order to support passthrough device with PASID capability in QEMU, e.g., DSA device, kernel needs to support attaching PASID to a domain. But attaching is not allowed if the domain is a second stage domain or nested domain with dirty tracking. The reason is kernel lacking support for dirty tracking on such domain attached to PASID. By adding dirty tracking on PASID, the check can be removed. Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com> Reviewed-by: Yi Liu <yi.l.liu@intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20260330101108.12594-4-zhenzhong.duan@intel.com Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r--drivers/iommu/intel/iommu.c12
-rw-r--r--drivers/iommu/intel/nested.c6
2 files changed, 10 insertions, 8 deletions
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 965e0330ec4b..26135ff3a289 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -3618,9 +3618,6 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
return -EOPNOTSUPP;
- if (domain->dirty_ops)
- return -EINVAL;
-
if (context_copied(iommu, info->bus, info->devfn))
return -EBUSY;
@@ -3688,6 +3685,7 @@ static void *intel_iommu_hw_info(struct device *dev, u32 *length,
static int domain_set_dirty_tracking(struct dmar_domain *domain, bool enable)
{
struct device_domain_info *info;
+ struct dev_pasid_info *dev_pasid;
int ret = 0;
lockdep_assert_held(&domain->lock);
@@ -3696,6 +3694,14 @@ static int domain_set_dirty_tracking(struct dmar_domain *domain, bool enable)
ret = intel_pasid_setup_dirty_tracking(info->iommu, info->dev,
IOMMU_NO_PASID, enable);
if (ret)
+ return ret;
+ }
+
+ list_for_each_entry(dev_pasid, &domain->dev_pasids, link_domain) {
+ info = dev_iommu_priv_get(dev_pasid->dev);
+ ret = intel_pasid_setup_dirty_tracking(info->iommu, info->dev,
+ dev_pasid->pasid, enable);
+ if (ret)
break;
}
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index 16c82ba47d30..2b979bec56ce 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -148,7 +148,6 @@ static int intel_nested_set_dev_pasid(struct iommu_domain *domain,
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
- struct iommu_domain *s2_domain = &dmar_domain->s2_domain->domain;
struct intel_iommu *iommu = info->iommu;
struct dev_pasid_info *dev_pasid;
int ret;
@@ -156,13 +155,10 @@ static int intel_nested_set_dev_pasid(struct iommu_domain *domain,
if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
return -EOPNOTSUPP;
- if (s2_domain->dirty_ops)
- return -EINVAL;
-
if (context_copied(iommu, info->bus, info->devfn))
return -EBUSY;
- ret = paging_domain_compatible(s2_domain, dev);
+ ret = paging_domain_compatible(&dmar_domain->s2_domain->domain, dev);
if (ret)
return ret;