AMD IOMMU: fix per-device IOMMU bypass when IR is enabled

When interrupt remapping (IR) is enabled, the device table entry
(DTE) for a given device will likely be initialized by
amdiommu_ir_find() during MSI configuration.  This function directly
calls amdiommu_get_ctx_for_dev() with id_mapped=false, which means that
any attempt to disable DMA remapping for the device (e.g. by setting
hw.busdma.pciD.B.S.F='bounce' in the loader tunables) will effectively
be ignored as the paging mode field in the DTE will not be set to
0 as required for identity mapping.  This will ultimately produce
an unusable device, because busdma will later observe the bounce
configuration through iommu_instantiate_ctx() and will employ the
non-translated 'bounce' busdma methods for the device, while the DTE
remains configured to enable translation.

Fix this by tweaking iommu_instantiate_ctx() to always return the
relevant per-device context object even if translation is disabled,
and adopt it in amdiommu_ir_find() instead of directly calling
amdiommu_get_ctx_for_dev().

Reviewed by:	kib
MFC after:	1 week
Differential Revision:	https://reviews.freebsd.org/D53209
This commit is contained in:
Jason A. Harmening
2025-10-19 20:53:08 -05:00
parent 2b5c62494d
commit 35170408a7
2 changed files with 9 additions and 7 deletions
+5 -2
View File
@@ -295,7 +295,6 @@ iommu_instantiate_ctx(struct iommu_unit *unit, device_t dev, bool rmrr)
} else {
iommu_free_ctx_locked(unit, ctx);
}
ctx = NULL;
}
return (ctx);
}
@@ -303,6 +302,7 @@ iommu_instantiate_ctx(struct iommu_unit *unit, device_t dev, bool rmrr)
struct iommu_ctx *
iommu_get_dev_ctx(device_t dev)
{
struct iommu_ctx *ctx;
struct iommu_unit *unit;
unit = iommu_find(dev, bootverbose);
@@ -313,7 +313,10 @@ iommu_get_dev_ctx(device_t dev)
return (NULL);
iommu_unit_pre_instantiate_ctx(unit);
return (iommu_instantiate_ctx(unit, dev, false));
ctx = iommu_instantiate_ctx(unit, dev, false);
if (ctx != NULL && (ctx->flags & IOMMU_CTX_DISABLED) != 0)
ctx = NULL;
return (ctx);
}
bus_dma_tag_t
+4 -5
View File
@@ -223,9 +223,9 @@ static struct amdiommu_ctx *
amdiommu_ir_find(device_t src, uint16_t *ridp, bool *is_iommu)
{
devclass_t src_class;
device_t requester;
struct amdiommu_unit *unit;
struct amdiommu_ctx *ctx;
struct iommu_ctx *ioctx;
uint32_t edte;
uint16_t rid;
uint8_t dte;
@@ -255,10 +255,9 @@ amdiommu_ir_find(device_t src, uint16_t *ridp, bool *is_iommu)
error = amdiommu_find_unit(src, &unit, &rid, &dte, &edte,
bootverbose);
if (error == 0) {
error = iommu_get_requester(src, &requester, &rid);
MPASS(error == 0);
ctx = amdiommu_get_ctx_for_dev(unit, src,
rid, 0, false /* XXXKIB */, false, dte, edte);
ioctx = iommu_instantiate_ctx(AMD2IOMMU(unit), src, false);
if (ioctx != NULL)
ctx = IOCTX2CTX(ioctx);
}
}
if (ridp != NULL)