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

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



On Tue, Mar 10, 2015 at 08:13:59AM -0400, Quan Xu wrote:
> 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)

Line too line.

> +{
> +    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);

Please don't use hardcode /local/domain/0. And I suspect this will be
wrong mostly of the time since this function is not Dom0 only.

> +    if (l == NULL || nb == 0)
> +        nextid = 0;
> +    else
> +        nextid = strtoul(l[nb - 1], NULL, 10) + 1;
> +
> +    return nextid;
> +}

And this function looks very much like libxl__device_nextid. The only
difference is the xenstore path, right? Please factor out the common
bits of both function to a helper.

> +
>  /* 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)
> +{
[...]
> +    libxl_device_vtpm_dispose(&vtpm_saved);
> +    libxl_domain_config_dispose(&d_config);
> +    aodev->rc = rc;
> +    if (rc)
> +        aodev->callback(egc, aodev);
> +    return;
> +}
> +

This looks repetitive as well. I think the only difference between _pv
and _hvm is the xenstore nodes they write to. You need to do some
refactoring as well.

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

No need to define a macro for this, since there is only one user of
this.  But after looking further down I think you're doing it wrong.

There should still be a unified libxl_device_vtpm_add function that
works for both PV and HVM (if this is the case because your change).

> +
>  
> /******************************************************************************/
>  
>  /*
> 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;
> +        }
> +    }
> +

Why do you not need to call libxl__device_vtpm_setdefault for PV guest?

>      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);
> +

Why is vtpms added here instead of its usual location? I.e. the place
you stubbed out in previous patch. That is ...

>          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) {

... here?

BTW this hunk doesn't have meaningful changes...

>         /* 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);
> +

You need to define xenstore protocol first.

And, why is it special? I don't know because you haven't defined what
the protocol looks like.

>      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)
> +

It's fine by me that you just hand code this function without using this
macro.

But, I don't think the function body as-is is correct. There should not
be a loop. This function should only handle one device.

> +#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);

Please use GCSPRINTF.

> +        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");

How do you add vtpm for hvm guest?

Wei.

>          return 1;
>      }
>      libxl_device_vtpm_dispose(&vtpm);
> -- 
> 1.8.3.2
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel

_______________________________________________
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®.