|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v3] iommu/amd-vi: do not zero IOMMU MMIO region
Attempting to memset the whole IOMMU MMIO region to zero is dangerous to
say the least. We don't know what registers might be there, nor which
values might be safe for those registers. On a forthcoming platform doing
the zeroing of the MMIO region does put the IOMMU in a broken state, which
is not recoverable by the IOMMU initialization procedure in Xen.
Instead just zero the control register, which mimics the current behavior
with regards to how the control register is handled, and ensures the IOMU
setup is done with the unit disabled. This approach will need revisiting
in order to support Preboot DMA Protection.
Fold map_iommu_mmio_region() into its only caller, as the function body is
just an ioremap() call after the removal of the memset().
Fixes: 0700c962ac2d ("Add AMD IOMMU support into hypervisor")
Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
Changes since v2:
- Avoid the disable_iommu() dance.
- Expand commit message a bit.
Changes since v1:
- Zero the control register after calling disable_iommu().
- Print a warning message if the IOMMU is handed enabled to Xen from
firmware.
- Fix commit log grammar issues.
---
xen/drivers/passthrough/amd/iommu_init.c | 33 ++++++++++++++----------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/xen/drivers/passthrough/amd/iommu_init.c
b/xen/drivers/passthrough/amd/iommu_init.c
index d77dd8511288..e0c8925c33f7 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -42,18 +42,6 @@ static bool iommu_has_ht_flag(struct amd_iommu *iommu, u8
mask)
return iommu->ht_flags & mask;
}
-static int __init map_iommu_mmio_region(struct amd_iommu *iommu)
-{
- iommu->mmio_base = ioremap(iommu->mmio_base_phys,
- IOMMU_MMIO_REGION_LENGTH);
- if ( !iommu->mmio_base )
- return -ENOMEM;
-
- memset(iommu->mmio_base, 0, IOMMU_MMIO_REGION_LENGTH);
-
- return 0;
-}
-
static void __init unmap_iommu_mmio_region(struct amd_iommu *iommu)
{
if ( iommu->mmio_base )
@@ -1367,11 +1355,14 @@ static int __init amd_iommu_prepare_one(struct
amd_iommu *iommu)
{
int rc = alloc_ivrs_mappings(iommu->sbdf.seg);
- if ( !rc )
- rc = map_iommu_mmio_region(iommu);
if ( rc )
return rc;
+ iommu->mmio_base = ioremap(iommu->mmio_base_phys,
+ IOMMU_MMIO_REGION_LENGTH);
+ if ( !iommu->mmio_base )
+ return -ENOMEM;
+
get_iommu_features(iommu);
/*
@@ -1381,6 +1372,20 @@ static int __init amd_iommu_prepare_one(struct amd_iommu
*iommu)
if ( amd_iommu_max_paging_mode < amd_iommu_min_paging_mode )
return -ERANGE;
+ /*
+ * Check whether the IOMMU is already enabled and unconditionally disable
+ * it (zero the control register) ahead of Xen setup. Needs to be
+ * revisited to support Preboot DMA Protection.
+ */
+ iommu->ctrl.raw = readq(iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
+ if ( iommu->ctrl.iommu_en )
+ printk(XENLOG_WARNING
+ "AMD-Vi: IOMMU %pp enabled by firmware (ctrl %016lx)\n",
+ &iommu->sbdf, iommu->ctrl.raw);
+
+ iommu->ctrl.raw = 0;
+ writeq(0, iommu->mmio_base + IOMMU_CONTROL_MMIO_OFFSET);
+
return 0;
}
--
2.53.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |