git: 35170408a7b8 - main - AMD IOMMU: fix per-device IOMMU bypass when IR is enabled
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 20 Oct 2025 21:08:14 UTC
The branch main has been updated by jah:
URL: https://cgit.FreeBSD.org/src/commit/?id=35170408a7b86a879d7e2ffb5ddb70fe75951d89
commit 35170408a7b86a879d7e2ffb5ddb70fe75951d89
Author: Jason A. Harmening <jah@FreeBSD.org>
AuthorDate: 2025-10-20 01:53:08 +0000
Commit: Jason A. Harmening <jah@FreeBSD.org>
CommitDate: 2025-10-20 21:06:47 +0000
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
---
sys/dev/iommu/busdma_iommu.c | 7 +++++--
sys/x86/iommu/amd_intrmap.c | 9 ++++-----
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/sys/dev/iommu/busdma_iommu.c b/sys/dev/iommu/busdma_iommu.c
index 668ccf056463..82f73d469585 100644
--- a/sys/dev/iommu/busdma_iommu.c
+++ b/sys/dev/iommu/busdma_iommu.c
@@ -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
diff --git a/sys/x86/iommu/amd_intrmap.c b/sys/x86/iommu/amd_intrmap.c
index f8900fe0561f..cce4f57ca323 100644
--- a/sys/x86/iommu/amd_intrmap.c
+++ b/sys/x86/iommu/amd_intrmap.c
@@ -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)