[PATCH 6/8] iommu/vt-d: Use intel_pasid_write() for second-stage setup

From: Lu Baolu

Date: Mon Mar 09 2026 - 02:10:31 EST


Refactor intel_pasid_setup_second_level() to utilize the
intel_pasid_write() helper. Similar to the first-stage setup, moves the
second stage setup logic to the entry_sync library by constructing the
target PASID entry in a local buffer and committing it via
intel_pasid_write().

Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
---
drivers/iommu/intel/iommu.c | 19 ++++---------------
drivers/iommu/intel/pasid.c | 26 ++++----------------------
2 files changed, 8 insertions(+), 37 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index db5e8dad50dc..b98020ac9de2 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1248,17 +1248,6 @@ static void domain_context_clear_one(struct device_domain_info *info, u8 bus, u8
__iommu_flush_cache(iommu, context, sizeof(*context));
}

-static int domain_setup_second_level(struct intel_iommu *iommu,
- struct dmar_domain *domain,
- struct device *dev, ioasid_t pasid,
- struct iommu_domain *old)
-{
- if (old)
- intel_pasid_tear_down_entry(iommu, dev, pasid, false);
-
- return intel_pasid_setup_second_level(iommu, domain, dev, pasid);
-}
-
static int domain_setup_passthrough(struct intel_iommu *iommu,
struct device *dev, ioasid_t pasid,
struct iommu_domain *old)
@@ -1323,8 +1312,8 @@ static int dmar_domain_attach_device(struct dmar_domain *domain,
ret = domain_setup_first_level(iommu, domain, dev,
IOMMU_NO_PASID, NULL);
else if (intel_domain_is_ss_paging(domain))
- ret = domain_setup_second_level(iommu, domain, dev,
- IOMMU_NO_PASID, NULL);
+ ret = intel_pasid_setup_second_level(iommu, domain,
+ dev, IOMMU_NO_PASID);
else if (WARN_ON(true))
ret = -EINVAL;

@@ -3634,8 +3623,8 @@ static int intel_iommu_set_dev_pasid(struct iommu_domain *domain,
ret = domain_setup_first_level(iommu, dmar_domain,
dev, pasid, old);
else if (intel_domain_is_ss_paging(dmar_domain))
- ret = domain_setup_second_level(iommu, dmar_domain,
- dev, pasid, old);
+ ret = intel_pasid_setup_second_level(iommu, dmar_domain,
+ dev, pasid);
else if (WARN_ON(true))
ret = -EINVAL;

diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index 8ea1ac8cbf5e..3084afb3d4a1 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -590,10 +590,7 @@ static void pasid_pte_config_second_level(struct intel_iommu *iommu,
{
struct pt_iommu_vtdss_hw_info pt_info;

- lockdep_assert_held(&iommu->lock);
-
pt_iommu_vtdss_hw_info(&domain->sspt, &pt_info);
- pasid_clear_entry(pte);
pasid_set_domain_id(pte, did);
pasid_set_slptr(pte, pt_info.ssptptr);
pasid_set_address_width(pte, pt_info.aw);
@@ -611,9 +608,10 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
struct dmar_domain *domain,
struct device *dev, u32 pasid)
{
- struct pasid_entry *pte;
+ struct pasid_entry new_pte = {0};
u16 did;

+ iommu_group_mutex_assert(dev);

/*
* If hardware advertises no support for second level
@@ -626,25 +624,9 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
}

did = domain_id_iommu(domain, iommu);
+ pasid_pte_config_second_level(iommu, &new_pte, domain, did);

- spin_lock(&iommu->lock);
- pte = intel_pasid_get_entry(dev, pasid);
- if (!pte) {
- spin_unlock(&iommu->lock);
- return -ENODEV;
- }
-
- if (pasid_pte_is_present(pte)) {
- spin_unlock(&iommu->lock);
- return -EBUSY;
- }
-
- pasid_pte_config_second_level(iommu, pte, domain, did);
- spin_unlock(&iommu->lock);
-
- pasid_flush_caches(iommu, pte, pasid, did);
-
- return 0;
+ return intel_pasid_write(iommu, dev, pasid, (u128 *)&new_pte);
}

/*
--
2.43.0