[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v3 4/7] vTPM: add vTPM device for HVM virtual machine



refactor libxl__device_vtpm_add to call the right helpers
libxl__device_vtpm_add_{pv,hvm}. For HVM virtual machine,
it does not support hot-plug and hot-unplug, as it requires
SeaBios to initalize ACPI and virtual MMIO space for TPM
TIS when virtual machine starts.

Signed-off-by: Quan Xu <quan.xu@xxxxxxxxx>
---
 tools/libxl/libxl.c          | 176 +++++++++++++++++++++++++++++++++++++++++--
 tools/libxl/libxl.h          |   7 +-
 tools/libxl/libxl_create.c   |  32 +++++---
 tools/libxl/libxl_device.c   |  38 +++++++++-
 tools/libxl/libxl_dm.c       |  12 +++
 tools/libxl/libxl_internal.h |   6 +-
 tools/libxl/xl_cmdimpl.c     |   4 +-
 7 files changed, 253 insertions(+), 22 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 18561fb..c2d4baa 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1904,6 +1904,25 @@ out:
     return;
 }
 
+static int libxl__frontend_device_nextid(libxl__gc *gc, uint32_t domid, char 
*device)
+{
+    char *dompath, **l;
+    unsigned int nb;
+    int nextid = -1;
+
+    if (!(dompath = libxl__xs_get_dompath(gc, domid)))
+        return nextid;
+
+    l = libxl__xs_directory(gc, XBT_NULL,
+            GCSPRINTF("/local/domain/0/frontend/%s/%u", device, domid), &nb);
+    if (l == NULL || nb == 0)
+        nextid = 0;
+    else
+        nextid = strtoul(l[nb - 1], NULL, 10) + 1;
+
+    return nextid;
+}
+
 /* common function to get next device id */
 static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
 {
@@ -1957,9 +1976,9 @@ static int libxl__device_from_vtpm(libxl__gc *gc, 
uint32_t domid,
    return 0;
 }
 
-void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
-                           libxl_device_vtpm *vtpm,
-                           libxl__ao_device *aodev)
+void libxl__device_vtpm_add_pv(libxl__egc *egc, uint32_t domid,
+                               libxl_device_vtpm *vtpm,
+                               libxl__ao_device *aodev)
 {
     STATE_AO_GC(aodev->ao);
     flexarray_t *front;
@@ -2073,6 +2092,134 @@ out:
     return;
 }
 
+void libxl__device_vtpm_add_hvm(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;
+    unsigned int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_vtpm vtpm_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_vtpm_init(&vtpm_saved);
+    libxl_device_vtpm_copy(CTX, &vtpm_saved, vtpm);
+
+    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 = libxl__frontend_device_nextid(gc,
+                           vtpm->backend_domid, "vtpm")) < 0) {
+        rc =  ERROR_FAIL;
+        goto out;
+    }
+
+    GCNEW(device);
+    rc = libxl__device_from_vtpm(gc, 0, vtpm, device);
+    if (rc != 0)
+        goto out;
+    flexarray_append(back, "frontend-id");
+    flexarray_append(back, "0");
+    flexarray_append(back, "online");
+    flexarray_append(back, "1");
+    flexarray_append(back, "state");
+    flexarray_append(back, "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, "1");
+    flexarray_append(front, "handle");
+    flexarray_append(front, GCSPRINTF("%d", vtpm->devid));
+
+    flexarray_append(front, "domain");
+    flexarray_append(front, GCSPRINTF("%s", libxl__domid_to_name(gc, domid)));
+
+    if (aodev->update_json) {
+        lock = libxl__lock_domain_userdata(gc, domid);
+        if (!lock) {
+            rc = ERROR_LOCK_FAIL;
+            goto out;
+        }
+
+        rc = libxl__get_domain_configuration(gc, domid, &d_config);
+        if (rc)
+            goto out;
+
+        DEVICE_ADD(vtpm, vtpms, domid, &vtpm_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_vtpm_dispose(&vtpm_saved);
+    libxl_domain_config_dispose(&d_config);
+    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);
@@ -4179,11 +4326,28 @@ DEFINE_DEVICE_ADD(disk)
 /* nic */
 DEFINE_DEVICE_ADD(nic)
 
-/* vtpm */
-DEFINE_DEVICE_ADD(vtpm)
-
 #undef DEFINE_DEVICE_ADD
 
+#define DEFINE_VTPM_ADD_PV(type)                                        \
+    int libxl_device_##type##_add_pv(libxl_ctx *ctx,                    \
+        uint32_t domid, libxl_device_##type *type,                      \
+        const libxl_asyncop_how *ao_how)                                \
+    {                                                                   \
+        AO_CREATE(ctx, domid, ao_how);                                  \
+        libxl__ao_device *aodev;                                        \
+                                                                        \
+        GCNEW(aodev);                                                   \
+        libxl__prepare_ao_device(ao, aodev);                            \
+        aodev->callback = device_addrm_aocomplete;                      \
+        aodev->update_json = true;                                      \
+        libxl__device_##type##_add_pv(egc, domid, type, aodev);         \
+                                                                        \
+        return AO_INPROGRESS;                                           \
+    }
+
+/* vtpm */
+DEFINE_VTPM_ADD_PV(vtpm)
+
 
/******************************************************************************/
 
 /*
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index c3451bd..38d3542 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1183,9 +1183,10 @@ int libxl_device_channel_getinfo(libxl_ctx *ctx, 
uint32_t domid,
                                  libxl_channelinfo *channelinfo);
 
 /* 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_add_pv(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)
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index ffb124a..b88e1cb 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -901,6 +901,14 @@ static void initiate_domain_create(libxl__egc *egc,
             d_config->nics[i].devid = ++last_devid;
     }
 
+    if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) {
+        for (i = 0; i < d_config->num_vtpms; i++) {
+            ret = libxl__device_vtpm_setdefault(gc, &d_config->vtpms[i]);
+            if (ret)
+                goto error_out;
+        }
+    }
+
     if (restore_fd >= 0) {
         LOG(DEBUG, "restoring, not running bootloader");
         domcreate_bootloader_done(egc, &dcs->bl, 0);
@@ -1244,6 +1252,13 @@ static void domcreate_launch_dm(libxl__egc *egc, 
libxl__multidev *multidev,
         libxl__device_vkb_add(gc, domid, &vkb);
         libxl_device_vkb_dispose(&vkb);
 
+        /*
+         * Plug vtpm devices. dcs->multidev.callback is NULL, no need to call
+         * libxl__multidev_prepared().
+         */
+        libxl__multidev_begin(ao, &dcs->multidev);
+        libxl__add_vtpms(egc, ao, domid, d_config, &dcs->multidev);
+
         dcs->dmss.dm.guest_domid = domid;
         if (libxl_defbool_val(d_config->b_info.device_model_stubdomain))
             libxl__spawn_stub_dm(egc, &dcs->dmss);
@@ -1361,15 +1376,14 @@ static void domcreate_attach_vtpms(libxl__egc *egc,
        goto error_out;
    }
 
-    /*
-     * Plug vtpm devices only for PV guest. The xenstore directory is very
-     * different for PV guest and HVM guest, but it is still call it for
-     * creating HVM guest, and xl should create xenstore directory before
-     * spawning QEMU. So try to make it only for PV guest.
-     */
-    if (d_config->num_vtpms > 0 &&
-        d_config->b_info.type == LIBXL_DOMAIN_TYPE_PV) {
-
+   /*
+    * Plug vtpm devices only for PV guest. The xenstore directory is very
+    * different for PV guest and HVM guest, but it is still call it for
+    * creating HVM guest, and xl should create xenstore directory before
+    * spawning QEMU. So try to make it only for PV guest.
+    */
+   if (d_config->num_vtpms > 0 &&
+       d_config->b_info.type == LIBXL_DOMAIN_TYPE_PV) {
        /* Attach vtpms */
        libxl__multidev_begin(ao, &dcs->multidev);
        dcs->multidev.callback = domcreate_attach_pci;
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 4b51ded..b1a71fe 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -26,6 +26,13 @@ char *libxl__device_frontend_path(libxl__gc *gc, 
libxl__device *device)
     if (device->kind == LIBXL__DEVICE_KIND_CONSOLE && device->devid == 0)
         return GCSPRINTF("%s/console", dom_path);
 
+    /* vTPM for HVM virtual machine is a special case */
+    else if (device->backend_kind == LIBXL__DEVICE_KIND_VTPM &&
+             device->domid == 0)
+        return GCSPRINTF("/local/domain/0/frontend/%s/%u/%d",
+            libxl__device_kind_to_string(device->backend_kind),
+            device->backend_domid, device->devid);
+
     return GCSPRINTF("%s/device/%s/%d", dom_path,
                      libxl__device_kind_to_string(device->kind),
                      device->devid);
@@ -560,10 +567,39 @@ void libxl__multidev_prepared(libxl__egc *egc,
 
 DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
-DEFINE_DEVICES_ADD(vtpm)
 
 #undef DEFINE_DEVICES_ADD
 
+#define DEFINE_VTPM_ADD(_type)                                          \
+    void libxl__add_##_type##s(libxl__egc *egc, libxl__ao *ao,          \
+                               uint32_t domid,                          \
+                               libxl_domain_config *d_config,           \
+                               libxl__multidev *multidev)               \
+    {                                                                   \
+        AO_GC;                                                          \
+        int i;                                                          \
+        for (i = 0; i < d_config->num_##_type##s; i++) {                \
+            libxl__ao_device *aodev = libxl__multidev_prepare(multidev); \
+            switch(d_config->c_info.type) {                             \
+            case LIBXL_DOMAIN_TYPE_PV:                                  \
+                libxl__device_##_type##_add_pv(egc, domid,              \
+                                               &d_config->_type##s[i],  \
+                                               aodev);                  \
+                break;                                                  \
+            case LIBXL_DOMAIN_TYPE_HVM:                                 \
+                libxl__device_##_type##_add_hvm(egc, domid,             \
+                                               &d_config->_type##s[i],  \
+                                               aodev);                  \
+                break;                                                  \
+            default:                                                    \
+                break;                                                  \
+            }                                                           \
+        }                                                               \
+    }
+
+DEFINE_VTPM_ADD(vtpm)
+
+#undef DEFINE_VTPM_ADD
 
/******************************************************************************/
 
 int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 3e191c3..183910c 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -414,6 +414,7 @@ static char ** libxl__build_device_model_args_new(libxl__gc 
*gc,
     const libxl_device_nic *nics = guest_config->nics;
     const int num_disks = guest_config->num_disks;
     const int num_nics = guest_config->num_nics;
+    const int num_vtpms = guest_config->num_vtpms;
     const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config);
     const libxl_sdl_info *sdl = dm_sdl(guest_config);
     const char *keymap = dm_keymap(guest_config);
@@ -747,6 +748,17 @@ static char ** 
libxl__build_device_model_args_new(libxl__gc *gc,
         abort();
     }
 
+    /* Add vTPM parameters for HVM virtual machine */
+    if (b_info->type == LIBXL_DOMAIN_TYPE_HVM &&
+        num_vtpms > 0) {
+        flexarray_vappend(dm_args, "-tpmdev",
+                          libxl__sprintf(gc, "xenstubdoms,id=xenvtpm%d",
+                                         guest_domid), NULL);
+        flexarray_vappend(dm_args,"-device",
+                          libxl__sprintf(gc, "tpm-tis,tpmdev=xenvtpm%d",
+                                         guest_domid), NULL);
+    }
+
     ram_size = libxl__sizekb_to_mb(b_info->max_memkb - b_info->video_memkb);
     flexarray_append(dm_args, "-m");
     flexarray_append(dm_args, libxl__sprintf(gc, "%"PRId64, ram_size));
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 4361421..c6c82dd 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2384,10 +2384,14 @@ _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,
+_hidden void libxl__device_vtpm_add_pv(libxl__egc *egc, uint32_t domid,
                                    libxl_device_vtpm *vtpm,
                                    libxl__ao_device *aodev);
 
+void libxl__device_vtpm_add_hvm(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);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 3c9f146..e01d341 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -6490,8 +6490,8 @@ int main_vtpmattach(int argc, char **argv)
        return 0;
     }
 
-    if (libxl_device_vtpm_add(ctx, domid, &vtpm, 0)) {
-        fprintf(stderr, "libxl_device_vtpm_add failed.\n");
+    if (libxl_device_vtpm_add_pv(ctx, domid, &vtpm, 0)) {
+        fprintf(stderr, "libxl_device_vtpm_add_pv failed.\n");
         return 1;
     }
     libxl_device_vtpm_dispose(&vtpm);
-- 
1.8.3.2


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.