Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 08 Aug 2026 07:22:53 +0000
From:      Kevin Bowling <kbowling@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 42d54a8fd466 - main - vmm: Tear down the IOMMU before AMD-Vi detach
Message-ID:  <6a76d94d.428b0.788486bd@gitrepo.freebsd.org>

index | next in thread | raw e-mail

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


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a76d94d.428b0.788486bd>