Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F133631289
D31325.id93193.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D31325.id93193.diff
View Options
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(void);
+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(void)
+{
+ /* Try to load vmm(4) */
+ if (modfind("vmm") < 0)
+ kldload("vmm");
+
+ return (open("/dev/vmmctl", O_RDWR));
+}
+
+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 + 1];
+};
+
+#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
@@ -1063,6 +1065,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);
@@ -1085,11 +1092,63 @@
};
static int
-sysctl_vmm_create(SYSCTL_HANDLER_ARGS)
+vmm_create(const 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;
@@ -1105,52 +1164,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);
@@ -1161,73 +1189,6 @@
NULL, 0, sysctl_vmm_create, "A",
NULL);
-static void
-vmmdev_prison_cleanup(struct prison *pr)
-{
- struct vmmdev_softc *sc;
- struct vmmdev_softc *tsc;
-
- mtx_lock(&vmmdev_mtx);
-
- SLIST_FOREACH_SAFE(sc, &head, link, tsc) {
- if (sc->ucred->cr_prison == pr)
- vmm_destroy(sc);
- }
-
- mtx_unlock(&vmmdev_mtx);
-}
-
-static int
-vmmdev_prison_remove(void *obj, void *data __unused)
-{
- struct prison *pr = obj;
-
- vmmdev_prison_cleanup(pr);
- return (0);
-}
-
-static int
-vmmdev_prison_set(void *obj, void *data)
-{
- struct prison *pr = obj;
- struct vfsoptlist *opts = data;
-
- if (vfs_flagopt(opts, "allow.novmm", NULL, 0))
- vmmdev_prison_cleanup(pr);
-
- return (0);
-}
-
-void
-vmmdev_init(void)
-{
- osd_method_t methods[PR_MAXMETHOD] = {
- [PR_METHOD_SET] = vmmdev_prison_set,
- [PR_METHOD_REMOVE] = vmmdev_prison_remove,
- };
-
- mtx_init(&vmmdev_mtx, "vmm device mutex", NULL, MTX_DEF);
- pr_allow_flag = prison_add_allow(NULL, "vmm", NULL,
- "Allow use of vmm in a jail.");
-
- vmmdev_prison_slot = osd_jail_register(NULL, methods);
-}
-
-int
-vmmdev_cleanup(void)
-{
- int error;
-
- if (SLIST_EMPTY(&head)) {
- osd_jail_deregister(vmmdev_prison_slot);
- error = 0;
- } else {
- error = EBUSY;
- }
-
- return (error);
-}
-
static int
devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len,
struct vm_object **objp, int nprot)
@@ -1322,3 +1283,181 @@
dsc->cdev = NULL;
dsc->sc = NULL;
}
+
+struct fvmm {
+ TAILQ_HEAD(softc_list, vmmdev_softc) scs;
+};
+
+static int
+fvmm_destroy(struct fvmm *fvmm, const 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;
+ if (strnlen(op->name, VM_MAX_NAMELEN + 1) ==
+ VM_MAX_NAMELEN + 1) {
+ error = EINVAL;
+ break;
+ }
+ 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;
+ if (strnlen(op->name, VM_MAX_NAMELEN + 1) ==
+ VM_MAX_NAMELEN + 1) {
+ error = EINVAL;
+ break;
+ }
+ error = fvmm_destroy(fvmm, op->name);
+ break;
+ }
+
+ return (error);
+}
+
+static void
+vmmdev_prison_cleanup(struct prison *pr)
+{
+ struct vmmdev_softc *sc;
+ struct vmmdev_softc *tsc;
+
+ mtx_lock(&vmmdev_mtx);
+
+ SLIST_FOREACH_SAFE(sc, &head, link, tsc) {
+ if (sc->ucred->cr_prison == pr)
+ vmm_destroy(sc);
+ }
+
+ mtx_unlock(&vmmdev_mtx);
+}
+
+static int
+vmmdev_prison_remove(void *obj, void *data __unused)
+{
+ struct prison *pr = obj;
+
+ vmmdev_prison_cleanup(pr);
+ return (0);
+}
+
+static int
+vmmdev_prison_set(void *obj, void *data)
+{
+ struct prison *pr = obj;
+ struct vfsoptlist *opts = data;
+
+ if (vfs_flagopt(opts, "allow.novmm", NULL, 0))
+ vmmdev_prison_cleanup(pr);
+
+ return (0);
+}
+
+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;
+
+void
+vmmdev_init(void)
+{
+ osd_method_t methods[PR_MAXMETHOD] = {
+ [PR_METHOD_SET] = vmmdev_prison_set,
+ [PR_METHOD_REMOVE] = vmmdev_prison_remove,
+ };
+
+ mtx_init(&vmmdev_mtx, "vmm device mutex", NULL, MTX_DEF);
+ pr_allow_flag = prison_add_allow(NULL, "vmm", NULL,
+ "Allow use of vmm in a jail.");
+
+ vmmdev_prison_slot = osd_jail_register(NULL, methods);
+
+ vmmctl_dev = make_dev(&vmmctl_cdevsw, 0,
+ UID_ROOT, GID_WHEEL, 0600, "vmmctl");
+}
+
+int
+vmmdev_cleanup(void)
+{
+ int error;
+
+ if (SLIST_EMPTY(&head)) {
+ osd_jail_deregister(vmmdev_prison_slot);
+ destroy_dev(vmmctl_dev);
+ error = 0;
+ } else {
+ error = EBUSY;
+ }
+
+ return (error);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Oct 28, 3:52 AM (11 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24335449
Default Alt Text
D31325.id93193.diff (9 KB)
Attached To
Mode
D31325: vmm: Add new device file that handles creation/destruction of VMs
Attached
Detach File
Event Timeline
Log In to Comment