The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=99127fd103624de593c7d1d885387e7d3667d73d

commit 99127fd103624de593c7d1d885387e7d3667d73d
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2024-11-05 01:36:33 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2024-11-05 01:40:41 +0000

    libvmmapi: Use the vmmctl device file to create and destroy VMs
    
    This deprecates the vm_create() and vm_open() interfaces and introduces
    vm_openf(), which takes flags controlling its behaviour.  In particular,
    it will optionally create a VM first, and it can optionally reinitialize
    an existing VM.  This enables some simplification of existing consumers.
    
    Reviewed by:    jhb
    Differential Revision:  https://reviews.freebsd.org/D47030
---
 lib/libvmmapi/internal.h |   3 +-
 lib/libvmmapi/vmmapi.c   | 104 +++++++++++++++++++++++++++++++++++------------
 lib/libvmmapi/vmmapi.h   |   3 ++
 3 files changed, 83 insertions(+), 27 deletions(-)

diff --git a/lib/libvmmapi/internal.h b/lib/libvmmapi/internal.h
index 42be9ec59770..aa7b1d8e6a93 100644
--- a/lib/libvmmapi/internal.h
+++ b/lib/libvmmapi/internal.h
@@ -16,7 +16,8 @@ enum {
 };
 
 struct vmctx {
-       int     fd;
+       int     fd;             /* device file descriptor */
+       int     ctlfd;          /* vmm control descriptor */
        struct {
                vm_paddr_t base;
                vm_size_t size;
diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c
index 0cf051567110..5042a1f3914e 100644
--- a/lib/libvmmapi/vmmapi.c
+++ b/lib/libvmmapi/vmmapi.c
@@ -37,6 +37,7 @@
 #include <sys/cpuset.h>
 
 #include <capsicum_helpers.h>
+#include <err.h>
 #include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
@@ -50,11 +51,12 @@
 
 #include <vm/vm.h>
 #include <machine/vmm.h>
-#include <machine/vmm_dev.h>
 #ifdef WITH_VMMAPI_SNAPSHOT
 #include <machine/vmm_snapshot.h>
 #endif
 
+#include <dev/vmm/vmm_dev.h>
+
 #include "vmmapi.h"
 #include "internal.h"
 
@@ -78,58 +80,104 @@
 #define        PROT_RW         (PROT_READ | PROT_WRITE)
 #define        PROT_ALL        (PROT_READ | PROT_WRITE | PROT_EXEC)
 
-#define        CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), 
strlen((x)))
-#define        DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), 
strlen((x)))
-
 static int
 vm_device_open(const char *name)
 {
-       int fd, len;
-       char *vmfile;
+       char devpath[PATH_MAX];
 
-       len = strlen("/dev/vmm/") + strlen(name) + 1;
-       vmfile = malloc(len);
-       assert(vmfile != NULL);
-       snprintf(vmfile, len, "/dev/vmm/%s", name);
+       assert(strlen(name) <= VM_MAX_NAMELEN);
+       (void)snprintf(devpath, sizeof(devpath), "/dev/vmm/%s", name);
+       return (open(devpath, O_RDWR));
+}
 
-       /* Open the device file */
-       fd = open(vmfile, O_RDWR, 0);
+static int
+vm_ctl_create(const char *name, int ctlfd)
+{
+       struct vmmctl_vm_create vmc;
 
-       free(vmfile);
-       return (fd);
+       memset(&vmc, 0, sizeof(vmc));
+       if (strlcpy(vmc.name, name, sizeof(vmc.name)) >= sizeof(vmc.name)) {
+               errno = ENAMETOOLONG;
+               return (-1);
+       }
+       return (ioctl(ctlfd, VMMCTL_VM_CREATE, &vmc));
 }
 
 int
 vm_create(const char *name)
 {
+       int error, fd;
+
        /* Try to load vmm(4) module before creating a guest. */
-       if (modfind("vmm") < 0)
-               kldload("vmm");
-       return (CREATE(name));
+       if (modfind("vmm") < 0) {
+               error = kldload("vmm");
+               if (error != 0)
+                       return (-1);
+       }
+
+       fd = open("/dev/vmmctl", O_RDWR, 0);
+       if (fd < 0)
+               return (fd);
+       error = vm_ctl_create(name, fd);
+       if (error != 0) {
+               error = errno;
+               (void)close(fd);
+               errno = error;
+               return (-1);
+       }
+       (void)close(fd);
+       return (0);
 }
 
 struct vmctx *
 vm_open(const char *name)
+{
+       return (vm_openf(name, 0));
+}
+
+struct vmctx *
+vm_openf(const char *name, int flags)
 {
        struct vmctx *vm;
        int saved_errno;
+       bool created;
+
+       created = false;
 
        vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
        assert(vm != NULL);
 
-       vm->fd = -1;
+       vm->fd = vm->ctlfd = -1;
        vm->memflags = 0;
        vm->name = (char *)(vm + 1);
        strcpy(vm->name, name);
        memset(vm->memsegs, 0, sizeof(vm->memsegs));
 
-       if ((vm->fd = vm_device_open(vm->name)) < 0)
+       if ((vm->ctlfd = open("/dev/vmmctl", O_RDWR, 0)) < 0)
+               goto err;
+
+       vm->fd = vm_device_open(vm->name);
+       if (vm->fd < 0 && errno == ENOENT) {
+               if (flags & VMMAPI_OPEN_CREATE) {
+                       if (vm_ctl_create(vm->name, vm->ctlfd) != 0)
+                               goto err;
+                       vm->fd = vm_device_open(vm->name);
+                       created = true;
+               }
+       }
+       if (vm->fd < 0)
+               goto err;
+
+       if (!created && (flags & VMMAPI_OPEN_REINIT) != 0 && vm_reinit(vm) != 0)
                goto err;
 
        return (vm);
 err:
        saved_errno = errno;
-       free(vm);
+       if (created)
+               vm_destroy(vm);
+       else
+               vm_close(vm);
        errno = saved_errno;
        return (NULL);
 }
@@ -139,20 +187,24 @@ vm_close(struct vmctx *vm)
 {
        assert(vm != NULL);
 
-       close(vm->fd);
+       if (vm->fd >= 0)
+               (void)close(vm->fd);
+       if (vm->ctlfd >= 0)
+               (void)close(vm->ctlfd);
        free(vm);
 }
 
 void
 vm_destroy(struct vmctx *vm)
 {
-       assert(vm != NULL);
+       struct vmmctl_vm_destroy vmd;
 
-       if (vm->fd >= 0)
-               close(vm->fd);
-       DESTROY(vm->name);
+       memset(&vmd, 0, sizeof(vmd));
+       (void)strlcpy(vmd.name, vm->name, sizeof(vmd.name));
+       if (ioctl(vm->ctlfd, VMMCTL_VM_DESTROY, &vmd) != 0)
+               warn("ioctl(VMMCTL_VM_DESTROY)");
 
-       free(vm);
+       vm_close(vm);
 }
 
 struct vcpu *
diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h
index 0ea1d5824271..440064ad13cb 100644
--- a/lib/libvmmapi/vmmapi.h
+++ b/lib/libvmmapi/vmmapi.h
@@ -117,6 +117,9 @@ int vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, 
size_t len);
 
 int    vm_create(const char *name);
 struct vmctx *vm_open(const char *name);
+#define        VMMAPI_OPEN_CREATE      0x01    /* create if the VM does not 
exist */
+#define        VMMAPI_OPEN_REINIT      0x02    /* reinitialize the VM if it 
exists */
+struct vmctx *vm_openf(const char *name, int flags);
 void   vm_close(struct vmctx *ctx);
 void   vm_destroy(struct vmctx *ctx);
 int    vm_limit_rights(struct vmctx *ctx);

Reply via email to