summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Fiddaman <omnios@citrus-it.co.uk>2019-03-18 15:05:23 +0000
committerTrent Mick <trentm@gmail.com>2019-03-18 15:05:23 +0000
commit5c6fb82c4cd0e5404da55f4ba4c73fb22d4d396b (patch)
tree57a64b260e5ecdef98daded75b56d92e94279348
parent7909161cccf1283e5c7a7057bb9c7f305a30e55a (diff)
downloadillumos-joyent-cr5979-OS-XXXX.tar.gz
OS-XXXX bhyve should not hold HMA registration with no running VMscr5979-OS-XXXX
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
index 4b759b44e9..2249774988 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm_sol_dev.c
@@ -12,6 +12,7 @@
/*
* Copyright 2015 Pluribus Networks Inc.
* Copyright 2019 Joyent, Inc.
+ * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
*/
#include <sys/types.h>
@@ -1205,17 +1206,28 @@ vmmdev_do_vm_create(char *name, cred_t *cr)
vmm_softc_t *sc = NULL;
minor_t minor;
int error = ENOMEM;
+ hma_reg_t *reg = NULL;
if (strnlen(name, VM_MAX_NAMELEN) >= VM_MAX_NAMELEN) {
return (EINVAL);
}
+ mutex_enter(&vmmdev_mtx);
mutex_enter(&vmm_mtx);
+ if (vmmdev_hma_reg == NULL) {
+ if ((reg = hma_register(vmmdev_hvm_name)) == NULL) {
+ cmn_err(CE_WARN, "%s HMA registration failed.",
+ vmmdev_hvm_name);
+ error = ENXIO;
+ goto exit;
+ }
+ }
+
/* Look for duplicates names */
if (vmm_lookup(name) != NULL) {
- mutex_exit(&vmm_mtx);
- return (EEXIST);
+ error = EEXIST;
+ goto exit;
}
/* Allow only one instance per non-global zone. */
@@ -1223,8 +1235,8 @@ vmmdev_do_vm_create(char *name, cred_t *cr)
for (sc = list_head(&vmm_list); sc != NULL;
sc = list_next(&vmm_list, sc)) {
if (sc->vmm_zone == curzone) {
- mutex_exit(&vmm_mtx);
- return (EINVAL);
+ error = EINVAL;
+ goto exit;
}
}
}
@@ -1256,7 +1268,12 @@ vmmdev_do_vm_create(char *name, cred_t *cr)
vmm_zsd_add_vm(sc);
list_insert_tail(&vmm_list, sc);
+ if (reg != NULL) {
+ VERIFY(vmmdev_hma_reg == NULL);
+ vmmdev_hma_reg = reg;
+ }
mutex_exit(&vmm_mtx);
+ mutex_exit(&vmmdev_mtx);
return (0);
}
@@ -1266,7 +1283,13 @@ fail:
if (sc != NULL) {
ddi_soft_state_free(vmm_statep, minor);
}
+exit:
+ if (reg != NULL) {
+ hma_unregister(reg);
+ }
+
mutex_exit(&vmm_mtx);
+ mutex_exit(&vmmdev_mtx);
return (error);
}
@@ -1487,6 +1510,7 @@ vmm_do_vm_destroy_locked(vmm_softc_t *sc, boolean_t clean_zsd)
dev_info_t *pdip = ddi_get_parent(vmmdev_dip);
minor_t minor;
+ ASSERT(MUTEX_HELD(&vmmdev_mtx));
ASSERT(MUTEX_HELD(&vmm_mtx));
if (clean_zsd) {
@@ -1514,6 +1538,11 @@ vmm_do_vm_destroy_locked(vmm_softc_t *sc, boolean_t clean_zsd)
}
(void) devfs_clean(pdip, NULL, DV_CLEAN_FORCE);
+ if (list_is_empty(&vmm_list)) {
+ hma_unregister(vmmdev_hma_reg);
+ vmmdev_hma_reg = NULL;
+ }
+
return (0);
}
@@ -1522,9 +1551,11 @@ vmm_do_vm_destroy(vmm_softc_t *sc, boolean_t clean_zsd)
{
int err;
+ mutex_enter(&vmmdev_mtx);
mutex_enter(&vmm_mtx);
err = vmm_do_vm_destroy_locked(sc, clean_zsd);
mutex_exit(&vmm_mtx);
+ mutex_exit(&vmmdev_mtx);
return (err);
}
@@ -1539,27 +1570,30 @@ vmmdev_do_vm_destroy(const char *name, cred_t *cr)
if (crgetuid(cr) != 0)
return (EPERM);
+ mutex_enter(&vmmdev_mtx);
mutex_enter(&vmm_mtx);
if ((sc = vmm_lookup(name)) == NULL) {
- mutex_exit(&vmm_mtx);
- return (ENOENT);
+ err = ENOENT;
+ goto exit;
}
/*
* We don't check this in vmm_lookup() since that function is also used
* for validation during create and currently vmm names must be unique.
*/
if (!INGLOBALZONE(curproc) && sc->vmm_zone != curzone) {
- mutex_exit(&vmm_mtx);
- return (EPERM);
+ err = EPERM;
+ goto exit;
}
err = vmm_do_vm_destroy_locked(sc, B_TRUE);
+
+exit:
mutex_exit(&vmm_mtx);
+ mutex_exit(&vmmdev_mtx);
return (err);
}
-
static int
vmm_open(dev_t *devp, int flag, int otyp, cred_t *credp)
{
@@ -1875,12 +1909,18 @@ vmm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
vmm_sol_glue_init();
vmm_arena_init();
+ /*
+ * Perform temporary HMA registration to determine if the hardware
+ * is capable.
+ */
if ((reg = hma_register(vmmdev_hvm_name)) == NULL) {
goto fail;
} else if (vmm_mod_load() != 0) {
goto fail;
}
vmm_loaded = B_TRUE;
+ hma_unregister(reg);
+ reg = NULL;
/* Create control node. Other nodes will be created on demand. */
if (ddi_create_minor_node(dip, "ctl", S_IFCHR,
@@ -1894,7 +1934,6 @@ vmm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
}
ddi_report_dev(dip);
- vmmdev_hma_reg = reg;
vmmdev_sdev_hdl = sph;
vmmdev_dip = dip;
mutex_exit(&vmmdev_mtx);
@@ -1951,8 +1990,10 @@ vmm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
vmmdev_dip = NULL;
VERIFY0(vmm_mod_unload());
- hma_unregister(vmmdev_hma_reg);
- vmmdev_hma_reg = NULL;
+ if (vmmdev_hma_reg != NULL) {
+ hma_unregister(vmmdev_hma_reg);
+ vmmdev_hma_reg = NULL;
+ }
vmm_arena_fini();
vmm_sol_glue_cleanup();