* [PATCH 1/7] iommu/vt-d: Avoid out-of-range shift in qi_desc_dev_iotlb_pasid()
2026-09-09 7:50 [PATCH 0/7] iommu/vt-d: Fix issues reported by Sashiko Lu Baolu
@ 2026-09-09 7:51 ` Lu Baolu
2026-09-09 7:51 ` [PATCH 2/7] iommu/vt-d: Do not ignore context table copy failures Lu Baolu
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Lu Baolu @ 2026-09-09 7:51 UTC (permalink / raw)
To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe, Kevin Tian
Cc: iommu, linux-kernel, Lu Baolu, stable, Sashiko
Callers request a full Device-TLB flush by passing MAX_AGAW_PFN_WIDTH
(64 - VTD_PAGE_SHIFT == 52) as @size_order. Two expressions in
qi_desc_dev_iotlb_pasid() are not prepared for a value that large:
unsigned long mask = 1UL << (VTD_PAGE_SHIFT + size_order - 1);
...
if (!IS_ALIGNED(addr, VTD_PAGE_SIZE << size_order))
The second evaluates to 1UL << 64, which is undefined on all
architectures. On x86_64 the shift count masks to zero, IS_ALIGNED(addr,
1) is trivially true, and the alignment sanity check silently degrades
into a no-op.
The first evaluates to 1UL << 63. That is well defined on 64-bit builds,
where unsigned long is 64 bits wide, but is undefined on 32-bit ones. In
practice x86 masks the shift count to five bits, so the expression yields
1UL << 31 and ~mask becomes 0x7fffffff. That value is zero-extended when
applied to the 64-bit descriptor, so
desc->qw1 &= ~mask;
clears qw1[63:32] as well as bit 31, collapsing the ADDR field that had
just been filled with ones. Reaching that requires a scalable-mode PASID
configuration on 32-bit x86, which is not a realistic deployment, but the
construct is wrong regardless.
Compute the mask with BIT_ULL() so that it is 64-bit on every
architecture, and skip the alignment check for a full flush, where it is
both meaningless and the source of the out-of-range shift.
Note that @size_order must not be clamped below 64 - VTD_PAGE_SHIFT. With
S set, hardware derives the invalidation range from the least significant
zero bit N of ADDR and matches bits [63:N+1] of the incoming address. For
size_order 52 the descriptor sets ADDR[63:12] and clears bit 63, making
N = 63 and the comparison range empty, so everything is invalidated.
Reducing @size_order to 51 would instead leave N = 62 and cause hardware
to compare address bit 63; since callers pass an address of 0, only the
lower half of the address space would be invalidated. Bound @size_order
at 64 - VTD_PAGE_SHIFT so that a bogus caller cannot reintroduce an
out-of-range shift, without altering the full-flush encoding.
The non-PASID variant qi_desc_dev_iotlb() already uses 1ULL and is
unaffected.
Fixes: f701c9f36bcb7 ("iommu/vt-d: Factor out invalidation descriptor composition")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260623060122.3796325-1-guanghuifeng%40linux.alibaba.com
Assisted-by: Claude:claude-opus-5
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.h | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/intel/iommu.h b/drivers/iommu/intel/iommu.h
index 23dbe6c24439..5b3d234ae265 100644
--- a/drivers/iommu/intel/iommu.h
+++ b/drivers/iommu/intel/iommu.h
@@ -1105,12 +1105,20 @@ static inline void qi_desc_dev_iotlb_pasid(u16 sid, u16 pfsid, u32 pasid,
unsigned int size_order,
struct qi_desc *desc)
{
- unsigned long mask = 1UL << (VTD_PAGE_SHIFT + size_order - 1);
-
desc->qw0 = QI_DEV_EIOTLB_PASID(pasid) | QI_DEV_EIOTLB_SID(sid) |
QI_DEV_EIOTLB_QDEP(qdep) | QI_DEIOTLB_TYPE |
QI_DEV_IOTLB_PFSID(pfsid);
+ /*
+ * The widest range the descriptor can express is a full flush, encoded
+ * by making bit 63 the least significant zero bit of ADDR, that is
+ * @size_order == 64 - VTD_PAGE_SHIFT. Bound @size_order there so that
+ * a caller passing something larger cannot produce an out-of-range
+ * shift below.
+ */
+ if (size_order > 64 - VTD_PAGE_SHIFT)
+ size_order = 64 - VTD_PAGE_SHIFT;
+
/*
* If S bit is 0, we only flush a single page. If S bit is set,
* The least significant zero bit indicates the invalidation address
@@ -1120,7 +1128,8 @@ static inline void qi_desc_dev_iotlb_pasid(u16 sid, u16 pfsid, u32 pasid,
* Max Invs Pending (MIP) is set to 0 for now until we have DIT in
* ECAP.
*/
- if (!IS_ALIGNED(addr, VTD_PAGE_SIZE << size_order))
+ if (size_order < 64 - VTD_PAGE_SHIFT &&
+ !IS_ALIGNED(addr, BIT_ULL(VTD_PAGE_SHIFT + size_order)))
pr_warn_ratelimited("Invalidate non-aligned address %llx, order %d\n",
addr, size_order);
@@ -1136,7 +1145,7 @@ static inline void qi_desc_dev_iotlb_pasid(u16 sid, u16 pfsid, u32 pasid,
desc->qw1 |= GENMASK_ULL(size_order + VTD_PAGE_SHIFT - 1,
VTD_PAGE_SHIFT);
/* Clear size_order bit to indicate size */
- desc->qw1 &= ~mask;
+ desc->qw1 &= ~BIT_ULL(VTD_PAGE_SHIFT + size_order - 1);
/* Set the S bit to indicate flushing more than 1 page */
desc->qw1 |= QI_DEV_EIOTLB_SIZE;
}
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 2/7] iommu/vt-d: Do not ignore context table copy failures
2026-09-09 7:50 [PATCH 0/7] iommu/vt-d: Fix issues reported by Sashiko Lu Baolu
2026-09-09 7:51 ` [PATCH 1/7] iommu/vt-d: Avoid out-of-range shift in qi_desc_dev_iotlb_pasid() Lu Baolu
@ 2026-09-09 7:51 ` Lu Baolu
2026-09-09 7:51 ` [PATCH 3/7] iommu/vt-d: Handle DID reservation errors when copying context tables Lu Baolu
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Lu Baolu @ 2026-09-09 7:51 UTC (permalink / raw)
To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe, Kevin Tian
Cc: iommu, linux-kernel, Lu Baolu
copy_translation_tables() currently logs copy_context_table() failures
but still returns success, so partial copy failures are silently ignored.
That means Intel IOMMU may run with only part of the old tables copied.
Then some old domain IDs may not be reserved, and later may be reused by
new domains. With stale hardware cache entries still around, this can
cause bad DMA translations, DMA faults, or domain aliasing.
Fix by aborting on the first context-table copy failure, freeing temporary
context-table pages, and returning an error so caller falls back to a
clean root table path.
Fixes: f93b4ac5929a ("iommu/vt-d: Use ida to manage domain id")
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.c | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 2e3b3ab216f8..38e2a670df9a 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1591,7 +1591,7 @@ static int copy_translation_tables(struct intel_iommu *iommu)
if (ret) {
pr_err("%s: Failed to copy context table for bus %d\n",
iommu->name, bus);
- continue;
+ goto err_free_ctxt_tbls;
}
}
@@ -1623,11 +1623,27 @@ static int copy_translation_tables(struct intel_iommu *iommu)
memunmap(old_rt);
return 0;
+err_free_ctxt_tbls:
+ /*
+ * None of these tables have been linked into iommu->root_entry yet,
+ * so they are unreachable and must be freed here.
+ */
+ for (bus = 0; bus < ctxt_table_entries; bus++)
+ iommu_free_pages(ctxt_tbls[bus]);
+ kfree(ctxt_tbls);
out_unmap:
memunmap(old_rt);
err_free_bitmap:
bitmap_free(iommu->copied_tables);
iommu->copied_tables = NULL;
+
+ /*
+ * Only reservations taken from the old context entries can be in the
+ * ida at this point; no domain has been allocated on this IOMMU yet.
+ * ida_destroy() empties it and leaves it ready for reuse.
+ */
+ ida_destroy(&iommu->domain_ida);
+
return ret;
}
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 3/7] iommu/vt-d: Handle DID reservation errors when copying context tables
2026-09-09 7:50 [PATCH 0/7] iommu/vt-d: Fix issues reported by Sashiko Lu Baolu
2026-09-09 7:51 ` [PATCH 1/7] iommu/vt-d: Avoid out-of-range shift in qi_desc_dev_iotlb_pasid() Lu Baolu
2026-09-09 7:51 ` [PATCH 2/7] iommu/vt-d: Do not ignore context table copy failures Lu Baolu
@ 2026-09-09 7:51 ` Lu Baolu
2026-09-09 7:51 ` [PATCH 4/7] iommu/vt-d: Reserve scalable-mode DIDs from PASID entries during copy Lu Baolu
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Lu Baolu @ 2026-09-09 7:51 UTC (permalink / raw)
To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe, Kevin Tian
Cc: iommu, linux-kernel, Lu Baolu
When kdump reuses old translation tables, all old domain IDs (DIDs) must
be reserved in the new kernel before new domains are created. Today
copy_context_table() ignores ida_alloc_range() return values, so a real
-ENOMEM can be missed and an ID may stay unreserved.
That can allow DID reuse while stale hardware cache entries still exist,
risking domain aliasing.
Fix this by moving DID reservation into a helper that:
- treats duplicate reservations (-ENOSPC) as expected success,
- skips out-of-range IDs as success,
- propagates real allocation failures (like -ENOMEM), and
- normalize successful return values.
On failure, unwind as in existing copy-allocation failure paths.
Fixes: f93b4ac5929a ("iommu/vt-d: Use ida to manage domain id")
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.c | 39 +++++++++++++++++++++++++++++++++----
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 38e2a670df9a..ab46058d76c5 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1452,12 +1452,39 @@ static void intel_iommu_init_qi(struct intel_iommu *iommu)
}
}
+/*
+ * Reserve a domain ID inherited from the previous kernel so that it is not
+ * handed out again while the copied translation structures are still live.
+ *
+ * Returns 0 when the ID is reserved, was already reserved, or cannot be
+ * re-assigned, and a negative errno for a genuine allocation failure.
+ */
+static int reserve_domain_id(struct intel_iommu *iommu, int did)
+{
+ int ret;
+
+ if (did < 0 || did >= iommu->max_domain_id)
+ return 0;
+
+ ret = ida_alloc_range(&iommu->domain_ida, did, did, GFP_KERNEL);
+ /*
+ * Devices sharing a domain share its ID, so the same ID is seen in
+ * more than one context entry; -ENOSPC merely reports that it is
+ * already reserved. On success the allocated ID is returned, which
+ * is not an error either.
+ */
+ if (ret == -ENOSPC || ret >= 0)
+ return 0;
+
+ return ret;
+}
+
static int copy_context_table(struct intel_iommu *iommu,
struct root_entry *old_re,
struct context_entry **tbl,
int bus, bool ext)
{
- int tbl_idx, tbl_slot = 0, idx, devfn, ret = 0, did;
+ int tbl_idx, tbl_slot = 0, idx, devfn, ret = 0;
struct context_entry *new_ce = NULL, ce;
struct context_entry *old_ce = NULL;
struct root_entry re;
@@ -1520,9 +1547,13 @@ static int copy_context_table(struct intel_iommu *iommu,
if (!context_present(&ce))
continue;
- did = context_domain_id(&ce);
- if (did >= 0 && did < iommu->max_domain_id)
- ida_alloc_range(&iommu->domain_ida, did, did, GFP_KERNEL);
+ ret = reserve_domain_id(iommu, context_domain_id(&ce));
+ if (ret) {
+ /* Not yet published through @tbl, so free it here. */
+ iommu_free_pages(new_ce);
+ new_ce = NULL;
+ goto out_unmap;
+ }
set_context_copied(iommu, bus, devfn);
new_ce[idx] = ce;
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 4/7] iommu/vt-d: Reserve scalable-mode DIDs from PASID entries during copy
2026-09-09 7:50 [PATCH 0/7] iommu/vt-d: Fix issues reported by Sashiko Lu Baolu
` (2 preceding siblings ...)
2026-09-09 7:51 ` [PATCH 3/7] iommu/vt-d: Handle DID reservation errors when copying context tables Lu Baolu
@ 2026-09-09 7:51 ` Lu Baolu
2026-09-09 7:51 ` [PATCH 5/7] iommu/vt-d: Use old domain parameter when attaching the blocking domain Lu Baolu
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Lu Baolu @ 2026-09-09 7:51 UTC (permalink / raw)
To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe, Kevin Tian
Cc: iommu, linux-kernel, Lu Baolu
copy_context_table() reserves old domain IDs (DIDs) from context entries.
That works for legacy mode, but not for scalable mode: scalable context
entries do not carry DID, so this path ends up reserving the wrong value
(often DID 0) repeatedly.
In scalable mode, real DIDs are stored in PASID table entries. If they
are not reserved during kdump table copy, new domains may reuse old DIDs
while stale PASID/IOTLB cache state still exists, causing translation
conflicts and DMA faults.
Fix this by walking PASID tables in scalable mode, and reserving DIDs
from present PASID entries. If PASID structures cannot be remapped, return
error so caller can fall back safely instead of continuing with an unsafe
DID space.
Fixes: 0c5f6c0d8201 ("iommu/vt-d: Fix kdump kernels boot failure with scalable mode")
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.c | 74 ++++++++++++++++++++++++++++++++++++-
1 file changed, 72 insertions(+), 2 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index ab46058d76c5..5553c57130f7 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -1479,6 +1479,70 @@ static int reserve_domain_id(struct intel_iommu *iommu, int did)
return ret;
}
+/*
+ * Reserve the domain IDs used by a scalable mode context entry copied from
+ * the previous kernel.
+ */
+static int copy_pasid_table_dids(struct intel_iommu *iommu, struct context_entry *ce)
+{
+ struct pasid_dir_entry *dir;
+ unsigned long dir_size;
+ phys_addr_t dir_phys;
+ int ret = 0;
+ int i, j;
+
+ dir_phys = ce->lo & VTD_PAGE_MASK;
+ if (!dir_phys)
+ return 0;
+
+ dir_size = get_pasid_dir_size(ce);
+ dir = memremap(dir_phys, dir_size * sizeof(*dir), MEMREMAP_WB);
+ if (!dir)
+ return -ENOMEM;
+
+ for (i = 0; i < dir_size; i++) {
+ struct pasid_entry *table;
+ phys_addr_t table_phys;
+
+ if (!pasid_pde_is_present(&dir[i]))
+ continue;
+
+ /*
+ * Do not use get_pasid_table_from_pde(); that returns a
+ * phys_to_virt() pointer, which is not valid for memory
+ * owned by the previous kernel.
+ */
+ table_phys = READ_ONCE(dir[i].val) & PDE_PFN_MASK;
+ if (!table_phys)
+ continue;
+
+ /* A PASID table is one page: PASID_TBL_ENTRIES * 64 bytes. */
+ table = memremap(table_phys, PAGE_SIZE, MEMREMAP_WB);
+ if (!table) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (j = 0; j < PASID_TBL_ENTRIES; j++) {
+ if (!pasid_pte_is_present(&table[j]))
+ continue;
+
+ ret = reserve_domain_id(iommu, pasid_get_domain_id(&table[j]));
+ if (ret) {
+ memunmap(table);
+ goto out;
+ }
+ }
+
+ memunmap(table);
+ }
+
+out:
+ memunmap(dir);
+
+ return ret;
+}
+
static int copy_context_table(struct intel_iommu *iommu,
struct root_entry *old_re,
struct context_entry **tbl,
@@ -1546,8 +1610,14 @@ static int copy_context_table(struct intel_iommu *iommu,
if (!context_present(&ce))
continue;
-
- ret = reserve_domain_id(iommu, context_domain_id(&ce));
+ /*
+ * The context entry only holds a domain ID in legacy mode.
+ * In scalable mode the IDs are in the PASID table entries.
+ */
+ if (ext)
+ ret = copy_pasid_table_dids(iommu, &ce);
+ else
+ ret = reserve_domain_id(iommu, context_domain_id(&ce));
if (ret) {
/* Not yet published through @tbl, so free it here. */
iommu_free_pages(new_ce);
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 5/7] iommu/vt-d: Use old domain parameter when attaching the blocking domain
2026-09-09 7:50 [PATCH 0/7] iommu/vt-d: Fix issues reported by Sashiko Lu Baolu
` (3 preceding siblings ...)
2026-09-09 7:51 ` [PATCH 4/7] iommu/vt-d: Reserve scalable-mode DIDs from PASID entries during copy Lu Baolu
@ 2026-09-09 7:51 ` Lu Baolu
2026-09-09 7:51 ` [PATCH 6/7] iommu/vt-d: Fix iopf refcount leak in nested attach Lu Baolu
2026-09-09 7:51 ` [PATCH 7/7] iommu/vt-d: Drop old iopf ref only after attach succeeds Lu Baolu
6 siblings, 0 replies; 8+ messages in thread
From: Lu Baolu @ 2026-09-09 7:51 UTC (permalink / raw)
To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe, Kevin Tian
Cc: iommu, linux-kernel, Lu Baolu
blocking_domain_attach_dev() drops the old domain’s iopf reference using
info->domain, but that value may already be cleared by
device_block_translation().
On attach failure fallback paths, this can cause the function to drop a
NULL-domain ref instead of @old, leaking the real old-domain reference.
Repeated leaks grow info->iopf_refcount, keep the device stuck on the
iopf queue, and can trigger WARN_ON(info->iopf_refcount) when PRI is
disabled.
Use the core-provided @old parameter directly. It always identifies the
correct domain to release and matches other attach paths.
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 5553c57130f7..99cf6716f602 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -2899,9 +2899,7 @@ static int blocking_domain_attach_dev(struct iommu_domain *domain,
struct device *dev,
struct iommu_domain *old)
{
- struct device_domain_info *info = dev_iommu_priv_get(dev);
-
- iopf_for_domain_remove(info->domain ? &info->domain->domain : NULL, dev);
+ iopf_for_domain_remove(old, dev);
device_block_translation(dev);
return 0;
}
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 6/7] iommu/vt-d: Fix iopf refcount leak in nested attach
2026-09-09 7:50 [PATCH 0/7] iommu/vt-d: Fix issues reported by Sashiko Lu Baolu
` (4 preceding siblings ...)
2026-09-09 7:51 ` [PATCH 5/7] iommu/vt-d: Use old domain parameter when attaching the blocking domain Lu Baolu
@ 2026-09-09 7:51 ` Lu Baolu
2026-09-09 7:51 ` [PATCH 7/7] iommu/vt-d: Drop old iopf ref only after attach succeeds Lu Baolu
6 siblings, 0 replies; 8+ messages in thread
From: Lu Baolu @ 2026-09-09 7:51 UTC (permalink / raw)
To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe, Kevin Tian
Cc: iommu, linux-kernel, Lu Baolu
intel_nested_attach_dev() takes an iopf reference for the new domain but
does not drop the possible reference from the old domain. This leaks
info->iopf_refcount, can keep the device permanently on the iopf queue,
and later triggers WARN_ON(info->iopf_refcount) when PRI is disabled.
Fix this by dropping the possible reference from the old domain after
the nested translation setup completes.
Fixes: 17fce9d2336d9 ("iommu/vt-d: Put iopf enablement in domain attach path")
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/nested.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/iommu/intel/nested.c b/drivers/iommu/intel/nested.c
index 2b979bec56ce..f84fc8b41fde 100644
--- a/drivers/iommu/intel/nested.c
+++ b/drivers/iommu/intel/nested.c
@@ -59,6 +59,8 @@ static int intel_nested_attach_dev(struct iommu_domain *domain,
if (ret)
goto disable_iopf;
+ iopf_for_domain_remove(old, dev);
+
info->domain = dmar_domain;
info->domain_attached = true;
spin_lock_irqsave(&dmar_domain->lock, flags);
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 7/7] iommu/vt-d: Drop old iopf ref only after attach succeeds
2026-09-09 7:50 [PATCH 0/7] iommu/vt-d: Fix issues reported by Sashiko Lu Baolu
` (5 preceding siblings ...)
2026-09-09 7:51 ` [PATCH 6/7] iommu/vt-d: Fix iopf refcount leak in nested attach Lu Baolu
@ 2026-09-09 7:51 ` Lu Baolu
6 siblings, 0 replies; 8+ messages in thread
From: Lu Baolu @ 2026-09-09 7:51 UTC (permalink / raw)
To: Joerg Roedel, Will Deacon, Robin Murphy, Jason Gunthorpe, Kevin Tian
Cc: iommu, linux-kernel, Lu Baolu
identity_domain_attach_dev() currently removes the old domain’s iopf
reference before programming pass-through. If pass-through setup fails,
attach fails but the old domain is still effectively attached — now
with its IOPF ref already dropped.
This can undercount info->iopf_refcount and may disable iopf queue
handling while the old domain can still issue page requests.
Fix it by removing the old domain’s iopf reference only after
pass-through setup succeeds, matching other attach paths.
Fixes: 236dd58fabd2 ("iommu/vt-d: Fix iopf_refcount leak on RID domain replacement")
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
---
drivers/iommu/intel/iommu.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 99cf6716f602..c1529be63650 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -3985,6 +3985,14 @@ static int identity_domain_attach_dev(struct iommu_domain *domain,
if (dev_is_real_dma_subdevice(dev))
return 0;
+ if (sm_supported(iommu))
+ ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID);
+ else
+ ret = device_setup_pass_through(dev);
+
+ if (ret)
+ return ret;
+
/*
* The identity domain has no iopf_handler, so no IOPF reference is
* taken for it. The reference held by the old domain must still be
@@ -3992,16 +4000,9 @@ static int identity_domain_attach_dev(struct iommu_domain *domain,
* not affect the IOPF reference count.
*/
iopf_for_domain_remove(old, dev);
+ info->domain_attached = true;
- if (sm_supported(iommu))
- ret = intel_pasid_setup_pass_through(iommu, dev, IOMMU_NO_PASID);
- else
- ret = device_setup_pass_through(dev);
-
- if (!ret)
- info->domain_attached = true;
-
- return ret;
+ return 0;
}
static int identity_domain_set_dev_pasid(struct iommu_domain *domain,
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread