|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |