* [PATCH] iommufd: Keep reserved IOVA ranges when a replace within one IOAS fails
@ 2026-09-29 3:14 Donggeun Yoo
0 siblings, 0 replies; only message in thread
From: Donggeun Yoo @ 2026-09-29 3:14 UTC (permalink / raw)
To: Jason Gunthorpe, Kevin Tian
Cc: Joerg Roedel, Will Deacon, Robin Murphy, Lu Baolu, Nicolin Chen,
iommu, linux-kernel, Donggeun Yoo
iommufd_device_do_replace() installs the group's reserved IOVA ranges in
the new hwpt's IOAS only when it differs from the old hwpt's IOAS. If the
replace fails in iommufd_device_do_replace() or
iommufd_group_do_replace_reserved_iova(), the error paths remove the
ranges from the new hwpt's IOAS whether or not the IOAS is shared
between the old and new hwpt, which removes the ranges that the old hwpt
still needs.
For example, on x86 with intel-iommu, after a replace within a shared
IOAS fails with -ENODEV, IOMMU_IOAS_IOVA_RANGES goes from
0x0-0xfedfffff
0xfef00000-0xffffffffffff
to
0x0-0xffffffffffff
and IOMMU_IOAS_MAP at 0xfee00000 succeeds.
Remove the ranges on failure only when the replace installed them, and
look up the old hwpt_paging before the replace so that the error path
can compare the IOAS.
Fixes: e88d4ec154a8 ("iommufd: Add iommufd_device_replace()")
Assisted-by: LLM
Signed-off-by: Donggeun Yoo <donggeunyoo.kernel@gmail.com>
---
Tested on 72d3fcf802c4 in QEMU (q35, intel-iommu) with vfio-pci devices.
The replace was made to fail by moving a device without PRI to a hwpt
allocated with IOMMU_HWPT_FAULT_ID_VALID, which intel-iommu rejects.
Checked whether the MSI window (0xfee00000-0xfeefffff) is still reserved
in the original IOAS after each case:
case unpatched patched
replace fails, shared IOAS no yes
replace fails twice, then succeeds no yes
replace fails, different IOAS yes yes
replace succeeds, shared IOAS yes yes
replace succeeds, different IOAS no (moved) no (moved)
tools/testing/selftests/iommu: identical per-test results on both kernels.
drivers/iommu/iommufd/device.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index a664c70a6fe73..1b0bdf57ac8ab 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -849,7 +849,8 @@ iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup,
return 0;
err_unresv:
- iommufd_group_remove_reserved_iova(igroup, hwpt_paging);
+ if (!old_hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas)
+ iommufd_group_remove_reserved_iova(igroup, hwpt_paging);
return rc;
}
@@ -889,6 +890,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
return NULL;
}
+ old_hwpt_paging = find_hwpt_paging(old_hwpt);
if (attach_resv) {
rc = iommufd_group_do_replace_reserved_iova(igroup, hwpt_paging);
if (rc)
@@ -899,7 +901,6 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
if (rc)
goto err_unresv;
- old_hwpt_paging = find_hwpt_paging(old_hwpt);
if (old_hwpt_paging && pasid == IOMMU_NO_PASID &&
(!hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas))
iommufd_group_remove_reserved_iova(igroup, old_hwpt_paging);
@@ -920,7 +921,8 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
/* Caller must destroy old_hwpt */
return old_hwpt;
err_unresv:
- if (attach_resv)
+ if (attach_resv &&
+ (!old_hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas))
iommufd_group_remove_reserved_iova(igroup, hwpt_paging);
err_unlock:
mutex_unlock(&igroup->lock);
--
2.53.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-09-29 3:14 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-29 3:14 [PATCH] iommufd: Keep reserved IOVA ranges when a replace within one IOAS fails Donggeun Yoo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®