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

Re: [Xen-devel] [PATCH v5.1 01/12] mini-os/tpm{back, front}: Change shared page ABI



Is this in the wrong thread and should be in "[PATCH v5 00/12] vTPM
updates for 4.3" as an update to
<1363896689-11086-2-git-send-email-dgdegra@xxxxxxxxxxxxx> ?

On Fri, 2013-03-22 at 22:30 +0000, Daniel De Graaf wrote:
> This changes the vTPM shared page ABI from a copy of the Xen network
> interface to a single-page interface that better reflects the expected
> behavior of a TPM: only a single request packet can be sent at any given
> time, and every packet sent generates a single response packet. This
> protocol change should also increase efficiency as it avoids mapping and
> unmapping grants when possible. The vtpm xenbus device now requires a
> feature-protocol-v2 node in xenstore to avoid conflicts with existing
> (xen-patched) kernels supporting the old interface.
> 
> While the contents of the shared page have been defined to allow packets
> larger than a single page (actually 4088 bytes) by allowing the client
> to add extra grant references, the mapping of these extra references has
> not been implemented; a feature node in xenstore may be used in the
> future to indicate full support for the multi-page protocol. Most uses
> of the TPM should not require this feature.
> 
> Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
> Cc: Jan Beulich <JBeulich@xxxxxxxx>
> 
> ---
> 
> Changes from v5: handle xenbus states properly, and keep the old header
> contents intact.
> 
> Changes from v4: use feature-protocol-v2 nodes instead of changing the
> device name; add command cancellation support to the protocol.
> 
>  extras/mini-os/include/tpmback.h  |   1 +
>  extras/mini-os/include/tpmfront.h |   7 +-
>  extras/mini-os/tpmback.c          | 163 
> +++++++++++++++++++-------------------
>  extras/mini-os/tpmfront.c         | 143 ++++++++++++++++++---------------
>  xen/include/public/io/tpmif.h     |  28 +++++++
>  5 files changed, 190 insertions(+), 152 deletions(-)
> 
> diff --git a/extras/mini-os/include/tpmback.h 
> b/extras/mini-os/include/tpmback.h
> index ff86732..ec9eda4 100644
> --- a/extras/mini-os/include/tpmback.h
> +++ b/extras/mini-os/include/tpmback.h
> @@ -43,6 +43,7 @@
> 
>  struct tpmcmd {
>     domid_t domid;              /* Domid of the frontend */
> +   uint8_t locality;    /* Locality requested by the frontend */
>     unsigned int handle;        /* Handle of the frontend */
>     unsigned char uuid[16];                     /* uuid of the tpm interface 
> */
> 
> diff --git a/extras/mini-os/include/tpmfront.h 
> b/extras/mini-os/include/tpmfront.h
> index fd2cb17..a0c7c4d 100644
> --- a/extras/mini-os/include/tpmfront.h
> +++ b/extras/mini-os/include/tpmfront.h
> @@ -37,9 +37,7 @@ struct tpmfront_dev {
>     grant_ref_t ring_ref;
>     evtchn_port_t evtchn;
> 
> -   tpmif_tx_interface_t* tx;
> -
> -   void** pages;
> +   vtpm_shared_page_t *page;
> 
>     domid_t bedomid;
>     char* nodename;
> @@ -77,6 +75,9 @@ void shutdown_tpmfront(struct tpmfront_dev* dev);
>   * */
>  int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, size_t reqlen, 
> uint8_t** resp, size_t* resplen);
> 
> +/* Set the locality used for communicating with a vTPM */
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality);
> +
>  #ifdef HAVE_LIBC
>  #include <sys/stat.h>
>  /* POSIX IO functions:
> diff --git a/extras/mini-os/tpmback.c b/extras/mini-os/tpmback.c
> index 658fed1..d6a504e 100644
> --- a/extras/mini-os/tpmback.c
> +++ b/extras/mini-os/tpmback.c
> @@ -86,10 +86,7 @@ struct tpmif {
>     evtchn_port_t evtchn;
> 
>     /* Shared page */
> -   tpmif_tx_interface_t* tx;
> -
> -   /* pointer to TPMIF_RX_RING_SIZE pages */
> -   void** pages;
> +   vtpm_shared_page_t *page;
> 
>     enum xenbus_state state;
>     enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
> @@ -266,6 +263,7 @@ int insert_tpmif(tpmif_t* tpmif)
>     unsigned int i, j;
>     tpmif_t* tmp;
>     char* err;
> +   char path[512];
> 
>     local_irq_save(flags);
> 
> @@ -303,6 +301,16 @@ int insert_tpmif(tpmif_t* tpmif)
> 
>     local_irq_restore(flags);
> 
> +   snprintf(path, 512, "backend/vtpm/%u/%u/feature-protocol-v2", (unsigned 
> int) tpmif->domid, tpmif->handle);
> +   if ((err = xenbus_write(XBT_NIL, path, "1")))
> +   {
> +      /* if we got an error here we should carefully remove the interface 
> and then return */
> +      TPMBACK_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> +      free(err);
> +      remove_tpmif(tpmif);
> +      goto error_post_irq;
> +   }
> +
>     /*Listen for state changes on the new interface */
>     if((err = xenbus_watch_path_token(XBT_NIL, tpmif->fe_state_path, 
> tpmif->fe_state_path, &gtpmdev.events)))
>     {
> @@ -312,7 +320,6 @@ int insert_tpmif(tpmif_t* tpmif)
>        remove_tpmif(tpmif);
>        goto error_post_irq;
>     }
> -
>     return 0;
>  error:
>     local_irq_restore(flags);
> @@ -386,8 +393,7 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int 
> handle)
>     tpmif->fe_state_path = NULL;
>     tpmif->state = XenbusStateInitialising;
>     tpmif->status = DISCONNECTED;
> -   tpmif->tx = NULL;
> -   tpmif->pages = NULL;
> +   tpmif->page = NULL;
>     tpmif->flags = 0;
>     memset(tpmif->uuid, 0, sizeof(tpmif->uuid));
>     return tpmif;
> @@ -395,9 +401,6 @@ inline tpmif_t* __init_tpmif(domid_t domid, unsigned int 
> handle)
> 
>  void __free_tpmif(tpmif_t* tpmif)
>  {
> -   if(tpmif->pages) {
> -      free(tpmif->pages);
> -   }
>     if(tpmif->fe_path) {
>        free(tpmif->fe_path);
>     }
> @@ -430,12 +433,6 @@ tpmif_t* new_tpmif(domid_t domid, unsigned int handle)
>        goto error;
>     }
> 
> -   /* allocate pages to be used for shared mapping */
> -   if((tpmif->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE)) == NULL) {
> -      goto error;
> -   }
> -   memset(tpmif->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -
>     if(tpmif_change_state(tpmif, XenbusStateInitWait)) {
>        goto error;
>     }
> @@ -486,7 +483,7 @@ void free_tpmif(tpmif_t* tpmif)
>        tpmif->status = DISCONNECTING;
>        mask_evtchn(tpmif->evtchn);
> 
> -      if(gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->tx, 1)) {
> +      if(gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->page, 1)) {
>          TPMBACK_ERR("%u/%u Error occured while trying to unmap shared 
> page\n", (unsigned int) tpmif->domid, tpmif->handle);
>        }
> 
> @@ -529,15 +526,27 @@ void free_tpmif(tpmif_t* tpmif)
>  void tpmback_handler(evtchn_port_t port, struct pt_regs *regs, void *data)
>  {
>     tpmif_t* tpmif = (tpmif_t*) data;
> -   tpmif_tx_request_t* tx = &tpmif->tx->ring[0].req;
> -   /* Throw away 0 size events, these can trigger from event channel 
> unmasking */
> -   if(tx->size == 0)
> -      return;
> -
> -   TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) tpmif->domid, 
> tpmif->handle);
> -   tpmif_req_ready(tpmif);
> -   wake_up(&waitq);
> +   vtpm_shared_page_t* pg = tpmif->page;
> 
> +   switch (pg->state)
> +   {
> +   case VTPM_STATE_SUBMIT:
> +      TPMBACK_DEBUG("EVENT CHANNEL FIRE %u/%u\n", (unsigned int) 
> tpmif->domid, tpmif->handle);
> +      tpmif_req_ready(tpmif);
> +      wake_up(&waitq);
> +      break;
> +   case VTPM_STATE_CANCEL:
> +      /* If we are busy with a request, do nothing */
> +      if (tpmif->flags & TPMIF_REQ_READY)
> +         return;
> +      /* Acknowledge the cancellation if we are idle */
> +      pg->state = VTPM_STATE_IDLE;
> +      notify_remote_via_evtchn(tpmif->evtchn);
> +      return;
> +   default:
> +      /* Spurious wakeup; do nothing */
> +      return;
> +   }
>  }
> 
>  /* Connect to frontend */
> @@ -584,12 +593,25 @@ int connect_fe(tpmif_t* tpmif)
>     }
>     free(value);
> 
> +   /* Check that protocol v2 is being used */
> +   snprintf(path, 512, "%s/feature-protocol-v2", tpmif->fe_path);
> +   if((err = xenbus_read(XBT_NIL, path, &value))) {
> +      TPMBACK_ERR("Unable to read %s during tpmback initialization! error = 
> %s\n", path, err);
> +      free(err);
> +      return -1;
> +   }
> +   if(strcmp(value, "1")) {
> +      TPMBACK_ERR("%s has an invalid value (%s)\n", path, value);
> +      free(value);
> +      return -1;
> +   }
> +   free(value);
> +
>     domid = tpmif->domid;
> -   if((tpmif->tx = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 0, 
> &ringref, PROT_READ | PROT_WRITE)) == NULL) {
> +   if((tpmif->page = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 0, 
> &ringref, PROT_READ | PROT_WRITE)) == NULL) {
>        TPMBACK_ERR("Failed to map grant reference %u/%u\n", (unsigned int) 
> tpmif->domid, tpmif->handle);
>        return -1;
>     }
> -   memset(tpmif->tx, 0, PAGE_SIZE);
> 
>     /*Bind the event channel */
>     if((evtchn_bind_interdomain(tpmif->domid, evtchn, tpmback_handler, tpmif, 
> &tpmif->evtchn)))
> @@ -618,7 +640,7 @@ error_post_evtchn:
>     mask_evtchn(tpmif->evtchn);
>     unbind_evtchn(tpmif->evtchn);
>  error_post_map:
> -   gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->tx, 1);
> +   gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->page, 1);
>     return -1;
>  }
> 
> @@ -633,9 +655,9 @@ static int frontend_changed(tpmif_t* tpmif)
> 
>     switch (state) {
>        case XenbusStateInitialising:
> -      case XenbusStateInitialised:
>          break;
> 
> +      case XenbusStateInitialised:
>        case XenbusStateConnected:
>          if(connect_fe(tpmif)) {
>             TPMBACK_ERR("Failed to connect to front end %u/%u\n", (unsigned 
> int) tpmif->domid, tpmif->handle);
> @@ -874,6 +896,7 @@ void shutdown_tpmback(void)
>  inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t domid, unsigned int 
> handle, unsigned char uuid[16])
>  {
>     tpmcmd->domid = domid;
> +   tpmcmd->locality = -1;
>     tpmcmd->handle = handle;
>     memcpy(tpmcmd->uuid, uuid, sizeof(tpmcmd->uuid));
>     tpmcmd->req = NULL;
> @@ -884,12 +907,12 @@ inline void init_tpmcmd(tpmcmd_t* tpmcmd, domid_t 
> domid, unsigned int handle, un
> 
>  tpmcmd_t* get_request(tpmif_t* tpmif) {
>     tpmcmd_t* cmd;
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int tocopy;
> -   int i;
> -   uint32_t domid;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>     int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +   int i;
> +#endif
> 
>     local_irq_save(flags);
> 
> @@ -899,35 +922,22 @@ tpmcmd_t* get_request(tpmif_t* tpmif) {
>     }
>     init_tpmcmd(cmd, tpmif->domid, tpmif->handle, tpmif->uuid);
> 
> -   tx = &tpmif->tx->ring[0].req;
> -   cmd->req_len = tx->size;
> +   shr = tpmif->page;
> +   cmd->req_len = shr->length;
> +   cmd->locality = shr->locality;
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->req_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", 
> (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
> +   }
>     /* Allocate the buffer */
>     if(cmd->req_len) {
>        if((cmd->req = malloc(cmd->req_len)) == NULL) {
>          goto error;
>        }
>     }
> -   /* Copy the bits from the shared pages */
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->req_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 
> 0, &tx->ref, PROT_READ)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during read!\n", 
> (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->req_len - offset, PAGE_SIZE);
> -      memcpy(&cmd->req[offset], tpmif->pages[i], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->pages[i], 1);
> -
> -   }
> +   /* Copy the bits from the shared page(s) */
> +   memcpy(cmd->req, offset + (uint8_t*)shr, cmd->req_len);
> 
>  #ifdef TPMBACK_PRINT_DEBUG
>     TPMBACK_DEBUG("Received Tpm Command from %u/%u of size %u", (unsigned 
> int) tpmif->domid, tpmif->handle, cmd->req_len);
> @@ -958,38 +968,24 @@ error:
> 
>  void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>  {
> -   tpmif_tx_request_t* tx;
> -   int offset;
> -   int i;
> -   uint32_t domid;
> -   int tocopy;
> +   vtpm_shared_page_t* shr;
> +   unsigned int offset;
>     int flags;
> +#ifdef TPMBACK_PRINT_DEBUG
> +int i;
> +#endif
> 
>     local_irq_save(flags);
> 
> -   tx = &tpmif->tx->ring[0].req;
> -   tx->size = cmd->resp_len;
> -
> -   offset = 0;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && offset < cmd->resp_len; ++i) {
> -      tx = &tpmif->tx->ring[i].req;
> -
> -      /* Map the page with the data */
> -      domid = (uint32_t)tpmif->domid;
> -      if((tpmif->pages[i] = gntmap_map_grant_refs(&gtpmdev.map, 1, &domid, 
> 0, &tx->ref, PROT_WRITE)) == NULL) {
> -        TPMBACK_ERR("%u/%u Unable to map shared page during write!\n", 
> (unsigned int) tpmif->domid, tpmif->handle);
> -        goto error;
> -      }
> -
> -      /* do the copy now */
> -      tocopy = min(cmd->resp_len - offset, PAGE_SIZE);
> -      memcpy(tpmif->pages[i], &cmd->resp[offset], tocopy);
> -      offset += tocopy;
> -
> -      /* release the page */
> -      gntmap_munmap(&gtpmdev.map, (unsigned long)tpmif->pages[i], 1);
> +   shr = tpmif->page;
> +   shr->length = cmd->resp_len;
> 
> +   offset = sizeof(*shr) + 4*shr->nr_extra_pages;
> +   if (offset > PAGE_SIZE || offset + cmd->resp_len > PAGE_SIZE) {
> +      TPMBACK_ERR("%u/%u Command size too long for shared page!\n", 
> (unsigned int) tpmif->domid, tpmif->handle);
> +      goto error;
>     }
> +   memcpy(offset + (uint8_t*)shr, cmd->resp, cmd->resp_len);
> 
>  #ifdef TPMBACK_PRINT_DEBUG
>     TPMBACK_DEBUG("Sent response to %u/%u of size %u", (unsigned int) 
> tpmif->domid, tpmif->handle, cmd->resp_len);
> @@ -1003,6 +999,7 @@ void send_response(tpmcmd_t* cmd, tpmif_t* tpmif)
>  #endif
>     /* clear the ready flag and send the event channel notice to the frontend 
> */
>     tpmif_req_finished(tpmif);
> +   shr->state = VTPM_STATE_FINISH;
>     notify_remote_via_evtchn(tpmif->evtchn);
>  error:
>     local_irq_restore(flags);
> diff --git a/extras/mini-os/tpmfront.c b/extras/mini-os/tpmfront.c
> index 0218d7f..a15b5cf 100644
> --- a/extras/mini-os/tpmfront.c
> +++ b/extras/mini-os/tpmfront.c
> @@ -47,11 +47,21 @@
> 
>  void tpmfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) {
>     struct tpmfront_dev* dev = (struct tpmfront_dev*) data;
> +   vtpm_shared_page_t* shr = dev->page;
>     /*If we get a response when we didnt make a request, just ignore it */
>     if(!dev->waiting) {
>        return;
>     }
> 
> +   switch (shr->state) {
> +   case VTPM_STATE_FINISH: /* request was completed */
> +   case VTPM_STATE_IDLE:   /* request was cancelled */
> +      break;
> +   default:
> +      /* Spurious wakeup; do nothing, request is still pending */
> +      return;
> +   }
> +
>     dev->waiting = 0;
>  #ifdef HAVE_LIBC
>     if(dev->fd >= 0) {
> @@ -176,7 +186,7 @@ static int wait_for_backend_state_changed(struct 
> tpmfront_dev* dev, XenbusState
>          ret = wait_for_backend_closed(&events, path);
>          break;
>        default:
> -        break;
> +         TPMFRONT_ERR("Bad wait state %d, ignoring\n", state);
>     }
> 
>     if((err = xenbus_unwatch_path_token(XBT_NIL, path, path))) {
> @@ -190,13 +200,13 @@ static int tpmfront_connect(struct tpmfront_dev* dev)
>  {
>     char* err;
>     /* Create shared page */
> -   dev->tx = (tpmif_tx_interface_t*) alloc_page();
> -   if(dev->tx == NULL) {
> +   dev->page = (vtpm_shared_page_t*) alloc_page();
> +   if(dev->page == NULL) {
>        TPMFRONT_ERR("Unable to allocate page for shared memory\n");
>        goto error;
>     }
> -   memset(dev->tx, 0, PAGE_SIZE);
> -   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->tx), 
> 0);
> +   memset(dev->page, 0, PAGE_SIZE);
> +   dev->ring_ref = gnttab_grant_access(dev->bedomid, virt_to_mfn(dev->page), 
> 0);
>     TPMFRONT_DEBUG("grant ref is %lu\n", (unsigned long) dev->ring_ref);
> 
>     /*Create event channel */
> @@ -228,7 +238,7 @@ error_postevtchn:
>        unbind_evtchn(dev->evtchn);
>  error_postmap:
>        gnttab_end_access(dev->ring_ref);
> -      free_page(dev->tx);
> +      free_page(dev->page);
>  error:
>     return -1;
>  }
> @@ -240,7 +250,6 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>     char path[512];
>     char* value, *err;
>     unsigned long long ival;
> -   int i;
> 
>     printk("============= Init TPM Front ================\n");
> 
> @@ -279,6 +288,15 @@ struct tpmfront_dev* init_tpmfront(const char* _nodename)
>        goto error;
>     }
> 
> +   /* Publish protocol v2 feature */
> +   snprintf(path, 512, "%s/feature-protocol-v2", dev->nodename);
> +   if ((err = xenbus_write(XBT_NIL, path, "1")))
> +   {
> +      TPMFRONT_ERR("Unable to write feature-protocol-v2 node: %s\n", err);
> +      free(err);
> +      goto error;
> +   }
> +
>     /* Create and publish grant reference and event channel */
>     if (tpmfront_connect(dev)) {
>        goto error;
> @@ -289,18 +307,19 @@ struct tpmfront_dev* init_tpmfront(const char* 
> _nodename)
>        goto error;
>     }
> 
> -   /* Allocate pages that will contain the messages */
> -   dev->pages = malloc(sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   if(dev->pages == NULL) {
> +   /* Ensure backend is also using protocol v2 */
> +   snprintf(path, 512, "%s/feature-protocol-v2", dev->bepath);
> +   if((err = xenbus_read(XBT_NIL, path, &value))) {
> +      TPMFRONT_ERR("Unable to read %s during tpmfront initialization! error 
> = %s\n", path, err);
> +      free(err);
>        goto error;
>     }
> -   memset(dev->pages, 0, sizeof(void*) * TPMIF_TX_RING_SIZE);
> -   for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -      dev->pages[i] = (void*)alloc_page();
> -      if(dev->pages[i] == NULL) {
> -        goto error;
> -      }
> +   if(strcmp(value, "1")) {
> +      TPMFRONT_ERR("%s has an invalid value (%s)\n", path, value);
> +      free(value);
> +      goto error;
>     }
> +   free(value);
> 
>     TPMFRONT_LOG("Initialization Completed successfully\n");
> 
> @@ -314,8 +333,6 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>  {
>     char* err;
>     char path[512];
> -   int i;
> -   tpmif_tx_request_t* tx;
>     if(dev == NULL) {
>        return;
>     }
> @@ -349,27 +366,12 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
>        /* Wait for the backend to close and unmap shared pages, ignore any 
> errors */
>        wait_for_backend_state_changed(dev, XenbusStateClosed);
> 
> -      /* Cleanup any shared pages */
> -      if(dev->pages) {
> -        for(i = 0; i < TPMIF_TX_RING_SIZE; ++i) {
> -           if(dev->pages[i]) {
> -              tx = &dev->tx->ring[i].req;
> -              if(tx->ref != 0) {
> -                 gnttab_end_access(tx->ref);
> -              }
> -              free_page(dev->pages[i]);
> -           }
> -        }
> -        free(dev->pages);
> -      }
> -
>        /* Close event channel and unmap shared page */
>        mask_evtchn(dev->evtchn);
>        unbind_evtchn(dev->evtchn);
>        gnttab_end_access(dev->ring_ref);
> 
> -      free_page(dev->tx);
> -
> +      free_page(dev->page);
>     }
> 
>     /* Cleanup memory usage */
> @@ -387,13 +389,17 @@ void shutdown_tpmfront(struct tpmfront_dev* dev)
> 
>  int tpmfront_send(struct tpmfront_dev* dev, const uint8_t* msg, size_t 
> length)
>  {
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
>     int i;
> -   tpmif_tx_request_t* tx = NULL;
> +#endif
>     /* Error Checking */
>     if(dev == NULL || dev->state != XenbusStateConnected) {
>        TPMFRONT_ERR("Tried to send message through disconnected frontend\n");
>        return -1;
>     }
> +   shr = dev->page;
> 
>  #ifdef TPMFRONT_PRINT_DEBUG
>     TPMFRONT_DEBUG("Sending Msg to backend size=%u", (unsigned int) length);
> @@ -407,19 +413,16 @@ int tpmfront_send(struct tpmfront_dev* dev, const 
> uint8_t* msg, size_t length)
>  #endif
> 
>     /* Copy to shared pages now */
> -   for(i = 0; length > 0 && i < TPMIF_TX_RING_SIZE; ++i) {
> -      /* Share the page */
> -      tx = &dev->tx->ring[i].req;
> -      tx->unused = 0;
> -      tx->addr = virt_to_mach(dev->pages[i]);
> -      tx->ref = gnttab_grant_access(dev->bedomid, 
> virt_to_mfn(dev->pages[i]), 0);
> -      /* Copy the bits to the page */
> -      tx->size = length > PAGE_SIZE ? PAGE_SIZE : length;
> -      memcpy(dev->pages[i], &msg[i * PAGE_SIZE], tx->size);
> -
> -      /* Update counters */
> -      length -= tx->size;
> +   offset = sizeof(*shr);
> +   if (length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Message too long for shared page\n");
> +      return -1;
>     }
> +   memcpy(offset + (uint8_t*)shr, msg, length);
> +   shr->length = length;
> +   barrier();
> +   shr->state = VTPM_STATE_SUBMIT;
> +
>     dev->waiting = 1;
>     dev->resplen = 0;
>  #ifdef HAVE_LIBC
> @@ -434,44 +437,44 @@ int tpmfront_send(struct tpmfront_dev* dev, const 
> uint8_t* msg, size_t length)
>  }
>  int tpmfront_recv(struct tpmfront_dev* dev, uint8_t** msg, size_t *length)
>  {
> -   tpmif_tx_request_t* tx;
> -   int i;
> +   unsigned int offset;
> +   vtpm_shared_page_t* shr = NULL;
> +#ifdef TPMFRONT_PRINT_DEBUG
> +int i;
> +#endif
>     if(dev == NULL || dev->state != XenbusStateConnected) {
>        TPMFRONT_ERR("Tried to receive message from disconnected frontend\n");
>        return -1;
>     }
>     /*Wait for the response */
>     wait_event(dev->waitq, (!dev->waiting));
> +   shr = dev->page;
> 
>     /* Initialize */
>     *msg = NULL;
>     *length = 0;
> +   offset = sizeof(*shr);
> 
> -   /* special case, just quit */
> -   tx = &dev->tx->ring[0].req;
> -   if(tx->size == 0 ) {
> -       goto quit;
> -   }
> -   /* Get the total size */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      *length += tx->size;
> +   if (shr->state != VTPM_STATE_FINISH)
> +      goto quit;
> +
> +   *length = shr->length;
> +
> +   if (*length + offset > PAGE_SIZE) {
> +      TPMFRONT_ERR("Reply too long for shared page\n");
> +      return -1;
>     }
> +
>     /* Alloc the buffer */
>     if(dev->respbuf) {
>        free(dev->respbuf);
>     }
>     *msg = dev->respbuf = malloc(*length);
>     dev->resplen = *length;
> +
>     /* Copy the bits */
> -   tx = &dev->tx->ring[0].req;
> -   for(i = 0; i < TPMIF_TX_RING_SIZE && tx->size > 0; ++i) {
> -      tx = &dev->tx->ring[i].req;
> -      memcpy(&(*msg)[i * PAGE_SIZE], dev->pages[i], tx->size);
> -      gnttab_end_access(tx->ref);
> -      tx->ref = 0;
> -   }
> +   memcpy(*msg, offset + (uint8_t*)shr, *length);
> +
>  #ifdef TPMFRONT_PRINT_DEBUG
>     TPMFRONT_DEBUG("Received response from backend size=%u", (unsigned int) 
> *length);
>     for(i = 0; i < *length; ++i) {
> @@ -504,6 +507,14 @@ int tpmfront_cmd(struct tpmfront_dev* dev, uint8_t* req, 
> size_t reqlen, uint8_t*
>     return 0;
>  }
> 
> +int tpmfront_set_locality(struct tpmfront_dev* dev, int locality)
> +{
> +   if (!dev || !dev->page)
> +      return -1;
> +   dev->page->locality = locality;
> +   return 0;
> +}
> +
>  #ifdef HAVE_LIBC
>  #include <errno.h>
>  int tpmfront_open(struct tpmfront_dev* dev)
> diff --git a/xen/include/public/io/tpmif.h b/xen/include/public/io/tpmif.h
> index fca2c4e..afa4324 100644
> --- a/xen/include/public/io/tpmif.h
> +++ b/xen/include/public/io/tpmif.h
> @@ -64,6 +64,34 @@ struct tpmif_tx_interface {
>  };
>  typedef struct tpmif_tx_interface tpmif_tx_interface_t;
> 
> +/******************************************************************************
> + * TPM I/O interface for Xen guest OSes, v2
> + *
> + * Author: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
> + *
> + */
> +
> +enum vtpm_state {
> +    VTPM_STATE_IDLE,         /* no contents / vTPM idle / cancel complete */
> +    VTPM_STATE_SUBMIT,       /* request ready / vTPM working */
> +    VTPM_STATE_FINISH,       /* response ready / vTPM idle */
> +    VTPM_STATE_CANCEL,       /* cancel requested / vTPM working */
> +};
> +/* The backend should only change state to IDLE or FINISH, while the
> + * frontend should only change to SUBMIT or CANCEL. */
> +
> +struct vtpm_shared_page {
> +    uint32_t length;         /* request/response length in bytes */
> +
> +    uint8_t state;           /* enum vtpm_state */
> +    uint8_t locality;        /* for the current request */
> +    uint8_t pad;             /* should be zero */
> +
> +    uint8_t nr_extra_pages;  /* extra pages for long packets; may be zero */
> +    uint32_t extra_pages[0]; /* grant IDs; length is actually nr_extra_pages 
> */
> +};
> +typedef struct vtpm_shared_page vtpm_shared_page_t;
> +
>  #endif
> 
>  /*
> --
> 1.8.1.4
> 



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