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/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/module.h>
|
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/pcpu.h>
|
#include <sys/pcpu.h>
|
||||||
@@ -189,8 +188,6 @@ struct vm {
|
|||||||
#define VMM_CTR4(vcpu, format, p1, p2, p3, p4) \
|
#define VMM_CTR4(vcpu, format, p1, p2, p3, p4) \
|
||||||
VCPU_CTR4((vcpu)->vm, (vcpu)->vcpuid, 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 vmmops_panic(void);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -402,8 +399,8 @@ vm_exitinfo_cpuset(struct vcpu *vcpu)
|
|||||||
return (&vcpu->exitinfo_cpuset);
|
return (&vcpu->exitinfo_cpuset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
vmm_init(void)
|
vmm_modinit(void)
|
||||||
{
|
{
|
||||||
if (!vmm_is_hw_supported())
|
if (!vmm_is_hw_supported())
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
@@ -431,70 +428,17 @@ vmm_init(void)
|
|||||||
return (vmmops_modinit(vmm_ipinum));
|
return (vmmops_modinit(vmm_ipinum));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
vmm_handler(module_t mod, int what, void *arg)
|
vmm_modcleanup(void)
|
||||||
{
|
{
|
||||||
int error;
|
vmm_suspend_p = NULL;
|
||||||
|
vmm_resume_p = NULL;
|
||||||
switch (what) {
|
iommu_cleanup();
|
||||||
case MOD_LOAD:
|
if (vmm_ipinum != IPI_AST)
|
||||||
if (vmm_is_hw_supported()) {
|
lapic_ipi_free(vmm_ipinum);
|
||||||
error = vmmdev_init();
|
return (vmmops_modcleanup());
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
static void
|
||||||
vm_init(struct vm *vm, bool create)
|
vm_init(struct vm *vm, bool create)
|
||||||
{
|
{
|
||||||
@@ -579,13 +523,6 @@ vm_create(const char *name, struct vm **retvm)
|
|||||||
struct vm *vm;
|
struct vm *vm;
|
||||||
int error;
|
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) ==
|
if (name == NULL || strnlen(name, VM_MAX_NAMELEN + 1) ==
|
||||||
VM_MAX_NAMELEN + 1)
|
VM_MAX_NAMELEN + 1)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|||||||
+9
-64
@@ -33,7 +33,6 @@
|
|||||||
#include <sys/linker.h>
|
#include <sys/linker.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/module.h>
|
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/pcpu.h>
|
#include <sys/pcpu.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
@@ -138,8 +137,6 @@ struct vm {
|
|||||||
struct sx vcpus_init_lock; /* (o) */
|
struct sx vcpus_init_lock; /* (o) */
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool vmm_initialized = false;
|
|
||||||
|
|
||||||
static int vm_handle_wfi(struct vcpu *vcpu,
|
static int vm_handle_wfi(struct vcpu *vcpu,
|
||||||
struct vm_exit *vme, bool *retu);
|
struct vm_exit *vme, bool *retu);
|
||||||
|
|
||||||
@@ -323,11 +320,15 @@ vmm_unsupported_quirk(void)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
vmm_init(void)
|
vmm_modinit(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
error = vmm_unsupported_quirk();
|
||||||
|
if (error != 0)
|
||||||
|
return (error);
|
||||||
|
|
||||||
vm_maxcpu = mp_ncpus;
|
vm_maxcpu = mp_ncpus;
|
||||||
TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
|
TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
|
||||||
|
|
||||||
@@ -345,61 +346,12 @@ vmm_init(void)
|
|||||||
return (vmmops_modinit(0));
|
return (vmmops_modinit(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
vmm_handler(module_t mod, int what, void *arg)
|
vmm_modcleanup(void)
|
||||||
{
|
{
|
||||||
int error;
|
return (vmmops_modcleanup());
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
static void
|
||||||
vm_init(struct vm *vm, bool create)
|
vm_init(struct vm *vm, bool create)
|
||||||
{
|
{
|
||||||
@@ -485,13 +437,6 @@ vm_create(const char *name, struct vm **retvm)
|
|||||||
struct vm *vm;
|
struct vm *vm;
|
||||||
int error;
|
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)
|
if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
|
|||||||
+63
-2
@@ -14,6 +14,7 @@
|
|||||||
#include <sys/kernel.h>
|
#include <sys/kernel.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/module.h>
|
||||||
#include <sys/priv.h>
|
#include <sys/priv.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
@@ -78,6 +79,8 @@ struct vmmdev_softc {
|
|||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bool vmm_initialized = false;
|
||||||
|
|
||||||
static SLIST_HEAD(, vmmdev_softc) head;
|
static SLIST_HEAD(, vmmdev_softc) head;
|
||||||
|
|
||||||
static unsigned pr_allow_flag;
|
static unsigned pr_allow_flag;
|
||||||
@@ -1021,6 +1024,9 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
|
|||||||
char *buf;
|
char *buf;
|
||||||
int error, buflen;
|
int error, buflen;
|
||||||
|
|
||||||
|
if (!vmm_initialized)
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
error = vmm_priv_check(req->td->td_ucred);
|
error = vmm_priv_check(req->td->td_ucred);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
@@ -1106,7 +1112,7 @@ static struct cdevsw vmmctlsw = {
|
|||||||
.d_ioctl = vmmctl_ioctl,
|
.d_ioctl = vmmctl_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
static int
|
||||||
vmmdev_init(void)
|
vmmdev_init(void)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
@@ -1122,7 +1128,7 @@ vmmdev_init(void)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
vmmdev_cleanup(void)
|
vmmdev_cleanup(void)
|
||||||
{
|
{
|
||||||
sx_xlock(&vmmdev_mtx);
|
sx_xlock(&vmmdev_mtx);
|
||||||
@@ -1139,6 +1145,61 @@ vmmdev_cleanup(void)
|
|||||||
return (0);
|
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
|
static int
|
||||||
devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len,
|
devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len,
|
||||||
struct vm_object **objp, int nprot)
|
struct vm_object **objp, int nprot)
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ struct thread;
|
|||||||
struct vm;
|
struct vm;
|
||||||
struct vcpu;
|
struct vcpu;
|
||||||
|
|
||||||
int vmmdev_init(void);
|
int vmm_modinit(void);
|
||||||
int vmmdev_cleanup(void);
|
int vmm_modcleanup(void);
|
||||||
|
|
||||||
int vmmdev_machdep_ioctl(struct vm *vm, struct vcpu *vcpu, u_long cmd,
|
int vmmdev_machdep_ioctl(struct vm *vm, struct vcpu *vcpu, u_long cmd,
|
||||||
caddr_t data, int fflag, struct thread *td);
|
caddr_t data, int fflag, struct thread *td);
|
||||||
|
|
||||||
|
|||||||
+5
-60
@@ -38,7 +38,6 @@
|
|||||||
#include <sys/linker.h>
|
#include <sys/linker.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/malloc.h>
|
#include <sys/malloc.h>
|
||||||
#include <sys/module.h>
|
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/pcpu.h>
|
#include <sys/pcpu.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
@@ -133,8 +132,6 @@ struct vm {
|
|||||||
struct sx vcpus_init_lock; /* (o) */
|
struct sx vcpus_init_lock; /* (o) */
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool vmm_initialized = false;
|
|
||||||
|
|
||||||
static MALLOC_DEFINE(M_VMM, "vmm", "vmm");
|
static MALLOC_DEFINE(M_VMM, "vmm", "vmm");
|
||||||
|
|
||||||
/* statistics */
|
/* statistics */
|
||||||
@@ -210,10 +207,9 @@ vm_exitinfo(struct vcpu *vcpu)
|
|||||||
return (&vcpu->exitinfo);
|
return (&vcpu->exitinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
vmm_init(void)
|
vmm_modinit(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
vm_maxcpu = mp_ncpus;
|
vm_maxcpu = mp_ncpus;
|
||||||
|
|
||||||
TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
|
TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
|
||||||
@@ -229,56 +225,12 @@ vmm_init(void)
|
|||||||
return (vmmops_modinit());
|
return (vmmops_modinit());
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
vmm_handler(module_t mod, int what, void *arg)
|
vmm_modcleanup(void)
|
||||||
{
|
{
|
||||||
int error;
|
return (vmmops_modcleanup());
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
static void
|
||||||
vm_init(struct vm *vm, bool create)
|
vm_init(struct vm *vm, bool create)
|
||||||
{
|
{
|
||||||
@@ -359,13 +311,6 @@ vm_create(const char *name, struct vm **retvm)
|
|||||||
struct vm *vm;
|
struct vm *vm;
|
||||||
int error;
|
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)
|
if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user