[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 |