diff options
author | Patrick Mooney <pmooney@pfmooney.com> | 2020-07-01 18:11:25 +0000 |
---|---|---|
committer | Patrick Mooney <pmooney@oxide.computer> | 2020-07-13 17:20:06 +0000 |
commit | b38fc3ed80ecaf16c46433e690e6f17495c5e179 (patch) | |
tree | 3a92c70f1ae1f0c7f3fd371b03aba54f992085b4 /usr/src | |
parent | 88628b1bc8bd723915686a0f84bd0461ec80e590 (diff) | |
download | illumos-joyent-b38fc3ed80ecaf16c46433e690e6f17495c5e179.tar.gz |
12922 bhyve vmm ops could have stronger guardrail
Reviewed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Mike Zeller <mike.zeller@joyent.com>
Approved by: Dan McDonald <danmcd@joyent.com>
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm.c | 146 |
1 files changed, 53 insertions, 93 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/vmm.c b/usr/src/uts/i86pc/io/vmm/vmm.c index a215e73be3..b42bd733d5 100644 --- a/usr/src/uts/i86pc/io/vmm/vmm.c +++ b/usr/src/uts/i86pc/io/vmm/vmm.c @@ -39,6 +39,7 @@ * * Copyright 2015 Pluribus Networks Inc. * Copyright 2018 Joyent, Inc. + * Copyright 2020 Oxide Computer Company */ #include <sys/cdefs.h> @@ -203,35 +204,56 @@ struct vm { static int vmm_initialized; -static struct vmm_ops *ops; -#define VMM_INIT(num) (ops != NULL ? (*ops->init)(num) : 0) -#define VMM_CLEANUP() (ops != NULL ? (*ops->cleanup)() : 0) -#define VMM_RESUME() (ops != NULL ? (*ops->resume)() : 0) -#define VMINIT(vm, pmap) (ops != NULL ? (*ops->vminit)(vm, pmap): NULL) +static void +nullop_panic(void) +{ + panic("null vmm operation call"); +} + +/* Do not allow use of an un-set `ops` to do anything but panic */ +static struct vmm_ops vmm_ops_null = { + .init = (vmm_init_func_t)nullop_panic, + .cleanup = (vmm_cleanup_func_t)nullop_panic, + .resume = (vmm_resume_func_t)nullop_panic, + .vminit = (vmi_init_func_t)nullop_panic, + .vmrun = (vmi_run_func_t)nullop_panic, + .vmcleanup = (vmi_cleanup_func_t)nullop_panic, + .vmgetreg = (vmi_get_register_t)nullop_panic, + .vmsetreg = (vmi_set_register_t)nullop_panic, + .vmgetdesc = (vmi_get_desc_t)nullop_panic, + .vmsetdesc = (vmi_set_desc_t)nullop_panic, + .vmgetcap = (vmi_get_cap_t)nullop_panic, + .vmsetcap = (vmi_set_cap_t)nullop_panic, + .vmspace_alloc = (vmi_vmspace_alloc)nullop_panic, + .vmspace_free = (vmi_vmspace_free)nullop_panic, + .vlapic_init = (vmi_vlapic_init)nullop_panic, + .vlapic_cleanup = (vmi_vlapic_cleanup)nullop_panic, + .vmsavectx = (vmi_savectx)nullop_panic, + .vmrestorectx = (vmi_restorectx)nullop_panic, +}; + +static struct vmm_ops *ops = &vmm_ops_null; + +#define VMM_INIT(num) ((*ops->init)(num)) +#define VMM_CLEANUP() ((*ops->cleanup)()) +#define VMM_RESUME() ((*ops->resume)()) + +#define VMINIT(vm, pmap) ((*ops->vminit)(vm, pmap)) #define VMRUN(vmi, vcpu, rip, pmap, evinfo) \ - (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, pmap, evinfo) : ENXIO) -#define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL) -#define VMSPACE_ALLOC(min, max) \ - (ops != NULL ? (*ops->vmspace_alloc)(min, max) : NULL) -#define VMSPACE_FREE(vmspace) \ - (ops != NULL ? (*ops->vmspace_free)(vmspace) : ENXIO) -#define VMGETREG(vmi, vcpu, num, retval) \ - (ops != NULL ? (*ops->vmgetreg)(vmi, vcpu, num, retval) : ENXIO) -#define VMSETREG(vmi, vcpu, num, val) \ - (ops != NULL ? (*ops->vmsetreg)(vmi, vcpu, num, val) : ENXIO) -#define VMGETDESC(vmi, vcpu, num, desc) \ - (ops != NULL ? (*ops->vmgetdesc)(vmi, vcpu, num, desc) : ENXIO) -#define VMSETDESC(vmi, vcpu, num, desc) \ - (ops != NULL ? (*ops->vmsetdesc)(vmi, vcpu, num, desc) : ENXIO) -#define VMGETCAP(vmi, vcpu, num, retval) \ - (ops != NULL ? (*ops->vmgetcap)(vmi, vcpu, num, retval) : ENXIO) -#define VMSETCAP(vmi, vcpu, num, val) \ - (ops != NULL ? (*ops->vmsetcap)(vmi, vcpu, num, val) : ENXIO) -#define VLAPIC_INIT(vmi, vcpu) \ - (ops != NULL ? (*ops->vlapic_init)(vmi, vcpu) : NULL) -#define VLAPIC_CLEANUP(vmi, vlapic) \ - (ops != NULL ? (*ops->vlapic_cleanup)(vmi, vlapic) : NULL) + ((*ops->vmrun)(vmi, vcpu, rip, pmap, evinfo) ) +#define VMCLEANUP(vmi) ((*ops->vmcleanup)(vmi) ) +#define VMSPACE_ALLOC(min, max) ((*ops->vmspace_alloc)(min, max)) +#define VMSPACE_FREE(vmspace) ((*ops->vmspace_free)(vmspace)) + +#define VMGETREG(vmi, vcpu, num, rv) ((*ops->vmgetreg)(vmi, vcpu, num, rv)) +#define VMSETREG(vmi, vcpu, num, val) ((*ops->vmsetreg)(vmi, vcpu, num, val)) +#define VMGETDESC(vmi, vcpu, num, dsc) ((*ops->vmgetdesc)(vmi, vcpu, num, dsc)) +#define VMSETDESC(vmi, vcpu, num, dsc) ((*ops->vmsetdesc)(vmi, vcpu, num, dsc)) +#define VMGETCAP(vmi, vcpu, num, rv) ((*ops->vmgetcap)(vmi, vcpu, num, rv)) +#define VMSETCAP(vmi, vcpu, num, val) ((*ops->vmsetcap)(vmi, vcpu, num, val)) +#define VLAPIC_INIT(vmi, vcpu) ((*ops->vlapic_init)(vmi, vcpu)) +#define VLAPIC_CLEANUP(vmi, vlapic) ((*ops->vlapic_cleanup)(vmi, vlapic)) #define fpu_start_emulating() load_cr0(rcr0() | CR0_TS) #define fpu_stop_emulating() clts() @@ -380,14 +402,6 @@ vm_exitinfo(struct vm *vm, int cpuid) return (&vcpu->exitinfo); } -#ifdef __FreeBSD__ -static void -vmm_resume(void) -{ - VMM_RESUME(); -} -#endif - static int vmm_init(void) { @@ -423,67 +437,13 @@ vmm_init(void) return (VMM_INIT(vmm_ipinum)); } -#ifdef __FreeBSD__ - -static int -vmm_handler(module_t mod, int what, void *arg) -{ - int error; - - switch (what) { - case MOD_LOAD: - vmmdev_init(); - error = vmm_init(); - if (error == 0) - vmm_initialized = 1; - break; - case MOD_UNLOAD: - error = vmmdev_cleanup(); - if (error == 0) { - vmm_resume_p = NULL; - iommu_cleanup(); -#ifdef __FreeBSD__ - if (vmm_ipinum != IPI_AST) - lapic_ipi_free(vmm_ipinum); -#endif - error = VMM_CLEANUP(); - /* - * Something bad happened - prevent new - * VMs from being created - */ - if (error) - vmm_initialized = 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). - */ -DECLARE_MODULE(vmm, vmm_kmod, SI_SUB_SMP + 1, SI_ORDER_ANY); -MODULE_VERSION(vmm, 1); - -#else /* __FreeBSD__ */ - int vmm_mod_load() { int error; + VERIFY(vmm_initialized == 0); + error = vmm_init(); if (error == 0) vmm_initialized = 1; @@ -496,6 +456,8 @@ vmm_mod_unload() { int error; + VERIFY(vmm_initialized == 1); + iommu_cleanup(); error = VMM_CLEANUP(); if (error) @@ -505,8 +467,6 @@ vmm_mod_unload() return (0); } -#endif /* __FreeBSD__ */ - static void vm_init(struct vm *vm, bool create) { |