diff mbox

[1/2] libxl: add PV display device driver interface

Message ID 1490263832-9068-2-git-send-email-al1img@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Oleksandr Grytsov March 23, 2017, 10:10 a.m. UTC
From: Oleksandr Grytsov <oleksandr_grytsov@epam.com>

Signed-off-by: Oleksandr Grytsov <oleksandr_grytsov@epam.com>
---
 tools/libxl/Makefile                 |   2 +-
 tools/libxl/libxl.h                  |  21 ++++
 tools/libxl/libxl_create.c           |   1 +
 tools/libxl/libxl_internal.h         | 228 +++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl          |  22 +++-
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_utils.h            |   4 +
 tools/libxl/libxl_vdispl.c           | 137 +++++++++++++++++++++
 8 files changed, 413 insertions(+), 3 deletions(-)
 create mode 100644 tools/libxl/libxl_vdispl.c
diff mbox

Patch

diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index f00d9ef..cb7c17f 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -138,7 +138,7 @@  LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
 			libxl_dom_suspend.o libxl_dom_save.o libxl_usb.o \
 			libxl_vtpm.o libxl_nic.o libxl_disk.o libxl_console.o \
 			libxl_cpupool.o libxl_mem.o libxl_sched.o libxl_tmem.o \
-			libxl_domain.o \
+			libxl_domain.o libxl_vdispl.o \
                         $(LIBXL_OBJS-y)
 LIBXL_OBJS += libxl_genid.o
 LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 92f1751..a4fc304 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1833,6 +1833,27 @@  libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *n
 int libxl_device_vtpm_getinfo(libxl_ctx *ctx, uint32_t domid,
                                libxl_device_vtpm *vtpm, libxl_vtpminfo *vtpminfo);
 
+/* Virtual displays */
+int libxl_device_vdispl_add(libxl_ctx *ctx, uint32_t domid,
+                            libxl_device_vdispl *displ,
+                            const libxl_asyncop_how *ao_how)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vdispl_remove(libxl_ctx *ctx, uint32_t domid,
+                               libxl_device_vdispl *vdispl,
+                               const libxl_asyncop_how *ao_how)
+                               LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vdispl_destroy(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_vdispl *vdispl,
+                                const libxl_asyncop_how *ao_how)
+                                LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vdispl *libxl_device_vdispl_list(libxl_ctx *ctx, uint32_t domid,
+                                              int *num);
+void libxl_device_vdispl_list_free(libxl_device_vdispl* list, int num);
+int libxl_device_vdispl_getinfo(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_vdispl *vdispl,
+                                libxl_vdisplinfo *vdisplinfo);
+
 /* Keyboard */
 int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
                          const libxl_asyncop_how *ao_how)
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index e741b9a..19e0683 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1445,6 +1445,7 @@  const struct libxl_device_type *device_type_tbl[] = {
     &libxl__usbdev_devtype,
     &libxl__pcidev_devtype,
     &libxl__dtdev_devtype,
+    &libxl__vdispl_devtype,
     NULL
 };
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 5bbede5..787bebb 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3465,6 +3465,233 @@  _hidden void libxl__bootloader_run(libxl__egc*, libxl__bootloader_state *st);
     LIBXL_DEFINE_DEVICE_REMOVE_EXT(type, type, remove, 0)               \
     LIBXL_DEFINE_DEVICE_REMOVE_EXT(type, type, destroy, 1)
 
+#define LIBXL_DEFINE_DEVICE_COMMIT(type)                                \
+    static int libxl__device_##type##_commit(libxl__egc *egc,           \
+        uint32_t domid, libxl_device_##type *type,                      \
+        flexarray_t *front, flexarray_t *back,                          \
+        libxl__ao_device *aodev, int rc)                                \
+    {                                                                   \
+        STATE_AO_GC(aodev->ao);                                         \
+        libxl__device *device;                                          \
+        xs_transaction_t t = XBT_NULL;                                  \
+        libxl_domain_config d_config;                                   \
+        libxl__domain_userdata_lock *lock = NULL;                       \
+                                                                        \
+        libxl_domain_config_init(&d_config);                            \
+                                                                        \
+        if (rc) goto out;                                               \
+                                                                        \
+        if (aodev->update_json) {                                       \
+            lock = libxl__lock_domain_userdata(gc, domid);              \
+            if (!lock) { rc = ERROR_LOCK_FAIL; goto out; }              \
+                                                                        \
+            rc = libxl__get_domain_configuration(gc, domid, &d_config); \
+            if (rc) goto out;                                           \
+                                                                        \
+            DEVICE_ADD(type, type##s, domid, type,                      \
+                       COMPARE_DEVID, &d_config);                       \
+                                                                        \
+            rc = libxl__dm_check_start(gc, &d_config, domid);           \
+            if (rc) goto out;                                           \
+        }                                                               \
+                                                                        \
+        GCNEW(device);                                                  \
+        rc = libxl__device_from_##type(gc, domid, type, device);        \
+        if ( rc != 0 ) goto out;                                        \
+                                                                        \
+        for (;;) {                                                      \
+            rc = libxl__xs_transaction_start(gc, &t);                   \
+            if (rc) goto out;                                           \
+                                                                        \
+            rc = libxl__device_exists(gc, t, device);                   \
+            if (rc < 0) goto out;                                       \
+            if (rc == 1) {                                              \
+                LOGD(ERROR, domid, "device already exists in xenstore");\
+                aodev->action = LIBXL__DEVICE_ACTION_ADD;               \
+                rc = ERROR_DEVICE_EXISTS;                               \
+                goto out;                                               \
+            }                                                           \
+                                                                        \
+            if (aodev->update_json) {                                   \
+                rc = libxl__set_domain_configuration(gc, domid,         \
+                                                     &d_config);        \
+                if (rc) goto out;                                       \
+            }                                                           \
+                                                                        \
+            libxl__device_generic_add(gc, t, device,                    \
+                libxl__xs_kvs_of_flexarray(gc, back),                   \
+                libxl__xs_kvs_of_flexarray(gc, front),                  \
+                NULL);                                                  \
+                                                                        \
+            rc = libxl__xs_transaction_commit(gc, &t);                  \
+            if (rc < 0) { rc = ERROR_FAIL; goto out; }                  \
+            if (!rc) break;                                             \
+        }                                                               \
+                                                                        \
+        aodev->dev = device;                                            \
+        aodev->action = LIBXL__DEVICE_ACTION_ADD;                       \
+        libxl__wait_device_connection(egc, aodev);                      \
+        rc = 0;                                                         \
+                                                                        \
+    out:                                                                \
+        libxl__xs_transaction_abort(gc, &t);                            \
+        if (lock) libxl__unlock_domain_userdata(lock);                  \
+        libxl_domain_config_dispose(&d_config);                         \
+        aodev->rc = rc;                                                 \
+        if(rc) aodev->callback(egc, aodev);                             \
+        return rc;                                                      \
+    }
+
+#define LIBXL_DEFINE_DEVICE_LIST_GET(type)                              \
+    libxl_device_##type *libxl_device_##type##_list(libxl_ctx *ctx,     \
+                                                    uint32_t domid,     \
+                                                    int *num)           \
+    {                                                                   \
+        GC_INIT(ctx);                                                   \
+                                                                        \
+        libxl_device_##type* types = NULL;                              \
+        libxl_device_##type* r = NULL;                                  \
+        libxl_device_##type* type;                                      \
+        char *libxl_path;                                               \
+        char** dir = NULL;                                              \
+        unsigned int ndirs = 0;                                         \
+        int rc;                                                         \
+                                                                        \
+        *num = 0;                                                       \
+                                                                        \
+        libxl_path = GCSPRINTF("%s/device/%s",                          \
+             libxl__xs_libxl_path(gc, domid), #type);                   \
+                                                                        \
+        dir = libxl__xs_directory(gc, XBT_NULL, libxl_path, &ndirs);    \
+                                                                        \
+        if (dir && ndirs) {                                             \
+            types = malloc(sizeof(*types) * ndirs);                     \
+            libxl_device_##type* end = types + ndirs;                   \
+                                                                        \
+            for(type = types; type < end; ++type, ++dir) {              \
+                const char* be_path = libxl__xs_read(gc, XBT_NULL,      \
+                GCSPRINTF("%s/%s/backend", libxl_path, *dir));          \
+                                                                        \
+                libxl_device_##type##_init(type);                       \
+                                                                        \
+                type->devid = atoi(*dir);                               \
+                                                                        \
+                rc = libxl__backendpath_parse_domid(gc, be_path,        \
+                    &type->backend_domid);                              \
+                if (rc) goto out;                                       \
+            }                                                           \
+        }                                                               \
+                                                                        \
+        *num = ndirs;                                                   \
+        r = types;                                                      \
+        types = NULL;                                                   \
+                                                                        \
+    out:                                                                \
+        if (types) {                                                    \
+            for(; type >= types; --type) {                              \
+                libxl_device_##type##_dispose(type);                    \
+            }                                                           \
+            free(types);                                                \
+        }                                                               \
+                                                                        \
+        GC_FREE;                                                        \
+                                                                        \
+        return r;                                                       \
+    }
+
+#define LIBXL_DEFINE_DEVICE_LIST_FREE(type)                             \
+    void libxl_device_##type##_list_free(libxl_device_##type* list,     \
+                                         int nr)                        \
+    {                                                                   \
+        int i;                                                          \
+        for (i = 0; i < nr; i++) {                                      \
+            libxl_device_##type##_dispose(&list[i]);                    \
+        }                                                               \
+        free(list);                                                     \
+    }
+
+#define LIBXL_DEFINE_DEVID_TO_DEVICE(type)                              \
+    int libxl_devid_to_device_##type(libxl_ctx *ctx,                    \
+                                     uint32_t domid,                    \
+                                     int devid,                         \
+                                     libxl_device_##type *type)         \
+    {                                                                   \
+        libxl_device_##type *types = NULL;                              \
+        int n, i;                                                       \
+        int rc;                                                         \
+                                                                        \
+        libxl_device_##type##_init(type);                               \
+                                                                        \
+        types = libxl_device_##type##_list(ctx, domid, &n);             \
+        if (!types) { rc = ERROR_NOTFOUND; goto out; }                  \
+                                                                        \
+        for (i = 0; i < n; ++i) {                                       \
+            if (devid == types[i].devid) {                              \
+                type->backend_domid = types[i].backend_domid;           \
+                type->devid = types[i].devid;                           \
+                rc = 0;                                                 \
+                goto out;                                               \
+            }                                                           \
+        }                                                               \
+                                                                        \
+        rc = ERROR_NOTFOUND;                                            \
+                                                                        \
+    out:                                                                \
+        if (types) {                                                    \
+            libxl_device_##type##_list_free(types, n);                  \
+        }                                                               \
+        return rc;                                                      \
+    }
+
+#define LIBXL_DEFINE_DEVICE_GETINFO(type)                               \
+    int libxl_device_##type##_getinfo(libxl_ctx *ctx,                   \
+                                      uint32_t domid,                   \
+                                      libxl_device_##type *type,        \
+                                      libxl_##type##info *info)         \
+    {                                                                   \
+        GC_INIT(ctx);                                                   \
+        char *libxl_path, *dompath, *devpath;                           \
+        char *val;                                                      \
+        int rc;                                                         \
+                                                                        \
+        libxl_##type##info_init(info);                                  \
+        dompath = libxl__xs_get_dompath(gc, domid);                     \
+        info->devid = type->devid;                                      \
+                                                                        \
+        devpath = GCSPRINTF("%s/device/"#type"/%d",                     \
+                            dompath, info->devid);                      \
+        libxl_path = GCSPRINTF("%s/device/"#type"/%d",                  \
+                               libxl__xs_libxl_path(gc, domid),         \
+                               info->devid);                            \
+        info->backend = xs_read(ctx->xsh, XBT_NULL,                     \
+                                GCSPRINTF("%s/backend", libxl_path),    \
+                                NULL);                                  \
+        if (!info->backend) { rc = ERROR_FAIL; goto out; }              \
+                                                                        \
+        rc = libxl__backendpath_parse_domid(gc, info->backend,          \
+                                            &info->backend_id);         \
+        if (rc) { goto out; }                                           \
+                                                                        \
+        val = libxl__xs_read(gc, XBT_NULL,                              \
+                             GCSPRINTF("%s/state", devpath));           \
+        info->state = val ? strtoul(val, NULL, 10) : -1;                \
+                                                                        \
+        info->frontend = xs_read(ctx->xsh, XBT_NULL,                    \
+                                 GCSPRINTF("%s/frontend", libxl_path),  \
+                                 NULL);                                 \
+        info->frontend_id = domid;                                      \
+                                                                        \
+        rc = libxl__device_##type##_getinfo(gc, ctx->xsh,               \
+                                            libxl_path, info);          \
+        if (rc) { goto out; }                                           \
+                                                                        \
+        rc = 0;                                                         \
+                                                                        \
+    out:                                                                \
+         GC_FREE;                                                       \
+         return rc;                                                     \
+    }
+
 struct libxl_device_type {
     char *type;
     int skip_attach;   /* Skip entry in domcreate_attach_devices() if 1 */
@@ -3524,6 +3751,7 @@  extern const struct libxl_device_type libxl__vtpm_devtype;
 extern const struct libxl_device_type libxl__usbctrl_devtype;
 extern const struct libxl_device_type libxl__usbdev_devtype;
 extern const struct libxl_device_type libxl__pcidev_devtype;
+extern const struct libxl_device_type libxl__vdispl_devtype;
 
 extern const struct libxl_device_type *device_type_tbl[];
 
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index a612d1f..46845f0 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -690,7 +690,14 @@  libxl_device_vtpm = Struct("device_vtpm", [
     ("backend_domname",  string),
     ("devid",            libxl_devid),
     ("uuid",             libxl_uuid),
-])
+    ])
+
+libxl_device_vdispl = Struct("device_vdispl", [
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+    ("devid", libxl_devid),
+    ("be_alloc", bool),
+    ])
 
 libxl_device_channel = Struct("device_channel", [
     ("backend_domid", libxl_domid),
@@ -702,7 +709,7 @@  libxl_device_channel = Struct("device_channel", [
             ("pty", None),
             ("socket", Struct(None, [("path", string)])),
            ])),
-])
+    ])
 
 libxl_domain_config = Struct("domain_config", [
     ("c_info", libxl_domain_create_info),
@@ -716,6 +723,7 @@  libxl_domain_config = Struct("domain_config", [
     ("vfbs", Array(libxl_device_vfb, "num_vfbs")),
     ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
+    ("vdispls", Array(libxl_device_vdispl, "num_vdispls")),
     # a channel manifests as a console with a name,
     # see docs/misc/channels.txt
     ("channels", Array(libxl_device_channel, "num_channels")),
@@ -812,6 +820,16 @@  libxl_physinfo = Struct("physinfo", [
     ("cap_hvm_directio", bool),
     ], dir=DIR_OUT)
 
+libxl_vdisplinfo = Struct("vdisplinfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("be_alloc", bool),
+    ], dir=DIR_OUT)
+
 # NUMA node characteristics: size and free are how much memory it has, and how
 # much of it is free, respectively. dists is an array of distances from this
 # node to each other node.
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 82e5c07..cdef4d3 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -25,6 +25,7 @@  libxl__device_kind = Enumeration("device_kind", [
     (8, "VTPM"),
     (9, "VUSB"),
     (10, "QUSB"),
+    (11, "VDISPL")
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 25773d8..9e743dc 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -78,6 +78,10 @@  int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vtpm *vtpm);
 int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, uint32_t domid,
                                   int devid, libxl_device_usbctrl *usbctrl);
+
+int libxl_devid_to_device_vdispl(libxl_ctx *ctx, uint32_t domid,
+                                 int devid, libxl_device_vdispl *vdispl);
+
 int libxl_ctrlport_to_device_usbdev(libxl_ctx *ctx, uint32_t domid,
                                     int ctrl, int port,
                                     libxl_device_usbdev *usbdev);
diff --git a/tools/libxl/libxl_vdispl.c b/tools/libxl/libxl_vdispl.c
new file mode 100644
index 0000000..869aaa1
--- /dev/null
+++ b/tools/libxl/libxl_vdispl.c
@@ -0,0 +1,137 @@ 
+/*
+ * Copyright (C) 2016 EPAM Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h"
+
+#include "libxl_internal.h"
+
+static int libxl__device_vdispl_setdefault(libxl__gc *gc, domid_t domid,
+                                           libxl_device_vdispl *vdispl)
+{
+    int rc;
+
+    rc = libxl__resolve_domid(gc, vdispl->backend_domname,
+                              &vdispl->backend_domid);
+
+    if (vdispl->devid == -1) {
+        vdispl->devid = libxl__device_nextid(gc, domid,
+                (char*)libxl__device_kind_to_string(LIBXL__DEVICE_KIND_VDISPL));
+    }
+
+    return rc;
+}
+
+static int libxl__device_from_vdispl(libxl__gc *gc, uint32_t domid,
+                                     libxl_device_vdispl *vdispl,
+                                     libxl__device *device)
+{
+   device->backend_devid   = vdispl->devid;
+   device->backend_domid   = vdispl->backend_domid;
+   device->backend_kind    = LIBXL__DEVICE_KIND_VDISPL;
+   device->devid           = vdispl->devid;
+   device->domid           = domid;
+   device->kind            = LIBXL__DEVICE_KIND_VDISPL;
+
+   return 0;
+}
+
+LIBXL_DEFINE_DEVICE_COMMIT(vdispl)
+
+static void libxl__device_vdispl_add(libxl__egc *egc, uint32_t domid,
+                                   libxl_device_vdispl *vdispl,
+                                   libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    int rc;
+
+    rc = libxl__device_vdispl_setdefault(gc, domid, vdispl);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 16, 1);
+
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, GCSPRINTF("%d", domid));
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, GCSPRINTF("%d", XenbusStateInitialising));
+    flexarray_append(back, "handle");
+    flexarray_append(back, GCSPRINTF("%d", vdispl->devid));
+
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, GCSPRINTF("%d", vdispl->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, GCSPRINTF("%d", XenbusStateInitialising));
+    flexarray_append(front, "handle");
+    flexarray_append(front, GCSPRINTF("%d", vdispl->devid));
+    flexarray_append(front, "be_alloc");
+    flexarray_append(front, GCSPRINTF("%d", vdispl->be_alloc));
+
+out:
+    libxl__device_vdispl_commit(egc, domid, vdispl, front, back, aodev, rc);
+}
+
+static int libxl__device_vdispl_getinfo(libxl__gc *gc, struct xs_handle *xsh,
+                                        const char* libxl_path,
+                                        libxl_vdisplinfo *info)
+{
+    char *val;
+
+    val = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/be_alloc", libxl_path));
+    info->be_alloc = val ? strtoul(val, NULL, 10) : 0;
+
+    return 0;
+}
+
+static void libxl__update_config_vdispl(libxl__gc *gc, void *dst, void *src)
+{
+    libxl_device_vdispl *d, *s;
+
+    d = (libxl_device_vdispl*)dst;
+    s = (libxl_device_vdispl*)src;
+
+    d->devid = s->devid;
+    d->be_alloc = s->be_alloc;
+}
+
+static int libxl_device_vdispl_compare(libxl_device_vdispl *d1,
+                                       libxl_device_vdispl *d2)
+{
+    return COMPARE_DEVID(d1, d2);
+}
+
+LIBXL_DEFINE_DEVICE_ADD(vdispl)
+static LIBXL_DEFINE_DEVICES_ADD(vdispl)
+LIBXL_DEFINE_DEVICE_REMOVE(vdispl)
+
+LIBXL_DEFINE_DEVICE_LIST_GET(vdispl)
+LIBXL_DEFINE_DEVICE_LIST_FREE(vdispl)
+
+LIBXL_DEFINE_DEVID_TO_DEVICE(vdispl)
+LIBXL_DEFINE_DEVICE_GETINFO(vdispl)
+
+DEFINE_DEVICE_TYPE_STRUCT(vdispl,
+    .update_config = libxl__update_config_vdispl
+);
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */