xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC 0/6] Set of PV drivers used by production project
@ 2016-05-19 14:37 Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 1/6] libxl: implementation of PV rtc device interface Iurii Mykhalskyi
                   ` (8 more replies)
  0 siblings, 9 replies; 12+ messages in thread
From: Iurii Mykhalskyi @ 2016-05-19 14:37 UTC (permalink / raw)
  To: embedded-pv-devel
  Cc: wei.liu2, stefano.stabellini, ian.jackson, ian.campbell, xen-devel

This patches introduce set of pv drivers interfaces.
Drivers interfaces list:
 - PV RTC - real-time clock
 - PV TTY - interface for pv version for device controlled by
    via tty (e.g. GPS)
 - PV Audio - sound interface virtualization
 - PV DRM - direct rengering manager virtualization
 - PV RPMSG - remove procedure call interface, in our case
    used for playback codecs virtualization

Iurii Mykhalskyi (2):
  libxl: implementation of PV rtc device interface
  libxl: implementation of PV tty device interface.

Pavlo Suikov (4):
  libxl: implementation of PV audio device interface
  libxl: implementation of PV event device interface
  libxl: implementation of PV DRM device interface
  libxl: implementation of PV RPMSG device interface

 tools/libxl/libxl.c                  | 1781 +++++++++++++++++++++++++++++++++-
 tools/libxl/libxl.h                  |  102 ++
 tools/libxl/libxl_create.c           |  214 +++-
 tools/libxl/libxl_device.c           |   12 +
 tools/libxl/libxl_internal.c         |    8 +
 tools/libxl/libxl_internal.h         |   88 +-
 tools/libxl/libxl_types.idl          |  131 +++
 tools/libxl/libxl_types_internal.idl |    6 +
 tools/libxl/libxl_utils.h            |   19 +
 tools/libxl/xl.h                     |   18 +
 tools/libxl/xl_cmdimpl.c             | 1035 +++++++++++++++++++-
 tools/libxl/xl_cmdtable.c            |   95 ++
 12 files changed, 3499 insertions(+), 10 deletions(-)

-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH RFC 1/6] libxl: implementation of PV rtc device interface
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
@ 2016-05-19 14:37 ` Iurii Mykhalskyi
  2016-05-23 16:45   ` Olaf Hering
  2016-06-06 13:37   ` Wei Liu
  2016-05-19 14:37 ` [PATCH RFC 2/6] libxl: implementation of PV audio " Iurii Mykhalskyi
                   ` (7 subsequent siblings)
  8 siblings, 2 replies; 12+ messages in thread
From: Iurii Mykhalskyi @ 2016-05-19 14:37 UTC (permalink / raw)
  To: embedded-pv-devel
  Cc: wei.liu2, stefano.stabellini, ian.jackson, ian.campbell, xen-devel

PV rtc device interface is implemented in libxl and xl with
full support for device control. No JSON parser for domain
configuration yet.

Signed-off-by: Iurii Mykhalskyi <iurii.mykhalskyi@globallogic.com>
Signed-off-by: Glib Golubytskyi <glib.golubytskyi@globallogic.com>
Signed-off-by: Iurii Konovalenko <iurii.konovalenko@globallogic.com>
---
 tools/libxl/libxl.c                  | 287 ++++++++++++++++++++++++++++++++++-
 tools/libxl/libxl.h                  |  17 +++
 tools/libxl/libxl_create.c           |  39 ++++-
 tools/libxl/libxl_device.c           |   2 +
 tools/libxl/libxl_internal.h         |  19 ++-
 tools/libxl/libxl_types.idl          |  19 +++
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_utils.h            |   3 +
 tools/libxl/xl.h                     |   3 +
 tools/libxl/xl_cmdimpl.c             | 161 +++++++++++++++++++-
 tools/libxl/xl_cmdtable.c            |  15 ++
 11 files changed, 558 insertions(+), 8 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index ac50bda..09c4bc7 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2323,6 +2323,277 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx,
     return rc;
 }
 
+/******************************************************************************/
+
+int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc)
+{
+    int rc;
+
+    rc = libxl__resolve_domid(gc, vrtc->backend_domname, &vrtc->backend_domid);
+
+    return rc;
+}
+
+static int libxl__device_from_vrtc(libxl__gc *gc, uint32_t domid, libxl_device_vrtc *vrtc, libxl__device *device)
+{
+   device->backend_devid   = vrtc->devid;
+   device->backend_domid   = vrtc->backend_domid;
+   device->backend_kind    = LIBXL__DEVICE_KIND_VRTC;
+   device->devid           = vrtc->devid;
+   device->domid           = domid;
+   device->kind            = LIBXL__DEVICE_KIND_VRTC;
+
+   return 0;
+}
+
+static int libxl__device_vrtc_from_xs_be(libxl__gc *gc,
+                                        const char *be_path,
+                                        libxl_device_vrtc *vrtc)
+{
+    const char *tmp;
+    int rc;
+
+    libxl_device_vrtc_init(vrtc);
+
+    tmp = READ_BACKEND(gc, "device-id");
+    if (tmp)
+        vrtc->devid = atoi(tmp);
+    else
+        vrtc->devid = 0;
+
+    rc = 0;
+ out:
+    return rc;
+}
+
+int libxl_devid_to_device_vrtc(libxl_ctx *ctx, uint32_t domid,
+                              int devid, libxl_device_vrtc *vrtc)
+{
+    GC_INIT(ctx);
+    char *dompath, *path;
+    int rc = ERROR_FAIL;
+
+    libxl_device_vrtc_init(vrtc);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    if (!dompath)
+        goto out;
+
+    path = libxl__xs_read(gc, XBT_NULL,
+                          libxl__sprintf(gc, "%s/device/vrtc/%d/backend",
+                                         dompath, devid));
+    if (!path)
+        goto out;
+
+    rc = libxl__device_vrtc_from_xs_be(gc, path, vrtc);
+    if (rc) goto out;
+
+    rc = 0;
+out:
+    GC_FREE;
+    return rc;
+}
+
+void libxl__device_vrtc_add(libxl__egc *egc, uint32_t domid, libxl_device_vrtc *vrtc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_vrtc vrtc_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_vrtc_init(&vrtc_saved);
+    libxl_device_vrtc_copy(CTX, &vrtc_saved, vrtc);
+
+    rc = libxl__device_vrtc_setdefault(gc, vrtc);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 32, 1);
+
+    if ((vrtc->devid = libxl__device_nextid(gc, domid, "vrtc")) < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    GCNEW(device);
+    rc = libxl__device_from_vrtc(gc, domid, vrtc, device);
+    if ( rc != 0 ) goto out;
+
+    flexarray_append(back, "device-id");
+    flexarray_append(back, GCSPRINTF("%d", vrtc->devid));
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, GCSPRINTF("%d", domid));
+    flexarray_append(back, "device");
+    flexarray_append(back, vrtc->device);
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, GCSPRINTF("%d", 1));
+
+    flexarray_append(front, "device-id");
+    flexarray_append(front, GCSPRINTF("%d", vrtc->devid));
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, GCSPRINTF("%d", vrtc->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, GCSPRINTF("%d", 1));
+
+    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);
+        LOG(INFO, "aodev updates JSON, libxl__get_domain_configuration returned %d", rc);
+        if (rc) goto out;
+
+        DEVICE_ADD(vrtc, vrtcs, domid, &vrtc_saved, COMPARE_DEVID, &d_config);
+    }
+
+    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) {              /* already exists in xenstore */
+            LOG(ERROR, "device already exists in xenstore");
+            aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+            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,
+                                                             back->count),
+                                  libxl__xs_kvs_of_flexarray(gc, front,
+                                                             front->count),
+                                  NULL);
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    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_device_vrtc_dispose(&vrtc_saved);
+    libxl_domain_config_dispose(&d_config);
+    aodev->rc = rc;
+    if(rc) aodev->callback(egc, aodev);
+    return;
+
+}
+
+libxl_device_vrtc *libxl_device_vrtc_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_vrtc* vrtcs = NULL;
+    char* fe_path = NULL;
+    char** dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vrtc", libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+    if (dir && ndirs) {
+       vrtcs = malloc(sizeof(*vrtcs) * ndirs);
+       libxl_device_vrtc* vrtc;
+       libxl_device_vrtc* end = vrtcs + ndirs;
+       for(vrtc = vrtcs; vrtc < end; ++vrtc, ++dir) {
+          char* tmp;
+
+          libxl_device_vrtc_init(vrtc);
+
+          vrtc->devid = atoi(*dir);
+
+          tmp = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend-id",
+                   fe_path, *dir));
+          vrtc->backend_domid = atoi(tmp);
+       }
+    }
+    *num = ndirs;
+
+    GC_FREE;
+    return vrtcs;
+}
+
+int libxl_device_vrtc_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vrtc *vrtc, libxl_vrtcinfo *vrtcinfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *vrtcpath;
+    char *val;
+    int rc = 0;
+
+    libxl_vrtcinfo_init(vrtcinfo);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    vrtcinfo->devid = vrtc->devid;
+
+    vrtcpath = GCSPRINTF("%s/device/vrtc/%d", dompath, vrtcinfo->devid);
+    vrtcinfo->backend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/backend", vrtcpath), NULL);
+
+    if (!vrtcinfo->backend) {
+        goto err;
+    }
+
+    if(!libxl__xs_read(gc, XBT_NULL, vrtcinfo->backend)) {
+       goto err;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/backend-id", vrtcpath));
+    vrtcinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/state", vrtcpath));
+    vrtcinfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/event-channel", vrtcpath));
+    vrtcinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/ring-ref", vrtcpath));
+    vrtcinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+
+    vrtcinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/frontend", vrtcinfo->backend), NULL);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/frontend-id", vrtcinfo->backend));
+    vrtcinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    goto exit;
+err:
+    rc = ERROR_FAIL;
+exit:
+    GC_FREE;
+    return rc;
+}
+
+
 
 /******************************************************************************/
 
@@ -4131,12 +4402,14 @@ out:
  * libxl_device_disk_destroy
  * libxl_device_nic_remove
  * libxl_device_nic_destroy
- * libxl_device_vtpm_remove
- * libxl_device_vtpm_destroy
  * libxl_device_vkb_remove
  * libxl_device_vkb_destroy
  * libxl_device_vfb_remove
  * libxl_device_vfb_destroy
+ * libxl_device_vtpm_remove
+ * libxl_device_vtpm_destroy
+ * libxl_device_vrtc_remove
+ * libxl_device_vrtc_destroy
  */
 #define DEFINE_DEVICE_REMOVE(type, removedestroy, f)                    \
     int libxl_device_##type##_##removedestroy(libxl_ctx *ctx,           \
@@ -4188,6 +4461,10 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 DEFINE_DEVICE_REMOVE(vtpm, remove, 0)
 DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
 
+/* vrtc */
+DEFINE_DEVICE_REMOVE(vrtc, remove, 0)
+DEFINE_DEVICE_REMOVE(vrtc, destroy, 1)
+
 /* channel/console hotunplug is not implemented. There are 2 possibilities:
  * 1. add support for secondary consoles to xenconsoled
  * 2. dynamically add/remove qemu chardevs via qmp messages. */
@@ -4201,6 +4478,7 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
  * libxl_device_disk_add
  * libxl_device_nic_add
  * libxl_device_vtpm_add
+ * libxl_device_vrtc_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -4232,6 +4510,9 @@ DEFINE_DEVICE_ADD(nic)
 /* vtpm */
 DEFINE_DEVICE_ADD(vtpm)
 
+/* vrtc */
+DEFINE_DEVICE_ADD(vrtc)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
@@ -6747,6 +7028,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
 
     MERGE(vtpm, vtpms, COMPARE_DEVID, {});
 
+    MERGE(vrtc, vrtcs, COMPARE_DEVID, {});
+
     MERGE(pci, pcidevs, COMPARE_PCI, {});
 
     /* Take care of removable device. We maintain invariant in the
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index fa5aedd..9243b86 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1435,6 +1435,23 @@ 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);
 
+/* RTC */
+int libxl_device_vrtc_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vrtc *vrtc,
+                          const libxl_asyncop_how *ao_how)
+                          LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vrtc_remove(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_vrtc *vrtc,
+                             const libxl_asyncop_how *ao_how)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vrtc_destroy(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vrtc *vrtc,
+                              const libxl_asyncop_how *ao_how)
+                              LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vrtc *libxl_device_vrtc_list(libxl_ctx *ctx, uint32_t domid, int *num);
+int libxl_device_vrtc_getinfo(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vrtc *vrtc, libxl_vrtcinfo *vrtcinfo);
+
 /* 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 1c0579c..1206c34 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -734,6 +734,8 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *aodevs,
 
 static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
+static void domcreate_attach_vrtcs(libxl__egc *egc, libxl__multidev *multidev,
+                                   int ret);
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
                                  int ret);
 static void domcreate_attach_dtdev(libxl__egc *egc,
@@ -1392,12 +1394,45 @@ static void domcreate_attach_vtpms(libxl__egc *egc,
    if (d_config->num_vtpms > 0) {
        /* Attach vtpms */
        libxl__multidev_begin(ao, &dcs->multidev);
-       dcs->multidev.callback = domcreate_attach_pci;
+       dcs->multidev.callback = domcreate_attach_vrtcs;
        libxl__add_vtpms(egc, ao, domid, d_config, &dcs->multidev);
        libxl__multidev_prepared(egc, &dcs->multidev, 0);
        return;
    }
 
+   domcreate_attach_vrtcs(egc, multidev, 0);
+   return;
+
+error_out:
+   assert(ret);
+   domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_vrtcs(libxl__egc *egc,
+                                   libxl__multidev *multidev,
+                                   int ret)
+{
+   libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+   STATE_AO_GC(dcs->ao);
+   int domid = dcs->guest_domid;
+
+   libxl_domain_config* const d_config = dcs->guest_config;
+
+   if(ret) {
+       LOG(ERROR, "unable to add vtpm devices");
+       goto error_out;
+   }
+
+    /* Plug vrtc devices */
+   if (d_config->num_vrtcs > 0) {
+       /* Attach vrtcs */
+       libxl__multidev_begin(ao, &dcs->multidev);
+       dcs->multidev.callback = domcreate_attach_pci;
+       libxl__add_vrtcs(egc, ao, domid, d_config, &dcs->multidev);
+       libxl__multidev_prepared(egc, &dcs->multidev, 0);
+       return;
+   }
+
    domcreate_attach_pci(egc, multidev, 0);
    return;
 
@@ -1419,7 +1454,7 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
     libxl_domain_config *const d_config = dcs->guest_config;
 
     if (ret) {
-        LOG(ERROR, "unable to add vtpm devices");
+        LOG(ERROR, "unable to add vrtc devices");
         goto error_out;
     }
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 8bb5e93..72f09a0 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -544,6 +544,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_disks
  * libxl__add_nics
  * libxl__add_vtpms
+ * libxl__add_vrtcs
  */
 
 #define DEFINE_DEVICES_ADD(type)                                        \
@@ -563,6 +564,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
 DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vtpm)
+DEFINE_DEVICES_ADD(vrtc)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 5b0b50a..2a423b5 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -476,7 +476,8 @@ typedef struct {
 #define QEMU_BACKEND(dev) (\
     (dev)->backend_kind == LIBXL__DEVICE_KIND_QDISK || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VFB || \
-    (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD)
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD || \
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC)
 
 #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
@@ -1186,6 +1187,7 @@ _hidden int libxl__device_disk_setdefault(libxl__gc *gc,
 _hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
                                          uint32_t domid);
 _hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm);
+_hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc);
 _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
 _hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
 _hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
@@ -2549,6 +2551,8 @@ struct libxl__multidev {
  * xenstore entry afterwards. We have both JSON and xenstore entry,
  * it's a valid state.
  */
+
+/* AO operation to connect a disk device */
 _hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_disk *disk,
                                     libxl__ao_device *aodev);
@@ -2558,9 +2562,15 @@ _hidden void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
                                    libxl_device_nic *nic,
                                    libxl__ao_device *aodev);
 
+/* AO operation to connect a tpm device */
 _hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
-                                   libxl_device_vtpm *vtpm,
-                                   libxl__ao_device *aodev);
+                                    libxl_device_vtpm *vtpm,
+                                    libxl__ao_device *aodev);
+
+/* AO operation to connect an rtc device */
+_hidden void libxl__device_vrtc_add(libxl__egc *egc, uint32_t domid,
+                                    libxl_device_vrtc *vrtc,
+                                    libxl__ao_device *aodev);
 
 /* Internal function to connect a vkb device */
 _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
@@ -3278,6 +3288,9 @@ _hidden void libxl__add_vtpms(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
 
+_hidden void libxl__add_vrtcs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                             libxl_domain_config *d_config,
+                             libxl__multidev *multidev);
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index cd12117..27a750c 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -544,6 +544,13 @@ libxl_device_vkb = Struct("device_vkb", [
     ("devid", libxl_devid),
     ])
 
+libxl_device_vrtc = Struct("device_vrtc", [
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+    ("devid", libxl_devid),
+    ("device", string),
+    ])
+
 libxl_device_disk = Struct("device_disk", [
     ("backend_domid", libxl_domid),
     ("backend_domname", string),
@@ -631,6 +638,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")),
+    ("vrtcs", Array(libxl_device_vrtc, "num_vrtcs")),
     # a channel manifests as a console with a name,
     # see docs/misc/channels.txt
     ("channels", Array(libxl_device_channel, "num_channels")),
@@ -676,6 +684,17 @@ libxl_vtpminfo = Struct("vtpminfo", [
     ("uuid", libxl_uuid),
     ], dir=DIR_OUT)
 
+libxl_vrtcinfo = Struct("vrtcinfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("evtch", integer),
+    ("rref", integer),
+    ], dir=DIR_OUT)
+
 libxl_vcpuinfo = Struct("vcpuinfo", [
     ("vcpuid", uint32),
     ("cpu", uint32),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 5e55685..764efb8 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -22,6 +22,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (6, "VKBD"),
     (7, "CONSOLE"),
     (8, "VTPM"),
+    (9, "VRTC"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 339ebdf..d1b825c 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -77,6 +77,9 @@ int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
 int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vtpm *vtpm);
 
+int libxl_devid_to_device_vrtc(libxl_ctx *ctx, uint32_t domid,
+                               int devid, libxl_device_vrtc *vrtc);
+
 int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits);
     /* Allocated bimap is from malloc, libxl_bitmap_dispose() to be
      * called by the application when done. */
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 13bccba..3d46efb 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -82,6 +82,9 @@ int main_channellist(int argc, char **argv);
 int main_blockattach(int argc, char **argv);
 int main_blocklist(int argc, char **argv);
 int main_blockdetach(int argc, char **argv);
+int main_vrtcattach(int argc, char **argv);
+int main_vrtclist(int argc, char **argv);
+int main_vrtcdetach(int argc, char **argv);
 int main_vtpmattach(int argc, char **argv);
 int main_vtpmlist(int argc, char **argv);
 int main_vtpmdetach(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 63a6b17..77701e0 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1262,7 +1262,7 @@ static void parse_config_data(const char *config_source,
     const char *buf;
     long l, vcpus = 0;
     XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
@@ -1844,6 +1844,54 @@ static void parse_config_data(const char *config_source,
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vrtc", &vrtcs, 0, 0)) {
+        d_config->num_vrtcs = 0;
+        d_config->vrtcs = NULL;
+        while ((buf = xlu_cfg_get_listitem(vrtcs, d_config->num_vrtcs)) != NULL) {
+            libxl_device_vrtc *vrtc;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            vrtc = ARRAY_EXTEND_INIT(d_config->vrtcs, d_config->num_vrtcs,
+                                     libxl_device_vrtc_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse vrtc configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backendid")) {
+                    vrtc->backend_domid = atoi(value);
+                } else if (!strcmp(key, "backend")) {
+                    replace_string(&vrtc->backend_domname, value);
+                } else if (!strcmp(key, "devid")) {
+                    vrtc->devid = atoi(value);
+                } else if (!strcmp(key, "device")) {
+                    replace_string(&vrtc->device, value);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
     if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
         d_config->num_channels = 0;
         d_config->channels = NULL;
@@ -6735,6 +6783,117 @@ int main_blockdetach(int argc, char **argv)
     return rc;
 }
 
+int main_vrtcattach(int argc, char **argv)
+{
+
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_vrtc vrtc;
+    /*  XLU_Config *config = 0; */
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vrtc-attach", 2) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+    if (optind < argc) {
+        replace_string(&vrtc.device, argv[optind]);
+    }
+    optind++;
+
+/* TODO: fix this temporary hardcode */
+    vrtc.backend_domname = "Domain-D";
+    vrtc.backend_domid = 1;
+
+    if (dryrun_only) {
+        char *json = libxl_device_vrtc_to_json(ctx, &vrtc);
+        printf("vrtc: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_vrtc_add(ctx, fe_domid, &vrtc, 0)) {
+        fprintf(stderr, "libxl_device_vrtc_add failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+int main_vrtclist(int argc, char **argv)
+{
+	int opt;
+	int i, nb;
+	libxl_device_vrtc *vrtcs;
+	libxl_vrtcinfo vrtcinfo;
+
+	SWITCH_FOREACH_OPT(opt, "", NULL, "vrtc-list", 1) {
+		/* No options */
+	}
+
+	/* vrtcinfo.uuid should be outputted too */
+	printf("%-5s %-3s %-6s %-5s %-6s %-8s %-40s %-40s\n",
+			"Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path", "FE-path");
+	for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+		uint32_t domid;
+		if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+			fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+			continue;
+		}
+		vrtcs = libxl_device_vrtc_list(ctx, domid, &nb);
+		if (!vrtcs) {
+			continue;
+		}
+		for (i=0; i<nb; i++) {
+			if (!libxl_device_vrtc_getinfo(ctx, domid, &vrtcs[i], &vrtcinfo)) {
+				/*      Vdev BE   hdl  st   evch rref BE-path FE-path UUID */
+				printf("%-5d %-3d %-6d %-5d %-6d %-8d %-40s %-40s\n",
+						vrtcinfo.devid, vrtcinfo.backend_id, vrtcinfo.frontend_id,
+						vrtcinfo.state, vrtcinfo.evtch, vrtcinfo.rref, vrtcinfo.backend,
+						vrtcinfo.frontend);
+				libxl_vrtcinfo_dispose(&vrtcinfo);
+			}
+			libxl_device_vrtc_dispose(&vrtcs[i]);
+		}
+		free(vrtcs);
+	}
+	return 0;
+}
+
+int main_vrtcdetach(int argc, char **argv)
+{
+    uint32_t domid, devid;
+    int opt, rc = 0;
+    libxl_device_vrtc vrtc;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vrtc-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    if (libxl_devid_to_device_vrtc(ctx, domid, devid, &vrtc)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_vrtc_remove(ctx, domid, &vrtc, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vrtc_remove failed.\n");
+        return 1;
+    }
+
+    libxl_device_vrtc_dispose(&vrtc);
+    return rc;
+}
+
 int main_vtpmattach(int argc, char **argv)
 {
     int opt;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index 0071f12..8b8971e 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -351,6 +351,21 @@ struct cmd_spec cmd_table[] = {
       "Destroy a domain's virtual block device",
       "<Domain> <DevId>",
     },
+    { "vrtc-attach",
+      &main_vrtcattach, 1, 1,
+      "Create a new virtual rtc device",
+      "<Domain> <Device>",
+    },
+    { "vrtc-list",
+      &main_vrtclist, 0, 0,
+      "List virtual rtc devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vrtc-detach",
+      &main_vrtcdetach, 0, 1,
+      "Destroy a domain's virtual rtc device",
+      "<Domain> <DevId>",
+    },
     { "vtpm-attach",
       &main_vtpmattach, 1, 1,
       "Create a new virtual TPM device",
-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH RFC 2/6] libxl: implementation of PV audio device interface
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 1/6] libxl: implementation of PV rtc device interface Iurii Mykhalskyi
@ 2016-05-19 14:37 ` Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 3/6] libxl: implementation of PV tty " Iurii Mykhalskyi
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Iurii Mykhalskyi @ 2016-05-19 14:37 UTC (permalink / raw)
  To: embedded-pv-devel
  Cc: wei.liu2, stefano.stabellini, ian.jackson, ian.campbell, xen-devel

From: Pavlo Suikov <pavlo.suikov@globallogic.com>

PV Audio device interface is implemented in libxl and xl with
full support for device control

Signed-off-by: Pavlo Suikov <pavlo.suikov@globallogic.com>
Signed-off-by: Glib Golubytskyi <glib.golubytskyi@globallogic.com>
Signed-off-by: Iurii Konovalenko <iurii.konovalenko@globallogic.com>
---
 tools/libxl/libxl.c                  | 351 ++++++++++++++++++++++++++++++++++-
 tools/libxl/libxl.h                  |  16 ++
 tools/libxl/libxl_create.c           |  39 +++-
 tools/libxl/libxl_device.c           |   2 +
 tools/libxl/libxl_internal.c         |   4 +
 tools/libxl/libxl_internal.h         |  20 +-
 tools/libxl/libxl_types.idl          |  32 ++++
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_utils.h            |   3 +
 tools/libxl/xl.h                     |   3 +
 tools/libxl/xl_cmdimpl.c             | 229 ++++++++++++++++++++++-
 tools/libxl/xl_cmdtable.c            |  20 ++
 12 files changed, 715 insertions(+), 5 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 09c4bc7..d96172d 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2593,7 +2593,344 @@ exit:
     return rc;
 }
 
+/******************************************************************************/
+
+int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd)
+{
+    int rc;
+
+    rc = libxl__resolve_domid(gc, vsnd->backend_domname, &vsnd->backend_domid);
+
+    return rc;
+}
+
+static int libxl__device_from_vsnd(libxl__gc *gc, uint32_t domid, libxl_device_vsnd *vsnd, libxl__device *device)
+{
+   device->backend_devid   = vsnd->devid;
+   device->backend_domid   = vsnd->backend_domid;
+   device->backend_kind    = LIBXL__DEVICE_KIND_VSND;
+   device->devid           = vsnd->devid;
+   device->domid           = domid;
+   device->kind            = LIBXL__DEVICE_KIND_VSND;
+
+   return 0;
+}
+
+static int libxl__device_vsnd_from_xs_be(libxl__gc *gc,
+                                        const char *be_path,
+                                        libxl_device_vsnd *vsnd)
+{
+    const char *tmp;
+    int rc;
+
+    libxl_device_vsnd_init(vsnd);
+
+    tmp = READ_BACKEND(gc, "device-id");
+    if (tmp)
+        vsnd->devid = atoi(tmp);
+    else
+        vsnd->devid = 0;
+
+    vsnd->short_name = READ_BACKEND(gc, "short-name");
+    vsnd->long_name = READ_BACKEND(gc, "long-name");
+    vsnd->sample_formats = READ_BACKEND(gc, "sample-formats");
+    vsnd->rates = READ_BACKEND(gc, "rates");
+
+    tmp = READ_BACKEND(gc, "channels-min");
+    if (tmp)
+        vsnd->channels_min = atoi(tmp);
+    else
+        vsnd->channels_min = 0;
+
+    tmp = READ_BACKEND(gc, "channels-max");
+    if (tmp)
+        vsnd->channels_max = atoi(tmp);
+    else
+        vsnd->channels_max = 0;
+
+    tmp = READ_BACKEND(gc, "priority");
+    if (tmp)
+        vsnd->priority = atoi(tmp);
+    else
+        vsnd->priority = 0;
+
+    vsnd->slave_device = READ_BACKEND(gc, "slave-device");
+
+    rc = 0;
+ out:
+    return rc;
+}
+
+int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid,
+                              int devid, libxl_device_vsnd *vsnd)
+{
+    GC_INIT(ctx);
+    char *dompath, *path;
+    int rc = ERROR_FAIL;
+
+    libxl_device_vsnd_init(vsnd);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    if (!dompath)
+        goto out;
+
+    path = libxl__xs_read(gc, XBT_NULL,
+                          libxl__sprintf(gc, "%s/device/vsnd/%d/backend",
+                                         dompath, devid));
+    if (!path)
+        goto out;
+
+    rc = libxl__device_vsnd_from_xs_be(gc, path, vsnd);
+    if (rc) goto out;
+
+    rc = 0;
+out:
+    GC_FREE;
+    return rc;
+}
+
+
+void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid, libxl_device_vsnd *vsnd, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_vsnd vsnd_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_vsnd_init(&vsnd_saved);
+    libxl_device_vsnd_copy(CTX, &vsnd_saved, vsnd);
+
+    rc = libxl__device_vsnd_setdefault(gc, vsnd);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 32, 1);
+    back = flexarray_make(gc, 32, 1);
+    if (vsnd->devid == -1) {
+        if ((vsnd->devid = libxl__device_nextid(gc, domid, "vsnd")) < 0) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    libxl__update_config_vsnd(gc, &vsnd_saved, vsnd);
+
+    GCNEW(device);
+    rc = libxl__device_from_vsnd(gc, domid, vsnd, device);
+    if ( rc != 0 ) goto out;
+
+    flexarray_append(back, "DomD");
+    flexarray_append(back, "1");
+    flexarray_append(back, "DomU");
+    flexarray_append(back, "2");
+    flexarray_append(back, "device-id");
+    flexarray_append(back, GCSPRINTF("%d", vsnd->devid));
+    flexarray_append(back, "short-name");
+    flexarray_append(back, vsnd->short_name);
+    flexarray_append(back, "long-name");
+    flexarray_append(back, vsnd->long_name);
+    flexarray_append(back, "sample-formats");
+    flexarray_append(back, vsnd->sample_formats);
+    flexarray_append(back, "rates");
+    flexarray_append(back, vsnd->rates);
+    flexarray_append(back, "channels-min");
+    flexarray_append(back, GCSPRINTF("%d", vsnd->channels_min));
+    flexarray_append(back, "channels-max");
+    flexarray_append(back, GCSPRINTF("%d", vsnd->channels_max));
+    flexarray_append(back, "priority");
+    flexarray_append(back, GCSPRINTF("%d", vsnd->priority));
+    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", 1));
+    flexarray_append(back, "slave-device");
+    flexarray_append(back, vsnd->slave_device);
+
+    flexarray_append(front, "device-id");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->devid));
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, GCSPRINTF("%d", 1));
+    flexarray_append(front, "alsa-card-id");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->alsa_card_id));
+    flexarray_append(front, "short-name");
+    flexarray_append(front, vsnd->short_name);
+    flexarray_append(front, "long-name");
+    flexarray_append(front, vsnd->long_name);
+    flexarray_append(front, "sample-formats");
+    flexarray_append(front, vsnd->sample_formats);
+    flexarray_append(front, "rates");
+    flexarray_append(front, vsnd->rates);
+    flexarray_append(front, "channels-min");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->channels_min));
+    flexarray_append(front, "channels-max");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->channels_max));
+    flexarray_append(front, "buffer-bytes-max");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->buffer_bytes_max));
+    flexarray_append(front, "period-bytes-min");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->period_bytes_min));
+    flexarray_append(front, "period-bytes-max");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->period_bytes_max));
+    flexarray_append(front, "period-min");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->period_min));
+    flexarray_append(front, "period-max");
+    flexarray_append(front, GCSPRINTF("%d", vsnd->period_max));
+
+    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);
+        LOG(INFO, "aodev updates JSON, libxl__get_domain_configuration returned %d", rc);
+        if (rc) goto out;
+
+        DEVICE_ADD(vsnd, vsnds, domid, &vsnd_saved, COMPARE_DEVID, &d_config);
+    }
+
+    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) {              /* already exists in xenstore */
+            LOG(ERROR, "device already exists in xenstore");
+            aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+            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,
+                                                             back->count),
+                                  libxl__xs_kvs_of_flexarray(gc, front,
+                                                             front->count),
+                                  NULL);
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    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_device_vsnd_dispose(&vsnd_saved);
+    libxl_domain_config_dispose(&d_config);
+    aodev->rc = rc;
+    if(rc) aodev->callback(egc, aodev);
+    return;
+
+}
+
+libxl_device_vsnd *libxl_device_vsnd_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_vsnd* vsnds = NULL;
+    char* fe_path = NULL;
+    char** dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vsnd", libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+    if (dir && ndirs) {
+       vsnds = malloc(sizeof(*vsnds) * ndirs);
+       libxl_device_vsnd* vsnd;
+       libxl_device_vsnd* end = vsnds + ndirs;
+       for(vsnd = vsnds; vsnd < end; ++vsnd, ++dir) {
+          char* tmp;
+
+          libxl_device_vsnd_init(vsnd);
+
+          vsnd->devid = atoi(*dir);
+
+          tmp = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend-id",
+                   fe_path, *dir));
+          vsnd->backend_domid = atoi(tmp);
+       }
+    }
+    *num = ndirs;
+
+    GC_FREE;
+    return vsnds;
+}
+
+int libxl_device_vsnd_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vsnd *vsnd, libxl_vsndinfo *vsndinfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *vsndpath;
+    char *val;
+    int rc = 0;
+
+    libxl_vsndinfo_init(vsndinfo);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    vsndinfo->devid = vsnd->devid;
+
+    vsndpath = GCSPRINTF("%s/device/vsnd/%d", dompath, vsndinfo->devid);
+    vsndinfo->backend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/backend", vsndpath), NULL);
+    if (!vsndinfo->backend) {
+        goto err;
+    }
+    if(!libxl__xs_read(gc, XBT_NULL, vsndinfo->backend)) {
+       goto err;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/backend-id", vsndpath));
+    vsndinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/state", vsndpath));
+    vsndinfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/event-channel", vsndpath));
+    vsndinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/ring-ref", vsndpath));
+    vsndinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+
+    vsndinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/frontend", vsndinfo->backend), NULL);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/frontend-id", vsndinfo->backend));
+    vsndinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    goto exit;
+err:
+    rc = ERROR_FAIL;
+exit:
+    GC_FREE;
+    return rc;
+}
 
 /******************************************************************************/
 
@@ -4410,6 +4747,8 @@ out:
  * libxl_device_vtpm_destroy
  * libxl_device_vrtc_remove
  * libxl_device_vrtc_destroy
+ * libxl_device_vsnd_remove
+ * libxl_device_vsnd_destroy
  */
 #define DEFINE_DEVICE_REMOVE(type, removedestroy, f)                    \
     int libxl_device_##type##_##removedestroy(libxl_ctx *ctx,           \
@@ -4465,6 +4804,10 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
 DEFINE_DEVICE_REMOVE(vrtc, remove, 0)
 DEFINE_DEVICE_REMOVE(vrtc, destroy, 1)
 
+/* vsnd */
+DEFINE_DEVICE_REMOVE(vsnd, remove, 0)
+DEFINE_DEVICE_REMOVE(vsnd, destroy, 1)
+
 /* channel/console hotunplug is not implemented. There are 2 possibilities:
  * 1. add support for secondary consoles to xenconsoled
  * 2. dynamically add/remove qemu chardevs via qmp messages. */
@@ -4479,6 +4822,7 @@ DEFINE_DEVICE_REMOVE(vrtc, destroy, 1)
  * libxl_device_nic_add
  * libxl_device_vtpm_add
  * libxl_device_vrtc_add
+ * libxl_device_vsnd_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -4513,6 +4857,9 @@ DEFINE_DEVICE_ADD(vtpm)
 /* vrtc */
 DEFINE_DEVICE_ADD(vrtc)
 
+/* vsnd */
+DEFINE_DEVICE_ADD(vsnd)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
@@ -6956,7 +7303,7 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
         d_config->b_info.max_memkb = max_memkb;
     }
 
-    /* Devices: disk, nic, vtpm, pcidev etc. */
+    /* Devices: disk, nic, vtpm, vsnd, pcidev etc. */
 
     /* The MERGE macro implements following logic:
      * 0. retrieve JSON (done by now)
@@ -7030,6 +7377,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
 
     MERGE(vrtc, vrtcs, COMPARE_DEVID, {});
 
+    MERGE(vsnd, vsnds, COMPARE_DEVID, {});
+
     MERGE(pci, pcidevs, COMPARE_PCI, {});
 
     /* Take care of removable device. We maintain invariant in the
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 9243b86..3cb67e2 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1451,6 +1451,22 @@ int libxl_device_vrtc_destroy(libxl_ctx *ctx, uint32_t domid,
 libxl_device_vrtc *libxl_device_vrtc_list(libxl_ctx *ctx, uint32_t domid, int *num);
 int libxl_device_vrtc_getinfo(libxl_ctx *ctx, uint32_t domid,
                               libxl_device_vrtc *vrtc, libxl_vrtcinfo *vrtcinfo);
+/* Audio */
+int libxl_device_vsnd_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vsnd *vsnd,
+                          const libxl_asyncop_how *ao_how)
+                          LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vsnd_remove(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_vsnd *vsnd,
+                             const libxl_asyncop_how *ao_how)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vsnd_destroy(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vsnd *vsnd,
+                              const libxl_asyncop_how *ao_how)
+                              LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vsnd *libxl_device_vsnd_list(libxl_ctx *ctx, uint32_t domid, int *num);
+int libxl_device_vsnd_getinfo(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vsnd *vsnd, libxl_vsndinfo *vsndinfo);
 
 /* Keyboard */
 int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 1206c34..8ff4178 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -736,6 +736,8 @@ static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_vrtcs(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
+static void domcreate_attach_vsnds(libxl__egc *egc, libxl__multidev *multidev,
+                                   int ret);
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
                                  int ret);
 static void domcreate_attach_dtdev(libxl__egc *egc,
@@ -1427,12 +1429,45 @@ static void domcreate_attach_vrtcs(libxl__egc *egc,
    if (d_config->num_vrtcs > 0) {
        /* Attach vrtcs */
        libxl__multidev_begin(ao, &dcs->multidev);
-       dcs->multidev.callback = domcreate_attach_pci;
+       dcs->multidev.callback = domcreate_attach_vsnds;
        libxl__add_vrtcs(egc, ao, domid, d_config, &dcs->multidev);
        libxl__multidev_prepared(egc, &dcs->multidev, 0);
        return;
    }
 
+   domcreate_attach_vsnds(egc, multidev, 0);
+   return;
+
+error_out:
+   assert(ret);
+   domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_vsnds(libxl__egc *egc,
+                                   libxl__multidev *multidev,
+                                   int ret)
+{
+   libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+   STATE_AO_GC(dcs->ao);
+   int domid = dcs->guest_domid;
+
+   libxl_domain_config* const d_config = dcs->guest_config;
+
+   if(ret) {
+       LOG(ERROR, "unable to add vrtc devices");
+       goto error_out;
+   }
+
+   /* Plug vsnd devices */
+   if (d_config->num_vsnds > 0) {
+       /* Attach vsnds */
+       libxl__multidev_begin(ao, &dcs->multidev);
+       dcs->multidev.callback = domcreate_attach_pci;
+       libxl__add_vsnds(egc, ao, domid, d_config, &dcs->multidev);
+       libxl__multidev_prepared(egc, &dcs->multidev, 0);
+       return;
+   }
+
    domcreate_attach_pci(egc, multidev, 0);
    return;
 
@@ -1454,7 +1489,7 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
     libxl_domain_config *const d_config = dcs->guest_config;
 
     if (ret) {
-        LOG(ERROR, "unable to add vrtc devices");
+        LOG(ERROR, "unable to add vsnd devices");
         goto error_out;
     }
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 72f09a0..419af16 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -545,6 +545,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_nics
  * libxl__add_vtpms
  * libxl__add_vrtcs
+ * libxl__add_vsnds
  */
 
 #define DEFINE_DEVICES_ADD(type)                                        \
@@ -565,6 +566,7 @@ DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vtpm)
 DEFINE_DEVICES_ADD(vrtc)
+DEFINE_DEVICES_ADD(vsnd)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c
index 366ea05..f75840d 100644
--- a/tools/libxl/libxl_internal.c
+++ b/tools/libxl/libxl_internal.c
@@ -547,6 +547,10 @@ void libxl__update_domain_configuration(libxl__gc *gc,
     for (i = 0; i < src->num_vtpms; i++)
         libxl__update_config_vtpm(gc, &dst->vtpms[i], &src->vtpms[i]);
 
+    /* update vsnd information */
+    for (i = 0; i < src->num_vsnds; i++)
+        libxl__update_config_vsnd(gc, &dst->vsnds[i], &src->vsnds[i]);
+
     /* update guest UUID */
     libxl_uuid_copy(CTX, &dst->c_info.uuid, &src->c_info.uuid);
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 2a423b5..d78dd79 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -477,7 +477,8 @@ typedef struct {
     (dev)->backend_kind == LIBXL__DEVICE_KIND_QDISK || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VFB || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD || \
-    (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC)
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC || \
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VSND)
 
 #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
@@ -1188,6 +1189,7 @@ _hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
                                          uint32_t domid);
 _hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm);
 _hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc);
+_hidden int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd);
 _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
 _hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
 _hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
@@ -2572,6 +2574,11 @@ _hidden void libxl__device_vrtc_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_vrtc *vrtc,
                                     libxl__ao_device *aodev);
 
+/* AO operation to connect a sound device */
+_hidden void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid,
+                                    libxl_device_vsnd *vsnd,
+                                    libxl__ao_device *aodev);
+
 /* Internal function to connect a vkb device */
 _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
                                   libxl_device_vkb *vkb);
@@ -3291,6 +3298,10 @@ _hidden void libxl__add_vtpms(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
 _hidden void libxl__add_vrtcs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
+
+_hidden void libxl__add_vsnds(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                             libxl_domain_config *d_config,
+                             libxl__multidev *multidev);
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
@@ -3954,6 +3965,13 @@ static inline void libxl__update_config_vtpm(libxl__gc *gc,
     libxl_uuid_copy(CTX, &dst->uuid, &src->uuid);
 }
 
+static inline void libxl__update_config_vsnd(libxl__gc *gc,
+                                             libxl_device_vsnd *dst,
+                                             libxl_device_vsnd *src)
+{
+    dst->devid = src->devid;
+}
+
 /* Macros used to compare device identifier. Returns true if the two
  * devices have same identifier. */
 #define COMPARE_DEVID(a, b) ((a)->devid == (b)->devid)
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 27a750c..8fa29b1 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -551,6 +551,26 @@ libxl_device_vrtc = Struct("device_vrtc", [
     ("device", string),
     ])
 
+libxl_device_vsnd = Struct("device_vsnd", [
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+    ("devid", libxl_devid),
+    ("short_name", string),
+    ("long_name", string),
+    ("sample_formats", string),
+    ("rates", string),
+    ("channels_min", integer),
+    ("channels_max", integer),
+    ("priority", integer),
+    ("slave_device", string),
+    ("alsa_card_id", integer),
+    ("buffer_bytes_max", integer),
+    ("period_bytes_min", integer),
+    ("period_bytes_max", integer),
+    ("period_min", integer),
+    ("period_max", integer),
+    ])
+
 libxl_device_disk = Struct("device_disk", [
     ("backend_domid", libxl_domid),
     ("backend_domname", string),
@@ -639,6 +659,7 @@ libxl_domain_config = Struct("domain_config", [
     ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
     ("vrtcs", Array(libxl_device_vrtc, "num_vrtcs")),
+    ("vsnds", Array(libxl_device_vsnd, "num_vsnds")),
     # a channel manifests as a console with a name,
     # see docs/misc/channels.txt
     ("channels", Array(libxl_device_channel, "num_channels")),
@@ -695,6 +716,17 @@ libxl_vrtcinfo = Struct("vrtcinfo", [
     ("rref", integer),
     ], dir=DIR_OUT)
 
+libxl_vsndinfo = Struct("vsndinfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("evtch", integer),
+    ("rref", integer),
+    ], dir=DIR_OUT)
+
 libxl_vcpuinfo = Struct("vcpuinfo", [
     ("vcpuid", uint32),
     ("cpu", uint32),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 764efb8..ec63e23 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -23,6 +23,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (7, "CONSOLE"),
     (8, "VTPM"),
     (9, "VRTC"),
+    (10, "VSND"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index d1b825c..f6532ce 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -80,6 +80,9 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
 int libxl_devid_to_device_vrtc(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vrtc *vrtc);
 
+int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid,
+                               int devid, libxl_device_vsnd *vsnd);
+
 int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits);
     /* Allocated bimap is from malloc, libxl_bitmap_dispose() to be
      * called by the application when done. */
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 3d46efb..81a78c0 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -85,6 +85,9 @@ int main_blockdetach(int argc, char **argv);
 int main_vrtcattach(int argc, char **argv);
 int main_vrtclist(int argc, char **argv);
 int main_vrtcdetach(int argc, char **argv);
+int main_vsndattach(int argc, char **argv);
+int main_vsndlist(int argc, char **argv);
+int main_vsnddetach(int argc, char **argv);
 int main_vtpmattach(int argc, char **argv);
 int main_vtpmlist(int argc, char **argv);
 int main_vtpmdetach(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 77701e0..cb2d8c6 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -627,6 +627,15 @@ static void set_default_nic_values(libxl_device_nic *nic)
     }
 }
 
+static void set_default_vsnd_values(libxl_device_vsnd *vsnd)
+{
+    vsnd->short_name = "Unknown";
+    vsnd->long_name = "Unknown";
+    vsnd->sample_formats = "";
+    vsnd->rates = "";
+    vsnd->slave_device = "";
+}
+
 static void split_string_into_string_list(const char *str,
                                           const char *delim,
                                           libxl_string_list *psl)
@@ -1262,7 +1271,7 @@ static void parse_config_data(const char *config_source,
     const char *buf;
     long l, vcpus = 0;
     XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs, *vsnds;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
@@ -1892,6 +1901,83 @@ static void parse_config_data(const char *config_source,
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vsnd", &vsnds, 0, 0)) {
+        d_config->num_vsnds = 0;
+        d_config->vsnds = NULL;
+        while ((buf = xlu_cfg_get_listitem(vsnds, d_config->num_vsnds)) != NULL) {
+            libxl_device_vsnd *vsnd;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            vsnd = ARRAY_EXTEND_INIT(d_config->vsnds, d_config->num_vsnds,
+                                   libxl_device_vsnd_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse vsnd configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backendid")) {
+                    vsnd->backend_domid = atoi(value);
+                } else if (!strcmp(key, "backend")) {
+                    replace_string(&vsnd->backend_domname, value);
+                } else if (!strcmp(key, "devid")) {
+                    vsnd->devid = atoi(value);
+                } else if (!strcmp(key, "shortname")) {
+                    replace_string(&vsnd->short_name, value);
+                } else if (!strcmp(key, "longname")) {
+                    replace_string(&vsnd->long_name, value);
+                } else if (!strcmp(key, "sampleformats")) {
+                    replace_string(&vsnd->sample_formats, value);
+                } else if (!strcmp(key, "rates")) {
+                    replace_string(&vsnd->rates, value);
+                } else if (!strcmp(key, "channels_min")) {
+                    vsnd->channels_min = atoi(value);
+                } else if (!strcmp(key, "channels_max")) {
+                    vsnd->channels_max = atoi(value);
+                } else if (!strcmp(key, "priority")) {
+                    vsnd->priority = atoi(value);
+                } else if (!strcmp(key, "slave")) {
+                    replace_string(&vsnd->slave_device, value);
+                } else if (!strcmp(key, "alsacardid")) {
+                    vsnd->alsa_card_id = atoi(value);
+                } else if (!strcmp(key, "bufferbytesmax")) {
+                    vsnd->buffer_bytes_max = atoi(value);
+                } else if (!strcmp(key, "periodbytesmin")) {
+                    vsnd->period_bytes_min = atoi(value);
+                } else if (!strcmp(key, "periodbytesmax")) {
+                    vsnd->period_bytes_max = atoi(value);
+                } else if (!strcmp(key, "periodmin")) {
+                    vsnd->period_min = atoi(value);
+                } else if (!strcmp(key, "periodmax")) {
+                    vsnd->period_max = atoi(value);
+                } else {
+                    fprintf(stderr, "unknown vsnd parameter '%s',"
+                                  " ignoring\n", key);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
     if (!xlu_cfg_get_list (config, "channel", &channels, 0, 0)) {
         d_config->num_channels = 0;
         d_config->channels = NULL;
@@ -6894,6 +6980,147 @@ int main_vrtcdetach(int argc, char **argv)
     return rc;
 }
 
+
+int main_vsndattach(int argc, char **argv)
+{
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_vsnd vsnd;
+    char *oparg;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-attach", 1) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+    libxl_device_vsnd_init(&vsnd);
+    set_default_vsnd_values(&vsnd);
+
+    for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
+        if (MATCH_OPTION("backend", *argv, oparg)) {
+            replace_string(&vsnd.backend_domname, oparg);
+        } else if (MATCH_OPTION("devid", *argv, oparg)) {
+            vsnd.devid = atoi(oparg);
+        } else if (MATCH_OPTION("shortname", *argv, oparg)) {
+            replace_string(&vsnd.short_name, oparg);
+        } else if (MATCH_OPTION("longname", *argv, oparg)) {
+            replace_string(&vsnd.long_name, oparg);
+        } else if (MATCH_OPTION("sampleformats", *argv, oparg)) {
+            replace_string(&vsnd.sample_formats, oparg);
+        } else if (MATCH_OPTION("rates", *argv, oparg)) {
+            replace_string(&vsnd.rates, oparg);
+        } else if (MATCH_OPTION("channelsmin", *argv, oparg)) {
+            vsnd.channels_min = atoi(oparg);
+        } else if (MATCH_OPTION("channelsmax", *argv, oparg)) {
+            vsnd.channels_max = atoi(oparg);
+        } else if (MATCH_OPTION("priority", *argv, oparg)) {
+            vsnd.priority = atoi(oparg);
+        } else if (MATCH_OPTION("slave", *argv, oparg)) {
+            replace_string(&vsnd.slave_device, oparg);
+        } else if (MATCH_OPTION("alsacardid", *argv, oparg)) {
+            vsnd.alsa_card_id = atoi(oparg);
+        } else if (MATCH_OPTION("bufferbytesmax", *argv, oparg)) {
+            vsnd.buffer_bytes_max = atoi(oparg);
+        } else if (MATCH_OPTION("periodbytesmin", *argv, oparg)) {
+            vsnd.period_bytes_min = atoi(oparg);
+        } else if (MATCH_OPTION("periodbytesmax", *argv, oparg)) {
+            vsnd.period_bytes_max = atoi(oparg);
+        } else if (MATCH_OPTION("periodmin", *argv, oparg)) {
+            vsnd.period_min = atoi(oparg);
+        } else if (MATCH_OPTION("periodmax", *argv, oparg)) {
+            vsnd.period_max = atoi(oparg);
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
+            return 1;
+        }
+    }
+
+    if (dryrun_only) {
+        char *json = libxl_device_vsnd_to_json(ctx, &vsnd);
+        printf("vsnd: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_vsnd_add(ctx, fe_domid, &vsnd, 0)) {
+        fprintf(stderr, "libxl_device_vsnd_add failed.\n");
+        return 1;
+    }
+    return 0;
+}
+
+int main_vsndlist(int argc, char **argv)
+{
+    int opt;
+    int i, nb;
+    libxl_device_vsnd *vsnds;
+    libxl_vsndinfo vsndinfo;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-list", 1) {
+        /* No options */
+    }
+
+    printf("%-5s %-3s %-6s %-5s %-6s %-8s %-40s %-40s\n",
+           "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path", "FE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid;
+        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        vsnds = libxl_device_vsnd_list(ctx, domid, &nb);
+        if (!vsnds) {
+            continue;
+        }
+        for (i=0; i<nb; i++) {
+            if (!libxl_device_vsnd_getinfo(ctx, domid, &vsnds[i], &vsndinfo)) {
+                /*      Vdev BE   hdl  st   evch rref BE-path FE-path */
+                printf("%-5d %-3d %-6d %-5d %-6d %-8d %-40s %-40s\n",
+                       vsndinfo.devid, vsndinfo.backend_id, vsndinfo.frontend_id,
+                       vsndinfo.state, vsndinfo.evtch, vsndinfo.rref, vsndinfo.backend,
+                       vsndinfo.frontend);
+                libxl_vsndinfo_dispose(&vsndinfo);
+            }
+            libxl_device_vsnd_dispose(&vsnds[i]);
+        }
+        free(vsnds);
+    }
+    return 0;
+}
+
+int main_vsnddetach(int argc, char **argv)
+{
+    uint32_t domid, devid;
+    int opt, rc = 0;
+    libxl_device_vsnd vsnd;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vsnd-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    if (libxl_devid_to_device_vsnd(ctx, domid, devid, &vsnd)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_vsnd_remove(ctx, domid, &vsnd, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vsnd_remove failed.\n");
+        return 1;
+    }
+    libxl_device_vsnd_dispose(&vsnd);
+    return rc;
+}
+
 int main_vtpmattach(int argc, char **argv)
 {
     int opt;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index 8b8971e..78f0700 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -366,6 +366,26 @@ struct cmd_spec cmd_table[] = {
       "Destroy a domain's virtual rtc device",
       "<Domain> <DevId>",
     },
+    { "vsnd-attach",
+      &main_vsndattach, 1, 1,
+      "Create a new virtual audio device",
+      "<Domain> [backend=<BackDomain>] [devid=<DeviceId>] [shortname=<ShortName>]\n"
+      "[longname=<LongName>] [sampleformats=<SampleFormats>] [rates=<Rates>]\n"
+      "[channelsmin=<ChannelsMin>] [channelsmax=<ChannelsMax>] [priority=<Priority>]\n"
+      "[slave=<SlaveDevice>] [alsacardid=<AlsaCardId>] [bufferbytesmax=<BufferBytesMax>]\n"
+      "[periodbytesmin=<PeriodBytesMin>] [periodbytesmax=<PeriodBytesMax>]\n"
+      "[periodmin=<PeriodMin>] [periodmax=<PeriodMax>]",
+    },
+    { "vsnd-list",
+      &main_vsndlist, 0, 0,
+      "List virtual audio devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vsnd-detach",
+      &main_vsnddetach, 0, 1,
+      "Destroy a domain's virtual audio device",
+      "<Domain> <DevId|uuid>",
+    },
     { "vtpm-attach",
       &main_vtpmattach, 1, 1,
       "Create a new virtual TPM device",
-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH RFC 3/6] libxl: implementation of PV tty device interface.
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 1/6] libxl: implementation of PV rtc device interface Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 2/6] libxl: implementation of PV audio " Iurii Mykhalskyi
@ 2016-05-19 14:37 ` Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 4/6] libxl: implementation of PV event " Iurii Mykhalskyi
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Iurii Mykhalskyi @ 2016-05-19 14:37 UTC (permalink / raw)
  To: embedded-pv-devel
  Cc: wei.liu2, stefano.stabellini, ian.jackson, ian.campbell, xen-devel

PV tty device interface is implemented in libxl and xl with
full support for device control. No JSON parser for domain
configuration yet.

Signed-off-by: Iurii Mykhalskyi <iurii.mykhalskyi@globallogic.com>
Signed-off-by: Iurii Konovalenko <iurii.konovalenko@globallogic.com>
---
 tools/libxl/libxl.c                  | 282 +++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.h                  |  17 +++
 tools/libxl/libxl_create.c           |  37 ++++-
 tools/libxl/libxl_device.c           |   2 +
 tools/libxl/libxl_internal.h         |  13 +-
 tools/libxl/libxl_types.idl          |  19 +++
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_utils.h            |   3 +
 tools/libxl/xl.h                     |   3 +
 tools/libxl/xl_cmdimpl.c             | 160 +++++++++++++++++++-
 tools/libxl/xl_cmdtable.c            |  15 ++
 11 files changed, 549 insertions(+), 3 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index d96172d..1426bf6 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2595,6 +2595,276 @@ exit:
 
 /******************************************************************************/
 
+int libxl__device_vtty_setdefault(libxl__gc *gc, libxl_device_vtty *vtty)
+{
+    int rc;
+
+    rc = libxl__resolve_domid(gc, vtty->backend_domname, &vtty->backend_domid);
+
+    return rc;
+}
+
+static int libxl__device_from_vtty(libxl__gc *gc, uint32_t domid, libxl_device_vtty *vtty, libxl__device *device)
+{
+   device->backend_devid   = vtty->devid;
+   device->backend_domid   = vtty->backend_domid;
+   device->backend_kind    = LIBXL__DEVICE_KIND_VTTY;
+   device->devid           = vtty->devid;
+   device->domid           = domid;
+   device->kind            = LIBXL__DEVICE_KIND_VTTY;
+
+   return 0;
+}
+
+static int libxl__device_vtty_from_xs_be(libxl__gc *gc,
+                                        const char *be_path,
+                                        libxl_device_vtty *vtty)
+{
+    const char *tmp;
+    int rc;
+
+    libxl_device_vtty_init(vtty);
+
+    tmp = READ_BACKEND(gc, "device-id");
+    if (tmp)
+    	vtty->devid = atoi(tmp);
+    else
+    	vtty->devid = 0;
+
+    rc = 0;
+ out:
+    return rc;
+}
+
+int libxl_devid_to_device_vtty(libxl_ctx *ctx, uint32_t domid,
+                              int devid, libxl_device_vtty *vtty)
+{
+    GC_INIT(ctx);
+    char *dompath, *path;
+    int rc = ERROR_FAIL;
+
+    libxl_device_vtty_init(vtty);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    if (!dompath)
+        goto out;
+
+    path = libxl__xs_read(gc, XBT_NULL,
+                          libxl__sprintf(gc, "%s/device/vtty/%d/backend",
+                                         dompath, devid));
+    if (!path)
+        goto out;
+
+    rc = libxl__device_vtty_from_xs_be(gc, path, vtty);
+    if (rc) goto out;
+
+    rc = 0;
+out:
+    GC_FREE;
+    return rc;
+}
+
+void libxl__device_vtty_add(libxl__egc *egc, uint32_t domid, libxl_device_vtty *vtty, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_vtty vtty_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_vtty_init(&vtty_saved);
+    libxl_device_vtty_copy(CTX, &vtty_saved, vtty);
+
+    rc = libxl__device_vtty_setdefault(gc, vtty);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 32, 1);
+
+    if ((vtty->devid = libxl__device_nextid(gc, domid, "vtty")) < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    GCNEW(device);
+    rc = libxl__device_from_vtty(gc, domid, vtty, device);
+    if ( rc != 0 ) goto out;
+
+    flexarray_append(back, "device-id");
+    flexarray_append(back, GCSPRINTF("%d", vtty->devid));
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, GCSPRINTF("%d", domid));
+    flexarray_append(back, "device");
+    flexarray_append(back, vtty->device);
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, GCSPRINTF("%d", 1));
+
+    flexarray_append(front, "device-id");
+    flexarray_append(front, GCSPRINTF("%d", vtty->devid));
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, GCSPRINTF("%d", vtty->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, GCSPRINTF("%d", 1));
+
+    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);
+        LOG(INFO, "aodev updates JSON, libxl__get_domain_configuration returned %d", rc);
+        if (rc) goto out;
+
+        DEVICE_ADD(vtty, vttys, domid, &vtty_saved, COMPARE_DEVID, &d_config);
+    }
+
+    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) {              /* already exists in xenstore */
+            LOG(ERROR, "device already exists in xenstore");
+            aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+            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,
+                                                             back->count),
+                                  libxl__xs_kvs_of_flexarray(gc, front,
+                                                             front->count),
+                                  NULL);
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    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_device_vtty_dispose(&vtty_saved);
+    libxl_domain_config_dispose(&d_config);
+    aodev->rc = rc;
+    if(rc) aodev->callback(egc, aodev);
+    return;
+
+}
+
+libxl_device_vtty *libxl_device_vtty_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_vtty* vttys = NULL;
+    char* fe_path = NULL;
+    char** dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vtty", libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+    if (dir && ndirs) {
+       vttys = malloc(sizeof(*vttys) * ndirs);
+       libxl_device_vtty* vtty;
+       libxl_device_vtty* end = vttys + ndirs;
+       for(vtty = vttys; vtty < end; ++vtty, ++dir) {
+          char* tmp;
+
+          libxl_device_vtty_init(vtty);
+
+          vtty->devid = atoi(*dir);
+
+          tmp = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend-id",
+                   fe_path, *dir));
+          vtty->backend_domid = atoi(tmp);
+       }
+    }
+    *num = ndirs;
+
+    GC_FREE;
+    return vttys;
+}
+
+int libxl_device_vtty_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vtty *vtty, libxl_vttyinfo *vttyinfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *vttypath;
+    char *val;
+    int rc = 0;
+
+    libxl_vttyinfo_init(vttyinfo);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    vttyinfo->devid = vtty->devid;
+
+    vttypath = GCSPRINTF("%s/device/vtty/%d", dompath, vttyinfo->devid);
+    vttyinfo->backend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/backend", vttypath), NULL);
+
+    if (!vttyinfo->backend) {
+        goto err;
+    }
+
+    if(!libxl__xs_read(gc, XBT_NULL, vttyinfo->backend)) {
+       goto err;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/backend-id", vttypath));
+    vttyinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/state", vttypath));
+    vttyinfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/event-channel", vttypath));
+    vttyinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/ring-ref", vttypath));
+    vttyinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+
+    vttyinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/frontend", vttyinfo->backend), NULL);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/frontend-id", vttyinfo->backend));
+    vttyinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    goto exit;
+err:
+    rc = ERROR_FAIL;
+exit:
+    GC_FREE;
+    return rc;
+}
+
+/******************************************************************************/
+
 int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd)
 {
     int rc;
@@ -4749,6 +5019,8 @@ out:
  * libxl_device_vrtc_destroy
  * libxl_device_vsnd_remove
  * libxl_device_vsnd_destroy
+ * libxl_device_vtty_remove
+ * libxl_device_vtty_destroy
  */
 #define DEFINE_DEVICE_REMOVE(type, removedestroy, f)                    \
     int libxl_device_##type##_##removedestroy(libxl_ctx *ctx,           \
@@ -4808,6 +5080,10 @@ DEFINE_DEVICE_REMOVE(vrtc, destroy, 1)
 DEFINE_DEVICE_REMOVE(vsnd, remove, 0)
 DEFINE_DEVICE_REMOVE(vsnd, destroy, 1)
 
+/* vtty */
+DEFINE_DEVICE_REMOVE(vtty, remove, 0)
+DEFINE_DEVICE_REMOVE(vtty, destroy, 1)
+
 /* channel/console hotunplug is not implemented. There are 2 possibilities:
  * 1. add support for secondary consoles to xenconsoled
  * 2. dynamically add/remove qemu chardevs via qmp messages. */
@@ -4823,6 +5099,7 @@ DEFINE_DEVICE_REMOVE(vsnd, destroy, 1)
  * libxl_device_vtpm_add
  * libxl_device_vrtc_add
  * libxl_device_vsnd_add
+ * libxl_device_vtty_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -4860,6 +5137,9 @@ DEFINE_DEVICE_ADD(vrtc)
 /* vsnd */
 DEFINE_DEVICE_ADD(vsnd)
 
+/* vtty */
+DEFINE_DEVICE_ADD(vtty)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
@@ -7381,6 +7661,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
 
     MERGE(pci, pcidevs, COMPARE_PCI, {});
 
+    MERGE(vtty, vttys, COMPARE_DEVID, {});
+
     /* Take care of removable device. We maintain invariant in the
      * insert / remove operation so that:
      * 1. if xenstore is "empty" while JSON is not, the result
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 3cb67e2..47829dd 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1468,6 +1468,23 @@ libxl_device_vsnd *libxl_device_vsnd_list(libxl_ctx *ctx, uint32_t domid, int *n
 int libxl_device_vsnd_getinfo(libxl_ctx *ctx, uint32_t domid,
                               libxl_device_vsnd *vsnd, libxl_vsndinfo *vsndinfo);
 
+/* TTY */
+int libxl_device_vtty_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vtty *vtty,
+                          const libxl_asyncop_how *ao_how)
+                          LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vtty_remove(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_vtty *vtty,
+                             const libxl_asyncop_how *ao_how)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vtty_destroy(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vtty *vtty,
+                              const libxl_asyncop_how *ao_how)
+                              LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vtty *libxl_device_vtty_list(libxl_ctx *ctx, uint32_t domid, int *num);
+int libxl_device_vtty_getinfo(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vtty *vtty, libxl_vttyinfo *vttyinfo);
+
 /* 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 8ff4178..38d9b12 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -736,6 +736,8 @@ static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_vrtcs(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
+static void domcreate_attach_vttys(libxl__egc *egc, libxl__multidev *multidev,
+                                   int ret);
 static void domcreate_attach_vsnds(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
@@ -1429,12 +1431,45 @@ static void domcreate_attach_vrtcs(libxl__egc *egc,
    if (d_config->num_vrtcs > 0) {
        /* Attach vrtcs */
        libxl__multidev_begin(ao, &dcs->multidev);
-       dcs->multidev.callback = domcreate_attach_vsnds;
+       dcs->multidev.callback = domcreate_attach_vttys;
        libxl__add_vrtcs(egc, ao, domid, d_config, &dcs->multidev);
        libxl__multidev_prepared(egc, &dcs->multidev, 0);
        return;
    }
 
+   domcreate_attach_vttys(egc, multidev, 0);
+   return;
+
+error_out:
+   assert(ret);
+   domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_vttys(libxl__egc *egc,
+                                   libxl__multidev *multidev,
+                                   int ret)
+{
+   libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+   STATE_AO_GC(dcs->ao);
+   int domid = dcs->guest_domid;
+
+   libxl_domain_config* const d_config = dcs->guest_config;
+
+   if(ret) {
+       LOG(ERROR, "unable to add vtty devices");
+       goto error_out;
+   }
+
+    /* Plug vtty devices */
+   if (d_config->num_vttys > 0) {
+       /* Attach vttys */
+       libxl__multidev_begin(ao, &dcs->multidev);
+       dcs->multidev.callback = domcreate_attach_vsnds;
+       libxl__add_vttys(egc, ao, domid, d_config, &dcs->multidev);
+       libxl__multidev_prepared(egc, &dcs->multidev, 0);
+       return;
+   }
+
    domcreate_attach_vsnds(egc, multidev, 0);
    return;
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 419af16..df50fdb 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -546,6 +546,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_vtpms
  * libxl__add_vrtcs
  * libxl__add_vsnds
+ * libxl__add_vttys
  */
 
 #define DEFINE_DEVICES_ADD(type)                                        \
@@ -567,6 +568,7 @@ DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vtpm)
 DEFINE_DEVICES_ADD(vrtc)
 DEFINE_DEVICES_ADD(vsnd)
+DEFINE_DEVICES_ADD(vtty)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index d78dd79..1bacc73 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -478,7 +478,8 @@ typedef struct {
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VFB || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC || \
-    (dev)->backend_kind == LIBXL__DEVICE_KIND_VSND)
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VSND || \
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VTTY)
 
 #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
@@ -1190,6 +1191,7 @@ _hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
 _hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm);
 _hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc);
 _hidden int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd);
+_hidden int libxl__device_vtty_setdefault(libxl__gc *gc, libxl_device_vtty *vtty);
 _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
 _hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
 _hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
@@ -2579,6 +2581,11 @@ _hidden void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_vsnd *vsnd,
                                     libxl__ao_device *aodev);
 
+/* AO operation to connect a tty device */
+_hidden void libxl__device_vtty_add(libxl__egc *egc, uint32_t domid,
+                                    libxl_device_vtty *vtty,
+                                    libxl__ao_device *aodev);
+
 /* Internal function to connect a vkb device */
 _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
                                   libxl_device_vkb *vkb);
@@ -3299,6 +3306,10 @@ _hidden void libxl__add_vrtcs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
 
+_hidden void libxl__add_vttys(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                              libxl_domain_config *d_config,
+                              libxl__multidev *multidev);
+
 _hidden void libxl__add_vsnds(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 8fa29b1..4477297 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -571,6 +571,13 @@ libxl_device_vsnd = Struct("device_vsnd", [
     ("period_max", integer),
     ])
 
+libxl_device_vtty = Struct("device_vtty", [
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+    ("devid", libxl_devid),
+    ("device", string),
+    ])
+
 libxl_device_disk = Struct("device_disk", [
     ("backend_domid", libxl_domid),
     ("backend_domname", string),
@@ -660,6 +667,7 @@ libxl_domain_config = Struct("domain_config", [
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
     ("vrtcs", Array(libxl_device_vrtc, "num_vrtcs")),
     ("vsnds", Array(libxl_device_vsnd, "num_vsnds")),
+    ("vttys", Array(libxl_device_vtty, "num_vttys")),
     # a channel manifests as a console with a name,
     # see docs/misc/channels.txt
     ("channels", Array(libxl_device_channel, "num_channels")),
@@ -727,6 +735,17 @@ libxl_vsndinfo = Struct("vsndinfo", [
     ("rref", integer),
     ], dir=DIR_OUT)
 
+libxl_vttyinfo = Struct("vttyinfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("evtch", integer),
+    ("rref", integer),
+    ], dir=DIR_OUT)
+
 libxl_vcpuinfo = Struct("vcpuinfo", [
     ("vcpuid", uint32),
     ("cpu", uint32),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index ec63e23..182aeee 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -24,6 +24,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (8, "VTPM"),
     (9, "VRTC"),
     (10, "VSND"),
+    (11, "VTTY"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index f6532ce..3d47534 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -83,6 +83,9 @@ int libxl_devid_to_device_vrtc(libxl_ctx *ctx, uint32_t domid,
 int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vsnd *vsnd);
 
+int libxl_devid_to_device_vtty(libxl_ctx *ctx, uint32_t domid,
+                               int devid, libxl_device_vtty *vtty);
+
 int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits);
     /* Allocated bimap is from malloc, libxl_bitmap_dispose() to be
      * called by the application when done. */
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 81a78c0..cc990c1 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -88,6 +88,9 @@ int main_vrtcdetach(int argc, char **argv);
 int main_vsndattach(int argc, char **argv);
 int main_vsndlist(int argc, char **argv);
 int main_vsnddetach(int argc, char **argv);
+int main_vttyattach(int argc, char **argv);
+int main_vttylist(int argc, char **argv);
+int main_vttydetach(int argc, char **argv);
 int main_vtpmattach(int argc, char **argv);
 int main_vtpmlist(int argc, char **argv);
 int main_vtpmdetach(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index cb2d8c6..5ac9b81 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1271,7 +1271,7 @@ static void parse_config_data(const char *config_source,
     const char *buf;
     long l, vcpus = 0;
     XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs, *vsnds;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs, *vttys, *vsnds;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
@@ -1901,6 +1901,54 @@ static void parse_config_data(const char *config_source,
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vtty", &vttys, 0, 0)) {
+        d_config->num_vttys = 0;
+        d_config->vttys = NULL;
+        while ((buf = xlu_cfg_get_listitem(vttys, d_config->num_vttys)) != NULL) {
+            libxl_device_vtty *vtty;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            vtty = ARRAY_EXTEND_INIT(d_config->vttys, d_config->num_vttys,
+                                     libxl_device_vtty_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse vtty configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backendid")) {
+                    vtty->backend_domid = atoi(value);
+                } else if (!strcmp(key, "backend")) {
+                    replace_string(&vtty->backend_domname, value);
+                } else if (!strcmp(key, "devid")) {
+                    vtty->devid = atoi(value);
+                } else if (!strcmp(key, "device")) {
+                    replace_string(&vtty->device, value);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
     if (!xlu_cfg_get_list(config, "vsnd", &vsnds, 0, 0)) {
         d_config->num_vsnds = 0;
         d_config->vsnds = NULL;
@@ -7121,6 +7169,116 @@ int main_vsnddetach(int argc, char **argv)
     return rc;
 }
 
+int main_vttyattach(int argc, char **argv)
+{
+
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_vtty vtty;
+    /*  XLU_Config *config = 0; */
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtty-attach", 2) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+	if (optind < argc) {
+		replace_string(&vtty.device, argv[optind]);
+	}
+
+    /* TODO: fix this temporary hardcode */
+    vtty.backend_domname = "Domain-D";
+    vtty.backend_domid = 1;
+
+    if (dryrun_only) {
+        char *json = libxl_device_vtty_to_json(ctx, &vtty);
+        printf("vtty: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_vtty_add(ctx, fe_domid, &vtty, 0)) {
+        fprintf(stderr, "libxl_device_vtty_add failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+int main_vttylist(int argc, char **argv)
+{
+   int opt;
+   int i, nb;
+   libxl_device_vtty *vttys;
+   libxl_vttyinfo vttyinfo;
+
+   SWITCH_FOREACH_OPT(opt, "", NULL, "vtty-list", 1) {
+       /* No options */
+   }
+
+   /* vttyinfo.uuid should be outputted too */
+   printf("%-5s %-3s %-6s %-5s %-6s %-8s %-40s %-40s\n",
+           "Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path", "FE-path");
+   for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+       uint32_t domid;
+       if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+           fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+           continue;
+       }
+       vttys = libxl_device_vtty_list(ctx, domid, &nb);
+       if (!vttys) {
+           continue;
+       }
+       for (i=0; i<nb; i++) {
+           if (!libxl_device_vtty_getinfo(ctx, domid, &vttys[i], &vttyinfo)) {
+               /*      Vdev BE   hdl  st   evch rref BE-path FE-path UUID */
+               printf("%-5d %-3d %-6d %-5d %-6d %-8d %-40s %-40s\n",
+                       vttyinfo.devid, vttyinfo.backend_id, vttyinfo.frontend_id,
+                       vttyinfo.state, vttyinfo.evtch, vttyinfo.rref, vttyinfo.backend,
+                       vttyinfo.frontend);
+               libxl_vttyinfo_dispose(&vttyinfo);
+           }
+           libxl_device_vtty_dispose(&vttys[i]);
+       }
+       free(vttys);
+   }
+   return 0;
+}
+
+int main_vttydetach(int argc, char **argv)
+{
+    uint32_t domid, devid;
+    int opt, rc = 0;
+    libxl_device_vtty vtty;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vtty-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    if (libxl_devid_to_device_vtty(ctx, domid, devid, &vtty)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_vtty_remove(ctx, domid, &vtty, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vtty_remove failed.\n");
+        return 1;
+    }
+
+    libxl_device_vtty_dispose(&vtty);
+    return rc;
+}
+
 int main_vtpmattach(int argc, char **argv)
 {
     int opt;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index 78f0700..7e3a8eb 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -386,6 +386,21 @@ struct cmd_spec cmd_table[] = {
       "Destroy a domain's virtual audio device",
       "<Domain> <DevId|uuid>",
     },
+    { "vtty-attach",
+      &main_vttyattach, 1, 1,
+      "Create a new virtual tty device",
+      "<Domain> <Device>",
+    },
+    { "vtty-list",
+      &main_vttylist, 0, 0,
+      "List virtual tty devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vtty-detach",
+      &main_vttydetach, 0, 1,
+      "Destroy a domain's virtual rtc device",
+      "<Domain> <DevId>",
+    },
     { "vtpm-attach",
       &main_vtpmattach, 1, 1,
       "Create a new virtual TPM device",
-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH RFC 4/6] libxl: implementation of PV event device interface
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
                   ` (2 preceding siblings ...)
  2016-05-19 14:37 ` [PATCH RFC 3/6] libxl: implementation of PV tty " Iurii Mykhalskyi
@ 2016-05-19 14:37 ` Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 5/6] libxl: implementation of PV DRM " Iurii Mykhalskyi
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Iurii Mykhalskyi @ 2016-05-19 14:37 UTC (permalink / raw)
  To: embedded-pv-devel
  Cc: wei.liu2, stefano.stabellini, ian.jackson, ian.campbell, xen-devel

From: Pavlo Suikov <pavlo.suikov@globallogic.com>

Touchscreen events device configuration support. Can be further
extended to support any event device whatsoever.

Signed-off-by: Pavlo Suikov <pavlo.suikov@globallogic.com>
Signed-off-by: Iurii Konovalenko <iurii.konovalenko@globallogic.com>
Signed-off-by: Iurii Mykhalskyi <iurii.mykhalskyi@globallogic.com>
---
 tools/libxl/libxl.c                  | 289 ++++++++++++++++++++++++++++++++++-
 tools/libxl/libxl.h                  |  17 +++
 tools/libxl/libxl_create.c           |  39 ++++-
 tools/libxl/libxl_device.c           |   2 +
 tools/libxl/libxl_internal.c         |   4 +
 tools/libxl/libxl_internal.h         |  20 ++-
 tools/libxl/libxl_types.idl          |  21 +++
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_utils.h            |   4 +
 tools/libxl/xl.h                     |   3 +
 tools/libxl/xl_cmdimpl.c             | 170 ++++++++++++++++++++-
 tools/libxl/xl_cmdtable.c            |  15 ++
 12 files changed, 580 insertions(+), 5 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 1426bf6..b64815e 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -5003,6 +5003,282 @@ out:
 
 /******************************************************************************/
 
+int libxl__device_vevent_setdefault(libxl__gc *gc, libxl_device_vevent *vevent)
+{
+    int rc;
+    rc = libxl__resolve_domid(gc, vevent->backend_domname, &vevent->backend_domid);
+    return rc;
+}
+
+static int libxl__device_from_vevent(libxl__gc *gc, uint32_t domid,
+                                     libxl_device_vevent *vevent,
+                                     libxl__device *device)
+{
+    device->backend_devid = vevent->devid;
+    device->backend_domid = vevent->backend_domid;
+    device->backend_kind = LIBXL__DEVICE_KIND_VEVENT;
+    device->devid = vevent->devid;
+    device->domid = domid;
+    device->kind = LIBXL__DEVICE_KIND_VEVENT;
+
+    return 0;
+}
+
+static int libxl__device_vevent_from_xs_be(libxl__gc *gc,
+                                           const char *be_path,
+                                           libxl_device_vevent *vevent)
+{
+    const char *tmp;
+    int rc;
+
+    libxl_device_vevent_init(vevent);
+
+    tmp = READ_BACKEND(gc, "device-id");
+    if (tmp)
+        vevent->devid = atoi(tmp);
+    else
+        vevent->devid = 0;
+
+    rc = 0;
+out:
+    return rc;
+}
+
+int libxl_devid_to_device_vevent(libxl_ctx *ctx, uint32_t domid,
+                                 int devid, libxl_device_vevent *vevent)
+{
+    GC_INIT(ctx);
+    char *dompath, *path;
+    int rc = ERROR_FAIL;
+
+    libxl_device_vevent_init(vevent);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    if (!dompath)
+        goto out;
+
+    path = libxl__xs_read(gc, XBT_NULL,
+                          libxl__sprintf(gc, "%s/device/vevent/%d/backend",
+                                         dompath, devid));
+    if (!path)
+        goto out;
+
+    rc = libxl__device_vevent_from_xs_be(gc, path, vevent);
+    if (rc) goto out;
+
+    rc = 0;
+out:
+    GC_FREE;
+    return rc;
+}
+
+void libxl__device_vevent_add(libxl__egc *egc, uint32_t domid,
+                              libxl_device_vevent *vevent,
+                              libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_vevent vevent_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_vevent_init(&vevent_saved);
+    libxl_device_vevent_copy(CTX, &vevent_saved, vevent);
+
+    rc = libxl__device_vevent_setdefault(gc, vevent);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 16, 1);
+    if (vevent->devid == -1) {
+        if ((vevent->devid = libxl__device_nextid(gc, domid, "vevent")) < 0) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    libxl__update_config_vevent(gc, &vevent_saved, vevent);
+
+    GCNEW(device);
+    rc = libxl__device_from_vevent(gc, domid, vevent, device);
+    if ( rc != 0 ) goto out;
+
+    flexarray_append(back, "feature-abs-pointer");
+    flexarray_append(back, libxl__sprintf(gc, "%d", vevent->feature_abs_pointer));
+    flexarray_append(back, "abs-width");
+    flexarray_append(back, libxl__sprintf(gc, "%d", vevent->abs_width));
+    flexarray_append(back, "abs-height");
+    flexarray_append(back, libxl__sprintf(gc, "%d", vevent->abs_height));
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, libxl__sprintf(gc, "%d", domid));
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, libxl__sprintf(gc, "%d", 1));
+
+    flexarray_append(front, "device-id");
+    flexarray_append(front, GCSPRINTF("%d", vevent->devid));
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, libxl__sprintf(gc, "%d", vevent->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, libxl__sprintf(gc, "%d", 1));
+
+    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);
+        LOG(INFO, "aodev updates JSON, libxl__get_domain_configuration returned %d", rc);
+        if (rc) goto out;
+
+        DEVICE_ADD(vevent, vevents, domid, &vevent_saved, COMPARE_DEVID, &d_config);
+    }
+
+    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) {              /* already exists in xenstore */
+            LOG(ERROR, "device already exists in xenstore");
+            aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+            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,
+                                                             back->count),
+                                  libxl__xs_kvs_of_flexarray(gc, front,
+                                                             front->count),
+                                  NULL);
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    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_device_vevent_dispose(&vevent_saved);
+    libxl_domain_config_dispose(&d_config);
+    aodev->rc = rc;
+    if(rc) aodev->callback(egc, aodev);
+    return;
+}
+
+libxl_device_vevent *libxl_device_vevent_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_vevent* vevents = NULL;
+    char* fe_path = NULL;
+    char** dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vevent", libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+    if (dir && ndirs) {
+       vevents = malloc(sizeof(*vevents) * ndirs);
+       libxl_device_vevent* vevent;
+       libxl_device_vevent* end = vevents + ndirs;
+       for(vevent = vevents; vevent < end; ++vevent, ++dir) {
+          char* tmp;
+
+          libxl_device_vevent_init(vevent);
+
+          vevent->devid = atoi(*dir);
+
+          tmp = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend-id",
+                   fe_path, *dir));
+          vevent->backend_domid = atoi(tmp);
+       }
+    }
+    *num = ndirs;
+
+    GC_FREE;
+    return vevents;
+}
+
+int libxl_device_vevent_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vevent *vevent, libxl_veventinfo *veventinfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *veventpath;
+    char *val;
+    int rc = 0;
+
+    libxl_veventinfo_init(veventinfo);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    veventinfo->devid = vevent->devid;
+
+    veventpath = GCSPRINTF("%s/device/vevent/%d", dompath, veventinfo->devid);
+    veventinfo->backend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/backend", veventpath), NULL);
+
+    if (!veventinfo->backend) {
+        goto err;
+    }
+
+    if(!libxl__xs_read(gc, XBT_NULL, veventinfo->backend)) {
+       goto err;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/backend-id", veventpath));
+    veventinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/state", veventpath));
+    veventinfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/event-channel", veventpath));
+    veventinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/ring-ref", veventpath));
+    veventinfo->rref = val ? strtoul(val, NULL, 10) : -1;
+
+    veventinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/frontend", veventinfo->backend), NULL);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/frontend-id", veventinfo->backend));
+    veventinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    goto exit;
+err:
+    rc = ERROR_FAIL;
+exit:
+    GC_FREE;
+    return rc;
+}
+
+/******************************************************************************/
+
 /* Macro for defining device remove/destroy functions in a compact way */
 /* The following functions are defined:
  * libxl_device_disk_remove
@@ -5021,6 +5297,8 @@ out:
  * libxl_device_vsnd_destroy
  * libxl_device_vtty_remove
  * libxl_device_vtty_destroy
+ * libxl_device_vevent_remove
+ * libxl_device_vevent_destroy
  */
 #define DEFINE_DEVICE_REMOVE(type, removedestroy, f)                    \
     int libxl_device_##type##_##removedestroy(libxl_ctx *ctx,           \
@@ -5064,7 +5342,6 @@ DEFINE_DEVICE_REMOVE(vkb, remove, 0)
 DEFINE_DEVICE_REMOVE(vkb, destroy, 1)
 
 /* vfb */
-
 DEFINE_DEVICE_REMOVE(vfb, remove, 0)
 DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 
@@ -5084,6 +5361,10 @@ DEFINE_DEVICE_REMOVE(vsnd, destroy, 1)
 DEFINE_DEVICE_REMOVE(vtty, remove, 0)
 DEFINE_DEVICE_REMOVE(vtty, destroy, 1)
 
+/* vevent */
+DEFINE_DEVICE_REMOVE(vevent, remove, 0)
+DEFINE_DEVICE_REMOVE(vevent, destroy, 1)
+
 /* channel/console hotunplug is not implemented. There are 2 possibilities:
  * 1. add support for secondary consoles to xenconsoled
  * 2. dynamically add/remove qemu chardevs via qmp messages. */
@@ -5100,6 +5381,7 @@ DEFINE_DEVICE_REMOVE(vtty, destroy, 1)
  * libxl_device_vrtc_add
  * libxl_device_vsnd_add
  * libxl_device_vtty_add
+ * libxl_device_vevent_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -5140,6 +5422,9 @@ DEFINE_DEVICE_ADD(vsnd)
 /* vtty */
 DEFINE_DEVICE_ADD(vtty)
 
+/* vevent */
+DEFINE_DEVICE_ADD(vevent)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
@@ -7663,6 +7948,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
 
     MERGE(vtty, vttys, COMPARE_DEVID, {});
 
+    MERGE(vevent, vevents, COMPARE_DEVID, {});
+
     /* Take care of removable device. We maintain invariant in the
      * insert / remove operation so that:
      * 1. if xenstore is "empty" while JSON is not, the result
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 47829dd..7799374 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1511,6 +1511,23 @@ int libxl_device_vfb_destroy(libxl_ctx *ctx, uint32_t domid,
                              const libxl_asyncop_how *ao_how)
                              LIBXL_EXTERNAL_CALLERS_ONLY;
 
+/* Event device (e.g. touchscreen) */
+int libxl_device_vevent_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vevent *vevent,
+                            const libxl_asyncop_how *ao_how)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vevent_remove(libxl_ctx *ctx, uint32_t domid,
+                               libxl_device_vevent *vevent,
+                               const libxl_asyncop_how *ao_how)
+                               LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vevent_destroy(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_vevent *vevent,
+                                const libxl_asyncop_how *ao_how)
+                                LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vevent *libxl_device_vevent_list(libxl_ctx *ctx, uint32_t domid, int *num);
+int libxl_device_vevent_getinfo(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vevent *vevent, libxl_veventinfo *veventinfo);
+
 /* PCI Passthrough */
 int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid,
                          libxl_device_pci *pcidev,
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 38d9b12..1752499 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -740,6 +740,8 @@ static void domcreate_attach_vttys(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_vsnds(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
+static void domcreate_attach_vevents(libxl__egc *egc, libxl__multidev *multidev,
+                                     int ret);
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
                                  int ret);
 static void domcreate_attach_dtdev(libxl__egc *egc,
@@ -1497,12 +1499,45 @@ static void domcreate_attach_vsnds(libxl__egc *egc,
    if (d_config->num_vsnds > 0) {
        /* Attach vsnds */
        libxl__multidev_begin(ao, &dcs->multidev);
-       dcs->multidev.callback = domcreate_attach_pci;
+       dcs->multidev.callback = domcreate_attach_vevents;
        libxl__add_vsnds(egc, ao, domid, d_config, &dcs->multidev);
        libxl__multidev_prepared(egc, &dcs->multidev, 0);
        return;
    }
 
+    domcreate_attach_vevents(egc, multidev, 0);
+   return;
+
+error_out:
+   assert(ret);
+   domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_vevents(libxl__egc *egc,
+                                     libxl__multidev *multidev,
+                                     int ret)
+{
+   libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+   STATE_AO_GC(dcs->ao);
+   int domid = dcs->guest_domid;
+
+   libxl_domain_config* const d_config = dcs->guest_config;
+
+   if(ret) {
+       LOG(ERROR, "unable to add vsnd devices");
+       goto error_out;
+   }
+
+    /* Plug vevent devices */
+   if (d_config->num_vevents > 0) {
+       /* Attach vevents */
+       libxl__multidev_begin(ao, &dcs->multidev);
+       dcs->multidev.callback = domcreate_attach_pci;
+       libxl__add_vevents(egc, ao, domid, d_config, &dcs->multidev);
+       libxl__multidev_prepared(egc, &dcs->multidev, 0);
+       return;
+   }
+
    domcreate_attach_pci(egc, multidev, 0);
    return;
 
@@ -1524,7 +1559,7 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
     libxl_domain_config *const d_config = dcs->guest_config;
 
     if (ret) {
-        LOG(ERROR, "unable to add vsnd devices");
+        LOG(ERROR, "unable to add vevent devices");
         goto error_out;
     }
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index df50fdb..65569e1 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -547,6 +547,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_vrtcs
  * libxl__add_vsnds
  * libxl__add_vttys
+ * libxl__add_vevents
  */
 
 #define DEFINE_DEVICES_ADD(type)                                        \
@@ -569,6 +570,7 @@ DEFINE_DEVICES_ADD(vtpm)
 DEFINE_DEVICES_ADD(vrtc)
 DEFINE_DEVICES_ADD(vsnd)
 DEFINE_DEVICES_ADD(vtty)
+DEFINE_DEVICES_ADD(vevent)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c
index f75840d..32ce8bd 100644
--- a/tools/libxl/libxl_internal.c
+++ b/tools/libxl/libxl_internal.c
@@ -551,6 +551,10 @@ void libxl__update_domain_configuration(libxl__gc *gc,
     for (i = 0; i < src->num_vsnds; i++)
         libxl__update_config_vsnd(gc, &dst->vsnds[i], &src->vsnds[i]);
 
+    /* update vevent information */
+    for (i = 0; i < src->num_vevents; i++)
+        libxl__update_config_vevent(gc, &dst->vevents[i], &src->vevents[i]);
+
     /* update guest UUID */
     libxl_uuid_copy(CTX, &dst->c_info.uuid, &src->c_info.uuid);
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 1bacc73..330d56f 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -479,7 +479,8 @@ typedef struct {
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VSND || \
-    (dev)->backend_kind == LIBXL__DEVICE_KIND_VTTY)
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VTTY || \
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VEVENT)
 
 #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
@@ -1193,6 +1194,7 @@ _hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc
 _hidden int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd);
 _hidden int libxl__device_vtty_setdefault(libxl__gc *gc, libxl_device_vtty *vtty);
 _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
+_hidden int libxl__device_vevent_setdefault(libxl__gc *gc, libxl_device_vevent *vevent);
 _hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
 _hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
 _hidden void libxl__rdm_setdefault(libxl__gc *gc,
@@ -2594,6 +2596,11 @@ _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
 _hidden int libxl__device_vfb_add(libxl__gc *gc, uint32_t domid,
                                   libxl_device_vfb *vfb);
 
+/* AO operation to connect a vevent device */
+_hidden void libxl__device_vevent_add(libxl__egc *egc, uint32_t domid,
+                                      libxl_device_vevent *vevent,
+                                      libxl__ao_device *aodev);
+
 /* Waits for the passed device to reach state XenbusStateInitWait.
  * This is not really useful by itself, but is important when executing
  * hotplug scripts, since we need to be sure the device is in the correct
@@ -3313,6 +3320,10 @@ _hidden void libxl__add_vttys(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
 _hidden void libxl__add_vsnds(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
+
+_hidden void libxl__add_vevents(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                                libxl_domain_config *d_config,
+                                libxl__multidev *multidev);
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
@@ -3983,6 +3994,13 @@ static inline void libxl__update_config_vsnd(libxl__gc *gc,
     dst->devid = src->devid;
 }
 
+static inline void libxl__update_config_vevent(libxl__gc *gc,
+                                               libxl_device_vevent *dst,
+                                               libxl_device_vevent *src)
+{
+    dst->devid = src->devid;
+}
+
 /* Macros used to compare device identifier. Returns true if the two
  * devices have same identifier. */
 #define COMPARE_DEVID(a, b) ((a)->devid == (b)->devid)
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 4477297..23fcf50 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -538,6 +538,15 @@ libxl_device_vfb = Struct("device_vfb", [
     ("keymap",        string),
     ])
 
+libxl_device_vevent = Struct("device_vevent", [
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+    ("devid", libxl_devid),
+    ("feature_abs_pointer", integer),
+    ("abs_width", integer),
+    ("abs_height", integer),
+    ])
+
 libxl_device_vkb = Struct("device_vkb", [
     ("backend_domid", libxl_domid),
     ("backend_domname", string),
@@ -663,6 +672,7 @@ libxl_domain_config = Struct("domain_config", [
     ("rdms", Array(libxl_device_rdm, "num_rdms")),
     ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")),
     ("vfbs", Array(libxl_device_vfb, "num_vfbs")),
+    ("vevents", Array(libxl_device_vevent, "num_vevents")),
     ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
     ("vrtcs", Array(libxl_device_vrtc, "num_vrtcs")),
@@ -746,6 +756,17 @@ libxl_vttyinfo = Struct("vttyinfo", [
     ("rref", integer),
     ], dir=DIR_OUT)
 
+libxl_veventinfo = Struct("veventinfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("evtch", integer),
+    ("rref", integer),
+    ], dir=DIR_OUT)
+
 libxl_vcpuinfo = Struct("vcpuinfo", [
     ("vcpuid", uint32),
     ("cpu", uint32),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 182aeee..a86325c 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", [
     (9, "VRTC"),
     (10, "VSND"),
     (11, "VTTY"),
+    (12, "VEVENT"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 3d47534..24a8205 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -86,6 +86,10 @@ int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid,
 int libxl_devid_to_device_vtty(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vtty *vtty);
 
+int libxl_devid_to_device_vevent(libxl_ctx *ctx, uint32_t domid,
+                                 int devid, libxl_device_vevent *vevent);
+
+
 int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits);
     /* Allocated bimap is from malloc, libxl_bitmap_dispose() to be
      * called by the application when done. */
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index cc990c1..905276d 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -91,6 +91,9 @@ int main_vsnddetach(int argc, char **argv);
 int main_vttyattach(int argc, char **argv);
 int main_vttylist(int argc, char **argv);
 int main_vttydetach(int argc, char **argv);
+int main_veventattach(int argc, char **argv);
+int main_veventlist(int argc, char **argv);
+int main_veventdetach(int argc, char **argv);
 int main_vtpmattach(int argc, char **argv);
 int main_vtpmlist(int argc, char **argv);
 int main_vtpmdetach(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 5ac9b81..f8f9edf 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1271,7 +1271,8 @@ static void parse_config_data(const char *config_source,
     const char *buf;
     long l, vcpus = 0;
     XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms, *vrtcs, *vttys, *vsnds;
+    XLU_ConfigList *cpus, *cpuids, *vbds, *nics, *pcis;
+    XLU_ConfigList *cvfbs, *vevents, *vtpms, *vrtcs, *vttys, *vsnds;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
@@ -2195,6 +2196,61 @@ skip_vfb:
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vevent", &vevents, 0, 0)) {
+        d_config->num_vevents = 0;
+        d_config->vevents = NULL;
+        while ((buf = xlu_cfg_get_listitem(vevents, d_config->num_vevents)) != NULL) {
+            libxl_device_vevent *vevent;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            vevent = ARRAY_EXTEND_INIT(d_config->vevents, d_config->num_vevents,
+                                       libxl_device_vevent_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse vevent configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backendid")) {
+                    vevent->backend_domid = atoi(value);
+                } else if (!strcmp(key, "backend")) {
+                    replace_string(&vevent->backend_domname, value);
+                } else if (!strcmp(key, "devid")) {
+                    vevent->devid = atoi(value);
+                } else if (!strcmp(key, "featureabsptr")) {
+                    vevent->feature_abs_pointer = atoi(value);
+                } else if (!strcmp(key, "abswidth")) {
+                    vevent->abs_width = atoi(value);
+                } else if (!strcmp(key, "absheight")) {
+                    vevent->abs_height = atoi(value);
+                } else {
+                    fprintf(stderr, "unknown vevent parameter '%s',"
+                                  " ignoring\n", key);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
     if (!xlu_cfg_get_long (config, "pci_msitranslate", &l, 0))
         pci_msitranslate = l;
 
@@ -7279,6 +7335,118 @@ int main_vttydetach(int argc, char **argv)
     return rc;
 }
 
+int main_veventattach(int argc, char **argv)
+{
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_vevent vevent;
+    char *oparg;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vevent-attach", 1) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+    for (argv += optind+1, argc -= optind+1; argc > 0; ++argv, --argc) {
+        if (MATCH_OPTION("backend", *argv, oparg)) {
+            replace_string(&vevent.backend_domname, oparg);
+        } else if (MATCH_OPTION("devid", *argv, oparg)) {
+            vevent.devid = atoi(oparg);
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", *argv);
+            return 1;
+        }
+    }
+
+    if (dryrun_only) {
+        char *json = libxl_device_vevent_to_json(ctx, &vevent);
+        printf("vevent: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_vevent_add(ctx, fe_domid, &vevent, 0)) {
+        fprintf(stderr, "libxl_device_vevent_add failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+int main_veventlist(int argc, char **argv)
+{
+    int opt;
+    int i, nb;
+    libxl_device_vevent *vevents;
+    libxl_veventinfo veventinfo;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vevent-list", 1) {
+        /* No options */
+    }
+
+    printf("%-5s %-3s %-6s %-5s %-6s %-8s %-40s %-40s\n",
+           "Vdev", "BE", "handle", "state", "evt-ch",
+           "ring-ref", "BE-path", "FE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid;
+        if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+            continue;
+        }
+        vevents = libxl_device_vevent_list(ctx, domid, &nb);
+        if (!vevents) {
+            continue;
+        }
+        for (i=0; i<nb; i++) {
+            if (!libxl_device_vevent_getinfo(ctx, domid, &vevents[i], &veventinfo)) {
+                /*      Vdev BE   hdl  st   evch rref BE-path FE-path */
+                printf("%-5d %-3d %-6d %-5d %-6d %-8d %-40s %-40s\n",
+                       veventinfo.devid, veventinfo.backend_id, veventinfo.frontend_id,
+                       veventinfo.state, veventinfo.evtch, veventinfo.rref,
+                       veventinfo.backend, veventinfo.frontend);
+                libxl_veventinfo_dispose(&veventinfo);
+            }
+            libxl_device_vevent_dispose(&vevents[i]);
+        }
+        free(vevents);
+    }
+
+    return 0;
+}
+
+int main_veventdetach(int argc, char **argv)
+{
+    uint32_t domid, devid;
+    int opt, rc = 0;
+    libxl_device_vevent vevent;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vevent-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    if (libxl_devid_to_device_vevent(ctx, domid, devid, &vevent)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_vevent_remove(ctx, domid, &vevent, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vevent_remove failed.\n");
+        return 1;
+    }
+    libxl_device_vevent_dispose(&vevent);
+    return rc;
+}
+
 int main_vtpmattach(int argc, char **argv)
 {
     int opt;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index 7e3a8eb..bb410ca 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -401,6 +401,21 @@ struct cmd_spec cmd_table[] = {
       "Destroy a domain's virtual rtc device",
       "<Domain> <DevId>",
     },
+    { "vevent-attach",
+      &main_veventattach, 1, 1,
+      "Create a new virtual event device",
+      "<Domain> [backend=<BackDomain>] [devid=<DeviceId>]",
+    },
+    { "vevent-list",
+      &main_veventlist, 0, 0,
+      "List virtual event devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vevent-detach",
+      &main_veventdetach, 0, 1,
+      "Destroy a domain's virtual event device",
+      "<Domain> <DevId>",
+    },
     { "vtpm-attach",
       &main_vtpmattach, 1, 1,
       "Create a new virtual TPM device",
-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH RFC 5/6] libxl: implementation of PV DRM device interface
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
                   ` (3 preceding siblings ...)
  2016-05-19 14:37 ` [PATCH RFC 4/6] libxl: implementation of PV event " Iurii Mykhalskyi
@ 2016-05-19 14:37 ` Iurii Mykhalskyi
  2016-05-19 14:37 ` [PATCH RFC 6/6] libxl: implementation of PV RPMSG " Iurii Mykhalskyi
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Iurii Mykhalskyi @ 2016-05-19 14:37 UTC (permalink / raw)
  To: embedded-pv-devel
  Cc: wei.liu2, stefano.stabellini, ian.jackson, ian.campbell, xen-devel

From: Pavlo Suikov <pavlo.suikov@globallogic.com>

Signed-off-by: Pavlo Suikov <pavlo.suikov@globallogic.com>
Signed-off-by: Glib Golubytskyi <glib.golubytskyi@globallogic.com>
Signed-off-by: Iurii Konovalenko <iurii.konovalenko@globallogic.com>
Signed-off-by: Iurii Mykhalskyi <iurii.mykhalskyi@globallogic.com>
---
 tools/libxl/libxl.c                  | 290 +++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.h                  |  18 +++
 tools/libxl/libxl_create.c           |  42 ++++-
 tools/libxl/libxl_device.c           |   2 +
 tools/libxl/libxl_internal.h         |  13 +-
 tools/libxl/libxl_types.idl          |  21 +++
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_utils.h            |   3 +
 tools/libxl/xl.h                     |   3 +
 tools/libxl/xl_cmdimpl.c             | 164 +++++++++++++++++++-
 tools/libxl/xl_cmdtable.c            |  15 ++
 11 files changed, 567 insertions(+), 5 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b64815e..ccb0411 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2595,6 +2595,284 @@ exit:
 
 /******************************************************************************/
 
+int libxl__device_vdrm_setdefault(libxl__gc *gc, libxl_device_vdrm *vdrm)
+{
+    int rc;
+
+    rc = libxl__resolve_domid(gc, vdrm->backend_domname, &vdrm->backend_domid);
+
+    return rc;
+}
+
+static int libxl__device_from_vdrm(libxl__gc *gc, uint32_t domid, libxl_device_vdrm *vdrm, libxl__device *device)
+{
+   device->backend_devid   = vdrm->devid;
+   device->backend_domid   = vdrm->backend_domid;
+   device->backend_kind    = LIBXL__DEVICE_KIND_VDRM;
+   device->devid           = vdrm->devid;
+   device->domid           = domid;
+   device->kind            = LIBXL__DEVICE_KIND_VDRM;
+
+   return 0;
+}
+
+static int libxl__device_vdrm_from_xs_be(libxl__gc *gc,
+                                        const char *be_path,
+                                        libxl_device_vdrm *vdrm)
+{
+    const char *tmp;
+    int rc;
+
+    libxl_device_vdrm_init(vdrm);
+
+    tmp = READ_BACKEND(gc, "device-id");
+    if (tmp)
+        vdrm->devid = atoi(tmp);
+    else
+        vdrm->devid = 0;
+
+    rc = 0;
+ out:
+    return rc;
+}
+
+int libxl_devid_to_device_vdrm(libxl_ctx *ctx, uint32_t domid,
+                              int devid, libxl_device_vdrm *vdrm)
+{
+    GC_INIT(ctx);
+    char *dompath, *path;
+    int rc = ERROR_FAIL;
+
+    libxl_device_vdrm_init(vdrm);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    if (!dompath)
+        goto out;
+
+    path = libxl__xs_read(gc, XBT_NULL,
+                          libxl__sprintf(gc, "%s/device/vdrm/%d/backend",
+                                         dompath, devid));
+    if (!path)
+        goto out;
+
+    rc = libxl__device_vdrm_from_xs_be(gc, path, vdrm);
+    if (rc) goto out;
+
+    rc = 0;
+out:
+    GC_FREE;
+    return rc;
+}
+
+void libxl__device_vdrm_add(libxl__egc *egc, uint32_t domid, libxl_device_vdrm *vdrm, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_vdrm vdrm_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_vdrm_init(&vdrm_saved);
+    libxl_device_vdrm_copy(CTX, &vdrm_saved, vdrm);
+
+    rc = libxl__device_vdrm_setdefault(gc, vdrm);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 32, 1);
+
+    if ((vdrm->devid = libxl__device_nextid(gc, domid, "vdrm")) < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    GCNEW(device);
+    rc = libxl__device_from_vdrm(gc, domid, vdrm, device);
+    if ( rc != 0 ) goto out;
+
+    flexarray_append(back, "device-id");
+    flexarray_append(back, GCSPRINTF("%d", vdrm->devid));
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, GCSPRINTF("%d", domid));
+    flexarray_append(back, "device");
+    flexarray_append(back, vdrm->device);
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, GCSPRINTF("%d", 1));
+    flexarray_append(back, "mode0");
+    flexarray_append(back, vdrm->mode0);
+    flexarray_append(back, "mode1");
+    flexarray_append(back, vdrm->mode1);
+
+    flexarray_append(front, "device-id");
+    flexarray_append(front, GCSPRINTF("%d", vdrm->devid));
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, GCSPRINTF("%d", vdrm->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, GCSPRINTF("%d", 1));
+    flexarray_append(front, "mode0");
+    flexarray_append(front, vdrm->mode0);
+    flexarray_append(front, "mode1");
+    flexarray_append(front, vdrm->mode1);
+
+    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);
+        LOG(INFO, "aodev updates JSON, libxl__get_domain_configuration returned %d", rc);
+        if (rc) goto out;
+
+        DEVICE_ADD(vdrm, vdrms, domid, &vdrm_saved, COMPARE_DEVID, &d_config);
+    }
+
+    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) {              /* already exists in xenstore */
+            LOG(ERROR, "device already exists in xenstore");
+            aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+            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,
+                                                             back->count),
+                                  libxl__xs_kvs_of_flexarray(gc, front,
+                                                             front->count),
+                                  NULL);
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    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_device_vdrm_dispose(&vdrm_saved);
+    libxl_domain_config_dispose(&d_config);
+    aodev->rc = rc;
+    if(rc) aodev->callback(egc, aodev);
+    return;
+
+}
+
+libxl_device_vdrm *libxl_device_vdrm_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_vdrm* vdrms = NULL;
+    char* fe_path = NULL;
+    char** dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vdrm", libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+    if (dir && ndirs) {
+       vdrms = malloc(sizeof(*vdrms) * ndirs);
+       libxl_device_vdrm* vdrm;
+       libxl_device_vdrm* end = vdrms + ndirs;
+       for(vdrm = vdrms; vdrm < end; ++vdrm, ++dir) {
+          char* tmp;
+
+          libxl_device_vdrm_init(vdrm);
+
+          vdrm->devid = atoi(*dir);
+
+          tmp = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend-id",
+                   fe_path, *dir));
+          vdrm->backend_domid = atoi(tmp);
+       }
+    }
+    *num = ndirs;
+
+    GC_FREE;
+    return vdrms;
+}
+
+int libxl_device_vdrm_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vdrm *vdrm, libxl_vdrminfo *vdrminfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *vdrmpath;
+    char *val;
+    int rc = 0;
+
+    libxl_vdrminfo_init(vdrminfo);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    vdrminfo->devid = vdrm->devid;
+
+    vdrmpath = GCSPRINTF("%s/device/vdrm/%d", dompath, vdrminfo->devid);
+    vdrminfo->backend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/backend", vdrmpath), NULL);
+
+    if (!vdrminfo->backend) {
+        goto err;
+    }
+
+    if(!libxl__xs_read(gc, XBT_NULL, vdrminfo->backend)) {
+       goto err;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/backend-id", vdrmpath));
+    vdrminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/state", vdrmpath));
+    vdrminfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/event-channel", vdrmpath));
+    vdrminfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/ring-ref", vdrmpath));
+    vdrminfo->rref = val ? strtoul(val, NULL, 10) : -1;
+
+    vdrminfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/frontend", vdrminfo->backend), NULL);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/frontend-id", vdrminfo->backend));
+    vdrminfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    goto exit;
+err:
+    rc = ERROR_FAIL;
+exit:
+    GC_FREE;
+    return rc;
+}
+
+/******************************************************************************/
+
 int libxl__device_vtty_setdefault(libxl__gc *gc, libxl_device_vtty *vtty)
 {
     int rc;
@@ -5293,6 +5571,8 @@ exit:
  * libxl_device_vtpm_destroy
  * libxl_device_vrtc_remove
  * libxl_device_vrtc_destroy
+ * libxl_device_vdrm_remove
+ * libxl_device_vdrm_destroy
  * libxl_device_vsnd_remove
  * libxl_device_vsnd_destroy
  * libxl_device_vtty_remove
@@ -5353,6 +5633,10 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
 DEFINE_DEVICE_REMOVE(vrtc, remove, 0)
 DEFINE_DEVICE_REMOVE(vrtc, destroy, 1)
 
+/* vdrm */
+DEFINE_DEVICE_REMOVE(vdrm, remove, 0)
+DEFINE_DEVICE_REMOVE(vdrm, destroy, 1)
+
 /* vsnd */
 DEFINE_DEVICE_REMOVE(vsnd, remove, 0)
 DEFINE_DEVICE_REMOVE(vsnd, destroy, 1)
@@ -5379,6 +5663,7 @@ DEFINE_DEVICE_REMOVE(vevent, destroy, 1)
  * libxl_device_nic_add
  * libxl_device_vtpm_add
  * libxl_device_vrtc_add
+ * libxl_device_vdrm_add
  * libxl_device_vsnd_add
  * libxl_device_vtty_add
  * libxl_device_vevent_add
@@ -5416,6 +5701,9 @@ DEFINE_DEVICE_ADD(vtpm)
 /* vrtc */
 DEFINE_DEVICE_ADD(vrtc)
 
+/* vdrm */
+DEFINE_DEVICE_ADD(vdrm)
+
 /* vsnd */
 DEFINE_DEVICE_ADD(vsnd)
 
@@ -7942,6 +8230,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
 
     MERGE(vrtc, vrtcs, COMPARE_DEVID, {});
 
+    MERGE(vdrm, vdrms, COMPARE_DEVID, {});
+
     MERGE(vsnd, vsnds, COMPARE_DEVID, {});
 
     MERGE(pci, pcidevs, COMPARE_PCI, {});
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 7799374..57f3e03 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1451,6 +1451,24 @@ int libxl_device_vrtc_destroy(libxl_ctx *ctx, uint32_t domid,
 libxl_device_vrtc *libxl_device_vrtc_list(libxl_ctx *ctx, uint32_t domid, int *num);
 int libxl_device_vrtc_getinfo(libxl_ctx *ctx, uint32_t domid,
                               libxl_device_vrtc *vrtc, libxl_vrtcinfo *vrtcinfo);
+
+/* DRM */
+int libxl_device_vdrm_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vdrm *vdrm,
+                          const libxl_asyncop_how *ao_how)
+                          LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vdrm_remove(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_vdrm *vdrm,
+                             const libxl_asyncop_how *ao_how)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vdrm_destroy(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vdrm *vdrm,
+                              const libxl_asyncop_how *ao_how)
+                              LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vdrm *libxl_device_vdrm_list(libxl_ctx *ctx, uint32_t domid, int *num);
+int libxl_device_vdrm_getinfo(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vdrm *vdrm, libxl_vdrminfo *vdrminfo);
+
 /* Audio */
 int libxl_device_vsnd_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vsnd *vsnd,
                           const libxl_asyncop_how *ao_how)
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 1752499..6e1c0d8 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -736,6 +736,8 @@ static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_vrtcs(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
+static void domcreate_attach_vdrms(libxl__egc *egc, libxl__multidev *multidev,
+                                   int ret);
 static void domcreate_attach_vttys(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_vsnds(libxl__egc *egc, libxl__multidev *multidev,
@@ -1433,12 +1435,45 @@ static void domcreate_attach_vrtcs(libxl__egc *egc,
    if (d_config->num_vrtcs > 0) {
        /* Attach vrtcs */
        libxl__multidev_begin(ao, &dcs->multidev);
-       dcs->multidev.callback = domcreate_attach_vttys;
+       dcs->multidev.callback = domcreate_attach_vdrms;
        libxl__add_vrtcs(egc, ao, domid, d_config, &dcs->multidev);
        libxl__multidev_prepared(egc, &dcs->multidev, 0);
        return;
    }
 
+   domcreate_attach_vdrms(egc, multidev, 0);
+   return;
+
+error_out:
+   assert(ret);
+   domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_vdrms(libxl__egc *egc,
+                                   libxl__multidev *multidev,
+                                   int ret)
+{
+   libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+   STATE_AO_GC(dcs->ao);
+   int domid = dcs->guest_domid;
+
+   libxl_domain_config* const d_config = dcs->guest_config;
+
+   if(ret) {
+       LOG(ERROR, "unable to add vrtc devices");
+       goto error_out;
+   }
+
+    /* Plug vdrm devices */
+   if (d_config->num_vdrms > 0) {
+       /* Attach vdrms */
+       libxl__multidev_begin(ao, &dcs->multidev);
+       dcs->multidev.callback = domcreate_attach_vttys;
+       libxl__add_vdrms(egc, ao, domid, d_config, &dcs->multidev);
+       libxl__multidev_prepared(egc, &dcs->multidev, 0);
+       return;
+   }
+
    domcreate_attach_vttys(egc, multidev, 0);
    return;
 
@@ -1447,6 +1482,7 @@ error_out:
    domcreate_complete(egc, dcs, ret);
 }
 
+
 static void domcreate_attach_vttys(libxl__egc *egc,
                                    libxl__multidev *multidev,
                                    int ret)
@@ -1458,7 +1494,7 @@ static void domcreate_attach_vttys(libxl__egc *egc,
    libxl_domain_config* const d_config = dcs->guest_config;
 
    if(ret) {
-       LOG(ERROR, "unable to add vtty devices");
+       LOG(ERROR, "unable to add vdrm devices");
        goto error_out;
    }
 
@@ -1491,7 +1527,7 @@ static void domcreate_attach_vsnds(libxl__egc *egc,
    libxl_domain_config* const d_config = dcs->guest_config;
 
    if(ret) {
-       LOG(ERROR, "unable to add vrtc devices");
+       LOG(ERROR, "unable to add vtty devices");
        goto error_out;
    }
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 65569e1..13c4a7b 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -545,6 +545,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_nics
  * libxl__add_vtpms
  * libxl__add_vrtcs
+ * libxl__add_vdrms
  * libxl__add_vsnds
  * libxl__add_vttys
  * libxl__add_vevents
@@ -568,6 +569,7 @@ DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vtpm)
 DEFINE_DEVICES_ADD(vrtc)
+DEFINE_DEVICES_ADD(vdrm)
 DEFINE_DEVICES_ADD(vsnd)
 DEFINE_DEVICES_ADD(vtty)
 DEFINE_DEVICES_ADD(vevent)
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 330d56f..80754df 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -480,7 +480,8 @@ typedef struct {
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VSND || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VTTY || \
-    (dev)->backend_kind == LIBXL__DEVICE_KIND_VEVENT)
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VEVENT || \
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VDRM)
 
 #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
@@ -1191,6 +1192,7 @@ _hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
                                          uint32_t domid);
 _hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm);
 _hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc);
+_hidden int libxl__device_vdrm_setdefault(libxl__gc *gc, libxl_device_vdrm *vdrm);
 _hidden int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd);
 _hidden int libxl__device_vtty_setdefault(libxl__gc *gc, libxl_device_vtty *vtty);
 _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
@@ -2578,6 +2580,11 @@ _hidden void libxl__device_vrtc_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_vrtc *vrtc,
                                     libxl__ao_device *aodev);
 
+/* AO operation to connect a drm device */
+_hidden void libxl__device_vdrm_add(libxl__egc *egc, uint32_t domid,
+                                    libxl_device_vdrm *vdrm,
+                                    libxl__ao_device *aodev);
+
 /* AO operation to connect a sound device */
 _hidden void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_vsnd *vsnd,
@@ -3313,6 +3320,10 @@ _hidden void libxl__add_vrtcs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
 
+_hidden void libxl__add_vdrms(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                              libxl_domain_config *d_config,
+                              libxl__multidev *multidev);
+
 _hidden void libxl__add_vttys(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                               libxl_domain_config *d_config,
                               libxl__multidev *multidev);
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 23fcf50..27583cc 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -560,6 +560,15 @@ libxl_device_vrtc = Struct("device_vrtc", [
     ("device", string),
     ])
 
+libxl_device_vdrm = Struct("device_vdrm", [
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+    ("devid", libxl_devid),
+    ("device", string),
+    ("mode0", string),
+    ("mode1", string),
+    ])
+
 libxl_device_vsnd = Struct("device_vsnd", [
     ("backend_domid", libxl_domid),
     ("backend_domname", string),
@@ -676,6 +685,7 @@ libxl_domain_config = Struct("domain_config", [
     ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
     ("vrtcs", Array(libxl_device_vrtc, "num_vrtcs")),
+    ("vdrms", Array(libxl_device_vdrm, "num_vdrms")),
     ("vsnds", Array(libxl_device_vsnd, "num_vsnds")),
     ("vttys", Array(libxl_device_vtty, "num_vttys")),
     # a channel manifests as a console with a name,
@@ -734,6 +744,17 @@ libxl_vrtcinfo = Struct("vrtcinfo", [
     ("rref", integer),
     ], dir=DIR_OUT)
 
+libxl_vdrminfo = Struct("vdrminfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("evtch", integer),
+    ("rref", integer),
+    ], dir=DIR_OUT)
+
 libxl_vsndinfo = Struct("vsndinfo", [
     ("backend", string),
     ("backend_id", uint32),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index a86325c..9a68700 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -26,6 +26,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (10, "VSND"),
     (11, "VTTY"),
     (12, "VEVENT"),
+    (13, "VDRM"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 24a8205..e1532a2 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -80,6 +80,9 @@ int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
 int libxl_devid_to_device_vrtc(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vrtc *vrtc);
 
+int libxl_devid_to_device_vdrm(libxl_ctx *ctx, uint32_t domid,
+                               int devid, libxl_device_vdrm *vdrm);
+
 int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vsnd *vsnd);
 
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 905276d..7c0082c 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -85,6 +85,9 @@ int main_blockdetach(int argc, char **argv);
 int main_vrtcattach(int argc, char **argv);
 int main_vrtclist(int argc, char **argv);
 int main_vrtcdetach(int argc, char **argv);
+int main_vdrmattach(int argc, char **argv);
+int main_vdrmlist(int argc, char **argv);
+int main_vdrmdetach(int argc, char **argv);
 int main_vsndattach(int argc, char **argv);
 int main_vsndlist(int argc, char **argv);
 int main_vsnddetach(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index f8f9edf..df9ebd2 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1272,7 +1272,7 @@ static void parse_config_data(const char *config_source,
     long l, vcpus = 0;
     XLU_Config *config;
     XLU_ConfigList *cpus, *cpuids, *vbds, *nics, *pcis;
-    XLU_ConfigList *cvfbs, *vevents, *vtpms, *vrtcs, *vttys, *vsnds;
+    XLU_ConfigList *cvfbs, *vevents, *vtpms, *vrtcs, *vttys, *vsnds, *vdrms;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
@@ -1902,6 +1902,58 @@ static void parse_config_data(const char *config_source,
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vdrm", &vdrms, 0, 0)) {
+        d_config->num_vdrms = 0;
+        d_config->vdrms = NULL;
+        while ((buf = xlu_cfg_get_listitem(vdrms, d_config->num_vdrms)) != NULL) {
+            libxl_device_vdrm *vdrm;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            vdrm = ARRAY_EXTEND_INIT(d_config->vdrms, d_config->num_vdrms,
+                                     libxl_device_vdrm_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse vdrm configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backendid")) {
+                    vdrm->backend_domid = atoi(value);
+                } else if (!strcmp(key, "backend")) {
+                    replace_string(&vdrm->backend_domname, value);
+                } else if (!strcmp(key, "devid")) {
+                    vdrm->devid = atoi(value);
+                } else if (!strcmp(key, "device")) {
+                    replace_string(&vdrm->device, value);
+                } else if (!strcmp(key, "mode0")) {
+                    replace_string(&vdrm->mode0, value);
+                } else if (!strcmp(key, "mode1")) {
+                    replace_string(&vdrm->mode1, value);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
     if (!xlu_cfg_get_list(config, "vtty", &vttys, 0, 0)) {
         d_config->num_vttys = 0;
         d_config->vttys = NULL;
@@ -7084,6 +7136,116 @@ int main_vrtcdetach(int argc, char **argv)
     return rc;
 }
 
+int main_vdrmattach(int argc, char **argv)
+{
+
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_vdrm vdrm;
+    /*  XLU_Config *config = 0; */
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vdrm-attach", 2) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+    if (optind < argc) {
+        replace_string(&vdrm.device, argv[optind]);
+    }
+    optind++;
+
+/* TODO: fix this temporary hardcode */
+    vdrm.backend_domname = "Domain-D";
+    vdrm.backend_domid = 1;
+
+    if (dryrun_only) {
+        char *json = libxl_device_vdrm_to_json(ctx, &vdrm);
+        printf("vdrm: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_vdrm_add(ctx, fe_domid, &vdrm, 0)) {
+        fprintf(stderr, "libxl_device_vdrm_add failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+int main_vdrmlist(int argc, char **argv)
+{
+	int opt;
+	int i, nb;
+	libxl_device_vdrm *vdrms;
+	libxl_vdrminfo vdrminfo;
+
+	SWITCH_FOREACH_OPT(opt, "", NULL, "vdrm-list", 1) {
+		/* No options */
+	}
+
+	/* vdrminfo.uuid should be outputted too */
+	printf("%-5s %-3s %-6s %-5s %-6s %-8s %-40s %-40s\n",
+			"Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path", "FE-path");
+	for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+		uint32_t domid;
+		if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+			fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+			continue;
+		}
+		vdrms = libxl_device_vdrm_list(ctx, domid, &nb);
+		if (!vdrms) {
+			continue;
+		}
+		for (i=0; i<nb; i++) {
+			if (!libxl_device_vdrm_getinfo(ctx, domid, &vdrms[i], &vdrminfo)) {
+				/*      Vdev BE   hdl  st   evch rref BE-path FE-path UUID */
+				printf("%-5d %-3d %-6d %-5d %-6d %-8d %-40s %-40s\n",
+						vdrminfo.devid, vdrminfo.backend_id, vdrminfo.frontend_id,
+						vdrminfo.state, vdrminfo.evtch, vdrminfo.rref, vdrminfo.backend,
+						vdrminfo.frontend);
+				libxl_vdrminfo_dispose(&vdrminfo);
+			}
+			libxl_device_vdrm_dispose(&vdrms[i]);
+		}
+		free(vdrms);
+	}
+	return 0;
+}
+
+int main_vdrmdetach(int argc, char **argv)
+{
+    uint32_t domid, devid;
+    int opt, rc = 0;
+    libxl_device_vdrm vdrm;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vdrm-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    if (libxl_devid_to_device_vdrm(ctx, domid, devid, &vdrm)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_vdrm_remove(ctx, domid, &vdrm, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vdrm_remove failed.\n");
+        return 1;
+    }
+
+    libxl_device_vdrm_dispose(&vdrm);
+    return rc;
+}
 
 int main_vsndattach(int argc, char **argv)
 {
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index bb410ca..daa07d7 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -366,6 +366,21 @@ struct cmd_spec cmd_table[] = {
       "Destroy a domain's virtual rtc device",
       "<Domain> <DevId>",
     },
+    { "vdrm-attach",
+      &main_vdrmattach, 1, 1,
+      "Create a new virtual rtc device",
+      "<Domain> <Device>",
+    },
+    { "vdrm-list",
+      &main_vdrmlist, 0, 0,
+      "List virtual rtc devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vdrm-detach",
+      &main_vdrmdetach, 0, 1,
+      "Destroy a domain's virtual rtc device",
+      "<Domain> <DevId>",
+    },
     { "vsnd-attach",
       &main_vsndattach, 1, 1,
       "Create a new virtual audio device",
-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH RFC 6/6] libxl: implementation of PV RPMSG device interface
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
                   ` (4 preceding siblings ...)
  2016-05-19 14:37 ` [PATCH RFC 5/6] libxl: implementation of PV DRM " Iurii Mykhalskyi
@ 2016-05-19 14:37 ` Iurii Mykhalskyi
  2016-05-19 17:52 ` [Embedded-pv-devel] [PATCH RFC 0/6] Set of PV drivers used by production project Meng Xu
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Iurii Mykhalskyi @ 2016-05-19 14:37 UTC (permalink / raw)
  To: embedded-pv-devel
  Cc: wei.liu2, stefano.stabellini, ian.jackson, ian.campbell, xen-devel

From: Pavlo Suikov <pavlo.suikov@globallogic.com>

Signed-off-by: Pavlo Suikov <pavlo.suikov@globallogic.com>
Signed-off-by: Iurii Konovalenko <iurii.konovalenko@globallogic.com>
Signed-off-by: Iurii Mykhalskyi <iurii.mykhalskyi@globallogic.com>
---
 tools/libxl/libxl.c                  | 282 +++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.h                  |  17 +++
 tools/libxl/libxl_create.c           |  40 ++++-
 tools/libxl/libxl_device.c           |   2 +
 tools/libxl/libxl_internal.h         |  13 +-
 tools/libxl/libxl_types.idl          |  19 +++
 tools/libxl/libxl_types_internal.idl |   1 +
 tools/libxl/libxl_utils.h            |   3 +
 tools/libxl/xl.h                     |   3 +
 tools/libxl/xl_cmdimpl.c             | 161 +++++++++++++++++++-
 tools/libxl/xl_cmdtable.c            |  21 ++-
 11 files changed, 554 insertions(+), 8 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index ccb0411..871061d 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2873,6 +2873,276 @@ exit:
 
 /******************************************************************************/
 
+int libxl__device_vrpmsg_setdefault(libxl__gc *gc, libxl_device_vrpmsg *vrpmsg)
+{
+    int rc;
+
+    rc = libxl__resolve_domid(gc, vrpmsg->backend_domname, &vrpmsg->backend_domid);
+
+    return rc;
+}
+
+static int libxl__device_from_vrpmsg(libxl__gc *gc, uint32_t domid, libxl_device_vrpmsg *vrpmsg, libxl__device *device)
+{
+   device->backend_devid   = vrpmsg->devid;
+   device->backend_domid   = vrpmsg->backend_domid;
+   device->backend_kind    = LIBXL__DEVICE_KIND_VRPMSG;
+   device->devid           = vrpmsg->devid;
+   device->domid           = domid;
+   device->kind            = LIBXL__DEVICE_KIND_VRPMSG;
+
+   return 0;
+}
+
+static int libxl__device_vrpmsg_from_xs_be(libxl__gc *gc,
+                                        const char *be_path,
+                                        libxl_device_vrpmsg *vrpmsg)
+{
+    const char *tmp;
+    int rc;
+
+    libxl_device_vrpmsg_init(vrpmsg);
+
+    tmp = READ_BACKEND(gc, "device-id");
+    if (tmp)
+        vrpmsg->devid = atoi(tmp);
+    else
+        vrpmsg->devid = 0;
+
+    rc = 0;
+ out:
+    return rc;
+}
+
+int libxl_devid_to_device_vrpmsg(libxl_ctx *ctx, uint32_t domid,
+                              int devid, libxl_device_vrpmsg *vrpmsg)
+{
+    GC_INIT(ctx);
+    char *dompath, *path;
+    int rc = ERROR_FAIL;
+
+    libxl_device_vrpmsg_init(vrpmsg);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    if (!dompath)
+        goto out;
+
+    path = libxl__xs_read(gc, XBT_NULL,
+                          libxl__sprintf(gc, "%s/device/vrpmsg/%d/backend",
+                                         dompath, devid));
+    if (!path)
+        goto out;
+
+    rc = libxl__device_vrpmsg_from_xs_be(gc, path, vrpmsg);
+    if (rc) goto out;
+
+    rc = 0;
+out:
+    GC_FREE;
+    return rc;
+}
+
+void libxl__device_vrpmsg_add(libxl__egc *egc, uint32_t domid, libxl_device_vrpmsg *vrpmsg, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_vrpmsg vrpmsg_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_vrpmsg_init(&vrpmsg_saved);
+    libxl_device_vrpmsg_copy(CTX, &vrpmsg_saved, vrpmsg);
+
+    rc = libxl__device_vrpmsg_setdefault(gc, vrpmsg);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 32, 1);
+
+    if ((vrpmsg->devid = libxl__device_nextid(gc, domid, "vrpmsg")) < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    GCNEW(device);
+    rc = libxl__device_from_vrpmsg(gc, domid, vrpmsg, device);
+    if ( rc != 0 ) goto out;
+
+    flexarray_append(back, "device-id");
+    flexarray_append(back, GCSPRINTF("%d", vrpmsg->devid));
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, GCSPRINTF("%d", domid));
+    flexarray_append(back, "device");
+    flexarray_append(back, vrpmsg->device);
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, GCSPRINTF("%d", 1));
+
+    flexarray_append(front, "device-id");
+    flexarray_append(front, GCSPRINTF("%d", vrpmsg->devid));
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, GCSPRINTF("%d", vrpmsg->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, GCSPRINTF("%d", 1));
+
+    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);
+        LOG(INFO, "aodev updates JSON, libxl__get_domain_configuration returned %d", rc);
+        if (rc) goto out;
+
+        DEVICE_ADD(vrpmsg, vrpmsgs, domid, &vrpmsg_saved, COMPARE_DEVID, &d_config);
+    }
+
+    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) {              /* already exists in xenstore */
+            LOG(ERROR, "device already exists in xenstore");
+            aodev->action = LIBXL__DEVICE_ACTION_ADD; /* for error message */
+            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,
+                                                             back->count),
+                                  libxl__xs_kvs_of_flexarray(gc, front,
+                                                             front->count),
+                                  NULL);
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    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_device_vrpmsg_dispose(&vrpmsg_saved);
+    libxl_domain_config_dispose(&d_config);
+    aodev->rc = rc;
+    if(rc) aodev->callback(egc, aodev);
+    return;
+
+}
+
+libxl_device_vrpmsg *libxl_device_vrpmsg_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_vrpmsg* vrpmsgs = NULL;
+    char* fe_path = NULL;
+    char** dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vrpmsg", libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+    if (dir && ndirs) {
+       vrpmsgs = malloc(sizeof(*vrpmsgs) * ndirs);
+       libxl_device_vrpmsg* vrpmsg;
+       libxl_device_vrpmsg* end = vrpmsgs + ndirs;
+       for(vrpmsg = vrpmsgs; vrpmsg < end; ++vrpmsg, ++dir) {
+          char* tmp;
+
+          libxl_device_vrpmsg_init(vrpmsg);
+
+          vrpmsg->devid = atoi(*dir);
+
+          tmp = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend-id",
+                   fe_path, *dir));
+          vrpmsg->backend_domid = atoi(tmp);
+       }
+    }
+    *num = ndirs;
+
+    GC_FREE;
+    return vrpmsgs;
+}
+
+int libxl_device_vrpmsg_getinfo(libxl_ctx *ctx, uint32_t domid, libxl_device_vrpmsg *vrpmsg, libxl_vrpmsginfo *vrpmsginfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *vrpmsgpath;
+    char *val;
+    int rc = 0;
+
+    libxl_vrpmsginfo_init(vrpmsginfo);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    vrpmsginfo->devid = vrpmsg->devid;
+
+    vrpmsgpath = GCSPRINTF("%s/device/vrpmsg/%d", dompath, vrpmsginfo->devid);
+    vrpmsginfo->backend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/backend", vrpmsgpath), NULL);
+
+    if (!vrpmsginfo->backend) {
+        goto err;
+    }
+
+    if(!libxl__xs_read(gc, XBT_NULL, vrpmsginfo->backend)) {
+       goto err;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/backend-id", vrpmsgpath));
+    vrpmsginfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/state", vrpmsgpath));
+    vrpmsginfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/event-channel", vrpmsgpath));
+    vrpmsginfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/ring-ref", vrpmsgpath));
+    vrpmsginfo->rref = val ? strtoul(val, NULL, 10) : -1;
+
+    vrpmsginfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/frontend", vrpmsginfo->backend), NULL);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/frontend-id", vrpmsginfo->backend));
+    vrpmsginfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    goto exit;
+err:
+    rc = ERROR_FAIL;
+exit:
+    GC_FREE;
+    return rc;
+}
+
+/******************************************************************************/
+
 int libxl__device_vtty_setdefault(libxl__gc *gc, libxl_device_vtty *vtty)
 {
     int rc;
@@ -5573,6 +5843,8 @@ exit:
  * libxl_device_vrtc_destroy
  * libxl_device_vdrm_remove
  * libxl_device_vdrm_destroy
+ * libxl_device_vrpmsg_remove
+ * libxl_device_vrpmsg_destroy
  * libxl_device_vsnd_remove
  * libxl_device_vsnd_destroy
  * libxl_device_vtty_remove
@@ -5637,6 +5909,10 @@ DEFINE_DEVICE_REMOVE(vrtc, destroy, 1)
 DEFINE_DEVICE_REMOVE(vdrm, remove, 0)
 DEFINE_DEVICE_REMOVE(vdrm, destroy, 1)
 
+/* vrpmsg */
+DEFINE_DEVICE_REMOVE(vrpmsg, remove, 0)
+DEFINE_DEVICE_REMOVE(vrpmsg, destroy, 1)
+
 /* vsnd */
 DEFINE_DEVICE_REMOVE(vsnd, remove, 0)
 DEFINE_DEVICE_REMOVE(vsnd, destroy, 1)
@@ -5664,6 +5940,7 @@ DEFINE_DEVICE_REMOVE(vevent, destroy, 1)
  * libxl_device_vtpm_add
  * libxl_device_vrtc_add
  * libxl_device_vdrm_add
+ * libxl_device_vrpmsg_add
  * libxl_device_vsnd_add
  * libxl_device_vtty_add
  * libxl_device_vevent_add
@@ -5704,6 +5981,9 @@ DEFINE_DEVICE_ADD(vrtc)
 /* vdrm */
 DEFINE_DEVICE_ADD(vdrm)
 
+/* vrpmsg */
+DEFINE_DEVICE_ADD(vrpmsg)
+
 /* vsnd */
 DEFINE_DEVICE_ADD(vsnd)
 
@@ -8232,6 +8512,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
 
     MERGE(vdrm, vdrms, COMPARE_DEVID, {});
 
+    MERGE(vrpmsg, vrpmsgs, COMPARE_DEVID, {});
+
     MERGE(vsnd, vsnds, COMPARE_DEVID, {});
 
     MERGE(pci, pcidevs, COMPARE_PCI, {});
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 57f3e03..fb2f8d4 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1469,6 +1469,23 @@ libxl_device_vdrm *libxl_device_vdrm_list(libxl_ctx *ctx, uint32_t domid, int *n
 int libxl_device_vdrm_getinfo(libxl_ctx *ctx, uint32_t domid,
                               libxl_device_vdrm *vdrm, libxl_vdrminfo *vdrminfo);
 
+/* RPMSG */
+int libxl_device_vrpmsg_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vrpmsg *vrpmsg,
+                          const libxl_asyncop_how *ao_how)
+                          LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vrpmsg_remove(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_vrpmsg *vrpmsg,
+                             const libxl_asyncop_how *ao_how)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vrpmsg_destroy(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vrpmsg *vrpmsg,
+                              const libxl_asyncop_how *ao_how)
+                              LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vrpmsg *libxl_device_vrpmsg_list(libxl_ctx *ctx, uint32_t domid, int *num);
+int libxl_device_vrpmsg_getinfo(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vrpmsg *vrpmsg, libxl_vrpmsginfo *vrpmsginfo);
+
 /* Audio */
 int libxl_device_vsnd_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vsnd *vsnd,
                           const libxl_asyncop_how *ao_how)
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 6e1c0d8..11ae349 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -738,6 +738,8 @@ static void domcreate_attach_vrtcs(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_vdrms(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
+static void domcreate_attach_vrpmsgs(libxl__egc *egc, libxl__multidev *multidev,
+                                     int ret);
 static void domcreate_attach_vttys(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
 static void domcreate_attach_vsnds(libxl__egc *egc, libxl__multidev *multidev,
@@ -1468,13 +1470,13 @@ static void domcreate_attach_vdrms(libxl__egc *egc,
    if (d_config->num_vdrms > 0) {
        /* Attach vdrms */
        libxl__multidev_begin(ao, &dcs->multidev);
-       dcs->multidev.callback = domcreate_attach_vttys;
+       dcs->multidev.callback = domcreate_attach_vrpmsgs;
        libxl__add_vdrms(egc, ao, domid, d_config, &dcs->multidev);
        libxl__multidev_prepared(egc, &dcs->multidev, 0);
        return;
    }
 
-   domcreate_attach_vttys(egc, multidev, 0);
+   domcreate_attach_vrpmsgs(egc, multidev, 0);
    return;
 
 error_out:
@@ -1482,6 +1484,38 @@ error_out:
    domcreate_complete(egc, dcs, ret);
 }
 
+static void domcreate_attach_vrpmsgs(libxl__egc *egc,
+                                     libxl__multidev *multidev,
+                                     int ret)
+{
+   libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+   STATE_AO_GC(dcs->ao);
+   int domid = dcs->guest_domid;
+
+   libxl_domain_config* const d_config = dcs->guest_config;
+
+   if(ret) {
+       LOG(ERROR, "unable to add vdrm devices");
+       goto error_out;
+   }
+
+    /* Plug vrpmsg devices */
+   if (d_config->num_vrpmsgs > 0) {
+       /* Attach vrpmsgs */
+       libxl__multidev_begin(ao, &dcs->multidev);
+       dcs->multidev.callback = domcreate_attach_vttys;
+       libxl__add_vrpmsgs(egc, ao, domid, d_config, &dcs->multidev);
+       libxl__multidev_prepared(egc, &dcs->multidev, 0);
+       return;
+   }
+
+   domcreate_attach_vttys(egc, multidev, 0);
+   return;
+
+error_out:
+   assert(ret);
+   domcreate_complete(egc, dcs, ret);
+}
 
 static void domcreate_attach_vttys(libxl__egc *egc,
                                    libxl__multidev *multidev,
@@ -1494,7 +1528,7 @@ static void domcreate_attach_vttys(libxl__egc *egc,
    libxl_domain_config* const d_config = dcs->guest_config;
 
    if(ret) {
-       LOG(ERROR, "unable to add vdrm devices");
+       LOG(ERROR, "unable to add vrpmsg devices");
        goto error_out;
    }
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 13c4a7b..1949dd4 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -546,6 +546,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_vtpms
  * libxl__add_vrtcs
  * libxl__add_vdrms
+ * libxl__add_vrpmsgs
  * libxl__add_vsnds
  * libxl__add_vttys
  * libxl__add_vevents
@@ -570,6 +571,7 @@ DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vtpm)
 DEFINE_DEVICES_ADD(vrtc)
 DEFINE_DEVICES_ADD(vdrm)
+DEFINE_DEVICES_ADD(vrpmsg)
 DEFINE_DEVICES_ADD(vsnd)
 DEFINE_DEVICES_ADD(vtty)
 DEFINE_DEVICES_ADD(vevent)
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 80754df..fb9e858 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -481,7 +481,8 @@ typedef struct {
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VSND || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VTTY || \
     (dev)->backend_kind == LIBXL__DEVICE_KIND_VEVENT || \
-    (dev)->backend_kind == LIBXL__DEVICE_KIND_VDRM)
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VDRM || \
+    (dev)->backend_kind == LIBXL__DEVICE_KIND_VRPMSG)
 
 #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
 #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
@@ -1193,6 +1194,7 @@ _hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
 _hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm);
 _hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc);
 _hidden int libxl__device_vdrm_setdefault(libxl__gc *gc, libxl_device_vdrm *vdrm);
+_hidden int libxl__device_vrpmsg_setdefault(libxl__gc *gc, libxl_device_vrpmsg *vrpmsg);
 _hidden int libxl__device_vsnd_setdefault(libxl__gc *gc, libxl_device_vsnd *vsnd);
 _hidden int libxl__device_vtty_setdefault(libxl__gc *gc, libxl_device_vtty *vtty);
 _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
@@ -2585,6 +2587,11 @@ _hidden void libxl__device_vdrm_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_vdrm *vdrm,
                                     libxl__ao_device *aodev);
 
+/* AO operation to connect an rpmsg device */
+_hidden void libxl__device_vrpmsg_add(libxl__egc *egc, uint32_t domid,
+                                      libxl_device_vrpmsg *vrpmsg,
+                                      libxl__ao_device *aodev);
+
 /* AO operation to connect a sound device */
 _hidden void libxl__device_vsnd_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_vsnd *vsnd,
@@ -3324,6 +3331,10 @@ _hidden void libxl__add_vdrms(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                               libxl_domain_config *d_config,
                               libxl__multidev *multidev);
 
+_hidden void libxl__add_vrpmsgs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                                libxl_domain_config *d_config,
+                                libxl__multidev *multidev);
+
 _hidden void libxl__add_vttys(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                               libxl_domain_config *d_config,
                               libxl__multidev *multidev);
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 27583cc..a422350 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -569,6 +569,13 @@ libxl_device_vdrm = Struct("device_vdrm", [
     ("mode1", string),
     ])
 
+libxl_device_vrpmsg = Struct("device_vrpmsg", [
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+    ("devid", libxl_devid),
+    ("device", string),
+    ])
+
 libxl_device_vsnd = Struct("device_vsnd", [
     ("backend_domid", libxl_domid),
     ("backend_domname", string),
@@ -686,6 +693,7 @@ libxl_domain_config = Struct("domain_config", [
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
     ("vrtcs", Array(libxl_device_vrtc, "num_vrtcs")),
     ("vdrms", Array(libxl_device_vdrm, "num_vdrms")),
+    ("vrpmsgs", Array(libxl_device_vrpmsg, "num_vrpmsgs")),
     ("vsnds", Array(libxl_device_vsnd, "num_vsnds")),
     ("vttys", Array(libxl_device_vtty, "num_vttys")),
     # a channel manifests as a console with a name,
@@ -755,6 +763,17 @@ libxl_vdrminfo = Struct("vdrminfo", [
     ("rref", integer),
     ], dir=DIR_OUT)
 
+libxl_vrpmsginfo = Struct("vrpmsginfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("evtch", integer),
+    ("rref", integer),
+    ], dir=DIR_OUT)
+
 libxl_vsndinfo = Struct("vsndinfo", [
     ("backend", string),
     ("backend_id", uint32),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 9a68700..d5ca05e 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -27,6 +27,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (11, "VTTY"),
     (12, "VEVENT"),
     (13, "VDRM"),
+    (14, "VRPMSG"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index e1532a2..04a88fd 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -83,6 +83,9 @@ int libxl_devid_to_device_vrtc(libxl_ctx *ctx, uint32_t domid,
 int libxl_devid_to_device_vdrm(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vdrm *vdrm);
 
+int libxl_devid_to_device_vrpmsg(libxl_ctx *ctx, uint32_t domid,
+                                 int devid, libxl_device_vrpmsg *vrpmsg);
+
 int libxl_devid_to_device_vsnd(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vsnd *vsnd);
 
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 7c0082c..93892da 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -88,6 +88,9 @@ int main_vrtcdetach(int argc, char **argv);
 int main_vdrmattach(int argc, char **argv);
 int main_vdrmlist(int argc, char **argv);
 int main_vdrmdetach(int argc, char **argv);
+int main_vrpmsgattach(int argc, char **argv);
+int main_vrpmsglist(int argc, char **argv);
+int main_vrpmsgdetach(int argc, char **argv);
 int main_vsndattach(int argc, char **argv);
 int main_vsndlist(int argc, char **argv);
 int main_vsnddetach(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index df9ebd2..bc6e89f 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1272,7 +1272,7 @@ static void parse_config_data(const char *config_source,
     long l, vcpus = 0;
     XLU_Config *config;
     XLU_ConfigList *cpus, *cpuids, *vbds, *nics, *pcis;
-    XLU_ConfigList *cvfbs, *vevents, *vtpms, *vrtcs, *vttys, *vsnds, *vdrms;
+    XLU_ConfigList *cvfbs, *vevents, *vtpms, *vrtcs, *vttys, *vsnds, *vdrms, *vrpmsgs;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
@@ -1954,6 +1954,54 @@ static void parse_config_data(const char *config_source,
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vrpmsg", &vrpmsgs, 0, 0)) {
+        d_config->num_vrpmsgs = 0;
+        d_config->vrpmsgs = NULL;
+        while ((buf = xlu_cfg_get_listitem(vrpmsgs, d_config->num_vrpmsgs)) != NULL) {
+            libxl_device_vrpmsg *vrpmsg;
+            libxl_string_list pairs;
+            char *path = NULL;
+            int len;
+
+            vrpmsg = ARRAY_EXTEND_INIT(d_config->vrpmsgs, d_config->num_vrpmsgs,
+                                     libxl_device_vrpmsg_init);
+
+            split_string_into_string_list(buf, ",", &pairs);
+            len = libxl_string_list_length(&pairs);
+
+            for (i = 0; i < len; i++) {
+                char *key, *key_untrimmed, *value, *value_untrimmed;
+                int rc;
+                rc = split_string_into_pair(pairs[i], "=",
+                                            &key_untrimmed,
+                                            &value_untrimmed);
+                if (rc != 0) {
+                    fprintf(stderr, "failed to parse vrpmsg configuration: %s",
+                            pairs[i]);
+                    exit(1);
+                }
+                trim(isspace, key_untrimmed, &key);
+                trim(isspace, value_untrimmed, &value);
+
+                if (!strcmp(key, "backendid")) {
+                    vrpmsg->backend_domid = atoi(value);
+                } else if (!strcmp(key, "backend")) {
+                    replace_string(&vrpmsg->backend_domname, value);
+                } else if (!strcmp(key, "devid")) {
+                    vrpmsg->devid = atoi(value);
+                } else if (!strcmp(key, "device")) {
+                    replace_string(&vrpmsg->device, value);
+                }
+                free(key);
+                free(key_untrimmed);
+                free(value);
+                free(value_untrimmed);
+            }
+            libxl_string_list_dispose(&pairs);
+            free(path);
+        }
+    }
+
     if (!xlu_cfg_get_list(config, "vtty", &vttys, 0, 0)) {
         d_config->num_vttys = 0;
         d_config->vttys = NULL;
@@ -7247,6 +7295,117 @@ int main_vdrmdetach(int argc, char **argv)
     return rc;
 }
 
+int main_vrpmsgattach(int argc, char **argv)
+{
+
+    int opt;
+    uint32_t fe_domid;
+    libxl_device_vrpmsg vrpmsg;
+    /*  XLU_Config *config = 0; */
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vrpmsg-attach", 2) {
+        /* No options */
+    }
+
+    if (libxl_domain_qualifier_to_domid(ctx, argv[optind], &fe_domid) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]);
+        return 1;
+    }
+    optind++;
+
+    if (optind < argc) {
+        replace_string(&vrpmsg.device, argv[optind]);
+    }
+    optind++;
+
+/* TODO: fix this temporary hardcode */
+    vrpmsg.backend_domname = "Domain-D";
+    vrpmsg.backend_domid = 1;
+
+    if (dryrun_only) {
+        char *json = libxl_device_vrpmsg_to_json(ctx, &vrpmsg);
+        printf("vrpmsg: %s\n", json);
+        free(json);
+        if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); }
+        return 0;
+    }
+
+    if (libxl_device_vrpmsg_add(ctx, fe_domid, &vrpmsg, 0)) {
+        fprintf(stderr, "libxl_device_vrpmsg_add failed.\n");
+        return 1;
+    }
+
+    return 0;
+}
+
+int main_vrpmsglist(int argc, char **argv)
+{
+	int opt;
+	int i, nb;
+	libxl_device_vrpmsg *vrpmsgs;
+	libxl_vrpmsginfo vrpmsginfo;
+
+	SWITCH_FOREACH_OPT(opt, "", NULL, "vrpmsg-list", 1) {
+		/* No options */
+	}
+
+	/* vrpmsginfo.uuid should be outputted too */
+	printf("%-5s %-3s %-6s %-5s %-6s %-8s %-40s %-40s\n",
+			"Vdev", "BE", "handle", "state", "evt-ch", "ring-ref", "BE-path", "FE-path");
+	for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+		uint32_t domid;
+		if (libxl_domain_qualifier_to_domid(ctx, *argv, &domid) < 0) {
+			fprintf(stderr, "%s is an invalid domain identifier\n", *argv);
+			continue;
+		}
+		vrpmsgs = libxl_device_vrpmsg_list(ctx, domid, &nb);
+		if (!vrpmsgs) {
+			continue;
+		}
+		for (i=0; i<nb; i++) {
+			if (!libxl_device_vrpmsg_getinfo(ctx, domid, &vrpmsgs[i], &vrpmsginfo)) {
+				/*      Vdev BE   hdl  st   evch rref BE-path FE-path UUID */
+				printf("%-5d %-3d %-6d %-5d %-6d %-8d %-40s %-40s\n",
+						vrpmsginfo.devid, vrpmsginfo.backend_id, vrpmsginfo.frontend_id,
+						vrpmsginfo.state, vrpmsginfo.evtch, vrpmsginfo.rref, vrpmsginfo.backend,
+						vrpmsginfo.frontend);
+				libxl_vrpmsginfo_dispose(&vrpmsginfo);
+			}
+			libxl_device_vrpmsg_dispose(&vrpmsgs[i]);
+		}
+		free(vrpmsgs);
+	}
+	return 0;
+}
+
+int main_vrpmsgdetach(int argc, char **argv)
+{
+    uint32_t domid, devid;
+    int opt, rc = 0;
+    libxl_device_vrpmsg vrpmsg;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "vrpmsg-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    if (libxl_devid_to_device_vrpmsg(ctx, domid, devid, &vrpmsg)) {
+        fprintf(stderr, "Error: Device %s not connected.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_vrpmsg_remove(ctx, domid, &vrpmsg, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vrpmsg_remove failed.\n");
+        return 1;
+    }
+
+    libxl_device_vrpmsg_dispose(&vrpmsg);
+    return rc;
+}
+
 int main_vsndattach(int argc, char **argv)
 {
     int opt;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index daa07d7..bc90cd7 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -368,17 +368,32 @@ struct cmd_spec cmd_table[] = {
     },
     { "vdrm-attach",
       &main_vdrmattach, 1, 1,
-      "Create a new virtual rtc device",
+      "Create a new virtual drm device",
       "<Domain> <Device>",
     },
     { "vdrm-list",
       &main_vdrmlist, 0, 0,
-      "List virtual rtc devices for a domain",
+      "List virtual drm devices for a domain",
       "<Domain(s)>",
     },
     { "vdrm-detach",
       &main_vdrmdetach, 0, 1,
-      "Destroy a domain's virtual rtc device",
+      "Destroy a domain's virtual drm device",
+      "<Domain> <DevId>",
+    },
+    { "vrpmsg-attach",
+      &main_vrpmsgattach, 1, 1,
+      "Create a new virtual rpmsg device",
+      "<Domain> <Device>",
+    },
+    { "vrpmsg-list",
+      &main_vrpmsglist, 0, 0,
+      "List virtual rpmsg devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vrpmsg-detach",
+      &main_vrpmsgdetach, 0, 1,
+      "Destroy a domain's virtual rpmsg device",
       "<Domain> <DevId>",
     },
     { "vsnd-attach",
-- 
2.8.2


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [Embedded-pv-devel] [PATCH RFC 0/6] Set of PV drivers used by production project
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
                   ` (5 preceding siblings ...)
  2016-05-19 14:37 ` [PATCH RFC 6/6] libxl: implementation of PV RPMSG " Iurii Mykhalskyi
@ 2016-05-19 17:52 ` Meng Xu
  2016-05-23 11:40 ` Wei Liu
  2016-06-02 16:12 ` Wei Liu
  8 siblings, 0 replies; 12+ messages in thread
From: Meng Xu @ 2016-05-19 17:52 UTC (permalink / raw)
  To: Iurii Mykhalskyi
  Cc: Wei Liu, Ian Campbell, Stefano Stabellini, Ian Jackson,
	xen-devel, embedded-pv-devel

Hi Lurii,

On Thu, May 19, 2016 at 10:37 AM, Iurii Mykhalskyi
<iurii.mykhalskyi@globallogic.com> wrote:
> This patches introduce set of pv drivers interfaces.

Thank you very much for these pv drivers interfaces! It will be useful
for automotive applications, IMO.

However, I do have some questions:
I'm wondering how general the pv driver interfaces are?
Which types of ARM boards (I assume it's for ARM) can they be used?
What are the ARM boards you have tested on?
What are the production use case we are talking about here?

Are you or globallogic going to contribute the PV drivers as well? I'm
looking forward to the PV drivers as well. :-)

Thanks and Best Regards,

Meng
-----------
Meng Xu
PhD Student in Computer and Information Science
University of Pennsylvania
http://www.cis.upenn.edu/~mengxu/

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/6] Set of PV drivers used by production project
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
                   ` (6 preceding siblings ...)
  2016-05-19 17:52 ` [Embedded-pv-devel] [PATCH RFC 0/6] Set of PV drivers used by production project Meng Xu
@ 2016-05-23 11:40 ` Wei Liu
  2016-06-02 16:12 ` Wei Liu
  8 siblings, 0 replies; 12+ messages in thread
From: Wei Liu @ 2016-05-23 11:40 UTC (permalink / raw)
  To: Iurii Mykhalskyi
  Cc: wei.liu2, ian.campbell, stefano.stabellini, ian.jackson,
	xen-devel, embedded-pv-devel

On Thu, May 19, 2016 at 05:37:29PM +0300, Iurii Mykhalskyi wrote:
> This patches introduce set of pv drivers interfaces.
> Drivers interfaces list:
>  - PV RTC - real-time clock
>  - PV TTY - interface for pv version for device controlled by
>     via tty (e.g. GPS)
>  - PV Audio - sound interface virtualization
>  - PV DRM - direct rengering manager virtualization
>  - PV RPMSG - remove procedure call interface, in our case
>     used for playback codecs virtualization
> 
> Iurii Mykhalskyi (2):
>   libxl: implementation of PV rtc device interface
>   libxl: implementation of PV tty device interface.
> 
> Pavlo Suikov (4):
>   libxl: implementation of PV audio device interface
>   libxl: implementation of PV event device interface
>   libxl: implementation of PV DRM device interface
>   libxl: implementation of PV RPMSG device interface
> 
>  tools/libxl/libxl.c                  | 1781 +++++++++++++++++++++++++++++++++-
>  tools/libxl/libxl.h                  |  102 ++
>  tools/libxl/libxl_create.c           |  214 +++-
>  tools/libxl/libxl_device.c           |   12 +
>  tools/libxl/libxl_internal.c         |    8 +
>  tools/libxl/libxl_internal.h         |   88 +-
>  tools/libxl/libxl_types.idl          |  131 +++
>  tools/libxl/libxl_types_internal.idl |    6 +
>  tools/libxl/libxl_utils.h            |   19 +
>  tools/libxl/xl.h                     |   18 +
>  tools/libxl/xl_cmdimpl.c             | 1035 +++++++++++++++++++-
>  tools/libxl/xl_cmdtable.c            |   95 ++
>  12 files changed, 3499 insertions(+), 10 deletions(-)
> 

I've added this series to my list of things to look at, but it will
probably need to wait a bit before I can get to it.

Wei.

> -- 
> 2.8.2
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/6] libxl: implementation of PV rtc device interface
  2016-05-19 14:37 ` [PATCH RFC 1/6] libxl: implementation of PV rtc device interface Iurii Mykhalskyi
@ 2016-05-23 16:45   ` Olaf Hering
  2016-06-06 13:37   ` Wei Liu
  1 sibling, 0 replies; 12+ messages in thread
From: Olaf Hering @ 2016-05-23 16:45 UTC (permalink / raw)
  To: Iurii Mykhalskyi
  Cc: wei.liu2, ian.campbell, stefano.stabellini, ian.jackson,
	xen-devel, embedded-pv-devel

On Thu, May 19, Iurii Mykhalskyi wrote:

> +    flexarray_append(back, "state");
> +    flexarray_append(back, GCSPRINTF("%d", 1));

This should use the enum values instead of hardcoded "1", see the other
users of "state" in staging.

Olaf

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 0/6] Set of PV drivers used by production project
  2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
                   ` (7 preceding siblings ...)
  2016-05-23 11:40 ` Wei Liu
@ 2016-06-02 16:12 ` Wei Liu
  8 siblings, 0 replies; 12+ messages in thread
From: Wei Liu @ 2016-06-02 16:12 UTC (permalink / raw)
  To: Iurii Mykhalskyi
  Cc: wei.liu2, ian.campbell, stefano.stabellini, ian.jackson,
	xen-devel, embedded-pv-devel

On Thu, May 19, 2016 at 05:37:29PM +0300, Iurii Mykhalskyi wrote:
> This patches introduce set of pv drivers interfaces.
> Drivers interfaces list:
>  - PV RTC - real-time clock
>  - PV TTY - interface for pv version for device controlled by
>     via tty (e.g. GPS)
>  - PV Audio - sound interface virtualization
>  - PV DRM - direct rengering manager virtualization
>  - PV RPMSG - remove procedure call interface, in our case
>     used for playback codecs virtualization
> 
> Iurii Mykhalskyi (2):
>   libxl: implementation of PV rtc device interface
>   libxl: implementation of PV tty device interface.
> 
> Pavlo Suikov (4):
>   libxl: implementation of PV audio device interface
>   libxl: implementation of PV event device interface
>   libxl: implementation of PV DRM device interface
>   libxl: implementation of PV RPMSG device interface
> 
>  tools/libxl/libxl.c                  | 1781 +++++++++++++++++++++++++++++++++-
>  tools/libxl/libxl.h                  |  102 ++
>  tools/libxl/libxl_create.c           |  214 +++-
>  tools/libxl/libxl_device.c           |   12 +
>  tools/libxl/libxl_internal.c         |    8 +
>  tools/libxl/libxl_internal.h         |   88 +-
>  tools/libxl/libxl_types.idl          |  131 +++
>  tools/libxl/libxl_types_internal.idl |    6 +
>  tools/libxl/libxl_utils.h            |   19 +
>  tools/libxl/xl.h                     |   18 +
>  tools/libxl/xl_cmdimpl.c             | 1035 +++++++++++++++++++-
>  tools/libxl/xl_cmdtable.c            |   95 ++
>  12 files changed, 3499 insertions(+), 10 deletions(-)
> 

Just a heads-up, we have now reworked the xenstore paths libxl used to
handle devices (XSA-175 and XSA-180), you might want to update this
series.

I will still review this series as if the paths have been updated when I
get around to it. But if you manage to finish a new version, don't
hesitate to send it out.

Wei.

> -- 
> 2.8.2
> 

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH RFC 1/6] libxl: implementation of PV rtc device interface
  2016-05-19 14:37 ` [PATCH RFC 1/6] libxl: implementation of PV rtc device interface Iurii Mykhalskyi
  2016-05-23 16:45   ` Olaf Hering
@ 2016-06-06 13:37   ` Wei Liu
  1 sibling, 0 replies; 12+ messages in thread
From: Wei Liu @ 2016-06-06 13:37 UTC (permalink / raw)
  To: Iurii Mykhalskyi
  Cc: wei.liu2, ian.campbell, stefano.stabellini, ian.jackson,
	xen-devel, embedded-pv-devel

On Thu, May 19, 2016 at 05:37:30PM +0300, Iurii Mykhalskyi wrote:
> PV rtc device interface is implemented in libxl and xl with
> full support for device control. No JSON parser for domain
> configuration yet.

I'm not sure I follow the last sentence. What JSON parser do you need?

Is there a specification for vrtc that I can reference? I don't see one
in xen/include/public/io.

> +
>  
>  /******************************************************************************/
>  
> @@ -4131,12 +4402,14 @@ out:
>   * libxl_device_disk_destroy
>   * libxl_device_nic_remove
>   * libxl_device_nic_destroy
> - * libxl_device_vtpm_remove
> - * libxl_device_vtpm_destroy
>   * libxl_device_vkb_remove
>   * libxl_device_vkb_destroy
>   * libxl_device_vfb_remove
>   * libxl_device_vfb_destroy
> + * libxl_device_vtpm_remove
> + * libxl_device_vtpm_destroy

Unrelated change here.

> + * libxl_device_vrtc_remove
> + * libxl_device_vrtc_destroy
>   */
>  #define DEFINE_DEVICE_REMOVE(type, removedestroy, f)                    \
>      int libxl_device_##type##_##removedestroy(libxl_ctx *ctx,           \
> @@ -4188,6 +4461,10 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
>  DEFINE_DEVICE_REMOVE(vtpm, remove, 0)
>  DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
>  
> +/* vrtc */
> +DEFINE_DEVICE_REMOVE(vrtc, remove, 0)
> +DEFINE_DEVICE_REMOVE(vrtc, destroy, 1)
> +
>  /* channel/console hotunplug is not implemented. There are 2 possibilities:
>   * 1. add support for secondary consoles to xenconsoled
>   * 2. dynamically add/remove qemu chardevs via qmp messages. */
> @@ -4201,6 +4478,7 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
>   * libxl_device_disk_add
>   * libxl_device_nic_add
>   * libxl_device_vtpm_add
> + * libxl_device_vrtc_add
>   */
>  
>  #define DEFINE_DEVICE_ADD(type)                                         \
> @@ -4232,6 +4510,9 @@ DEFINE_DEVICE_ADD(nic)
>  /* vtpm */
>  DEFINE_DEVICE_ADD(vtpm)
>  
> +/* vrtc */
> +DEFINE_DEVICE_ADD(vrtc)
> +
>  #undef DEFINE_DEVICE_ADD
>  
>  /******************************************************************************/
> @@ -6747,6 +7028,8 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
>  
>      MERGE(vtpm, vtpms, COMPARE_DEVID, {});
>  
> +    MERGE(vrtc, vrtcs, COMPARE_DEVID, {});
> +
>      MERGE(pci, pcidevs, COMPARE_PCI, {});
>  
>      /* Take care of removable device. We maintain invariant in the
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index fa5aedd..9243b86 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -1435,6 +1435,23 @@ 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);
>  
> +/* RTC */
> +int libxl_device_vrtc_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vrtc *vrtc,
> +                          const libxl_asyncop_how *ao_how)
> +                          LIBXL_EXTERNAL_CALLERS_ONLY;
> +int libxl_device_vrtc_remove(libxl_ctx *ctx, uint32_t domid,
> +                             libxl_device_vrtc *vrtc,
> +                             const libxl_asyncop_how *ao_how)
> +                             LIBXL_EXTERNAL_CALLERS_ONLY;
> +int libxl_device_vrtc_destroy(libxl_ctx *ctx, uint32_t domid,
> +                              libxl_device_vrtc *vrtc,
> +                              const libxl_asyncop_how *ao_how)
> +                              LIBXL_EXTERNAL_CALLERS_ONLY;
> +
> +libxl_device_vrtc *libxl_device_vrtc_list(libxl_ctx *ctx, uint32_t domid, int *num);
> +int libxl_device_vrtc_getinfo(libxl_ctx *ctx, uint32_t domid,
> +                              libxl_device_vrtc *vrtc, libxl_vrtcinfo *vrtcinfo);
> +
>  /* 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 1c0579c..1206c34 100644
> --- a/tools/libxl/libxl_create.c
> +++ b/tools/libxl/libxl_create.c
> @@ -734,6 +734,8 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *aodevs,
>  
>  static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
>                                     int ret);
> +static void domcreate_attach_vrtcs(libxl__egc *egc, libxl__multidev *multidev,
> +                                   int ret);
>  static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
>                                   int ret);
>  static void domcreate_attach_dtdev(libxl__egc *egc,
> @@ -1392,12 +1394,45 @@ static void domcreate_attach_vtpms(libxl__egc *egc,
>     if (d_config->num_vtpms > 0) {
>         /* Attach vtpms */
>         libxl__multidev_begin(ao, &dcs->multidev);
> -       dcs->multidev.callback = domcreate_attach_pci;
> +       dcs->multidev.callback = domcreate_attach_vrtcs;
>         libxl__add_vtpms(egc, ao, domid, d_config, &dcs->multidev);
>         libxl__multidev_prepared(egc, &dcs->multidev, 0);
>         return;
>     }
>  
> +   domcreate_attach_vrtcs(egc, multidev, 0);
> +   return;
> +
> +error_out:
> +   assert(ret);
> +   domcreate_complete(egc, dcs, ret);
> +}
> +
> +static void domcreate_attach_vrtcs(libxl__egc *egc,
> +                                   libxl__multidev *multidev,
> +                                   int ret)
> +{
> +   libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
> +   STATE_AO_GC(dcs->ao);
> +   int domid = dcs->guest_domid;
> +
> +   libxl_domain_config* const d_config = dcs->guest_config;
> +
> +   if(ret) {
> +       LOG(ERROR, "unable to add vtpm devices");
> +       goto error_out;
> +   }
> +
> +    /* Plug vrtc devices */
> +   if (d_config->num_vrtcs > 0) {
> +       /* Attach vrtcs */
> +       libxl__multidev_begin(ao, &dcs->multidev);
> +       dcs->multidev.callback = domcreate_attach_pci;
> +       libxl__add_vrtcs(egc, ao, domid, d_config, &dcs->multidev);
> +       libxl__multidev_prepared(egc, &dcs->multidev, 0);
> +       return;
> +   }
> +
>     domcreate_attach_pci(egc, multidev, 0);
>     return;
>  
> @@ -1419,7 +1454,7 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
>      libxl_domain_config *const d_config = dcs->guest_config;
>  
>      if (ret) {
> -        LOG(ERROR, "unable to add vtpm devices");
> +        LOG(ERROR, "unable to add vrtc devices");
>          goto error_out;
>      }
>  
> diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
> index 8bb5e93..72f09a0 100644
> --- a/tools/libxl/libxl_device.c
> +++ b/tools/libxl/libxl_device.c
> @@ -544,6 +544,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
>   * libxl__add_disks
>   * libxl__add_nics
>   * libxl__add_vtpms
> + * libxl__add_vrtcs
>   */
>  
>  #define DEFINE_DEVICES_ADD(type)                                        \
> @@ -563,6 +564,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
>  DEFINE_DEVICES_ADD(disk)
>  DEFINE_DEVICES_ADD(nic)
>  DEFINE_DEVICES_ADD(vtpm)
> +DEFINE_DEVICES_ADD(vrtc)
>  
>  #undef DEFINE_DEVICES_ADD
>  
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 5b0b50a..2a423b5 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -476,7 +476,8 @@ typedef struct {
>  #define QEMU_BACKEND(dev) (\
>      (dev)->backend_kind == LIBXL__DEVICE_KIND_QDISK || \
>      (dev)->backend_kind == LIBXL__DEVICE_KIND_VFB || \
> -    (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD)
> +    (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD || \
> +    (dev)->backend_kind == LIBXL__DEVICE_KIND_VRTC)
>  

So it is going to be backed by QEMU?

>  #define XC_PCI_BDF             "0x%x, 0x%x, 0x%x, 0x%x"
>  #define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
> @@ -1186,6 +1187,7 @@ _hidden int libxl__device_disk_setdefault(libxl__gc *gc,
>  _hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
>                                           uint32_t domid);
>  _hidden int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm);
> +_hidden int libxl__device_vrtc_setdefault(libxl__gc *gc, libxl_device_vrtc *vrtc);
>  _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
>  _hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
>  _hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
> @@ -2549,6 +2551,8 @@ struct libxl__multidev {
>   * xenstore entry afterwards. We have both JSON and xenstore entry,
>   * it's a valid state.
>   */
> +
> +/* AO operation to connect a disk device */

Unrelated change.

All these add comments should go to a separate patch.  But I don't think
they are absolutely needed.

>  _hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
>                                      libxl_device_disk *disk,
>                                      libxl__ao_device *aodev);
> @@ -2558,9 +2562,15 @@ _hidden void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
>                                     libxl_device_nic *nic,
>                                     libxl__ao_device *aodev);
>  
> +/* AO operation to connect a tpm device */
>  _hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
> -                                   libxl_device_vtpm *vtpm,
> -                                   libxl__ao_device *aodev);
> +                                    libxl_device_vtpm *vtpm,
> +                                    libxl__ao_device *aodev);
> +

Unrelated change.

> +/* AO operation to connect an rtc device */
> +_hidden void libxl__device_vrtc_add(libxl__egc *egc, uint32_t domid,
> +                                    libxl_device_vrtc *vrtc,
> +                                    libxl__ao_device *aodev);
>  
>  /* Internal function to connect a vkb device */
>  _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
> @@ -3278,6 +3288,9 @@ _hidden void libxl__add_vtpms(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
>                               libxl_domain_config *d_config,
>                               libxl__multidev *multidev);
>  
> +_hidden void libxl__add_vrtcs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
> +                             libxl_domain_config *d_config,
> +                             libxl__multidev *multidev);

Indentation.

I skim-read this patch. The structure and arrangement looks plausible.
Please fix the coding style issues and remove unrelated changes. Please
also provide some more references in commit message.

You also need to provide a LIBXL_HAVE macro in libxl.h.

I think my comments here apply to all patches in this series.

Please don't hesitate to ask if my comments are not clear.

Wei.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2016-06-06 13:37 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-19 14:37 [PATCH RFC 0/6] Set of PV drivers used by production project Iurii Mykhalskyi
2016-05-19 14:37 ` [PATCH RFC 1/6] libxl: implementation of PV rtc device interface Iurii Mykhalskyi
2016-05-23 16:45   ` Olaf Hering
2016-06-06 13:37   ` Wei Liu
2016-05-19 14:37 ` [PATCH RFC 2/6] libxl: implementation of PV audio " Iurii Mykhalskyi
2016-05-19 14:37 ` [PATCH RFC 3/6] libxl: implementation of PV tty " Iurii Mykhalskyi
2016-05-19 14:37 ` [PATCH RFC 4/6] libxl: implementation of PV event " Iurii Mykhalskyi
2016-05-19 14:37 ` [PATCH RFC 5/6] libxl: implementation of PV DRM " Iurii Mykhalskyi
2016-05-19 14:37 ` [PATCH RFC 6/6] libxl: implementation of PV RPMSG " Iurii Mykhalskyi
2016-05-19 17:52 ` [Embedded-pv-devel] [PATCH RFC 0/6] Set of PV drivers used by production project Meng Xu
2016-05-23 11:40 ` Wei Liu
2016-06-02 16:12 ` Wei Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).