git: 42d54a8fd466 - main - vmm: Tear down the IOMMU before AMD-Vi detach
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 08 Aug 2026 07:22:53 UTC
The branch main has been updated by kbowling:
URL: https://cgit.FreeBSD.org/src/commit/?id=42d54a8fd4665b97f56f91f450e310c61d4aee2c
commit 42d54a8fd4665b97f56f91f450e310c61d4aee2c
Author: Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-06 11:06:00 +0000
Commit: Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-08 07:22:48 +0000
vmm: Tear down the IOMMU before AMD-Vi detach
Register the vmm module handler after both the bundled device drivers
and SMP. On platforms without EARLY_AP_STARTUP, SI_SUB_SMP follows
SI_SUB_DRIVERS; using the later subsystem preserves the
smp_rendezvous() requirement.
The resulting reverse unload order performs IOMMU cleanup while every
IVHD softc remains valid. Refuse an independent IVHD detach while
translation state remains initialized.
MFC after: 2 weeks
---
sys/amd64/vmm/amd/ivrs_drv.c | 14 +++++++++-----
sys/amd64/vmm/io/iommu.c | 12 ++++++++++--
sys/amd64/vmm/io/iommu.h | 1 +
sys/dev/vmm/vmm_dev.c | 10 ++++++++--
4 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/sys/amd64/vmm/amd/ivrs_drv.c b/sys/amd64/vmm/amd/ivrs_drv.c
index 85171a5d51be..125c49839d9f 100644
--- a/sys/amd64/vmm/amd/ivrs_drv.c
+++ b/sys/amd64/vmm/amd/ivrs_drv.c
@@ -711,15 +711,19 @@ ivhd_detach(device_t dev)
{
struct amdvi_softc *softc;
+ /*
+ * amdvi_disable() and domain teardown require every IVHD softc. The
+ * vmm module handler normally performs that cleanup before the IVHD
+ * driver is unloaded. Refuse an out-of-order detach rather than leave
+ * enabled translation hardware referring to resources freed below.
+ */
+ if (iommu_is_initialized())
+ return (EBUSY);
+
softc = device_get_softc(dev);
amdvi_teardown_hw(softc);
free(softc->dev_cfg, M_DEVBUF);
-
- /*
- * XXX: delete the device.
- * don't allow detach, return EBUSY.
- */
return (0);
}
diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c
index 9fc612244699..71d3cb9ab883 100644
--- a/sys/amd64/vmm/io/iommu.c
+++ b/sys/amd64/vmm/io/iommu.c
@@ -194,7 +194,7 @@ iommu_init(void)
if (error)
return;
- iommu_avail = 1;
+ atomic_store_rel_int(&iommu_avail, 1);
/*
* Create a domain for the devices owned by the host
@@ -205,7 +205,7 @@ iommu_init(void)
printf("iommu_init: unable to create a host domain");
IOMMU_CLEANUP();
ops = NULL;
- iommu_avail = 0;
+ atomic_store_rel_int(&iommu_avail, 0);
return;
}
@@ -268,6 +268,7 @@ iommu_cleanup_int(bool iommu_disable)
IOMMU_DESTROY_DOMAIN(host_domain);
host_domain = NULL;
IOMMU_CLEANUP();
+ atomic_store_rel_int(&iommu_avail, 0);
}
void
@@ -276,6 +277,13 @@ iommu_cleanup(void)
iommu_cleanup_int(true);
}
+bool
+iommu_is_initialized(void)
+{
+
+ return (atomic_load_acq_int(&iommu_avail) != 0);
+}
+
void *
iommu_create_domain(vm_paddr_t maxaddr)
{
diff --git a/sys/amd64/vmm/io/iommu.h b/sys/amd64/vmm/io/iommu.h
index 5294a9d92a6b..3224b4884e9a 100644
--- a/sys/amd64/vmm/io/iommu.h
+++ b/sys/amd64/vmm/io/iommu.h
@@ -62,6 +62,7 @@ extern const struct iommu_ops iommu_ops_intel;
extern const struct iommu_ops iommu_ops_amd;
void iommu_cleanup(void);
+bool iommu_is_initialized(void);
void *iommu_host_domain(void);
void *iommu_create_domain(vm_paddr_t maxaddr);
void iommu_destroy_domain(void *dom);
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index a2775023838a..21cbd06ae2d0 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -1301,9 +1301,15 @@ static moduledata_t vmm_kmod = {
*
* - Initialization requires smp_rendezvous() and therefore must happen
* after SMP is fully functional (after SI_SUB_SMP).
- * - vmm device initialization requires an initialized devfs.
+ * - vmm device initialization requires an initialized devfs
+ * (SI_SUB_DRIVERS is after SI_SUB_DEVFS).
+ * - On amd64, vmm.ko also contains device drivers such as ppt and AMD-Vi/IVHD.
+ * Load this module handler after SI_SUB_DRIVERS so reverse-order unload runs
+ * iommu_cleanup() before those drivers detach. AMD-Vi disable still needs
+ * the IVHD softcs, and ivhd_detach() refuses while the IOMMU is initialized.
*/
-DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
+DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_DRIVERS, SI_SUB_SMP) + 1,
+ SI_ORDER_ANY);
MODULE_VERSION(vmm, 1);
static int