Page MenuHomeFreeBSD

D31325.id92823.diff
No OneTemporary

D31325.id92823.diff

diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
--- a/lib/libvmmapi/vmmapi.h
+++ b/lib/libvmmapi/vmmapi.h
@@ -33,6 +33,7 @@
#include <sys/param.h>
#include <sys/cpuset.h>
+#include <machine/vmm.h>
#include <machine/vmm_dev.h>
#include <stdbool.h>
@@ -113,6 +114,10 @@
int vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, size_t len);
+int vmmctl_open();
+int vm_fcreate(int fd, const char *name);
+int vm_fdestroy(int fd, const char *name);
+
int vm_create(const char *name);
int vm_get_device_fd(struct vmctx *ctx);
struct vmctx *vm_open(const char *name);
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -105,6 +105,44 @@
return (fd);
}
+int
+vmmctl_open()
+{
+ /* Try to load vmm(4) */
+ if (modfind("vmm") < 0)
+ kldload("vmm");
+
+ return (open("/dev/vmmctl", O_RDWR, 0));
+}
+
+int
+vm_fcreate(int fd, const char *name)
+{
+ struct vmmctl_op op;
+
+ if (strlen(name) >= VM_MAX_NAMELEN) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ strcpy(op.name, name);
+ return (ioctl(fd, VMMCTL_CREATE, &op));
+}
+
+int
+vm_fdestroy(int fd, const char *name)
+{
+ struct vmmctl_op op;
+
+ if (strlen(name) >= VM_MAX_NAMELEN) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ strcpy(op.name, name);
+ return (ioctl(fd, VMMCTL_DESTROY, &op));
+}
+
int
vm_create(const char *name)
{
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
@@ -347,6 +347,15 @@
IOCNUM_RESTORE_TIME = 115
};
+struct vmmctl_op {
+ char name[VM_MAX_NAMELEN];
+};
+
+#define VMMCTL_CREATE \
+ _IOWR('v', 101, struct vmmctl_op)
+#define VMMCTL_DESTROY \
+ _IOWR('v', 102, struct vmmctl_op)
+
#define VM_RUN \
_IOWR('v', IOCNUM_RUN, struct vm_run)
#define VM_SUSPEND \
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
@@ -79,12 +79,14 @@
};
struct vmmdev_softc {
- struct vm *vm; /* vm instance cookie */
+ struct vm *vm; /* vm instance cookie */
struct cdev *cdev;
struct ucred *ucred;
SLIST_ENTRY(vmmdev_softc) link;
SLIST_HEAD(, devmem_softc) devmem;
int flags;
+ TAILQ_ENTRY(vmmdev_softc) fvmm_next; /* next entry in fvmm list */
+ bool persistent; /* persistent = created via sysctl */
};
#define VSC_LINKED 0x01
@@ -1061,6 +1063,11 @@
mtx_lock(&vmmdev_mtx);
sc = vmmdev_lookup(buf);
+ if (!sc->persistent) {
+ mtx_unlock(&vmmdev_mtx);
+ error = EPERM;
+ goto out;
+ }
error = vmm_destroy(sc);
mtx_unlock(&vmmdev_mtx);
@@ -1083,11 +1090,64 @@
};
static int
-sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
+vmm_create(char *name, struct vmmdev_softc **sc)
{
- struct vm *vm;
struct cdev *cdev;
- struct vmmdev_softc *sc, *sc2;
+ struct vm *vm;
+ struct vmmdev_softc *tsc;
+ int error;
+
+ error = vm_create(name, &vm);
+ if (error != 0)
+ return (error);
+
+ tsc = malloc(sizeof(struct vmmdev_softc), M_VMMDEV, M_WAITOK | M_ZERO);
+ tsc->ucred = crhold(curthread->td_ucred);
+ tsc->vm = vm;
+ tsc->persistent = true;
+ SLIST_INIT(&tsc->devmem);
+
+ error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &vmmdevsw, tsc->ucred,
+ UID_ROOT, GID_WHEEL, 0600, "vmm/%s", name);
+ if (error != 0) {
+ vmmdev_destroy(tsc);
+ return (error);
+ }
+
+ tsc->cdev = cdev;
+ tsc->cdev->si_drv1 = tsc;
+ *sc = tsc;
+
+ return (0);
+}
+
+static int
+vmm_add(struct vmmdev_softc *sc)
+{
+ struct vmmdev_softc *tsc;
+
+ mtx_assert(&vmmdev_mtx, MA_OWNED);
+
+ /*
+ * Lookup the name just in case somebody sneaked in.
+ */
+ tsc = vmmdev_lookup(vm_name(sc->vm));
+ if (tsc == NULL) {
+ SLIST_INSERT_HEAD(&head, sc, link);
+ sc->flags |= VSC_LINKED;
+ }
+
+ if (tsc != NULL) {
+ return (EEXIST);
+ }
+
+ return (0);
+}
+
+static int
+sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
+{
+ struct vmmdev_softc *sc;
char *buf;
int error;
size_t buflen;
@@ -1103,52 +1163,21 @@
if (error != 0 || req->newptr == NULL)
goto out;
- mtx_lock(&vmmdev_mtx);
sc = vmmdev_lookup(buf);
- mtx_unlock(&vmmdev_mtx);
if (sc != NULL) {
error = EEXIST;
goto out;
}
- error = vm_create(buf, &vm);
+ error = vmm_create(buf, &sc);
if (error != 0)
goto out;
- sc = malloc(sizeof(struct vmmdev_softc), M_VMMDEV, M_WAITOK | M_ZERO);
- sc->ucred = crhold(curthread->td_ucred);
- sc->vm = vm;
- SLIST_INIT(&sc->devmem);
-
- /*
- * Lookup the name again just in case somebody sneaked in when we
- * dropped the lock.
- */
- mtx_lock(&vmmdev_mtx);
- sc2 = vmmdev_lookup(buf);
- if (sc2 == NULL) {
- SLIST_INSERT_HEAD(&head, sc, link);
- sc->flags |= VSC_LINKED;
- }
- mtx_unlock(&vmmdev_mtx);
-
- if (sc2 != NULL) {
- vmmdev_destroy(sc);
- error = EEXIST;
- goto out;
- }
-
- error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &vmmdevsw, sc->ucred,
- UID_ROOT, GID_WHEEL, 0600, "vmm/%s", buf);
- if (error != 0) {
- vmmdev_destroy(sc);
- goto out;
- }
-
mtx_lock(&vmmdev_mtx);
- sc->cdev = cdev;
- sc->cdev->si_drv1 = sc;
+ error = vmm_add(sc);
mtx_unlock(&vmmdev_mtx);
+ if (error != 0)
+ vmm_destroy(sc);
out:
free(buf, M_VMMDEV);
@@ -1320,3 +1349,129 @@
dsc->cdev = NULL;
dsc->sc = NULL;
}
+
+struct fvmm {
+ TAILQ_HEAD(softc_list, vmmdev_softc) scs;
+};
+
+static int
+fvmm_destroy(struct fvmm *fvmm, char *name)
+{
+ struct vmmdev_softc *sc, *tsc;
+ int error = ENOENT;
+
+ mtx_lock(&vmmdev_mtx);
+ TAILQ_FOREACH_SAFE(sc, &fvmm->scs, fvmm_next, tsc) {
+ if (strcmp(vm_name(sc->vm), name) == 0) {
+ vmm_destroy(sc);
+ TAILQ_REMOVE(&fvmm->scs, sc, fvmm_next);
+ error = 0;
+ }
+ }
+ mtx_unlock(&vmmdev_mtx);
+
+ return (error);
+}
+
+static void
+fvmm_dtor(void *data)
+{
+ struct fvmm *fvmm = data;
+ struct vmmdev_softc *sc;
+
+ mtx_lock(&vmmdev_mtx);
+ while ((sc = TAILQ_FIRST(&fvmm->scs))) {
+ TAILQ_REMOVE(&fvmm->scs, sc, fvmm_next);
+ vmm_destroy(sc);
+ }
+ mtx_unlock(&vmmdev_mtx);
+ free(fvmm, M_VMMDEV);
+}
+
+static int
+vmmctl_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct fvmm *fvmm;
+ int error;
+
+ fvmm = malloc(sizeof(struct fvmm), M_VMMDEV, M_WAITOK | M_ZERO);
+ TAILQ_INIT(&fvmm->scs);
+ error = devfs_set_cdevpriv(fvmm, fvmm_dtor);
+ if (error)
+ fvmm_dtor(fvmm);
+ return (error);
+}
+
+static int
+vmmctl_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
+ struct thread *td)
+{
+ struct fvmm *fvmm;
+ struct vmmdev_softc *sc;
+ struct vmmctl_op *op;
+ int error = 0;
+
+ devfs_get_cdevpriv((void **)&fvmm);
+
+ switch (cmd) {
+ case VMMCTL_CREATE:
+ op = (struct vmmctl_op *)data;
+ error = vmm_create(op->name, &sc);
+ if (error)
+ break;
+ sc->persistent = false;
+ mtx_lock(&vmmdev_mtx);
+ error = vmm_add(sc);
+ if (error) {
+ vmm_destroy(sc);
+ mtx_unlock(&vmmdev_mtx);
+ break;
+ }
+ TAILQ_INSERT_HEAD(&fvmm->scs, sc, fvmm_next);
+ mtx_unlock(&vmmdev_mtx);
+ break;
+ case VMMCTL_DESTROY:
+ op = (struct vmmctl_op *)data;
+ error = fvmm_destroy(fvmm, op->name);
+ break;
+ }
+
+ return (error);
+}
+
+static struct cdevsw vmmctl_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = vmmctl_open,
+ .d_ioctl = vmmctl_ioctl,
+ .d_name = "vmmctl",
+};
+static struct cdev *vmmctl_dev;
+
+/*
+ * Initialization code, both for static and dynamic loading.
+ */
+static int
+vmmctl_modevent(module_t mod, int type, void *unused)
+{
+ switch (type) {
+ case MOD_LOAD:
+ if (bootverbose)
+ printf("vmmctl: <vmmctl device>\n");
+ vmmctl_dev = make_dev(&vmmctl_cdevsw, 0,
+ UID_ROOT, GID_WHEEL, 0600, "vmmctl");
+ return 0;
+ case MOD_UNLOAD:
+ /*XXX disallow if active sessions */
+ destroy_dev(vmmctl_dev);
+ return 0;
+ }
+ return EINVAL;
+}
+
+static moduledata_t vmmctl_mod = {
+ "vmmctl",
+ vmmctl_modevent,
+ 0
+};
+MODULE_VERSION(vmmctl, 1);
+DECLARE_MODULE(vmmctl, vmmctl_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);

File Metadata

Mime Type
text/plain
Expires
Fri, May 22, 1:40 AM (4 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33412764
Default Alt Text
D31325.id92823.diff (7 KB)

Event Timeline