|
[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, >pmdev.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(>pmdev.map, (unsigned long)tpmif->tx, 1)) {
> + if(gntmap_munmap(>pmdev.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(>pmdev.map, 1, &domid, 0,
> &ringref, PROT_READ | PROT_WRITE)) == NULL) {
> + if((tpmif->page = gntmap_map_grant_refs(>pmdev.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(>pmdev.map, (unsigned long)tpmif->tx, 1);
> + gntmap_munmap(>pmdev.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(>pmdev.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(>pmdev.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(>pmdev.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(>pmdev.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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |