Skip to content

Commit e758074

Browse files
committed
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
1 parent 3faad9e commit e758074

File tree

5 files changed

+90
-201
lines changed

5 files changed

+90
-201
lines changed

sys/amd64/vmm/vmm.c

Lines changed: 10 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
#include <sys/param.h>
3232
#include <sys/systm.h>
3333
#include <sys/kernel.h>
34-
#include <sys/module.h>
3534
#include <sys/sysctl.h>
3635
#include <sys/malloc.h>
3736
#include <sys/pcpu.h>
@@ -189,8 +188,6 @@ struct vm {
189188
#define VMM_CTR4(vcpu, format, p1, p2, p3, p4) \
190189
VCPU_CTR4((vcpu)->vm, (vcpu)->vcpuid, format, p1, p2, p3, p4)
191190

192-
static int vmm_initialized;
193-
194191
static void vmmops_panic(void);
195192

196193
static void
@@ -402,8 +399,8 @@ vm_exitinfo_cpuset(struct vcpu *vcpu)
402399
return (&vcpu->exitinfo_cpuset);
403400
}
404401

405-
static int
406-
vmm_init(void)
402+
int
403+
vmm_modinit(void)
407404
{
408405
if (!vmm_is_hw_supported())
409406
return (ENXIO);
@@ -431,70 +428,17 @@ vmm_init(void)
431428
return (vmmops_modinit(vmm_ipinum));
432429
}
433430

434-
static int
435-
vmm_handler(module_t mod, int what, void *arg)
431+
int
432+
vmm_modcleanup(void)
436433
{
437-
int error;
438-
439-
switch (what) {
440-
case MOD_LOAD:
441-
if (vmm_is_hw_supported()) {
442-
error = vmmdev_init();
443-
if (error != 0)
444-
break;
445-
error = vmm_init();
446-
if (error == 0)
447-
vmm_initialized = 1;
448-
else
449-
(void)vmmdev_cleanup();
450-
} else {
451-
error = ENXIO;
452-
}
453-
break;
454-
case MOD_UNLOAD:
455-
if (vmm_is_hw_supported()) {
456-
error = vmmdev_cleanup();
457-
if (error == 0) {
458-
vmm_suspend_p = NULL;
459-
vmm_resume_p = NULL;
460-
iommu_cleanup();
461-
if (vmm_ipinum != IPI_AST)
462-
lapic_ipi_free(vmm_ipinum);
463-
error = vmmops_modcleanup();
464-
/*
465-
* Something bad happened - prevent new
466-
* VMs from being created
467-
*/
468-
if (error)
469-
vmm_initialized = 0;
470-
}
471-
} else {
472-
error = 0;
473-
}
474-
break;
475-
default:
476-
error = 0;
477-
break;
478-
}
479-
return (error);
434+
vmm_suspend_p = NULL;
435+
vmm_resume_p = NULL;
436+
iommu_cleanup();
437+
if (vmm_ipinum != IPI_AST)
438+
lapic_ipi_free(vmm_ipinum);
439+
return (vmmops_modcleanup());
480440
}
481441

482-
static moduledata_t vmm_kmod = {
483-
"vmm",
484-
vmm_handler,
485-
NULL
486-
};
487-
488-
/*
489-
* vmm initialization has the following dependencies:
490-
*
491-
* - VT-x initialization requires smp_rendezvous() and therefore must happen
492-
* after SMP is fully functional (after SI_SUB_SMP).
493-
* - vmm device initialization requires an initialized devfs.
494-
*/
495-
DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
496-
MODULE_VERSION(vmm, 1);
497-
498442
static void
499443
vm_init(struct vm *vm, bool create)
500444
{
@@ -579,13 +523,6 @@ vm_create(const char *name, struct vm **retvm)
579523
struct vm *vm;
580524
int error;
581525

582-
/*
583-
* If vmm.ko could not be successfully initialized then don't attempt
584-
* to create the virtual machine.
585-
*/
586-
if (!vmm_initialized)
587-
return (ENXIO);
588-
589526
if (name == NULL || strnlen(name, VM_MAX_NAMELEN + 1) ==
590527
VM_MAX_NAMELEN + 1)
591528
return (EINVAL);

sys/arm64/vmm/vmm.c

Lines changed: 9 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include <sys/linker.h>
3434
#include <sys/lock.h>
3535
#include <sys/malloc.h>
36-
#include <sys/module.h>
3736
#include <sys/mutex.h>
3837
#include <sys/pcpu.h>
3938
#include <sys/proc.h>
@@ -138,8 +137,6 @@ struct vm {
138137
struct sx vcpus_init_lock; /* (o) */
139138
};
140139

141-
static bool vmm_initialized = false;
142-
143140
static int vm_handle_wfi(struct vcpu *vcpu,
144141
struct vm_exit *vme, bool *retu);
145142

@@ -323,11 +320,15 @@ vmm_unsupported_quirk(void)
323320
return (0);
324321
}
325322

326-
static int
327-
vmm_init(void)
323+
int
324+
vmm_modinit(void)
328325
{
329326
int error;
330327

328+
error = vmm_unsupported_quirk();
329+
if (error != 0)
330+
return (error);
331+
331332
vm_maxcpu = mp_ncpus;
332333
TUNABLE_INT_FETCH("hw.vmm.maxcpu", &vm_maxcpu);
333334

@@ -345,61 +346,12 @@ vmm_init(void)
345346
return (vmmops_modinit(0));
346347
}
347348

348-
static int
349-
vmm_handler(module_t mod, int what, void *arg)
349+
int
350+
vmm_modcleanup(void)
350351
{
351-
int error;
352-
353-
switch (what) {
354-
case MOD_LOAD:
355-
error = vmm_unsupported_quirk();
356-
if (error != 0)
357-
break;
358-
error = vmmdev_init();
359-
if (error != 0)
360-
break;
361-
error = vmm_init();
362-
if (error == 0)
363-
vmm_initialized = true;
364-
else
365-
(void)vmmdev_cleanup();
366-
break;
367-
case MOD_UNLOAD:
368-
error = vmmdev_cleanup();
369-
if (error == 0 && vmm_initialized) {
370-
error = vmmops_modcleanup();
371-
if (error) {
372-
/*
373-
* Something bad happened - prevent new
374-
* VMs from being created
375-
*/
376-
vmm_initialized = false;
377-
}
378-
}
379-
break;
380-
default:
381-
error = 0;
382-
break;
383-
}
384-
return (error);
352+
return (vmmops_modcleanup());
385353
}
386354

387-
static moduledata_t vmm_kmod = {
388-
"vmm",
389-
vmm_handler,
390-
NULL
391-
};
392-
393-
/*
394-
* vmm initialization has the following dependencies:
395-
*
396-
* - HYP initialization requires smp_rendezvous() and therefore must happen
397-
* after SMP is fully functional (after SI_SUB_SMP).
398-
* - vmm device initialization requires an initialized devfs.
399-
*/
400-
DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
401-
MODULE_VERSION(vmm, 1);
402-
403355
static void
404356
vm_init(struct vm *vm, bool create)
405357
{
@@ -485,13 +437,6 @@ vm_create(const char *name, struct vm **retvm)
485437
struct vm *vm;
486438
int error;
487439

488-
/*
489-
* If vmm.ko could not be successfully initialized then don't attempt
490-
* to create the virtual machine.
491-
*/
492-
if (!vmm_initialized)
493-
return (ENXIO);
494-
495440
if (name == NULL || strlen(name) >= VM_MAX_NAMELEN)
496441
return (EINVAL);
497442

sys/dev/vmm/vmm_dev.c

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <sys/kernel.h>
1515
#include <sys/malloc.h>
1616
#include <sys/mman.h>
17+
#include <sys/module.h>
1718
#include <sys/priv.h>
1819
#include <sys/proc.h>
1920
#include <sys/queue.h>
@@ -78,6 +79,8 @@ struct vmmdev_softc {
7879
int flags;
7980
};
8081

82+
static bool vmm_initialized = false;
83+
8184
static SLIST_HEAD(, vmmdev_softc) head;
8285

8386
static unsigned pr_allow_flag;
@@ -1021,6 +1024,9 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
10211024
char *buf;
10221025
int error, buflen;
10231026

1027+
if (!vmm_initialized)
1028+
return (ENXIO);
1029+
10241030
error = vmm_priv_check(req->td->td_ucred);
10251031
if (error != 0)
10261032
return (error);
@@ -1106,7 +1112,7 @@ static struct cdevsw vmmctlsw = {
11061112
.d_ioctl = vmmctl_ioctl,
11071113
};
11081114

1109-
int
1115+
static int
11101116
vmmdev_init(void)
11111117
{
11121118
int error;
@@ -1122,7 +1128,7 @@ vmmdev_init(void)
11221128
return (error);
11231129
}
11241130

1125-
int
1131+
static int
11261132
vmmdev_cleanup(void)
11271133
{
11281134
sx_xlock(&vmmdev_mtx);
@@ -1139,6 +1145,61 @@ vmmdev_cleanup(void)
11391145
return (0);
11401146
}
11411147

1148+
static int
1149+
vmm_handler(module_t mod, int what, void *arg)
1150+
{
1151+
int error;
1152+
1153+
switch (what) {
1154+
case MOD_LOAD:
1155+
error = vmmdev_init();
1156+
if (error != 0)
1157+
break;
1158+
error = vmm_modinit();
1159+
if (error == 0)
1160+
vmm_initialized = true;
1161+
else {
1162+
error = vmmdev_cleanup();
1163+
KASSERT(error == 0,
1164+
("%s: vmmdev_cleanup failed: %d", __func__, error));
1165+
}
1166+
break;
1167+
case MOD_UNLOAD:
1168+
error = vmmdev_cleanup();
1169+
if (error == 0 && vmm_initialized) {
1170+
error = vmm_modcleanup();
1171+
if (error) {
1172+
/*
1173+
* Something bad happened - prevent new
1174+
* VMs from being created
1175+
*/
1176+
vmm_initialized = false;
1177+
}
1178+
}
1179+
break;
1180+
default:
1181+
error = 0;
1182+
break;
1183+
}
1184+
return (error);
1185+
}
1186+
1187+
static moduledata_t vmm_kmod = {
1188+
"vmm",
1189+
vmm_handler,
1190+
NULL
1191+
};
1192+
1193+
/*
1194+
* vmm initialization has the following dependencies:
1195+
*
1196+
* - Initialization requires smp_rendezvous() and therefore must happen
1197+
* after SMP is fully functional (after SI_SUB_SMP).
1198+
* - vmm device initialization requires an initialized devfs.
1199+
*/
1200+
DECLARE_MODULE(vmm, vmm_kmod, MAX(SI_SUB_SMP, SI_SUB_DEVFS) + 1, SI_ORDER_ANY);
1201+
MODULE_VERSION(vmm, 1);
1202+
11421203
static int
11431204
devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len,
11441205
struct vm_object **objp, int nprot)

sys/dev/vmm/vmm_dev.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ struct thread;
1818
struct vm;
1919
struct vcpu;
2020

21-
int vmmdev_init(void);
22-
int vmmdev_cleanup(void);
21+
int vmm_modinit(void);
22+
int vmm_modcleanup(void);
23+
2324
int vmmdev_machdep_ioctl(struct vm *vm, struct vcpu *vcpu, u_long cmd,
2425
caddr_t data, int fflag, struct thread *td);
2526

0 commit comments

Comments
 (0)