The branch main has been updated by markj:

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

commit e758074458df3b61773b7678ff47c4a835365d21
Author:     Mark Johnston <[email protected]>
AuthorDate: 2025-11-04 13:54:27 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2025-11-04 13:54:27 +0000

    vmm: Move the module load handler to vmm_dev.c
    
    Move the vmm_initialized check out of vm_create() and into the legacy
    sysctl handler.  If vmm_initialized is false, /dev/vmmctl will not be
    available and so cannot be used to create VMs.
    
    Introduce new MD vmm_modinit() and vmm_modcleanup() routines which
    handle MD (de)initialization.
    
    No functional change intended.
    
    Reviewed by:    corvink
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D53421
---
 sys/amd64/vmm/vmm.c   | 83 +++++++--------------------------------------------
 sys/arm64/vmm/vmm.c   | 73 ++++++--------------------------------------
 sys/dev/vmm/vmm_dev.c | 65 ++++++++++++++++++++++++++++++++++++++--
 sys/dev/vmm/vmm_dev.h |  5 ++--
 sys/riscv/vmm/vmm.c   | 65 ++++------------------------------------
 5 files changed, 90 insertions(+), 201 deletions(-)

diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 615a3c9867dd..627a5a2c5ece 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -31,7 +31,6 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
-#include <sys/module.h>
 #include <sys/sysctl.h>
 #include <sys/malloc.h>
 #include <sys/pcpu.h>
@@ -189,8 +188,6 @@ struct vm {
 #define        VMM_CTR4(vcpu, format, p1, p2, p3, p4)                          
\
        VCPU_CTR4((vcpu)->vm, (vcpu)->vcpuid, format, p1, p2, p3, p4)
 
-static int vmm_initialized;
-
 static void    vmmops_panic(void);
 
 static void
@@ -402,8 +399,8 @@ vm_exitinfo_cpuset(struct vcpu *vcpu)
        return (&vcpu->exitinfo_cpuset);
 }
 
-static int
-vmm_init(void)
+int
+vmm_modinit(void)
 {
        if (!vmm_is_hw_supported())
                return (ENXIO);
@@ -431,70 +428,17 @@ vmm_init(void)
        return (vmmops_modinit(vmm_ipinum));
 }
 
-static int
-vmm_handler(module_t mod, int what, void *arg)
+int
+vmm_modcleanup(void)
 {
-       int error;
-
-       switch (what) {
-       case MOD_LOAD:
-               if (vmm_is_hw_supported()) {
-                       error = vmmdev_init();
-                       if (error != 0)
-                               break;
-                       error = vmm_init();
-                       if (error == 0)
-                               vmm_initialized = 1;
-                       else
-                               (void)vmmdev_cleanup();
-               } else {
-                       error = ENXIO;
-               }
-               break;
-       case MOD_UNLOAD:
-               if (vmm_is_hw_supported()) {
-                       error = vmmdev_cleanup();
-                       if (error == 0) {
-                               vmm_suspend_p = NULL;
-                               vmm_resume_p = NULL;
-                               iommu_cleanup();
-                               if (vmm_ipinum != IPI_AST)
-                                       lapic_ipi_free(vmm_ipinum);
-                               error = vmmops_modcleanup();
-                               /*
-                                * Something bad happened - prevent new
-                                * VMs from being created
-                                */
-                               if (error)
-                                       vmm_initialized = 0;
-                       }
-               } else {
-                       error = 0;
-               }
-               break;
-       default:
-               error = 0;
-               break;
-       }
-       return (error);
+       vmm_suspend_p = NULL;
+       vmm_resume_p = NULL;
+       iommu_cleanup();
+       if (vmm_ipinum != IPI_AST)
+               lapic_ipi_free(vmm_ipinum);
+       return (vmmops_modcleanup());
 }
 
-static moduledata_t vmm_kmod = {
-       "vmm",
-       vmm_handler,
-       NULL
-};
-
-/*
- * vmm initialization has the following dependencies:
- *
- * - VT-x initialization requires smp_rendezvous() and therefore must happen
- *   after SMP is fully functional (after SI_SUB_SMP).
- * - vmm device initialization requires an initialized devfs.
- */
-DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
-MODULE_VERSION(vmm, 1);
-
 static void
 vm_init(struct vm *vm, bool create)
 {
@@ -579,13 +523,6 @@ vm_create(const char *name, struct vm **retvm)
        struct vm *vm;
        int error;
 
-       /*
-        * If vmm.ko could not be successfully initialized then don't attempt
-        * to create the virtual machine.
-        */
-       if (!vmm_initialized)
-               return (ENXIO);
-
        if (name == NULL || strnlen(name, VM_MAX_NAMELEN + 1) ==
            VM_MAX_NAMELEN + 1)
                return (EINVAL);
diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c
index e7b2b5d8c360..58f53b34b2cb 100644
--- a/sys/arm64/vmm/vmm.c
+++ b/sys/arm64/vmm/vmm.c
@@ -33,7 +33,6 @@
 #include <sys/linker.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/pcpu.h>
 #include <sys/proc.h>
@@ -138,8 +137,6 @@ struct vm {
        struct sx       vcpus_init_lock;        /* (o) */
 };
 
-static bool vmm_initialized = false;
-
 static int vm_handle_wfi(struct vcpu *vcpu,
                         struct vm_exit *vme, bool *retu);
 
@@ -323,11 +320,15 @@ vmm_unsupported_quirk(void)
        return (0);
 }
 
-static int
-vmm_init(void)
+int
+vmm_modinit(void)
 {
        int error;
 
+       error = vmm_unsupported_quirk();
+       if (error != 0)
+               return (error);
+
        vm_maxcpu = mp_ncpus;
        TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
 
@@ -345,61 +346,12 @@ vmm_init(void)
        return (vmmops_modinit(0));
 }
 
-static int
-vmm_handler(module_t mod, int what, void *arg)
+int
+vmm_modcleanup(void)
 {
-       int error;
-
-       switch (what) {
-       case MOD_LOAD:
-               error = vmm_unsupported_quirk();
-               if (error != 0)
-                       break;
-               error = vmmdev_init();
-               if (error != 0)
-                       break;
-               error = vmm_init();
-               if (error == 0)
-                       vmm_initialized = true;
-               else
-                       (void)vmmdev_cleanup();
-               break;
-       case MOD_UNLOAD:
-               error = vmmdev_cleanup();
-               if (error == 0 && vmm_initialized) {
-                       error = vmmops_modcleanup();
-                       if (error) {
-                               /*
-                                * Something bad happened - prevent new
-                                * VMs from being created
-                                */
-                               vmm_initialized = false;
-                       }
-               }
-               break;
-       default:
-               error = 0;
-               break;
-       }
-       return (error);
+       return (vmmops_modcleanup());
 }
 
-static moduledata_t vmm_kmod = {
-       "vmm",
-       vmm_handler,
-       NULL
-};
-
-/*
- * vmm initialization has the following dependencies:
- *
- * - HYP initialization requires smp_rendezvous() and therefore must happen
- *   after SMP is fully functional (after SI_SUB_SMP).
- * - vmm device initialization requires an initialized devfs.
- */
-DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
-MODULE_VERSION(vmm, 1);
-
 static void
 vm_init(struct vm *vm, bool create)
 {
@@ -485,13 +437,6 @@ vm_create(const char *name, struct vm **retvm)
        struct vm *vm;
        int error;
 
-       /*
-        * If vmm.ko could not be successfully initialized then don't attempt
-        * to create the virtual machine.
-        */
-       if (!vmm_initialized)
-               return (ENXIO);
-
        if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
                return (EINVAL);
 
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index bd20acac1d2d..08a53bb62a85 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -14,6 +14,7 @@
 #include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/mman.h>
+#include <sys/module.h>
 #include <sys/priv.h>
 #include <sys/proc.h>
 #include <sys/queue.h>
@@ -78,6 +79,8 @@ struct vmmdev_softc {
        int             flags;
 };
 
+static bool vmm_initialized = false;
+
 static SLIST_HEAD(, vmmdev_softc) head;
 
 static unsigned pr_allow_flag;
@@ -1021,6 +1024,9 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
        char *buf;
        int error, buflen;
 
+       if (!vmm_initialized)
+               return (ENXIO);
+
        error = vmm_priv_check(req->td->td_ucred);
        if (error != 0)
                return (error);
@@ -1106,7 +1112,7 @@ static struct cdevsw vmmctlsw = {
        .d_ioctl        = vmmctl_ioctl,
 };
 
-int
+static int
 vmmdev_init(void)
 {
        int error;
@@ -1122,7 +1128,7 @@ vmmdev_init(void)
        return (error);
 }
 
-int
+static int
 vmmdev_cleanup(void)
 {
        sx_xlock(&vmmdev_mtx);
@@ -1139,6 +1145,61 @@ vmmdev_cleanup(void)
        return (0);
 }
 
+static int
+vmm_handler(module_t mod, int what, void *arg)
+{
+       int error;
+
+       switch (what) {
+       case MOD_LOAD:
+               error = vmmdev_init();
+               if (error != 0)
+                       break;
+               error = vmm_modinit();
+               if (error == 0)
+                       vmm_initialized = true;
+               else {
+                       error = vmmdev_cleanup();
+                       KASSERT(error == 0,
+                           ("%s: vmmdev_cleanup failed: %d", __func__, error));
+               }
+               break;
+       case MOD_UNLOAD:
+               error = vmmdev_cleanup();
+               if (error == 0 && vmm_initialized) {
+                       error = vmm_modcleanup();
+                       if (error) {
+                               /*
+                                * Something bad happened - prevent new
+                                * VMs from being created
+                                */
+                               vmm_initialized = false;
+                       }
+               }
+               break;
+       default:
+               error = 0;
+               break;
+       }
+       return (error);
+}
+
+static moduledata_t vmm_kmod = {
+       "vmm",
+       vmm_handler,
+       NULL
+};
+
+/*
+ * vmm initialization has the following dependencies:
+ *
+ * - Initialization requires smp_rendezvous() and therefore must happen
+ *   after SMP is fully functional (after SI_SUB_SMP).
+ * - vmm device initialization requires an initialized devfs.
+ */
+DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
+MODULE_VERSION(vmm, 1);
+
 static int
 devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len,
     struct vm_object **objp, int nprot)
diff --git a/sys/dev/vmm/vmm_dev.h b/sys/dev/vmm/vmm_dev.h
index 2881a7063565..c691341d4350 100644
--- a/sys/dev/vmm/vmm_dev.h
+++ b/sys/dev/vmm/vmm_dev.h
@@ -18,8 +18,9 @@ struct thread;
 struct vm;
 struct vcpu;
 
-int    vmmdev_init(void);
-int    vmmdev_cleanup(void);
+int    vmm_modinit(void);
+int    vmm_modcleanup(void);
+
 int    vmmdev_machdep_ioctl(struct vm *vm, struct vcpu *vcpu, u_long cmd,
            caddr_t data, int fflag, struct thread *td);
 
diff --git a/sys/riscv/vmm/vmm.c b/sys/riscv/vmm/vmm.c
index a9eb9d144336..f2995b276072 100644
--- a/sys/riscv/vmm/vmm.c
+++ b/sys/riscv/vmm/vmm.c
@@ -38,7 +38,6 @@
 #include <sys/linker.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
-#include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/pcpu.h>
 #include <sys/proc.h>
@@ -133,8 +132,6 @@ struct vm {
        struct sx       vcpus_init_lock;        /* (o) */
 };
 
-static bool vmm_initialized = false;
-
 static MALLOC_DEFINE(M_VMM, "vmm", "vmm");
 
 /* statistics */
@@ -210,10 +207,9 @@ vm_exitinfo(struct vcpu *vcpu)
        return (&vcpu->exitinfo);
 }
 
-static int
-vmm_init(void)
+int
+vmm_modinit(void)
 {
-
        vm_maxcpu = mp_ncpus;
 
        TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
@@ -229,56 +225,12 @@ vmm_init(void)
        return (vmmops_modinit());
 }
 
-static int
-vmm_handler(module_t mod, int what, void *arg)
+int
+vmm_modcleanup(void)
 {
-       int error;
-
-       switch (what) {
-       case MOD_LOAD:
-               error = vmmdev_init();
-               if (error != 0)
-                       break;
-               error = vmm_init();
-               if (error == 0)
-                       vmm_initialized = true;
-               else
-                       (void)vmmdev_cleanup();
-               break;
-       case MOD_UNLOAD:
-               error = vmmdev_cleanup();
-               if (error == 0 && vmm_initialized) {
-                       error = vmmops_modcleanup();
-                       if (error) {
-                               /*
-                                * Something bad happened - prevent new
-                                * VMs from being created
-                                */
-                               vmm_initialized = false;
-                       }
-               }
-               break;
-       default:
-               error = 0;
-               break;
-       }
-       return (error);
+       return (vmmops_modcleanup());
 }
 
-static moduledata_t vmm_kmod = {
-       "vmm",
-       vmm_handler,
-       NULL
-};
-
-/*
- * vmm initialization has the following dependencies:
- *
- * - vmm device initialization requires an initialized devfs.
- */
-DECLARE_MODULE(vmm, vmm_kmod, SI_SUB_DEVFS + 1, SI_ORDER_ANY);
-MODULE_VERSION(vmm, 1);
-
 static void
 vm_init(struct vm *vm, bool create)
 {
@@ -359,13 +311,6 @@ vm_create(const char *name, struct vm **retvm)
        struct vm *vm;
        int error;
 
-       /*
-        * If vmm.ko could not be successfully initialized then don't attempt
-        * to create the virtual machine.
-        */
-       if (!vmm_initialized)
-               return (ENXIO);
-
        if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
                return (EINVAL);
 

Reply via email to