@@ -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
@@ -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)
@@ -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
};
@@ -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[];
@@ -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.
@@ -25,6 +25,7 @@ libxl__device_kind = Enumeration("device_kind", [
(8, "VTPM"),
(9, "VUSB"),
(10, "QUSB"),
+ (11, "VDISPL")
])
libxl__console_backend = Enumeration("console_backend", [
@@ -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);
new file mode 100644
@@ -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:
+ */