Page MenuHomeFreeBSD

D34954.diff
No OneTemporary

D34954.diff

diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
--- a/lib/libvmmapi/vmmapi.h
+++ b/lib/libvmmapi/vmmapi.h
@@ -116,7 +116,7 @@
int vm_create(const char *name);
int vm_get_device_fd(struct vmctx *ctx);
struct vmctx *vm_open(const char *name);
-void vm_destroy(struct vmctx *ctx);
+int vm_destroy(struct vmctx *ctx);
int vm_parse_memsize(const char *optarg, size_t *memsize);
int vm_setup_memory(struct vmctx *ctx, size_t len, enum vm_mmap_style s);
void *vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len);
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -140,16 +140,21 @@
return (NULL);
}
-void
+int
vm_destroy(struct vmctx *vm)
{
+ int dummy, error = 0;
+
assert(vm != NULL);
if (vm->fd >= 0)
- close(vm->fd);
- DESTROY(vm->name);
+ error = ioctl(vm->fd, VM_DESTROY, &dummy);
- free(vm);
+ if (error == 0) {
+ close(vm->fd);
+ free(vm);
+ }
+ return (error);
}
int
@@ -1694,7 +1699,8 @@
VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SUSPEND_CPU, VM_RESUME_CPU,
VM_SET_INTINFO, VM_GET_INTINFO,
VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME,
- VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY };
+ VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY,
+ VM_DESTROY };
if (len == NULL) {
cmds = malloc(sizeof(vm_ioctl_cmds));
diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h
--- a/sys/amd64/include/vmm_dev.h
+++ b/sys/amd64/include/vmm_dev.h
@@ -344,7 +344,8 @@
/* checkpoint */
IOCNUM_SNAPSHOT_REQ = 113,
- IOCNUM_RESTORE_TIME = 115
+ IOCNUM_RESTORE_TIME = 115,
+ IOCNUM_DESTROY = 116,
};
#define VM_RUN \
@@ -475,4 +476,6 @@
_IOWR('v', IOCNUM_SNAPSHOT_REQ, struct vm_snapshot_meta)
#define VM_RESTORE_TIME \
_IOWR('v', IOCNUM_RESTORE_TIME, int)
+#define VM_DESTROY \
+ _IOWR('v', IOCNUM_DESTROY, int)
#endif
diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
--- a/sys/amd64/vmm/vmm_dev.c
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -99,6 +99,7 @@
static int vmm_priv_check(struct ucred *ucred);
static int devmem_create_cdev(const char *vmname, int id, char *devmem);
static void devmem_destroy(void *arg);
+static void vmmdev_destroy(void *arg);
static int
vmm_priv_check(struct ucred *ucred)
@@ -353,6 +354,52 @@
return (error);
}
+static int
+vmm_destroy(struct vmmdev_softc *sc)
+{
+ struct devmem_softc *dsc;
+ struct cdev *cdev;
+ int error;
+
+ mtx_lock(&vmmdev_mtx);
+ if (sc == NULL || sc->cdev == NULL) {
+ mtx_unlock(&vmmdev_mtx);
+ error = EINVAL;
+ goto out;
+ }
+
+ /*
+ * The 'cdev' will be destroyed asynchronously when 'si_threadcount'
+ * goes down to 0 so we should not do it again in the callback.
+ *
+ * Setting 'sc->cdev' to NULL is also used to indicate that the VM
+ * is scheduled for destruction.
+ */
+ cdev = sc->cdev;
+ sc->cdev = NULL;
+ mtx_unlock(&vmmdev_mtx);
+
+ /*
+ * Schedule all cdevs to be destroyed:
+ *
+ * - any new operations on the 'cdev' will return an error (ENXIO).
+ *
+ * - when the 'si_threadcount' dwindles down to zero the 'cdev' will
+ * be destroyed and the callback will be invoked in a taskqueue
+ * context.
+ *
+ * - the 'devmem' cdevs are destroyed before the virtual machine 'cdev'
+ */
+ SLIST_FOREACH(dsc, &sc->devmem, link) {
+ KASSERT(dsc->cdev != NULL, ("devmem cdev already destroyed"));
+ destroy_dev_sched_cb(dsc->cdev, devmem_destroy, dsc);
+ }
+ destroy_dev_sched_cb(cdev, vmmdev_destroy, sc);
+ error = 0;
+out:
+ return (error);
+}
+
static int
vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
@@ -879,6 +926,9 @@
error = vm_restore_time(sc->vm);
break;
#endif
+ case VM_DESTROY:
+ error = vmm_destroy(sc);
+ break;
default:
error = ENOTTY;
break;
@@ -1001,9 +1051,7 @@
static int
sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS)
{
- struct devmem_softc *dsc;
struct vmmdev_softc *sc;
- struct cdev *cdev;
char *buf;
int error, buflen;
@@ -1020,41 +1068,9 @@
mtx_lock(&vmmdev_mtx);
sc = vmmdev_lookup(buf);
- if (sc == NULL || sc->cdev == NULL) {
- mtx_unlock(&vmmdev_mtx);
- error = EINVAL;
- goto out;
- }
-
- /*
- * The 'cdev' will be destroyed asynchronously when 'si_threadcount'
- * goes down to 0 so we should not do it again in the callback.
- *
- * Setting 'sc->cdev' to NULL is also used to indicate that the VM
- * is scheduled for destruction.
- */
- cdev = sc->cdev;
- sc->cdev = NULL;
mtx_unlock(&vmmdev_mtx);
- /*
- * Schedule all cdevs to be destroyed:
- *
- * - any new operations on the 'cdev' will return an error (ENXIO).
- *
- * - when the 'si_threadcount' dwindles down to zero the 'cdev' will
- * be destroyed and the callback will be invoked in a taskqueue
- * context.
- *
- * - the 'devmem' cdevs are destroyed before the virtual machine 'cdev'
- */
- SLIST_FOREACH(dsc, &sc->devmem, link) {
- KASSERT(dsc->cdev != NULL, ("devmem cdev already destroyed"));
- destroy_dev_sched_cb(dsc->cdev, devmem_destroy, dsc);
- }
- destroy_dev_sched_cb(cdev, vmmdev_destroy, sc);
- error = 0;
-
+ error = vmm_destroy(sc);
out:
free(buf, M_VMMDEV);
return (error);

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 15, 8:38 AM (5 h, 23 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14640228
Default Alt Text
D34954.diff (5 KB)

Event Timeline