This patch adds vtpm support to libxl. It adds vtpm parsing to config
files and 3 new xl commands:
vtpm-attach
vtpm-detach
vtpm-list
Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>
diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index 428da21..fe4fac9 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -298,6 +298,35 @@ Specifies the networking provision (both emulated network
adapters,
 and Xen virtual interfaces) to provided to the guest.  See
 F<docs/misc/xl-network-configuration.markdown>.
 
+=item B<vtpm=[ "VTPM_SPEC_STRING", "VTPM_SPEC_STRING",
...]>
+
+Specifies the virtual trusted platform module to be
+provided to the guest. Please see F<docs/misc/vtpm.txt>
+for more details.
+
+Each B<VTPM_SPEC_STRING> is a comma-separated list of C<KEY=VALUE>
+settings, from the following list:
+
+=over 4
+
+=item C<backend=DOMAIN>
+
+Specify the backend domain name of id. This value is required!
+If this domain is a guest, the backend should be set to the
+vtpm domain name. If this domain is a vtpm, the
+backend should be set to the vtpm manager domain name.
+
+=item C<uuid=UUID>
+
+Specify the uuid of this vtpm device. The uuid is used to uniquely
+identify the vtpm device. You can create one using the uuidgen
+program on unix systems. If left unspecified, a new uuid
+will be randomly generated every time the domain boots.
+If this is a vtpm domain, you should specify a value. The
+value is optional if this is a guest domain.
+
+=back
+
 =item B<vfb=[ "VFB_SPEC_STRING", "VFB_SPEC_STRING",
...]>
 
 Specifies the paravirtual framebuffer devices which should be supplied
diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
index 7b1f2cf..097fe43 100644
--- a/docs/man/xl.pod.1
+++ b/docs/man/xl.pod.1
@@ -1106,6 +1106,31 @@ List virtual network interfaces for a domain.
 
 =back
 
+=head2 VTPM DEVICES
+
+=over 4
+
+=item B<vtpm-attach> I<domain-id> I<vtpm-device>
+
+Creates a new vtpm device in the domain specified by I<domain-id>.
+I<vtpm-device> describes the device to attach, using the same format as
the
+B<vtpm> string in the domain config file. See L<xl.cfg> for
+more information.
+
+=item B<vtpm-detach> I<domain-id> I<devid|uuid>
+
+Removes the vtpm device from the domain specified by I<domain-id>.
+I<devid> is the numeric device id given to the virtual trusted
+platform module device. You will need to run B<xl vtpm-list> to determine
that number.
+Alternatively the I<uuid> of the vtpm can be used to
+select the virtual device to detach.
+
+=item B<vtpm-list> I<domain-id>
+
+List virtual trusted platform modules for a domain.
+
+=back
+
 =head1 PCI PASS-THROUGH
 
 =over 4
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 665385b..be457f4 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1710,6 +1710,243 @@ out:
 }
 
 /******************************************************************************/
+int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm)
+{
+   if(libxl_uuid_is_nil(&vtpm->uuid)) {
+      libxl_uuid_generate(&vtpm->uuid);
+   }
+   return 0;
+}
+
+static int libxl__device_from_vtpm(libxl__gc *gc, uint32_t domid,
+                                   libxl_device_vtpm *vtpm,
+                                   libxl__device *device)
+{
+   device->backend_devid   = vtpm->devid;
+   device->backend_domid   = vtpm->backend_domid;
+   device->backend_kind    = LIBXL__DEVICE_KIND_VTPM;
+   device->devid           = vtpm->devid;
+   device->domid           = domid;
+   device->kind            = LIBXL__DEVICE_KIND_VTPM;
+
+   return 0;
+}
+
+void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
+                           libxl_device_vtpm *vtpm,
+                           libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    char *dompath, **l;
+    unsigned int nb, rc;
+
+    rc = libxl__device_vtpm_setdefault(gc, vtpm);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 16, 1);
+    back = flexarray_make(gc, 16, 1);
+
+    if(vtpm->devid == -1) {
+        if (!(dompath = libxl__xs_get_dompath(gc, domid))) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+        l = libxl__xs_directory(gc, XBT_NULL,
+              GCSPRINTF("%s/device/vtpm", dompath), &nb);
+        if(l == NULL || nb == 0) {
+            vtpm->devid = 0;
+        } else {
+            vtpm->devid = strtoul(l[nb - 1], NULL, 10) + 1;
+        }
+    }
+
+    GCNEW(device);
+    rc = libxl__device_from_vtpm(gc, domid, vtpm, device);
+    if ( rc != 0 ) goto out;
+
+    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, "handle");
+    flexarray_append(back, GCSPRINTF("%d", vtpm->devid));
+
+    flexarray_append(back, "uuid");
+    flexarray_append(back, GCSPRINTF(LIBXL_UUID_FMT,
LIBXL_UUID_BYTES(vtpm->uuid)));
+    flexarray_append(back, "resume");
+    flexarray_append(back, "False");
+
+    flexarray_append(front, "backend-id");
+    flexarray_append(front, GCSPRINTF("%d", vtpm->backend_domid));
+    flexarray_append(front, "state");
+    flexarray_append(front, GCSPRINTF("%d", 1));
+    flexarray_append(front, "handle");
+    flexarray_append(front, GCSPRINTF("%d", vtpm->devid));
+
+    libxl__device_generic_add(gc, XBT_NULL, device,
+                             libxl__xs_kvs_of_flexarray(gc, back,
back->count),
+                             libxl__xs_kvs_of_flexarray(gc, front,
front->count));
+
+    aodev->dev = device;
+    aodev->action = DEVICE_CONNECT;
+    libxl__wait_device_connection(egc, aodev);
+
+    rc = 0;
+out:
+    aodev->rc = rc;
+    if(rc) aodev->callback(egc, aodev);
+    return;
+}
+
+libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int
*num)
+{
+    GC_INIT(ctx);
+
+    libxl_device_vtpm* vtpms = NULL;
+    char* fe_path = NULL;
+    char** dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = libxl__sprintf(gc, "%s/device/vtpm",
libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+    if(dir) {
+       vtpms = malloc(sizeof(*vtpms) * ndirs);
+       libxl_device_vtpm* vtpm;
+       libxl_device_vtpm* end = vtpms + ndirs;
+       for(vtpm = vtpms; vtpm < end; ++vtpm, ++dir) {
+          char* tmp;
+          const char* be_path = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend",
+                   fe_path, *dir));
+
+          vtpm->devid = atoi(*dir);
+
+          tmp = libxl__xs_read(gc, XBT_NULL,
+                GCSPRINTF("%s/%s/backend_id",
+                   fe_path, *dir));
+          vtpm->backend_domid = atoi(tmp);
+
+          tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid",
be_path));
+          if(tmp) {
+             if(libxl_uuid_from_string(&(vtpm->uuid), tmp)) {
+                LOG(ERROR, "%s/uuid is a malformed uuid?? (%s) Probably a
bug!!\n", be_path, tmp);
+                exit(1);
+             }
+          }
+       }
+    }
+    *num = ndirs;
+
+    GC_FREE;
+    return vtpms;
+}
+
+int libxl_device_vtpm_getinfo(libxl_ctx *ctx,
+                              uint32_t domid,
+                              libxl_device_vtpm *vtpm,
+                              libxl_vtpminfo *vtpminfo)
+{
+    GC_INIT(ctx);
+    char *dompath, *vtpmpath;
+    char *val;
+    int rc = 0;
+
+    libxl_vtpminfo_init(vtpminfo);
+    dompath = libxl__xs_get_dompath(gc, domid);
+    vtpminfo->devid = vtpm->devid;
+
+    vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath,
vtpminfo->devid);
+    vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/backend", vtpmpath), NULL);
+    if (!vtpminfo->backend) {
+        goto err;
+    }
+    if(!libxl__xs_read(gc, XBT_NULL, vtpminfo->backend)) {
+       goto err;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/backend-id", vtpmpath));
+    vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/state", vtpmpath));
+    vtpminfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/event-channel", vtpmpath));
+    vtpminfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/ring-ref", vtpmpath));
+    vtpminfo->rref = val ? strtoul(val, NULL, 10) : -1;
+
+    vtpminfo->frontend = xs_read(ctx->xsh, XBT_NULL,
+          GCSPRINTF("%s/frontend", vtpminfo->backend), NULL);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/frontend-id", vtpminfo->backend));
+    vtpminfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+          GCSPRINTF("%s/uuid", vtpminfo->backend));
+    if(val == NULL) {
+       LOG(ERROR, "%s/uuid does not exist!\n", vtpminfo->backend);
+       goto err;
+    }
+    if(libxl_uuid_from_string(&(vtpminfo->uuid), val)) {
+       LOG(ERROR,
+             "%s/uuid is a malformed uuid?? (%s) Probably a bug!\n",
+             vtpminfo->backend, val);
+       goto err;
+    }
+
+    goto exit;
+err:
+    rc = ERROR_FAIL;
+exit:
+    GC_FREE;
+    return rc;
+}
+
+int libxl_devid_to_device_vtpm(libxl_ctx *ctx,
+                               uint32_t domid,
+                               int devid,
+                               libxl_device_vtpm *vtpm)
+{
+    libxl_device_vtpm *vtpms;
+    int nb, i;
+    int rc;
+
+    vtpms = libxl_device_vtpm_list(ctx, domid, &nb);
+    if (!vtpms)
+        return ERROR_FAIL;
+
+    memset(vtpm, 0, sizeof (libxl_device_vtpm));
+    rc = 1;
+    for (i = 0; i < nb; ++i) {
+        if(devid == vtpms[i].devid) {
+            vtpm->backend_domid = vtpms[i].backend_domid;
+            vtpm->devid = vtpms[i].devid;
+            libxl_uuid_copy(&vtpm->uuid, &vtpms[i].uuid);
+            rc = 0;
+            break;
+        }
+    }
+
+    libxl_device_vtpm_list_free(vtpms, nb);
+    return rc;
+}
+
+
+/******************************************************************************/
 
 int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk)
 {
@@ -3046,6 +3283,8 @@ 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
@@ -3097,6 +3336,10 @@ DEFINE_DEVICE_REMOVE(vkb, destroy, 1)
 DEFINE_DEVICE_REMOVE(vfb, remove, 0)
 DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 
+/* vtpm */
+DEFINE_DEVICE_REMOVE(vtpm, remove, 0)
+DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
+
 #undef DEFINE_DEVICE_REMOVE
 
 /******************************************************************************/
@@ -3105,6 +3348,7 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 /* The following functions are defined:
  * libxl_device_disk_add
  * libxl_device_nic_add
+ * libxl_device_vtpm_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -3131,6 +3375,9 @@ DEFINE_DEVICE_ADD(disk)
 /* nic */
 DEFINE_DEVICE_ADD(nic)
 
+/* vtpm */
+DEFINE_DEVICE_ADD(vtpm)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 7a7c419..e2ba549 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -478,13 +478,14 @@ typedef struct {
     libxl_domain_create_info c_info;
     libxl_domain_build_info b_info;
 
-    int num_disks, num_nics, num_pcidevs, num_vfbs, num_vkbs;
+    int num_disks, num_nics, num_pcidevs, num_vfbs, num_vkbs, num_vtpms;
 
     libxl_device_disk *disks;
     libxl_device_nic *nics;
     libxl_device_pci *pcidevs;
     libxl_device_vfb *vfbs;
     libxl_device_vkb *vkbs;
+    libxl_device_vtpm *vtpms;
 
     libxl_action_on_shutdown on_poweroff;
     libxl_action_on_shutdown on_reboot;
@@ -645,6 +646,9 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t
domid,
                                 int *nb_vcpu, int *nr_vcpus_out);
 void libxl_vcpuinfo_list_free(libxl_vcpuinfo *, int nr_vcpus);
 
+void libxl_device_vtpm_list_free(libxl_device_vtpm*, int nr_vtpms);
+void libxl_vtpminfo_list_free(libxl_vtpminfo *, int nr_vtpms);
+
 /*
  * Devices
  * ======@@ -745,6 +749,23 @@ libxl_device_nic *libxl_device_nic_list(libxl_ctx
*ctx, uint32_t domid, int *num
 int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
                               libxl_device_nic *nic, libxl_nicinfo *nicinfo);
 
+/* Virtual TPMs */
+int libxl_device_vtpm_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vtpm
*vtpm,
+                          const libxl_asyncop_how *ao_how)
+                          LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vtpm_remove(libxl_ctx *ctx, uint32_t domid,
+                            libxl_device_vtpm *vtpm,
+                            const libxl_asyncop_how *ao_how)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_device_vtpm_destroy(libxl_ctx *ctx, uint32_t domid,
+                              libxl_device_vtpm *vtpm,
+                              const libxl_asyncop_how *ao_how)
+                              LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int
*num);
+int libxl_device_vtpm_getinfo(libxl_ctx *ctx, uint32_t domid,
+                               libxl_device_vtpm *vtpm, libxl_vtpminfo
*vtpminfo);
+
 /* 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 e81747b..9d20086 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -55,6 +55,8 @@ void libxl_domain_config_dispose(libxl_domain_config
*d_config)
         libxl_device_vkb_dispose(&d_config->vkbs[i]);
     free(d_config->vkbs);
 
+    libxl_device_vtpm_list_free(d_config->vtpms, d_config->num_vtpms);
+
     libxl_domain_create_info_dispose(&d_config->c_info);
     libxl_domain_build_info_dispose(&d_config->b_info);
 }
@@ -601,6 +603,8 @@ static void domcreate_bootloader_done(libxl__egc *egc,
 static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *aodevs,
                                 int ret);
 
+static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
+                                   int ret);
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
                                  int ret);
 
@@ -1085,13 +1089,13 @@ static void domcreate_devmodel_started(libxl__egc *egc,
     if (d_config->num_nics > 0) {
         /* Attach nics */
         libxl__multidev_begin(ao, &dcs->multidev);
-        dcs->multidev.callback = domcreate_attach_pci;
+        dcs->multidev.callback = domcreate_attach_vtpms;
         libxl__add_nics(egc, ao, domid, d_config, &dcs->multidev);
         libxl__multidev_prepared(egc, &dcs->multidev, 0);
         return;
     }
 
-    domcreate_attach_pci(egc, &dcs->multidev, 0);
+    domcreate_attach_vtpms(egc, &dcs->multidev, 0);
     return;
 
 error_out:
@@ -1099,6 +1103,39 @@ error_out:
     domcreate_complete(egc, dcs, ret);
 }
 
+static void domcreate_attach_vtpms(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 nic devices");
+       goto error_out;
+   }
+
+    /* Plug vtpm devices */
+   if (d_config->num_vtpms > 0) {
+       /* Attach vtpms */
+       libxl__multidev_begin(ao, &dcs->multidev);
+       dcs->multidev.callback = domcreate_attach_pci;
+       libxl__add_vtpms(egc, ao, domid, d_config, &dcs->multidev);
+       libxl__multidev_prepared(egc, &dcs->multidev, 0);
+       return;
+   }
+
+   domcreate_attach_pci(egc, multidev, 0);
+   return;
+
+error_out:
+   assert(ret);
+   domcreate_complete(egc, dcs, ret);
+}
+
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
                                  int ret)
 {
@@ -1112,7 +1149,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 nic devices");
+        LOG(ERROR, "unable to add vtpm devices");
         goto error_out;
     }
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index c3283f1..51dd06e 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -497,6 +497,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * The following functions are defined:
  * libxl__add_disks
  * libxl__add_nics
+ * libxl__add_vtpms
  */
 
 #define DEFINE_DEVICES_ADD(type)                                        \
@@ -515,6 +516,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
 
 DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
+DEFINE_DEVICES_ADD(vtpm)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 8f220cb..cba3616 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -958,6 +958,7 @@ _hidden int libxl__device_disk_setdefault(libxl__gc *gc,
                                           libxl_device_disk *disk);
 _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_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);
@@ -2007,6 +2008,10 @@ _hidden void libxl__device_nic_add(libxl__egc *egc,
uint32_t domid,
                                    libxl_device_nic *nic,
                                    libxl__ao_device *aodev);
 
+_hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
+                                   libxl_device_vtpm *vtpm,
+                                   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);
@@ -2439,6 +2444,10 @@ _hidden void libxl__add_nics(libxl__egc *egc, libxl__ao
*ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
 
+_hidden void libxl__add_vtpms(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 de111a6..7eac4a8 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -395,6 +395,12 @@ libxl_device_pci = Struct("device_pci", [
     ("permissive", bool),
     ])
 
+libxl_device_vtpm = Struct("device_vtpm", [
+    ("backend_domid",    libxl_domid),
+    ("devid",            libxl_devid),
+    ("uuid",             libxl_uuid),
+])
+
 libxl_diskinfo = Struct("diskinfo", [
     ("backend", string),
     ("backend_id", uint32),
@@ -418,6 +424,18 @@ libxl_nicinfo = Struct("nicinfo", [
     ("rref_rx", integer),
     ], dir=DIR_OUT)
 
+libxl_vtpminfo = Struct("vtpminfo", [
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("devid", libxl_devid),
+    ("state", integer),
+    ("evtch", integer),
+    ("rref", integer),
+    ("uuid", libxl_uuid),
+    ], 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 5ac8c9c..c40120e 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -19,6 +19,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (5, "VFB"),
     (6, "VKBD"),
     (7, "CONSOLE"),
+    (8, "VTPM"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 55cd299..8f78790 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -463,6 +463,33 @@ int libxl_pipe(libxl_ctx *ctx, int pipes[2])
     return 0;
 }
 
+int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
+                            libxl_uuid* uuid, libxl_device_vtpm *vtpm)
+{
+    libxl_device_vtpm *vtpms;
+    int nb, i;
+    int rc;
+
+    vtpms = libxl_device_vtpm_list(ctx, domid, &nb);
+    if (!vtpms)
+        return ERROR_FAIL;
+
+    memset(vtpm, 0, sizeof (libxl_device_vtpm));
+    rc = 1;
+    for (i = 0; i < nb; ++i) {
+        if(!libxl_uuid_compare(uuid, &vtpms[i].uuid)) {
+            vtpm->backend_domid = vtpms[i].backend_domid;
+            vtpm->devid = vtpms[i].devid;
+            libxl_uuid_copy(&vtpm->uuid, &vtpms[i].uuid);
+            rc = 0;
+            break;
+        }
+    }
+
+    libxl_device_vtpm_list_free(vtpms, nb);
+    return rc;
+}
+
 int libxl_mac_to_device_nic(libxl_ctx *ctx, uint32_t domid,
                             const char *mac, libxl_device_nic *nic)
 {
@@ -819,6 +846,22 @@ void libxl_cpupoolinfo_list_free(libxl_cpupoolinfo *list,
int nr)
     free(list);
 }
 
+void libxl_vtpminfo_list_free(libxl_vtpminfo* list, int nr)
+{
+   int i;
+   for (i = 0; i < nr; i++)
+      libxl_vtpminfo_dispose(&list[i]);
+   free(list);
+}
+
+void libxl_device_vtpm_list_free(libxl_device_vtpm* list, int nr)
+{
+   int i;
+   for (i = 0; i < nr; i++)
+      libxl_device_vtpm_dispose(&list[i]);
+   free(list);
+}
+
 int libxl_domid_valid_guest(uint32_t domid)
 {
     /* returns 1 if the value _could_ be a valid guest domid, 0 otherwise
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 83aaac7..40f3f30 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -64,6 +64,11 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid,
int devid,
 int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid, const char *vdev,
                                libxl_device_disk *disk);
 
+int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
+                               libxl_uuid *uuid, libxl_device_vtpm *vtpm);
+int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
+                               int devid, libxl_device_vtpm *vtpm);
+
 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 0b2f848..be6f38b 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -79,6 +79,9 @@ int main_networkdetach(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_vtpmattach(int argc, char **argv);
+int main_vtpmlist(int argc, char **argv);
+int main_vtpmdetach(int argc, char **argv);
 int main_uptime(int argc, char **argv);
 int main_tmem_list(int argc, char **argv);
 int main_tmem_freeze(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index a43b371..65f83bd 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -573,7 +573,7 @@ static void parse_config_data(const char *config_source,
     const char *buf;
     long l;
     XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms;
     XLU_ConfigList *ioports, *irqs, *iomem;
     int num_ioports, num_irqs, num_iomem;
     int pci_power_mgmt = 0;
@@ -1048,6 +1048,58 @@ static void parse_config_data(const char *config_source,
         }
     }
 
+    if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) {
+        d_config->num_vtpms = 0;
+        d_config->vtpms = NULL;
+        while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) !=
NULL) {
+            libxl_device_vtpm *vtpm;
+            char * buf2 = strdup(buf);
+            char *p, *p2;
+            bool got_backend = false;
+
+            d_config->vtpms = (libxl_device_vtpm *)
realloc(d_config->vtpms,
+                  sizeof(libxl_device_vtpm) * (d_config->num_vtpms+1));
+            vtpm = d_config->vtpms + d_config->num_vtpms;
+            libxl_device_vtpm_init(vtpm);
+            vtpm->devid = d_config->num_vtpms;
+
+            p = strtok(buf2, ",");
+            if(p) {
+               do {
+                  while(*p == '' '')
+                     ++p;
+                  if ((p2 = strchr(p, ''='')) == NULL)
+                     break;
+                  *p2 = ''\0'';
+                  if (!strcmp(p, "backend")) {
+                     if(domain_qualifier_to_domid(p2 + 1,
&(vtpm->backend_domid), 0))
+                     {
+                        fprintf(stderr,
+                              "Specified vtpm backend domain `%s''
does not exist!\n", p2 + 1);
+                        exit(1);
+                     }
+                     got_backend = true;
+                  } else if(!strcmp(p, "uuid")) {
+                     if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) {
+                        fprintf(stderr,
+                              "Failed to parse vtpm UUID: %s\n", p2 +
1);
+                        exit(1);
+                    }
+                  } else {
+                     fprintf(stderr, "Unknown string `%s'' in vtpm
spec\n", p);
+                     exit(1);
+                  }
+               } while ((p = strtok(NULL, ",")) != NULL);
+            }
+            if(!got_backend) {
+               fprintf(stderr, "vtpm spec missing required backend
field!\n");
+               exit(1);
+            }
+            free(buf2);
+            d_config->num_vtpms++;
+        }
+    }
+
     if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
         d_config->num_nics = 0;
         d_config->nics = NULL;
@@ -1073,7 +1125,7 @@ static void parse_config_data(const char *config_source,
 
             p = strtok(buf2, ",");
             if (!p)
-                goto skip;
+                goto skip_nic;
             do {
                 while (*p == '' '')
                     p++;
@@ -1137,7 +1189,7 @@ static void parse_config_data(const char *config_source,
                     fprintf(stderr, "the accel parameter for vifs is
currently not supported\n");
                 }
             } while ((p = strtok(NULL, ",")) != NULL);
-skip:
+skip_nic:
             free(buf2);
             d_config->num_nics++;
         }
@@ -5634,6 +5686,132 @@ int main_blockdetach(int argc, char **argv)
     return rc;
 }
 
+int main_vtpmattach(int argc, char **argv)
+{
+    int opt;
+    libxl_device_vtpm vtpm;
+    char *oparg;
+    unsigned int val;
+    uint32_t domid;
+
+    if ((opt = def_getopt(argc, argv, "", "vtpm-attach",
1)) != -1)
+        return opt;
+
+    if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) {
+        fprintf(stderr, "%s is an invalid domain identifier\n",
argv[optind]);
+        return 1;
+    }
+    ++optind;
+
+    libxl_device_vtpm_init(&vtpm);
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (MATCH_OPTION("uuid", *argv, oparg)) {
+            if(libxl_uuid_from_string(&(vtpm.uuid), oparg)) {
+                fprintf(stderr, "Invalid uuid specified (%s)\n",
oparg);
+                return 1;
+            }
+        } else if (MATCH_OPTION("backend", *argv, oparg)) {
+            if(domain_qualifier_to_domid(oparg, &val, 0)) {
+                fprintf(stderr,
+                      "Specified backend domain does not exist, defaulting
to Dom0\n");
+                val = 0;
+            }
+            vtpm.backend_domid = val;
+        } else {
+            fprintf(stderr, "unrecognized argument `%s''\n",
*argv);
+            return 1;
+        }
+    }
+
+    if(dryrun_only) {
+       char* json = libxl_device_vtpm_to_json(ctx, &vtpm);
+       printf("vtpm: %s\n", json);
+       free(json);
+       libxl_device_vtpm_dispose(&vtpm);
+       if (ferror(stdout) || fflush(stdout)) { perror("stdout");
exit(-1); }
+       return 0;
+    }
+
+    if (libxl_device_vtpm_add(ctx, domid, &vtpm, 0)) {
+        fprintf(stderr, "libxl_device_vtpm_add failed.\n");
+        return 1;
+    }
+    libxl_device_vtpm_dispose(&vtpm);
+    return 0;
+}
+
+int main_vtpmlist(int argc, char **argv)
+{
+    int opt;
+    libxl_device_vtpm *vtpms;
+    libxl_vtpminfo vtpminfo;
+    int nb, i;
+
+    if ((opt = def_getopt(argc, argv, "", "vtpm-list", 1))
!= -1)
+        return opt;
+
+    /*      Idx  BE   UUID   Hdl  Sta  evch rref  BE-path */
+    printf("%-3s %-2s %-36s %-6s %-5s %-6s %-5s %-10s\n",
+           "Idx", "BE", "Uuid",
"handle", "state", "evt-ch", "ring-ref",
"BE-path");
+    for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) {
+        uint32_t domid;
+        if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) {
+            fprintf(stderr, "%s is an invalid domain identifier\n",
*argv);
+            continue;
+        }
+        if (!(vtpms = libxl_device_vtpm_list(ctx, domid, &nb))) {
+            continue;
+        }
+        for (i = 0; i < nb; ++i) {
+           if(!libxl_device_vtpm_getinfo(ctx, domid, &vtpms[i],
&vtpminfo)) {
+              /*      Idx  BE     UUID             Hdl Sta evch rref BE-path*/
+              printf("%-3d %-2d " LIBXL_UUID_FMT " %6d %5d %6d
%8d %-30s\n",
+                    vtpminfo.devid, vtpminfo.backend_id,
+                    LIBXL_UUID_BYTES(vtpminfo.uuid),
+                    vtpminfo.devid, vtpminfo.state, vtpminfo.evtch,
+                    vtpminfo.rref, vtpminfo.backend);
+
+              libxl_vtpminfo_dispose(&vtpminfo);
+           }
+           libxl_device_vtpm_dispose(&vtpms[i]);
+        }
+        free(vtpms);
+    }
+    return 0;
+}
+
+int main_vtpmdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc=0;
+    libxl_device_vtpm vtpm;
+    libxl_uuid uuid;
+
+    if ((opt = def_getopt(argc, argv, "", "vtpm-detach",
2)) != -1)
+        return opt;
+
+    domid = find_domain(argv[optind]);
+
+    if ( libxl_uuid_from_string(&uuid, argv[optind+1])) {
+        if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]),
&vtpm)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    } else {
+        if (libxl_uuid_to_device_vtpm(ctx, domid, &uuid, &vtpm)) {
+            fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+            return 1;
+        }
+    }
+    rc = libxl_device_vtpm_remove(ctx, domid, &vtpm, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_vtpm_remove failed.\n");
+    }
+    libxl_device_vtpm_dispose(&vtpm);
+    return rc;
+}
+
+
 static char *uptime_to_string(unsigned long uptime, int short_mode)
 {
     int sec, min, hour, day;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index d3a215d..ac58642 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -341,6 +341,21 @@ struct cmd_spec cmd_table[] = {
       "Destroy a domain''s virtual block device",
       "<Domain> <DevId>",
     },
+    { "vtpm-attach",
+      &main_vtpmattach, 1, 1,
+      "Create a new virtual TPM device",
+      "<Domain> [uuid=<uuid>]
[backend=<BackDomain>]",
+    },
+    { "vtpm-list",
+      &main_vtpmlist, 0, 0,
+      "List virtual TPM devices for a domain",
+      "<Domain(s)>",
+    },
+    { "vtpm-detach",
+      &main_vtpmdetach, 0, 1,
+      "Destroy a domain''s virtual TPM device",
+      "<Domain> <DevId|uuid>",
+    },
     { "uptime",
       &main_uptime, 0, 0,
       "Print uptime for all/some domains",
-- 
1.7.10.4
On Thu, 2012-11-01 at 20:34 +0000, Matthew Fioravante wrote:> This patch adds vtpm support to libxl. It adds vtpm parsing to config > files and 3 new xl commands: > vtpm-attach > vtpm-detach > vtpm-list > > Signed-off-by: Matthew Fioravante <matthew.fioravante@jhuapl.edu>Acked-by: Ian Campbell <ian.campbell@citrix.com> and applied. thanks.> > diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5 > index 428da21..fe4fac9 100644 > --- a/docs/man/xl.cfg.pod.5 > +++ b/docs/man/xl.cfg.pod.5 > @@ -298,6 +298,35 @@ Specifies the networking provision (both emulated network adapters, > and Xen virtual interfaces) to provided to the guest. See > F<docs/misc/xl-network-configuration.markdown>. > > +=item B<vtpm=[ "VTPM_SPEC_STRING", "VTPM_SPEC_STRING", ...]> > + > +Specifies the virtual trusted platform module to be > +provided to the guest. Please see F<docs/misc/vtpm.txt> > +for more details. > + > +Each B<VTPM_SPEC_STRING> is a comma-separated list of C<KEY=VALUE> > +settings, from the following list: > + > +=over 4 > + > +=item C<backend=DOMAIN> > + > +Specify the backend domain name of id. This value is required! > +If this domain is a guest, the backend should be set to the > +vtpm domain name. If this domain is a vtpm, the > +backend should be set to the vtpm manager domain name. > + > +=item C<uuid=UUID> > + > +Specify the uuid of this vtpm device. The uuid is used to uniquely > +identify the vtpm device. You can create one using the uuidgen > +program on unix systems. If left unspecified, a new uuid > +will be randomly generated every time the domain boots. > +If this is a vtpm domain, you should specify a value. The > +value is optional if this is a guest domain. > + > +=back > + > =item B<vfb=[ "VFB_SPEC_STRING", "VFB_SPEC_STRING", ...]> > > Specifies the paravirtual framebuffer devices which should be supplied > diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1 > index 7b1f2cf..097fe43 100644 > --- a/docs/man/xl.pod.1 > +++ b/docs/man/xl.pod.1 > @@ -1106,6 +1106,31 @@ List virtual network interfaces for a domain. > > =back > > +=head2 VTPM DEVICES > + > +=over 4 > + > +=item B<vtpm-attach> I<domain-id> I<vtpm-device> > + > +Creates a new vtpm device in the domain specified by I<domain-id>. > +I<vtpm-device> describes the device to attach, using the same format as the > +B<vtpm> string in the domain config file. See L<xl.cfg> for > +more information. > + > +=item B<vtpm-detach> I<domain-id> I<devid|uuid> > + > +Removes the vtpm device from the domain specified by I<domain-id>. > +I<devid> is the numeric device id given to the virtual trusted > +platform module device. You will need to run B<xl vtpm-list> to determine that number. > +Alternatively the I<uuid> of the vtpm can be used to > +select the virtual device to detach. > + > +=item B<vtpm-list> I<domain-id> > + > +List virtual trusted platform modules for a domain. > + > +=back > + > =head1 PCI PASS-THROUGH > > =over 4 > diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c > index 665385b..be457f4 100644 > --- a/tools/libxl/libxl.c > +++ b/tools/libxl/libxl.c > @@ -1710,6 +1710,243 @@ out: > } > > /******************************************************************************/ > +int libxl__device_vtpm_setdefault(libxl__gc *gc, libxl_device_vtpm *vtpm) > +{ > + if(libxl_uuid_is_nil(&vtpm->uuid)) { > + libxl_uuid_generate(&vtpm->uuid); > + } > + return 0; > +} > + > +static int libxl__device_from_vtpm(libxl__gc *gc, uint32_t domid, > + libxl_device_vtpm *vtpm, > + libxl__device *device) > +{ > + device->backend_devid = vtpm->devid; > + device->backend_domid = vtpm->backend_domid; > + device->backend_kind = LIBXL__DEVICE_KIND_VTPM; > + device->devid = vtpm->devid; > + device->domid = domid; > + device->kind = LIBXL__DEVICE_KIND_VTPM; > + > + return 0; > +} > + > +void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid, > + libxl_device_vtpm *vtpm, > + libxl__ao_device *aodev) > +{ > + STATE_AO_GC(aodev->ao); > + flexarray_t *front; > + flexarray_t *back; > + libxl__device *device; > + char *dompath, **l; > + unsigned int nb, rc; > + > + rc = libxl__device_vtpm_setdefault(gc, vtpm); > + if (rc) goto out; > + > + front = flexarray_make(gc, 16, 1); > + back = flexarray_make(gc, 16, 1); > + > + if(vtpm->devid == -1) { > + if (!(dompath = libxl__xs_get_dompath(gc, domid))) { > + rc = ERROR_FAIL; > + goto out; > + } > + l = libxl__xs_directory(gc, XBT_NULL, > + GCSPRINTF("%s/device/vtpm", dompath), &nb); > + if(l == NULL || nb == 0) { > + vtpm->devid = 0; > + } else { > + vtpm->devid = strtoul(l[nb - 1], NULL, 10) + 1; > + } > + } > + > + GCNEW(device); > + rc = libxl__device_from_vtpm(gc, domid, vtpm, device); > + if ( rc != 0 ) goto out; > + > + 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, "handle"); > + flexarray_append(back, GCSPRINTF("%d", vtpm->devid)); > + > + flexarray_append(back, "uuid"); > + flexarray_append(back, GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(vtpm->uuid))); > + flexarray_append(back, "resume"); > + flexarray_append(back, "False"); > + > + flexarray_append(front, "backend-id"); > + flexarray_append(front, GCSPRINTF("%d", vtpm->backend_domid)); > + flexarray_append(front, "state"); > + flexarray_append(front, GCSPRINTF("%d", 1)); > + flexarray_append(front, "handle"); > + flexarray_append(front, GCSPRINTF("%d", vtpm->devid)); > + > + libxl__device_generic_add(gc, XBT_NULL, device, > + libxl__xs_kvs_of_flexarray(gc, back, back->count), > + libxl__xs_kvs_of_flexarray(gc, front, front->count)); > + > + aodev->dev = device; > + aodev->action = DEVICE_CONNECT; > + libxl__wait_device_connection(egc, aodev); > + > + rc = 0; > +out: > + aodev->rc = rc; > + if(rc) aodev->callback(egc, aodev); > + return; > +} > + > +libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *num) > +{ > + GC_INIT(ctx); > + > + libxl_device_vtpm* vtpms = NULL; > + char* fe_path = NULL; > + char** dir = NULL; > + unsigned int ndirs = 0; > + > + *num = 0; > + > + fe_path = libxl__sprintf(gc, "%s/device/vtpm", libxl__xs_get_dompath(gc, domid)); > + dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs); > + if(dir) { > + vtpms = malloc(sizeof(*vtpms) * ndirs); > + libxl_device_vtpm* vtpm; > + libxl_device_vtpm* end = vtpms + ndirs; > + for(vtpm = vtpms; vtpm < end; ++vtpm, ++dir) { > + char* tmp; > + const char* be_path = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/%s/backend", > + fe_path, *dir)); > + > + vtpm->devid = atoi(*dir); > + > + tmp = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/%s/backend_id", > + fe_path, *dir)); > + vtpm->backend_domid = atoi(tmp); > + > + tmp = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/uuid", be_path)); > + if(tmp) { > + if(libxl_uuid_from_string(&(vtpm->uuid), tmp)) { > + LOG(ERROR, "%s/uuid is a malformed uuid?? (%s) Probably a bug!!\n", be_path, tmp); > + exit(1); > + } > + } > + } > + } > + *num = ndirs; > + > + GC_FREE; > + return vtpms; > +} > + > +int libxl_device_vtpm_getinfo(libxl_ctx *ctx, > + uint32_t domid, > + libxl_device_vtpm *vtpm, > + libxl_vtpminfo *vtpminfo) > +{ > + GC_INIT(ctx); > + char *dompath, *vtpmpath; > + char *val; > + int rc = 0; > + > + libxl_vtpminfo_init(vtpminfo); > + dompath = libxl__xs_get_dompath(gc, domid); > + vtpminfo->devid = vtpm->devid; > + > + vtpmpath = GCSPRINTF("%s/device/vtpm/%d", dompath, vtpminfo->devid); > + vtpminfo->backend = xs_read(ctx->xsh, XBT_NULL, > + GCSPRINTF("%s/backend", vtpmpath), NULL); > + if (!vtpminfo->backend) { > + goto err; > + } > + if(!libxl__xs_read(gc, XBT_NULL, vtpminfo->backend)) { > + goto err; > + } > + > + val = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/backend-id", vtpmpath)); > + vtpminfo->backend_id = val ? strtoul(val, NULL, 10) : -1; > + > + val = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/state", vtpmpath)); > + vtpminfo->state = val ? strtoul(val, NULL, 10) : -1; > + > + val = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/event-channel", vtpmpath)); > + vtpminfo->evtch = val ? strtoul(val, NULL, 10) : -1; > + > + val = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/ring-ref", vtpmpath)); > + vtpminfo->rref = val ? strtoul(val, NULL, 10) : -1; > + > + vtpminfo->frontend = xs_read(ctx->xsh, XBT_NULL, > + GCSPRINTF("%s/frontend", vtpminfo->backend), NULL); > + > + val = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/frontend-id", vtpminfo->backend)); > + vtpminfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; > + > + val = libxl__xs_read(gc, XBT_NULL, > + GCSPRINTF("%s/uuid", vtpminfo->backend)); > + if(val == NULL) { > + LOG(ERROR, "%s/uuid does not exist!\n", vtpminfo->backend); > + goto err; > + } > + if(libxl_uuid_from_string(&(vtpminfo->uuid), val)) { > + LOG(ERROR, > + "%s/uuid is a malformed uuid?? (%s) Probably a bug!\n", > + vtpminfo->backend, val); > + goto err; > + } > + > + goto exit; > +err: > + rc = ERROR_FAIL; > +exit: > + GC_FREE; > + return rc; > +} > + > +int libxl_devid_to_device_vtpm(libxl_ctx *ctx, > + uint32_t domid, > + int devid, > + libxl_device_vtpm *vtpm) > +{ > + libxl_device_vtpm *vtpms; > + int nb, i; > + int rc; > + > + vtpms = libxl_device_vtpm_list(ctx, domid, &nb); > + if (!vtpms) > + return ERROR_FAIL; > + > + memset(vtpm, 0, sizeof (libxl_device_vtpm)); > + rc = 1; > + for (i = 0; i < nb; ++i) { > + if(devid == vtpms[i].devid) { > + vtpm->backend_domid = vtpms[i].backend_domid; > + vtpm->devid = vtpms[i].devid; > + libxl_uuid_copy(&vtpm->uuid, &vtpms[i].uuid); > + rc = 0; > + break; > + } > + } > + > + libxl_device_vtpm_list_free(vtpms, nb); > + return rc; > +} > + > + > +/******************************************************************************/ > > int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk) > { > @@ -3046,6 +3283,8 @@ 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 > @@ -3097,6 +3336,10 @@ DEFINE_DEVICE_REMOVE(vkb, destroy, 1) > DEFINE_DEVICE_REMOVE(vfb, remove, 0) > DEFINE_DEVICE_REMOVE(vfb, destroy, 1) > > +/* vtpm */ > +DEFINE_DEVICE_REMOVE(vtpm, remove, 0) > +DEFINE_DEVICE_REMOVE(vtpm, destroy, 1) > + > #undef DEFINE_DEVICE_REMOVE > > /******************************************************************************/ > @@ -3105,6 +3348,7 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1) > /* The following functions are defined: > * libxl_device_disk_add > * libxl_device_nic_add > + * libxl_device_vtpm_add > */ > > #define DEFINE_DEVICE_ADD(type) \ > @@ -3131,6 +3375,9 @@ DEFINE_DEVICE_ADD(disk) > /* nic */ > DEFINE_DEVICE_ADD(nic) > > +/* vtpm */ > +DEFINE_DEVICE_ADD(vtpm) > + > #undef DEFINE_DEVICE_ADD > > /******************************************************************************/ > diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h > index 7a7c419..e2ba549 100644 > --- a/tools/libxl/libxl.h > +++ b/tools/libxl/libxl.h > @@ -478,13 +478,14 @@ typedef struct { > libxl_domain_create_info c_info; > libxl_domain_build_info b_info; > > - int num_disks, num_nics, num_pcidevs, num_vfbs, num_vkbs; > + int num_disks, num_nics, num_pcidevs, num_vfbs, num_vkbs, num_vtpms; > > libxl_device_disk *disks; > libxl_device_nic *nics; > libxl_device_pci *pcidevs; > libxl_device_vfb *vfbs; > libxl_device_vkb *vkbs; > + libxl_device_vtpm *vtpms; > > libxl_action_on_shutdown on_poweroff; > libxl_action_on_shutdown on_reboot; > @@ -645,6 +646,9 @@ libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid, > int *nb_vcpu, int *nr_vcpus_out); > void libxl_vcpuinfo_list_free(libxl_vcpuinfo *, int nr_vcpus); > > +void libxl_device_vtpm_list_free(libxl_device_vtpm*, int nr_vtpms); > +void libxl_vtpminfo_list_free(libxl_vtpminfo *, int nr_vtpms); > + > /* > * Devices > * ======> @@ -745,6 +749,23 @@ libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num > int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, > libxl_device_nic *nic, libxl_nicinfo *nicinfo); > > +/* Virtual TPMs */ > +int libxl_device_vtpm_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vtpm *vtpm, > + const libxl_asyncop_how *ao_how) > + LIBXL_EXTERNAL_CALLERS_ONLY; > +int libxl_device_vtpm_remove(libxl_ctx *ctx, uint32_t domid, > + libxl_device_vtpm *vtpm, > + const libxl_asyncop_how *ao_how) > + LIBXL_EXTERNAL_CALLERS_ONLY; > +int libxl_device_vtpm_destroy(libxl_ctx *ctx, uint32_t domid, > + libxl_device_vtpm *vtpm, > + const libxl_asyncop_how *ao_how) > + LIBXL_EXTERNAL_CALLERS_ONLY; > + > +libxl_device_vtpm *libxl_device_vtpm_list(libxl_ctx *ctx, uint32_t domid, int *num); > +int libxl_device_vtpm_getinfo(libxl_ctx *ctx, uint32_t domid, > + libxl_device_vtpm *vtpm, libxl_vtpminfo *vtpminfo); > + > /* 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 e81747b..9d20086 100644 > --- a/tools/libxl/libxl_create.c > +++ b/tools/libxl/libxl_create.c > @@ -55,6 +55,8 @@ void libxl_domain_config_dispose(libxl_domain_config *d_config) > libxl_device_vkb_dispose(&d_config->vkbs[i]); > free(d_config->vkbs); > > + libxl_device_vtpm_list_free(d_config->vtpms, d_config->num_vtpms); > + > libxl_domain_create_info_dispose(&d_config->c_info); > libxl_domain_build_info_dispose(&d_config->b_info); > } > @@ -601,6 +603,8 @@ static void domcreate_bootloader_done(libxl__egc *egc, > static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *aodevs, > int ret); > > +static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev, > + int ret); > static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs, > int ret); > > @@ -1085,13 +1089,13 @@ static void domcreate_devmodel_started(libxl__egc *egc, > if (d_config->num_nics > 0) { > /* Attach nics */ > libxl__multidev_begin(ao, &dcs->multidev); > - dcs->multidev.callback = domcreate_attach_pci; > + dcs->multidev.callback = domcreate_attach_vtpms; > libxl__add_nics(egc, ao, domid, d_config, &dcs->multidev); > libxl__multidev_prepared(egc, &dcs->multidev, 0); > return; > } > > - domcreate_attach_pci(egc, &dcs->multidev, 0); > + domcreate_attach_vtpms(egc, &dcs->multidev, 0); > return; > > error_out: > @@ -1099,6 +1103,39 @@ error_out: > domcreate_complete(egc, dcs, ret); > } > > +static void domcreate_attach_vtpms(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 nic devices"); > + goto error_out; > + } > + > + /* Plug vtpm devices */ > + if (d_config->num_vtpms > 0) { > + /* Attach vtpms */ > + libxl__multidev_begin(ao, &dcs->multidev); > + dcs->multidev.callback = domcreate_attach_pci; > + libxl__add_vtpms(egc, ao, domid, d_config, &dcs->multidev); > + libxl__multidev_prepared(egc, &dcs->multidev, 0); > + return; > + } > + > + domcreate_attach_pci(egc, multidev, 0); > + return; > + > +error_out: > + assert(ret); > + domcreate_complete(egc, dcs, ret); > +} > + > static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev, > int ret) > { > @@ -1112,7 +1149,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 nic devices"); > + LOG(ERROR, "unable to add vtpm devices"); > goto error_out; > } > > diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c > index c3283f1..51dd06e 100644 > --- a/tools/libxl/libxl_device.c > +++ b/tools/libxl/libxl_device.c > @@ -497,6 +497,7 @@ void libxl__multidev_prepared(libxl__egc *egc, > * The following functions are defined: > * libxl__add_disks > * libxl__add_nics > + * libxl__add_vtpms > */ > > #define DEFINE_DEVICES_ADD(type) \ > @@ -515,6 +516,7 @@ void libxl__multidev_prepared(libxl__egc *egc, > > DEFINE_DEVICES_ADD(disk) > DEFINE_DEVICES_ADD(nic) > +DEFINE_DEVICES_ADD(vtpm) > > #undef DEFINE_DEVICES_ADD > > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h > index 8f220cb..cba3616 100644 > --- a/tools/libxl/libxl_internal.h > +++ b/tools/libxl/libxl_internal.h > @@ -958,6 +958,7 @@ _hidden int libxl__device_disk_setdefault(libxl__gc *gc, > libxl_device_disk *disk); > _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_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); > @@ -2007,6 +2008,10 @@ _hidden void libxl__device_nic_add(libxl__egc *egc, uint32_t domid, > libxl_device_nic *nic, > libxl__ao_device *aodev); > > +_hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid, > + libxl_device_vtpm *vtpm, > + 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); > @@ -2439,6 +2444,10 @@ _hidden void libxl__add_nics(libxl__egc *egc, libxl__ao *ao, uint32_t domid, > libxl_domain_config *d_config, > libxl__multidev *multidev); > > +_hidden void libxl__add_vtpms(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 de111a6..7eac4a8 100644 > --- a/tools/libxl/libxl_types.idl > +++ b/tools/libxl/libxl_types.idl > @@ -395,6 +395,12 @@ libxl_device_pci = Struct("device_pci", [ > ("permissive", bool), > ]) > > +libxl_device_vtpm = Struct("device_vtpm", [ > + ("backend_domid", libxl_domid), > + ("devid", libxl_devid), > + ("uuid", libxl_uuid), > +]) > + > libxl_diskinfo = Struct("diskinfo", [ > ("backend", string), > ("backend_id", uint32), > @@ -418,6 +424,18 @@ libxl_nicinfo = Struct("nicinfo", [ > ("rref_rx", integer), > ], dir=DIR_OUT) > > +libxl_vtpminfo = Struct("vtpminfo", [ > + ("backend", string), > + ("backend_id", uint32), > + ("frontend", string), > + ("frontend_id", uint32), > + ("devid", libxl_devid), > + ("state", integer), > + ("evtch", integer), > + ("rref", integer), > + ("uuid", libxl_uuid), > + ], 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 5ac8c9c..c40120e 100644 > --- a/tools/libxl/libxl_types_internal.idl > +++ b/tools/libxl/libxl_types_internal.idl > @@ -19,6 +19,7 @@ libxl__device_kind = Enumeration("device_kind", [ > (5, "VFB"), > (6, "VKBD"), > (7, "CONSOLE"), > + (8, "VTPM"), > ]) > > libxl__console_backend = Enumeration("console_backend", [ > diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c > index 55cd299..8f78790 100644 > --- a/tools/libxl/libxl_utils.c > +++ b/tools/libxl/libxl_utils.c > @@ -463,6 +463,33 @@ int libxl_pipe(libxl_ctx *ctx, int pipes[2]) > return 0; > } > > +int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid, > + libxl_uuid* uuid, libxl_device_vtpm *vtpm) > +{ > + libxl_device_vtpm *vtpms; > + int nb, i; > + int rc; > + > + vtpms = libxl_device_vtpm_list(ctx, domid, &nb); > + if (!vtpms) > + return ERROR_FAIL; > + > + memset(vtpm, 0, sizeof (libxl_device_vtpm)); > + rc = 1; > + for (i = 0; i < nb; ++i) { > + if(!libxl_uuid_compare(uuid, &vtpms[i].uuid)) { > + vtpm->backend_domid = vtpms[i].backend_domid; > + vtpm->devid = vtpms[i].devid; > + libxl_uuid_copy(&vtpm->uuid, &vtpms[i].uuid); > + rc = 0; > + break; > + } > + } > + > + libxl_device_vtpm_list_free(vtpms, nb); > + return rc; > +} > + > int libxl_mac_to_device_nic(libxl_ctx *ctx, uint32_t domid, > const char *mac, libxl_device_nic *nic) > { > @@ -819,6 +846,22 @@ void libxl_cpupoolinfo_list_free(libxl_cpupoolinfo *list, int nr) > free(list); > } > > +void libxl_vtpminfo_list_free(libxl_vtpminfo* list, int nr) > +{ > + int i; > + for (i = 0; i < nr; i++) > + libxl_vtpminfo_dispose(&list[i]); > + free(list); > +} > + > +void libxl_device_vtpm_list_free(libxl_device_vtpm* list, int nr) > +{ > + int i; > + for (i = 0; i < nr; i++) > + libxl_device_vtpm_dispose(&list[i]); > + free(list); > +} > + > int libxl_domid_valid_guest(uint32_t domid) > { > /* returns 1 if the value _could_ be a valid guest domid, 0 otherwise > diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h > index 83aaac7..40f3f30 100644 > --- a/tools/libxl/libxl_utils.h > +++ b/tools/libxl/libxl_utils.h > @@ -64,6 +64,11 @@ int libxl_devid_to_device_nic(libxl_ctx *ctx, uint32_t domid, int devid, > int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid, const char *vdev, > libxl_device_disk *disk); > > +int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid, > + libxl_uuid *uuid, libxl_device_vtpm *vtpm); > +int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid, > + int devid, libxl_device_vtpm *vtpm); > + > 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 0b2f848..be6f38b 100644 > --- a/tools/libxl/xl.h > +++ b/tools/libxl/xl.h > @@ -79,6 +79,9 @@ int main_networkdetach(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_vtpmattach(int argc, char **argv); > +int main_vtpmlist(int argc, char **argv); > +int main_vtpmdetach(int argc, char **argv); > int main_uptime(int argc, char **argv); > int main_tmem_list(int argc, char **argv); > int main_tmem_freeze(int argc, char **argv); > diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c > index a43b371..65f83bd 100644 > --- a/tools/libxl/xl_cmdimpl.c > +++ b/tools/libxl/xl_cmdimpl.c > @@ -573,7 +573,7 @@ static void parse_config_data(const char *config_source, > const char *buf; > long l; > XLU_Config *config; > - XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids; > + XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms; > XLU_ConfigList *ioports, *irqs, *iomem; > int num_ioports, num_irqs, num_iomem; > int pci_power_mgmt = 0; > @@ -1048,6 +1048,58 @@ static void parse_config_data(const char *config_source, > } > } > > + if (!xlu_cfg_get_list(config, "vtpm", &vtpms, 0, 0)) { > + d_config->num_vtpms = 0; > + d_config->vtpms = NULL; > + while ((buf = xlu_cfg_get_listitem (vtpms, d_config->num_vtpms)) != NULL) { > + libxl_device_vtpm *vtpm; > + char * buf2 = strdup(buf); > + char *p, *p2; > + bool got_backend = false; > + > + d_config->vtpms = (libxl_device_vtpm *) realloc(d_config->vtpms, > + sizeof(libxl_device_vtpm) * (d_config->num_vtpms+1)); > + vtpm = d_config->vtpms + d_config->num_vtpms; > + libxl_device_vtpm_init(vtpm); > + vtpm->devid = d_config->num_vtpms; > + > + p = strtok(buf2, ","); > + if(p) { > + do { > + while(*p == '' '') > + ++p; > + if ((p2 = strchr(p, ''='')) == NULL) > + break; > + *p2 = ''\0''; > + if (!strcmp(p, "backend")) { > + if(domain_qualifier_to_domid(p2 + 1, &(vtpm->backend_domid), 0)) > + { > + fprintf(stderr, > + "Specified vtpm backend domain `%s'' does not exist!\n", p2 + 1); > + exit(1); > + } > + got_backend = true; > + } else if(!strcmp(p, "uuid")) { > + if( libxl_uuid_from_string(&vtpm->uuid, p2 + 1) ) { > + fprintf(stderr, > + "Failed to parse vtpm UUID: %s\n", p2 + 1); > + exit(1); > + } > + } else { > + fprintf(stderr, "Unknown string `%s'' in vtpm spec\n", p); > + exit(1); > + } > + } while ((p = strtok(NULL, ",")) != NULL); > + } > + if(!got_backend) { > + fprintf(stderr, "vtpm spec missing required backend field!\n"); > + exit(1); > + } > + free(buf2); > + d_config->num_vtpms++; > + } > + } > + > if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) { > d_config->num_nics = 0; > d_config->nics = NULL; > @@ -1073,7 +1125,7 @@ static void parse_config_data(const char *config_source, > > p = strtok(buf2, ","); > if (!p) > - goto skip; > + goto skip_nic; > do { > while (*p == '' '') > p++; > @@ -1137,7 +1189,7 @@ static void parse_config_data(const char *config_source, > fprintf(stderr, "the accel parameter for vifs is currently not supported\n"); > } > } while ((p = strtok(NULL, ",")) != NULL); > -skip: > +skip_nic: > free(buf2); > d_config->num_nics++; > } > @@ -5634,6 +5686,132 @@ int main_blockdetach(int argc, char **argv) > return rc; > } > > +int main_vtpmattach(int argc, char **argv) > +{ > + int opt; > + libxl_device_vtpm vtpm; > + char *oparg; > + unsigned int val; > + uint32_t domid; > + > + if ((opt = def_getopt(argc, argv, "", "vtpm-attach", 1)) != -1) > + return opt; > + > + if (domain_qualifier_to_domid(argv[optind], &domid, 0) < 0) { > + fprintf(stderr, "%s is an invalid domain identifier\n", argv[optind]); > + return 1; > + } > + ++optind; > + > + libxl_device_vtpm_init(&vtpm); > + for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) { > + if (MATCH_OPTION("uuid", *argv, oparg)) { > + if(libxl_uuid_from_string(&(vtpm.uuid), oparg)) { > + fprintf(stderr, "Invalid uuid specified (%s)\n", oparg); > + return 1; > + } > + } else if (MATCH_OPTION("backend", *argv, oparg)) { > + if(domain_qualifier_to_domid(oparg, &val, 0)) { > + fprintf(stderr, > + "Specified backend domain does not exist, defaulting to Dom0\n"); > + val = 0; > + } > + vtpm.backend_domid = val; > + } else { > + fprintf(stderr, "unrecognized argument `%s''\n", *argv); > + return 1; > + } > + } > + > + if(dryrun_only) { > + char* json = libxl_device_vtpm_to_json(ctx, &vtpm); > + printf("vtpm: %s\n", json); > + free(json); > + libxl_device_vtpm_dispose(&vtpm); > + if (ferror(stdout) || fflush(stdout)) { perror("stdout"); exit(-1); } > + return 0; > + } > + > + if (libxl_device_vtpm_add(ctx, domid, &vtpm, 0)) { > + fprintf(stderr, "libxl_device_vtpm_add failed.\n"); > + return 1; > + } > + libxl_device_vtpm_dispose(&vtpm); > + return 0; > +} > + > +int main_vtpmlist(int argc, char **argv) > +{ > + int opt; > + libxl_device_vtpm *vtpms; > + libxl_vtpminfo vtpminfo; > + int nb, i; > + > + if ((opt = def_getopt(argc, argv, "", "vtpm-list", 1)) != -1) > + return opt; > + > + /* Idx BE UUID Hdl Sta evch rref BE-path */ > + printf("%-3s %-2s %-36s %-6s %-5s %-6s %-5s %-10s\n", > + "Idx", "BE", "Uuid", "handle", "state", "evt-ch", "ring-ref", "BE-path"); > + for (argv += optind, argc -= optind; argc > 0; --argc, ++argv) { > + uint32_t domid; > + if (domain_qualifier_to_domid(*argv, &domid, 0) < 0) { > + fprintf(stderr, "%s is an invalid domain identifier\n", *argv); > + continue; > + } > + if (!(vtpms = libxl_device_vtpm_list(ctx, domid, &nb))) { > + continue; > + } > + for (i = 0; i < nb; ++i) { > + if(!libxl_device_vtpm_getinfo(ctx, domid, &vtpms[i], &vtpminfo)) { > + /* Idx BE UUID Hdl Sta evch rref BE-path*/ > + printf("%-3d %-2d " LIBXL_UUID_FMT " %6d %5d %6d %8d %-30s\n", > + vtpminfo.devid, vtpminfo.backend_id, > + LIBXL_UUID_BYTES(vtpminfo.uuid), > + vtpminfo.devid, vtpminfo.state, vtpminfo.evtch, > + vtpminfo.rref, vtpminfo.backend); > + > + libxl_vtpminfo_dispose(&vtpminfo); > + } > + libxl_device_vtpm_dispose(&vtpms[i]); > + } > + free(vtpms); > + } > + return 0; > +} > + > +int main_vtpmdetach(int argc, char **argv) > +{ > + uint32_t domid; > + int opt, rc=0; > + libxl_device_vtpm vtpm; > + libxl_uuid uuid; > + > + if ((opt = def_getopt(argc, argv, "", "vtpm-detach", 2)) != -1) > + return opt; > + > + domid = find_domain(argv[optind]); > + > + if ( libxl_uuid_from_string(&uuid, argv[optind+1])) { > + if (libxl_devid_to_device_vtpm(ctx, domid, atoi(argv[optind+1]), &vtpm)) { > + fprintf(stderr, "Unknown device %s.\n", argv[optind+1]); > + return 1; > + } > + } else { > + if (libxl_uuid_to_device_vtpm(ctx, domid, &uuid, &vtpm)) { > + fprintf(stderr, "Unknown device %s.\n", argv[optind+1]); > + return 1; > + } > + } > + rc = libxl_device_vtpm_remove(ctx, domid, &vtpm, 0); > + if (rc) { > + fprintf(stderr, "libxl_device_vtpm_remove failed.\n"); > + } > + libxl_device_vtpm_dispose(&vtpm); > + return rc; > +} > + > + > static char *uptime_to_string(unsigned long uptime, int short_mode) > { > int sec, min, hour, day; > diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c > index d3a215d..ac58642 100644 > --- a/tools/libxl/xl_cmdtable.c > +++ b/tools/libxl/xl_cmdtable.c > @@ -341,6 +341,21 @@ struct cmd_spec cmd_table[] = { > "Destroy a domain''s virtual block device", > "<Domain> <DevId>", > }, > + { "vtpm-attach", > + &main_vtpmattach, 1, 1, > + "Create a new virtual TPM device", > + "<Domain> [uuid=<uuid>] [backend=<BackDomain>]", > + }, > + { "vtpm-list", > + &main_vtpmlist, 0, 0, > + "List virtual TPM devices for a domain", > + "<Domain(s)>", > + }, > + { "vtpm-detach", > + &main_vtpmdetach, 0, 1, > + "Destroy a domain''s virtual TPM device", > + "<Domain> <DevId|uuid>", > + }, > { "uptime", > &main_uptime, 0, 0, > "Print uptime for all/some domains", > -- > 1.7.10.4 >