git: 42d54a8fd466 - main - vmm: Tear down the IOMMU before AMD-Vi detach

Kevin Bowling <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src,gmane.os.freebsd.current.scm
Message-ID <[email protected]>
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=42d54a8fd4665b97f56f91f450e310c61d4aee2c

commit 42d54a8fd4665b97f56f91f450e310c61d4aee2c
Author:     Kevin Bowling <[email protected]>
AuthorDate: 2026-08-06 11:06:00 +0000
Commit:     Kevin Bowling <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.