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
This commit is contained in:
+10
-73
@@ -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);
|
||||
|
||||
+9
-64
@@ -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);
|
||||
|
||||
|
||||
+63
-2
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+5
-60
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user