qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/5] TPM device emulation
@ 2011-02-18 15:33 Andreas Niederl
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface Andreas Niederl
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Andreas Niederl @ 2011-02-18 15:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Niederl

Hi,

This patch series introduces TPM device emulation in QEMU.

The emulation is divided into a device frontend implementing the TPM TIS 1.2
interface (specification available at [1]) and a framework for implementation
specific backend drivers which are used by the frontend.

A backend driver for direct passthrough of a TPM device using the host driver
on a Linux system is provided and is enabled by passing
'-tpm type=host,path=...,id=...' to QEMU.

Since the Linux TPM driver requires blocking I/O to the TPM device, a custom
thread or a threadlet (using the threadlet patch series on this list, see
last patch) is needed for handling I/O operations in the host backend.


The frontend is integrated into the qdev device framework and can be enabled
using the '-device' argument specifying a valid backend driver, e.g.:
  qemu ... -tpm type=host,path=/dev/tpm0,id=tpm0 -device tpm,backend=tpm0

When the frontend is enabled, a SSDT ACPI table containing the device
description for hotplugging is loaded using the fw_cfg runtime configuration
interface to SeaBIOS.


This device emulation can be tested by loading an image and installing the
jTPMTools and the jTSS stack which ships a set of unit tests itself and is
available on [2].

Testing can also be done using the character device provided by the
TPM emulator [3] with the tpmd_dev kernel module.


This patch series is used in the acTvSM trusted virtualization platform which
also is available on [2].


Regards,
Andreas Niederl

[1] https://www.trustedcomputinggroup.org/
[2] http://trustedjava.sourceforge.net/
[3] http://tpm-emulator.berlios.de/


Andreas Niederl (5):
  Add TPM 1.2 device interface
  Provide SSDT for enabled TPM device
  Add TPM host passthrough device backend.
  Add configure script and command line options for TPM interface.
  Adapt TPM host backend to use threadlets

 Makefile.objs         |    3 +
 Makefile.target       |    3 +
 configure             |    9 +
 hw/acpi.c             |   28 ++
 hw/pc.h               |    1 +
 hw/tpm.h              |   24 ++
 hw/tpm_acpi.c         |   40 +++
 hw/tpm_backend.c      |   78 ++++++
 hw/tpm_host_backend.c |  235 ++++++++++++++++
 hw/tpm_int.h          |   56 ++++
 hw/tpm_ssdt.dsl       |   55 ++++
 hw/tpm_ssdt.hex       |   41 +++
 hw/tpm_tis.c          |  706 +++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-config.c         |   16 ++
 qemu-config.h         |    1 +
 qemu-options.hx       |    6 +
 rules.mak             |    7 +-
 vl.c                  |   45 +++
 18 files changed, 1353 insertions(+), 1 deletions(-)
 create mode 100644 hw/tpm.h
 create mode 100644 hw/tpm_acpi.c
 create mode 100644 hw/tpm_backend.c
 create mode 100644 hw/tpm_host_backend.c
 create mode 100644 hw/tpm_int.h
 create mode 100644 hw/tpm_ssdt.dsl
 create mode 100644 hw/tpm_ssdt.hex
 create mode 100644 hw/tpm_tis.c

-- 
1.7.4.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 15:33 [Qemu-devel] [PATCH 0/5] TPM device emulation Andreas Niederl
@ 2011-02-18 15:33 ` Andreas Niederl
  2011-02-18 16:37   ` Stefan Berger
  2011-02-18 21:03   ` Stefan Berger
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 2/5] Provide SSDT for enabled TPM device Andreas Niederl
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 17+ messages in thread
From: Andreas Niederl @ 2011-02-18 15:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Niederl

This implementation is based on the TPM 1.2 interface for virtualized TPM
devices from the Xen-4.0.0 ioemu-qemu-xen fork.

A backend driver infrastructure is provided to be able to use different
device backends.

Signed-off-by: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
---
 Makefile.objs    |    3 +
 hw/tpm.h         |   22 ++
 hw/tpm_backend.c |   77 ++++++
 hw/tpm_int.h     |   53 ++++
 hw/tpm_tis.c     |  705 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 860 insertions(+), 0 deletions(-)
 create mode 100644 hw/tpm.h
 create mode 100644 hw/tpm_backend.c
 create mode 100644 hw/tpm_int.h
 create mode 100644 hw/tpm_tis.c

diff --git a/Makefile.objs b/Makefile.objs
index b21f9d3..6c78453 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -283,6 +283,9 @@ hw-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p-debug.o
 hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
 hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
 
+# TPM passthrough device
+hw-obj-$(CONFIG_TPM) += tpm_tis.o tpm_backend.o
+
 ######################################################################
 # libdis
 # NOTE: the disassembler code is only needed for debugging
diff --git a/hw/tpm.h b/hw/tpm.h
new file mode 100644
index 0000000..f3e1395
--- /dev/null
+++ b/hw/tpm.h
@@ -0,0 +1,22 @@
+/*
+ * tpm.h - Interface for adding TPM backend drivers
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ *
+ * Author: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#ifndef TPM_H
+#define TPM_H
+
+#include "qemu-option.h"
+
+int qemu_tpm_add(QemuOpts *opts);
+
+#endif /* TPM_H */
diff --git a/hw/tpm_backend.c b/hw/tpm_backend.c
new file mode 100644
index 0000000..b87c089
--- /dev/null
+++ b/hw/tpm_backend.c
@@ -0,0 +1,77 @@
+/*
+ * tpm_backend.c - TPM backend driver framework
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ *
+ * Author: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+
+#include "qemu-option.h"
+
+#include "hw/tpm.h"
+#include "hw/tpm_int.h"
+
+
+static QLIST_HEAD(, TPMDriver) tpm_drivers =
+    QLIST_HEAD_INITIALIZER(tpm_drivers);
+
+TPMDriver *tpm_get_driver(const char *id)
+{
+    TPMDriver *drv;
+    QLIST_FOREACH(drv, &tpm_drivers, list) {
+        if (!strcmp(drv->id, id)) {
+            return drv;
+        }
+    }
+    return NULL;
+}
+
+
+typedef struct {
+    const char *name;
+    TPMDriver *(*open)(QemuOpts *opts);
+} TPMDriverTable;
+
+static const TPMDriverTable driver_table[] = {
+};
+
+int qemu_tpm_add(QemuOpts *opts) {
+    TPMDriver *drv = NULL;
+    int i;
+
+    if (qemu_opts_id(opts) == NULL) {
+        fprintf(stderr, "tpm: no id specified\n");
+        return -1;
+    }
+
+    for (i = 0; i < ARRAY_SIZE(driver_table); i++) {
+        if (strcmp(driver_table[i].name, qemu_opt_get(opts, "type")) == 0) {
+            break;
+        }
+    }
+
+    if (i == ARRAY_SIZE(driver_table)) {
+        fprintf(stderr, "tpm: backend type %s not found\n",
+                    qemu_opt_get(opts, "type"));
+        return -1;
+    }
+
+    drv = driver_table[i].open(opts);
+
+    if (drv == NULL) {
+        return -1;
+    }
+
+    drv->id = qemu_strdup(qemu_opts_id(opts));
+
+    QLIST_INSERT_HEAD(&tpm_drivers, drv, list);
+
+    return 0;
+}
diff --git a/hw/tpm_int.h b/hw/tpm_int.h
new file mode 100644
index 0000000..7869a81
--- /dev/null
+++ b/hw/tpm_int.h
@@ -0,0 +1,53 @@
+/*
+ * tpm_int.h - Internal header file for TPM device emulation
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ *
+ * Author: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#ifndef TPM_INT_H
+#define TPM_INT_H
+
+
+#include <inttypes.h>
+#include "qemu-queue.h"
+#include "qemu-option.h"
+
+
+typedef struct TPMDriver TPMDriver;
+struct TPMDriver {
+    char *id;
+
+    uint8_t  locty;
+    uint8_t *buf;
+
+    int (*send)(TPMDriver *drv, uint8_t locty, uint32_t len);
+    int (*recv)(TPMDriver *drv, uint8_t locty, uint32_t len);
+
+    QLIST_ENTRY(TPMDriver) list;
+};
+
+TPMDriver *tpm_get_driver(const char *id);
+
+#define TPM_MAX_PKT            4096
+#define TPM_MAX_PATH           4096
+
+/*#define DEBUG_TPM*/
+#ifdef DEBUG_TPM
+void show_buff(unsigned char *buff, const char *string);
+#define DPRINTF(fmt, ...) \
+    fprintf(stderr, "tpm_tis: %s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+#define DSHOW_BUFF(buf, info) show_buff(buf, info)
+#else
+#define DPRINTF(fmt, ...)
+#define DSHOW_BUFF(buf, info)
+#endif
+
+#endif /* TPM_INT_H */
diff --git a/hw/tpm_tis.c b/hw/tpm_tis.c
new file mode 100644
index 0000000..a4c2a4e
--- /dev/null
+++ b/hw/tpm_tis.c
@@ -0,0 +1,705 @@
+/*
+ * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface
+ *
+ * Copyright (C) 2006 IBM Corporation
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ *
+ * Author: Stefan Berger <stefanb@us.ibm.com>
+ *         David Safford <safford@us.ibm.com>
+ *
+ * Author: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
+ * Modified to use a separate TPM device backend
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ *
+ * Implementation of the TIS interface according to specs at
+ * https://www.trustedcomputinggroup.org/
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "hw/hw.h"
+#include "hw/pc.h"
+#include "hw/pci.h"
+#include "hw/pci_ids.h"
+#include "qemu-timer.h"
+
+#include "hw/tpm.h"
+#include "hw/tpm_int.h"
+
+
+#define TIS_ADDR_BASE                 0xFED40000
+
+/* tis registers */
+#define TPM_REG_ACCESS                0x00
+#define TPM_REG_INT_ENABLE            0x08
+#define TPM_REG_INT_VECTOR            0x0c
+#define TPM_REG_INT_STATUS            0x10
+#define TPM_REG_INTF_CAPABILITY       0x14
+#define TPM_REG_STS                   0x18
+#define TPM_REG_DATA_FIFO             0x24
+#define TPM_REG_DID_VID               0xf00
+#define TPM_REG_RID                   0xf04
+
+#define STS_VALID                    (1 << 7)
+#define STS_COMMAND_READY            (1 << 6)
+#define STS_TPM_GO                   (1 << 5)
+#define STS_DATA_AVAILABLE           (1 << 4)
+#define STS_EXPECT                   (1 << 3)
+#define STS_RESPONSE_RETRY           (1 << 1)
+
+#define ACCESS_TPM_REG_VALID_STS     (1 << 7)
+#define ACCESS_ACTIVE_LOCALITY       (1 << 5)
+#define ACCESS_BEEN_SEIZED           (1 << 4)
+#define ACCESS_SEIZE                 (1 << 3)
+#define ACCESS_PENDING_REQUEST       (1 << 2)
+#define ACCESS_REQUEST_USE           (1 << 1)
+#define ACCESS_TPM_ESTABLISHMENT     (1 << 0)
+
+#define INT_ENABLED                  (1 << 31)
+#define INT_DATA_AVAILABLE           (1 << 0)
+#define INT_LOCALITY_CHANGED         (1 << 2)
+#define INT_COMMAND_READY            (1 << 7)
+
+#define INTERRUPTS_SUPPORTED         (INT_LOCALITY_CHANGED | \
+                                      INT_DATA_AVAILABLE   | \
+                                      INT_COMMAND_READY)
+#define CAPABILITIES_SUPPORTED       ((1 << 4) |            \
+                                      INTERRUPTS_SUPPORTED)
+
+enum {
+  STATE_IDLE = 0,
+  STATE_READY,
+  STATE_COMPLETION,
+  STATE_EXECUTION,
+  STATE_RECEPTION
+};
+
+#define NUM_LOCALITIES   5
+#define NO_LOCALITY      0xff
+
+#define IS_VALID_LOC(x) ((x) < NUM_LOCALITIES)
+
+#define TPM_DID          0x0001
+#define TPM_VID          0x0001
+#define TPM_RID          0x0001
+
+/* locality data */
+typedef struct {
+    uint32_t state;
+    uint32_t inte;
+    uint32_t ints;
+    uint8_t  access;
+    uint8_t  sts;
+} TPMLocality;
+
+/* TPM device state */
+typedef struct {
+    ISADevice  dev;
+    qemu_irq   pic;
+    uint32_t   irq;
+    uint8_t    irq_pending;
+
+    QEMUTimer *poll_timer;
+    int        poll_attempts;
+
+    uint8_t    aborting;   /* boolean value */
+    uint32_t   offset;
+    uint8_t    buf[TPM_MAX_PKT];
+
+    uint8_t    active_locty;
+    uint8_t  aborting_locty;
+    uint8_t      next_locty;
+
+    TPMLocality loc[NUM_LOCALITIES];
+
+    char *backend;
+
+    TPMDriver *drv;
+} TPMState;
+
+
+/**********************************************************************
+ helper functions
+ *********************************************************************/
+
+static inline uint32_t tpm_get_size_from_buffer(const uint8_t *buffer)
+{
+    uint32_t len = (buffer[4] << 8) + buffer[5];
+    return len;
+}
+
+static inline uint8_t locality_from_addr(target_phys_addr_t addr)
+{
+    return (uint8_t)((addr >> 12) & 0x7);
+}
+
+
+#ifdef DEBUG_TPM
+/****************************************************************************/
+/*                                                                          */
+/* optional verbose logging of data to/from tpm chip                        */
+/*                                                                          */
+/****************************************************************************/
+void show_buff(unsigned char *buff, const char *string)
+{
+    uint32_t i, len;
+
+    len = tpm_get_size_from_buffer(buff);
+    printf("%s length=%d\n", string, len);
+    for (i = 0; i < len; i++) {
+        if (i && !(i % 16)) {
+            printf("\n");
+        }
+        printf("%.2X ", buff[i]);
+    }
+    printf("\n");
+}
+#endif
+
+
+/* raise an interrupt if allowed */
+static void tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask)
+{
+    if (!s->irq_pending &&
+        (s->loc[locty].inte & INT_ENABLED) &&
+        (s->loc[locty].inte & irqmask)) {
+        if ((irqmask & s->loc[locty].ints) == 0) {
+            DPRINTF("Raising IRQ for flag %08x\n",irqmask);
+            qemu_set_irq(s->pic, 1);
+            s->irq_pending = 1;
+            s->loc[locty].ints |= irqmask;
+        }
+    }
+}
+
+/* abort execution of command */
+static void tis_abort(TPMState *s)
+{
+    s->offset = 0;
+    s->active_locty = s->next_locty;
+
+    /*
+     * Need to react differently depending on who's aborting now and
+     * which locality will become active afterwards.
+     */
+    if (s->aborting_locty == s->next_locty) {
+        s->loc[s->aborting_locty].state = STATE_READY;
+        s->loc[s->aborting_locty].sts   = STS_COMMAND_READY;
+        tis_raise_irq(s, s->aborting_locty, INT_COMMAND_READY);
+    }
+
+    /* locality after abort is another one than the current one */
+    if (s->aborting_locty != s->next_locty && s->next_locty != NO_LOCALITY) {
+        s->loc[s->aborting_locty].access &= ~ACCESS_ACTIVE_LOCALITY;
+        s->loc[s->next_locty].access     |=  ACCESS_ACTIVE_LOCALITY;
+        tis_raise_irq(s, s->next_locty, INT_LOCALITY_CHANGED);
+    }
+
+    s->aborting_locty = NO_LOCALITY; /* nobody's aborting a command anymore */
+}
+
+/**********************************************************************/
+
+/*
+ * Prepare the next interrupt for example after a command has
+ * been sent out for the purpose of receiving the response.
+ * Depending on how many interrupts (used for polling on the fd) have
+ * already been schedule, this function determines the delta in time
+ * to the next interrupt. This accomodates for commands that finish
+ * quickly.
+ */
+static void tis_prep_next_interrupt(TPMState *s)
+{
+    int64_t expiration;
+    int rate = 5; /* 5 times per second */
+
+    /*
+     * poll often at the beginning for quickly finished commands,
+     * then back off
+     */
+    if (s->poll_attempts < 5) {
+        rate = 20;
+    } else if (s->poll_attempts < 10) {
+        rate = 10;
+    }
+
+    expiration = qemu_get_clock(vm_clock) + (get_ticks_per_sec() / rate);
+    qemu_mod_timer(s->poll_timer, expiration);
+    s->poll_attempts++;
+}
+
+
+/*
+ * The polling routine called when the 'timer interrupt' fires.
+ * Tries to receive a command from the vTPM.
+ */
+static void tis_poll_timer(void *opaque)
+{
+    TPMState *s   = opaque;
+    uint8_t locty = s->active_locty;
+
+    if (!IS_VALID_LOC(locty) ||
+        (!(s->loc[locty].inte & INT_ENABLED) &&
+          (s->aborting_locty != NO_LOCALITY))) {
+        /* no more interrupts requested, so no more polling needed */
+        qemu_del_timer(s->poll_timer);
+    }
+
+    if (s->aborting_locty != NO_LOCALITY) {
+        int n = s->drv->recv(s->drv, locty, TPM_MAX_PKT);
+        DPRINTF("Receiving for abort.\n");
+        if (n > 0) {
+            tis_abort(s);
+            DPRINTF("Abort is complete.\n");
+        } else {
+            tis_prep_next_interrupt(s);
+        }
+    } else if (IS_VALID_LOC(locty)) {
+        if (s->loc[locty].state == STATE_EXECUTION) {
+            int n = s->drv->recv(s->drv, locty, TPM_MAX_PKT);
+
+            /* poll for result */
+            if (n > 0) {
+                s->loc[locty].sts = STS_VALID | STS_DATA_AVAILABLE;
+                s->loc[locty].state = STATE_COMPLETION;
+                tis_raise_irq(s, locty, INT_DATA_AVAILABLE);
+            } else {
+                /* nothing received */
+                tis_prep_next_interrupt(s);
+            }
+        }
+    }
+}
+
+
+/*
+ * Try to receive a response from the backend TPM
+ */
+static void tis_attempt_receive(TPMState *s, uint8_t locty)
+{
+    /*
+     * Attempt to read from the backend TPM here if
+     * - not aborting a command
+     * - command has been sent and state is 'EXECUTION' now
+     * - no data are already available (data have already been read)
+     */
+    if (!IS_VALID_LOC(s->aborting_locty)) {
+        if (s->loc[locty].state == STATE_EXECUTION) {
+            if (0 == (s->loc[locty].sts & STS_DATA_AVAILABLE)){
+                int n = s->drv->recv(s->drv, locty, TPM_MAX_PKT);
+                if (n > 0) {
+                    s->loc[locty].sts = STS_VALID | STS_DATA_AVAILABLE;
+                    s->loc[locty].state = STATE_COMPLETION;
+                    tis_raise_irq(s, locty, INT_DATA_AVAILABLE);
+                }
+            }
+        }
+    }
+}
+
+/*
+ * read a byte of response data
+ */
+static uint32_t tpm_data_read(TPMState *s, uint8_t locty)
+{
+    uint32_t ret, len;
+
+    /* try to receive data, if none are there it is ok */
+    tis_attempt_receive(s, locty);
+
+    if (s->loc[locty].state != STATE_COMPLETION) {
+        DPRINTF("tpm_data_read with no data available!\n");
+        return 0xff;
+    }
+
+    len = tpm_get_size_from_buffer(s->buf);
+    ret = s->buf[s->offset++];
+    if (s->offset >= len) {
+        s->loc[locty].sts = STS_VALID ;
+        s->offset = 0;
+    }
+    DPRINTF("tpm_data_read byte x%02x [%d]\n", ret, s->offset - 1);
+    return ret;
+}
+
+
+/* abort current command */
+static void tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
+{
+    s->aborting_locty = locty; /* current locality */
+    s->next_locty =  newlocty; /* locality after successful abort */
+
+    /*
+     * only abort a command using an interrupt if currently executing
+     * a command AND if there's a valid connection to the vTPM.
+     */
+    if (s->loc[locty].state == STATE_EXECUTION) {
+        /* start timer and inside the timer wait for the result */
+        s->poll_attempts = 0;
+        tis_prep_next_interrupt(s);
+    } else {
+        tis_abort(s);
+    }
+}
+
+
+/*
+ * Read a register of the TIS interface
+ * See specs pages 33-63 for description of the registers
+ */
+static uint32_t tis_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+    TPMState *s     =  opaque;
+    uint16_t offset =  addr & 0xffc;
+    uint8_t shift   = (addr & 0x3) * 8;
+    uint32_t val    = 0;
+    uint8_t locty   = locality_from_addr(addr);
+
+    switch (offset) {
+        case TPM_REG_ACCESS:
+            if (s->active_locty == locty) {
+                s->loc[locty].access |= (1 << 5);
+            } else {
+                s->loc[locty].access &= ~(1 << 5);
+            }
+            val = s->loc[locty].access;
+            break;
+        case TPM_REG_INT_ENABLE:
+            val = s->loc[locty].inte;
+            break;
+        case TPM_REG_INT_VECTOR:
+            val = s->irq;
+            break;
+        case TPM_REG_INT_STATUS:
+            tis_attempt_receive(s, locty);
+            val = s->loc[locty].ints;
+            break;
+        case TPM_REG_INTF_CAPABILITY:
+            val = CAPABILITIES_SUPPORTED;
+            break;
+        case TPM_REG_STS: /* status register */
+            tis_attempt_receive(s, locty);
+            val = (sizeof(s->buf) - s->offset) << 8 | s->loc[locty].sts;
+            break;
+        case TPM_REG_DATA_FIFO:
+            val = tpm_data_read(s, locty);
+            break;
+        case TPM_REG_DID_VID:
+            val = (TPM_DID << 16) | TPM_VID;
+            break;
+        case TPM_REG_RID:
+            val = TPM_RID;
+            break;
+        default:
+            DPRINTF("Bad register offset %#08x\n", offset);
+            break;
+    }
+
+    if (shift && locty == 0) {
+        val >>= shift;
+    }
+
+    DPRINTF("read(0x" TARGET_FMT_plx ") = %#08x\n", addr, val);
+
+    return val;
+}
+
+/*
+ * Write a value to a register of the TIS interface
+ * See specs pages 33-63 for description of the registers
+ */
+static void tis_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+    TPMState* s     = opaque;
+    uint16_t offset = addr & 0xfff;
+    uint8_t locty   = locality_from_addr(addr);
+    uint32_t len;
+
+    DPRINTF("write(0x" TARGET_FMT_plx ") = %#08x\n", addr, val);
+
+    switch (offset) {
+        case TPM_REG_ACCESS:
+            if (val & ACCESS_ACTIVE_LOCALITY) {
+                /* give up locality if currently owned */
+                if (s->active_locty == locty) {
+                    /*uint8_t newlocty = NO_LOCALITY;*/
+                    s->loc[locty].access &= ~(ACCESS_PENDING_REQUEST);
+                    /* anybody wants the locality ? */
+                    if (s->loc[locty].access & ACCESS_REQUEST_USE) {
+                        s->loc[locty].access |= ACCESS_TPM_REG_VALID_STS;
+                        s->loc[locty].access &= ~ACCESS_REQUEST_USE;
+                    }
+                    tis_prep_abort(s, locty, locty);
+                }
+            }
+            if (val & ACCESS_BEEN_SEIZED) {
+                /* clear the flag */
+                s->loc[locty].access &= ~ACCESS_BEEN_SEIZED;
+            }
+            if (val & ACCESS_SEIZE) {
+                if (locty > s->active_locty && IS_VALID_LOC(s->active_locty)) {
+                    s->loc[s->active_locty].access |= ACCESS_BEEN_SEIZED;
+                    s->loc[locty].access = ACCESS_TPM_REG_VALID_STS;
+                    tis_prep_abort(s, s->active_locty, locty);
+                }
+            }
+            if (val & ACCESS_REQUEST_USE) {
+                if (IS_VALID_LOC(s->active_locty)) {
+                    /* locality election */
+                    s->loc[s->active_locty].access |= ACCESS_PENDING_REQUEST;
+                } else {
+                    /* no locality active -> make this one active now */
+                    s->loc[locty].access |= ACCESS_ACTIVE_LOCALITY;
+                    s->active_locty = locty;
+                    tis_raise_irq(s, locty, INT_LOCALITY_CHANGED);
+                }
+            }
+            break;
+        case TPM_REG_INT_ENABLE:
+            s->loc[locty].inte = (val & (INT_ENABLED | (0x3 << 3) |
+                        INTERRUPTS_SUPPORTED));
+            break;
+        case TPM_REG_INT_VECTOR:
+            /*
+             * isa_init_irq would exit qemu
+             * if the requested IRQ is already assigned
+             */
+            /*isa_init_irq(&s->dev, &s->pic, val);*/
+            DPRINTF("writes to TPM_INT_VECTOR not supported!\n");
+            break;
+        case TPM_REG_INT_STATUS:
+            /* clearing of interrupt flags */
+            if ((val & INTERRUPTS_SUPPORTED) &&
+                    (s->loc[locty].ints & INTERRUPTS_SUPPORTED)) {
+                qemu_set_irq(s->pic, 0);
+                s->irq_pending = 0;
+            }
+            s->loc[locty].ints &= ~(val & INTERRUPTS_SUPPORTED);
+            break;
+        case TPM_REG_STS:
+            if (val & STS_COMMAND_READY) {
+                if (s->loc[locty].state == STATE_IDLE) {
+                    s->loc[locty].sts   = STS_COMMAND_READY;
+                    s->loc[locty].state = STATE_READY;
+                    tis_raise_irq(s, locty, INT_COMMAND_READY);
+                } else if (s->loc[locty].state == STATE_COMPLETION ||
+                        s->loc[locty].state == STATE_EXECUTION  ||
+                        s->loc[locty].state == STATE_RECEPTION) {
+                    /* abort currently running command */
+                    tis_prep_abort(s, locty, locty);
+                }
+            }
+            if (val & STS_TPM_GO) {
+                if (s->loc[locty].state == STATE_RECEPTION) {
+                    int n = s->drv->send(s->drv, locty,
+                            tpm_get_size_from_buffer(s->buf));
+                    if (n > 0) {
+                        /* sending of data was successful */
+                        s->offset = 0;
+                        s->loc[locty].state = STATE_EXECUTION;
+                        if (s->loc[locty].inte &
+                                (INT_ENABLED | INT_DATA_AVAILABLE)) {
+                            s->poll_attempts = 0;
+                            tis_prep_next_interrupt(s);
+                        }
+                    }
+                }
+            }
+            if (val & STS_RESPONSE_RETRY) {
+                s->offset = 0;
+            }
+            break;
+        case TPM_REG_DATA_FIFO:
+            /* data fifo */
+            if (s->loc[locty].state == STATE_IDLE ||
+                    s->loc[locty].state == STATE_EXECUTION ||
+                    s->loc[locty].state == STATE_COMPLETION) {
+                /* drop the byte */
+            } else {
+                DPRINTF("Byte to send to TPM: %02x at offset: %03d\n", val,
+                        s->offset);
+                s->loc[locty].state = STATE_RECEPTION;
+
+                if (s->offset < TPM_MAX_PKT)
+                    s->buf[s->offset++] = (uint8_t)val;
+
+                if (s->offset > 5) {
+                    /* we have a packet length - see if we have all of it */
+                    len = tpm_get_size_from_buffer(s->buf);
+                    if (len > s->offset) {
+                        s->loc[locty].sts = STS_EXPECT | STS_VALID;
+                    } else {
+                        s->loc[locty].sts = STS_VALID;
+                    }
+                }
+            }
+            break;
+        default:
+            DPRINTF("Bad register offset %#08x\n", offset);
+            break;
+    }
+}
+
+
+static CPUReadMemoryFunc *  const tis_readfn[3] = {
+    tis_mem_readl,
+    tis_mem_readl,
+    tis_mem_readl
+};
+
+static CPUWriteMemoryFunc * const tis_writefn[3] = {
+    tis_mem_writel,
+    tis_mem_writel,
+    tis_mem_writel
+};
+
+/*
+ * Need to get any outstanding responses from the TPM back, so
+ * this might delay the suspend for a while.
+ */
+static void tpm_pre_save(void *opaque)
+{
+    TPMState *s = opaque;
+    uint8_t locty = s->active_locty;
+
+    /* need to wait for outstanding requests to complete */
+    if (s->loc[locty].state == STATE_EXECUTION) {
+        int repeats = 30; /* 30 seconds; really should be infty */
+        while (repeats > 0 &&
+               !(s->loc[s->active_locty].sts & STS_DATA_AVAILABLE)) {
+            sleep(1);
+        }
+    }
+}
+
+
+static void tpm_reset(TPMState *s)
+{
+    int c;
+
+    s->offset       = 0;
+    s->aborting     = 0;
+    s->active_locty = NO_LOCALITY;
+
+    for (c = 0; c < NUM_LOCALITIES; c++) {
+        s->loc[c].access = (1 << 7);
+        s->loc[c].sts    = 0;
+        s->loc[c].inte   = (1 << 3);
+        s->loc[c].ints   = 0;
+        s->loc[c].state  = STATE_IDLE;
+    }
+    s->aborting_locty = NO_LOCALITY;
+
+    memset(s->buf, 0, sizeof(s->buf));
+}
+
+static const VMStateDescription vmstate_loc = {
+    .name       = "loc",
+    .version_id = 0,
+    .fields     = (VMStateField []) {
+        VMSTATE_UINT32(state, TPMLocality),
+        VMSTATE_UINT32(inte,  TPMLocality),
+        VMSTATE_UINT32(ints,  TPMLocality),
+        VMSTATE_UINT8(access, TPMLocality),
+        VMSTATE_UINT8(sts,    TPMLocality),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_tpm = {
+    .name       = "tpm",
+    .version_id = 0,
+    .minimum_version_id     = 0,
+    .minimum_version_id_old = 0,
+    .pre_save   = tpm_pre_save,
+    .fields     = (VMStateField []) {
+        VMSTATE_UINT32(irq,    TPMState),
+        VMSTATE_UINT32(offset, TPMState),
+        VMSTATE_BUFFER(buf,    TPMState),
+        VMSTATE_UINT8(  active_locty, TPMState),
+        VMSTATE_UINT8(aborting_locty, TPMState),
+        VMSTATE_UINT8(    next_locty, TPMState),
+        VMSTATE_STRUCT_ARRAY(loc, TPMState, NUM_LOCALITIES, 0,
+                             vmstate_loc, TPMLocality),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+/*
+ * initialize TIS interface
+ */
+static int tpm_init(ISADevice *dev)
+{
+    TPMState  *s      = DO_UPCAST(TPMState, dev, dev);
+    int        isairq = 11;
+    TPMDriver *drv    = NULL;
+    int        iomem;
+    int        i;
+
+    if (!s->backend) {
+        fprintf(stderr, "tpm: no backend selected!\n");
+        return -1;
+    }
+    drv = tpm_get_driver(s->backend);
+    if (drv == NULL) {
+        fprintf(stderr, "tpm: backend id %s not found\n", s->backend);
+        return -1;
+    }
+
+    tpm_reset(s);
+
+    drv->buf = s->buf;
+    s->drv   = drv;
+
+    vmstate_register(&dev->qdev, 1, &vmstate_tpm, s);
+    for (i = 0; i < NUM_LOCALITIES; i++) {
+        vmstate_register(&dev->qdev, 1, &vmstate_loc, &s->loc[i]);
+    }
+
+    isa_init_irq(dev, &s->pic, isairq);
+    s->irq = isairq;
+
+    iomem = cpu_register_io_memory(tis_readfn, tis_writefn, s,
+            DEVICE_LITTLE_ENDIAN);
+    cpu_register_physical_memory(TIS_ADDR_BASE,
+            0x1000 * NUM_LOCALITIES, iomem);
+
+    s->poll_timer = qemu_new_timer(vm_clock, tis_poll_timer, s);
+
+    return 0;
+}
+
+static void qdev_tpm_reset(DeviceState *dev)
+{
+    TPMState *s = DO_UPCAST(TPMState, dev.qdev, dev);
+    tpm_reset(s);
+}
+
+static ISADeviceInfo tpm_info = {
+    .init          = tpm_init,
+    .qdev.name     = "tpm",
+    .qdev.desc     = "TPM TIS Interface",
+    .qdev.size     = sizeof (TPMState),
+    .qdev.vmsd     = &vmstate_tpm,
+    .qdev.reset    = qdev_tpm_reset,
+    .qdev.props    = (Property[]) {
+        DEFINE_PROP_STRING("backend", TPMState, backend),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void tpm_register (void)
+{
+    isa_qdev_register(&tpm_info);
+}
+device_init (tpm_register)
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH 2/5] Provide SSDT for enabled TPM device
  2011-02-18 15:33 [Qemu-devel] [PATCH 0/5] TPM device emulation Andreas Niederl
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface Andreas Niederl
@ 2011-02-18 15:33 ` Andreas Niederl
  2011-02-18 17:02   ` Stefan Berger
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 3/5] Add TPM host passthrough device backend Andreas Niederl
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Andreas Niederl @ 2011-02-18 15:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Niederl

Signed-off-by: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
---
 Makefile.target |    3 +++
 hw/acpi.c       |   28 ++++++++++++++++++++++++++++
 hw/pc.h         |    1 +
 hw/tpm.h        |    2 ++
 hw/tpm_acpi.c   |   40 ++++++++++++++++++++++++++++++++++++++++
 hw/tpm_ssdt.dsl |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/tpm_ssdt.hex |   41 +++++++++++++++++++++++++++++++++++++++++
 hw/tpm_tis.c    |    1 +
 rules.mak       |    7 ++++++-
 vl.c            |   23 +++++++++++++++++++++++
 10 files changed, 200 insertions(+), 1 deletions(-)
 create mode 100644 hw/tpm_acpi.c
 create mode 100644 hw/tpm_ssdt.dsl
 create mode 100644 hw/tpm_ssdt.hex

diff --git a/Makefile.target b/Makefile.target
index 5a0fd40..33ffe19 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -211,6 +211,9 @@ obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
 # Inter-VM PCI shared memory
 obj-$(CONFIG_KVM) += ivshmem.o
 
+# TPM acpi support
+obj-$(CONFIG_TPM) += tpm_acpi.o
+
 # Hardware support
 obj-i386-y += vga.o
 obj-i386-y += mc146818rtc.o i8259.o pc.o
diff --git a/hw/acpi.c b/hw/acpi.c
index 8071e7b..93656c5 100644
--- a/hw/acpi.c
+++ b/hw/acpi.c
@@ -35,6 +35,34 @@ struct acpi_table_header
 char *acpi_tables;
 size_t acpi_tables_len;
 
+
+/*
+ * add a table directly (e.g. iasl C source output)
+ */
+int acpi_table_add_raw(const char *t, uint32_t length)
+{
+    char *p;
+
+    if (!acpi_tables) {
+        acpi_tables_len = sizeof(uint16_t);
+        acpi_tables = qemu_mallocz(acpi_tables_len);
+    }
+    acpi_tables = qemu_realloc(acpi_tables,
+                               acpi_tables_len + sizeof(uint16_t) + length);
+    p = acpi_tables + acpi_tables_len;
+    acpi_tables_len += sizeof(uint16_t) + length;
+
+    *(uint16_t*)p = cpu_to_le32(length);
+    p += sizeof(uint16_t);
+
+    memcpy(p, t, length);
+
+    /* increase number of tables */
+    (*(uint16_t*)acpi_tables) =
+        cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
+    return 0;
+}
+
 static int acpi_checksum(const uint8_t *data, int len)
 {
     int sum, i;
diff --git a/hw/pc.h b/hw/pc.h
index d5d2f42..56ba5fc 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -118,6 +118,7 @@ extern size_t acpi_tables_len;
 
 void acpi_bios_init(void);
 int acpi_table_add(const char *table_desc);
+int acpi_table_add_raw(const char *table, uint32_t length);
 
 /* acpi_piix.c */
 
diff --git a/hw/tpm.h b/hw/tpm.h
index f3e1395..5dd40c8 100644
--- a/hw/tpm.h
+++ b/hw/tpm.h
@@ -19,4 +19,6 @@
 
 int qemu_tpm_add(QemuOpts *opts);
 
+int qemu_tpm_acpi_init(void);
+
 #endif /* TPM_H */
diff --git a/hw/tpm_acpi.c b/hw/tpm_acpi.c
new file mode 100644
index 0000000..8cfa98f
--- /dev/null
+++ b/hw/tpm_acpi.c
@@ -0,0 +1,40 @@
+/*
+ * tpm_acpi.c - ACPI integration for TPM device emulation
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ *
+ * Author: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+#include "hw/pc.h"
+#include "hw/tpm.h"
+
+/*
+ * Add SSDT entry for TPM device
+ *
+ * Only one such entry is possible because it specifies a fixed MMIO address
+ * as required by the TIS 1.2 specification.
+ */
+int qemu_tpm_acpi_init(void)
+{
+    int ret = 0;
+#ifdef TARGET_I386
+    static int init = 0;
+
+#include "hw/tpm_ssdt.hex"
+
+    if (!init) {
+        ret  = acpi_table_add_raw((char*)AmlCode, sizeof(AmlCode));
+        init = 1;
+    }
+#endif
+
+    return ret;
+}
+
diff --git a/hw/tpm_ssdt.dsl b/hw/tpm_ssdt.dsl
new file mode 100644
index 0000000..d9a48a7
--- /dev/null
+++ b/hw/tpm_ssdt.dsl
@@ -0,0 +1,55 @@
+/*
+ * ACPI SSDT ASL definition for TPM device emulation
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+DefinitionBlock (
+    "tpm-ssdt.aml",    // Output Filename
+    "SSDT",             // Signature
+    0x01,               // DSDT Compliance Revision
+    "BXPC",             // OEMID
+    "TPM-SSDT",         // TABLE ID
+    0x1                 // OEM Revision
+    )
+{
+
+    Scope(\_SB) {
+        /* Pass-through TPM device with emulated TPM TIS interface */
+        Device (TPM) {
+            Name (_HID, EisaID ("ATM1200"))
+            Name (_CID, EisaId ("PNP0C31"))
+            Name (_STR, Unicode ("Emulated TPM TIS pass-through device"))
+            Name (BUF1, ResourceTemplate ()
+            {
+                    Memory32Fixed (ReadOnly,
+                                   0xFED40000,         // Address Base
+                                   0x00005000,         // Address Length
+                                  )
+                    IRQNoFlags () {11}
+            })
+            Method (_CRS, 0, Serialized)
+            {
+                Return (BUF1)
+            }
+            Method (_STA, 0)
+            {
+                Return (0x0F)
+            }
+        }
+
+    }
+}
+
diff --git a/hw/tpm_ssdt.hex b/hw/tpm_ssdt.hex
new file mode 100644
index 0000000..da1d4c3
--- /dev/null
+++ b/hw/tpm_ssdt.hex
@@ -0,0 +1,41 @@
+/*
+ * 
+ * Intel ACPI Component Architecture
+ * ASL Optimizing Compiler version 20090123 [Jun  3 2009]
+ * Copyright (C) 2000 - 2009 Intel Corporation
+ * Supports ACPI Specification Revision 3.0a
+ * 
+ * Compilation of "hw/tpm_ssdt.dsl" - Wed Feb  2 17:49:34 2011
+ * 
+ * C source code output
+ *
+ */
+unsigned char AmlCode[] =
+{
+    0x53,0x53,0x44,0x54,0xCC,0x00,0x00,0x00,  /* 00000000    "SSDT...." */
+    0x01,0xEC,0x42,0x58,0x50,0x43,0x00,0x00,  /* 00000008    "..BXPC.." */
+    0x54,0x50,0x4D,0x2D,0x53,0x53,0x44,0x54,  /* 00000010    "TPM-SSDT" */
+    0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C,  /* 00000018    "....INTL" */
+    0x23,0x01,0x09,0x20,0x10,0x47,0x0A,0x5C,  /* 00000020    "#.. .G.\" */
+    0x5F,0x53,0x42,0x5F,0x5B,0x82,0x4E,0x09,  /* 00000028    "_SB_[.N." */
+    0x54,0x50,0x4D,0x5F,0x08,0x5F,0x48,0x49,  /* 00000030    "TPM_._HI" */
+    0x44,0x0C,0x06,0x8D,0x12,0x00,0x08,0x5F,  /* 00000038    "D......_" */
+    0x43,0x49,0x44,0x0C,0x41,0xD0,0x0C,0x31,  /* 00000040    "CID.A..1" */
+    0x08,0x5F,0x53,0x54,0x52,0x11,0x4E,0x04,  /* 00000048    "._STR.N." */
+    0x0A,0x4A,0x45,0x00,0x6D,0x00,0x75,0x00,  /* 00000050    ".JE.m.u." */
+    0x6C,0x00,0x61,0x00,0x74,0x00,0x65,0x00,  /* 00000058    "l.a.t.e." */
+    0x64,0x00,0x20,0x00,0x54,0x00,0x50,0x00,  /* 00000060    "d. .T.P." */
+    0x4D,0x00,0x20,0x00,0x54,0x00,0x49,0x00,  /* 00000068    "M. .T.I." */
+    0x53,0x00,0x20,0x00,0x70,0x00,0x61,0x00,  /* 00000070    "S. .p.a." */
+    0x73,0x00,0x73,0x00,0x2D,0x00,0x74,0x00,  /* 00000078    "s.s.-.t." */
+    0x68,0x00,0x72,0x00,0x6F,0x00,0x75,0x00,  /* 00000080    "h.r.o.u." */
+    0x67,0x00,0x68,0x00,0x20,0x00,0x64,0x00,  /* 00000088    "g.h. .d." */
+    0x65,0x00,0x76,0x00,0x69,0x00,0x63,0x00,  /* 00000090    "e.v.i.c." */
+    0x65,0x00,0x00,0x00,0x08,0x42,0x55,0x46,  /* 00000098    "e....BUF" */
+    0x31,0x11,0x14,0x0A,0x11,0x86,0x09,0x00,  /* 000000A0    "1......." */
+    0x00,0x00,0x00,0xD4,0xFE,0x00,0x50,0x00,  /* 000000A8    "......P." */
+    0x00,0x22,0x00,0x08,0x79,0x00,0x14,0x0B,  /* 000000B0    "."..y..." */
+    0x5F,0x43,0x52,0x53,0x08,0xA4,0x42,0x55,  /* 000000B8    "_CRS..BU" */
+    0x46,0x31,0x14,0x09,0x5F,0x53,0x54,0x41,  /* 000000C0    "F1.._STA" */
+    0x00,0xA4,0x0A,0x0F,
+};
diff --git a/hw/tpm_tis.c b/hw/tpm_tis.c
index a4c2a4e..589add6 100644
--- a/hw/tpm_tis.c
+++ b/hw/tpm_tis.c
@@ -635,6 +635,7 @@ static const VMStateDescription vmstate_tpm = {
     }
 };
 
+
 /*
  * initialize TIS interface
  */
diff --git a/rules.mak b/rules.mak
index ed59c9e..3c5cdc5 100644
--- a/rules.mak
+++ b/rules.mak
@@ -31,6 +31,11 @@ LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(1)
 %.a:
 	$(call quiet-command,rm -f $@ && $(AR) rcs $@ $^,"  AR    $(TARGET_DIR)$@")
 
+# ACPI table build rule
+%.hex: %.dsl
+	$(call quiet-command,iasl -tc -p $@ $<,"  GEN   $(TARGET_DIR)$@")
+
+
 quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
 
 # cc-option
@@ -39,7 +44,7 @@ quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
 cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
               >/dev/null 2>&1 && echo OK), $2, $3)
 
-VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi
+VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.texi %.dsl
 set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1)))
 
 # find-in-path
diff --git a/vl.c b/vl.c
index b436952..f74f37a 100644
--- a/vl.c
+++ b/vl.c
@@ -151,6 +151,9 @@ int main(int argc, char **argv)
 #ifdef CONFIG_VIRTFS
 #include "fsdev/qemu-fsdev.h"
 #endif
+#ifdef CONFIG_TPM
+#include "hw/tpm.h"
+#endif
 
 #include "disas.h"
 
@@ -1647,6 +1650,19 @@ static int fsdev_init_func(QemuOpts *opts, void *opaque)
 }
 #endif
 
+#ifdef CONFIG_TPM
+static int tpm_acpi_init_func(QemuOpts *opts, void *opaque)
+{
+    int ret = 0;
+
+    if (strcmp(qemu_opt_get(opts, "driver"), "tpm") == 0) {
+        ret = qemu_tpm_acpi_init();
+    }
+
+    return ret;
+}
+#endif
+
 static int mon_init_func(QemuOpts *opts, void *opaque)
 {
     CharDriverState *chr;
@@ -2864,6 +2880,13 @@ int main(int argc, char **argv, char **envp)
     }
 #endif
 
+#ifdef CONFIG_TPM
+    /* register TPM acpi table before machine->init is called */
+    if (qemu_opts_foreach(qemu_find_opts("device"), tpm_acpi_init_func, NULL, 1) != 0) {
+        exit(1);
+    }
+#endif
+
     os_daemonize();
 
     if (pid_file && qemu_create_pidfile(pid_file) != 0) {
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH 3/5] Add TPM host passthrough device backend.
  2011-02-18 15:33 [Qemu-devel] [PATCH 0/5] TPM device emulation Andreas Niederl
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface Andreas Niederl
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 2/5] Provide SSDT for enabled TPM device Andreas Niederl
@ 2011-02-18 15:33 ` Andreas Niederl
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 4/5] Add configure script and command line options for TPM interface Andreas Niederl
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 5/5] Adapt TPM host backend to use threadlets Andreas Niederl
  4 siblings, 0 replies; 17+ messages in thread
From: Andreas Niederl @ 2011-02-18 15:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Niederl

A separate thread is used for I/O to the host TPM device because the Linux TPM
driver does not allow non-blocking I/O.

Signed-off-by: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
---
 Makefile.objs         |    5 +-
 hw/tpm_backend.c      |    1 +
 hw/tpm_host_backend.c |  282 +++++++++++++++++++++++++++++++++++++++++++++++++
 hw/tpm_int.h          |    3 +
 4 files changed, 290 insertions(+), 1 deletions(-)
 create mode 100644 hw/tpm_host_backend.c

diff --git a/Makefile.objs b/Makefile.objs
index 6c78453..55fd6b5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -284,7 +284,10 @@ hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
 hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
 
 # TPM passthrough device
-hw-obj-$(CONFIG_TPM) += tpm_tis.o tpm_backend.o
+hw-obj-$(CONFIG_TPM) += tpm_tis.o tpm_backend.o tpm_host_backend.o
+ifndef CONFIG_THREAD
+common-obj-$(CONFIG_TPM) += qemu-thread.o
+endif
 
 ######################################################################
 # libdis
diff --git a/hw/tpm_backend.c b/hw/tpm_backend.c
index b87c089..41dbfd4 100644
--- a/hw/tpm_backend.c
+++ b/hw/tpm_backend.c
@@ -40,6 +40,7 @@ typedef struct {
 } TPMDriverTable;
 
 static const TPMDriverTable driver_table[] = {
+    { .name = "host", .open = qemu_tpm_host_open },
 };
 
 int qemu_tpm_add(QemuOpts *opts) {
diff --git a/hw/tpm_host_backend.c b/hw/tpm_host_backend.c
new file mode 100644
index 0000000..4ae9deb
--- /dev/null
+++ b/hw/tpm_host_backend.c
@@ -0,0 +1,282 @@
+/*
+ * tpm_host_backend.c - TPM host passthrough backend driver
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ *
+ * Author: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
+ *
+ * A custom thread is used for asynchronous I/O to the host TPM device
+ * because the Linux TPM driver does not allow non-blocking I/O.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ *
+ */
+
+
+#include <errno.h>
+#include <signal.h>
+
+#include "qemu-common.h"
+#include "qemu-thread.h"
+
+#include "hw/tpm_int.h"
+
+
+typedef struct {
+    QemuThread id;
+    QemuMutex  lock;
+    QemuCond   send_command;
+} TPMThread;
+
+#define STATUS_DONE        (1 << 1)
+#define STATUS_IN_PROGRESS (1 << 0)
+#define STATUS_IDLE         0
+
+typedef struct {
+    TPMDriver common;
+
+    TPMThread thread;
+
+    uint8_t   send_status;
+    uint8_t   recv_status;
+
+    int32_t  send_len;
+    int32_t  recv_len;
+
+    int fd;
+} TPMHostDriver;
+
+static int tpm_host_send(TPMDriver *drv, uint8_t locty, uint32_t len)
+{
+    TPMHostDriver *hdrv = DO_UPCAST(TPMHostDriver, common, drv);
+    int n = 0;
+
+    drv->locty = locty;
+
+    qemu_mutex_lock(&hdrv->thread.lock);
+    switch (hdrv->send_status) {
+        case STATUS_IN_PROGRESS:
+            break;
+        case STATUS_IDLE:
+            hdrv->send_len = len;
+            hdrv->recv_len = TPM_MAX_PKT;
+            /* asynchronous send */
+            n = 1;
+            qemu_cond_signal( &hdrv->thread.send_command);
+            break;
+        case STATUS_DONE:
+            n = hdrv->send_len;
+            hdrv->send_status = STATUS_IDLE;
+            break;
+        default:
+            n = -1;
+            fprintf(stderr,
+                    "tpm host backend: internal error on send status %d\n",
+                    hdrv->send_status);
+            break;
+    }
+    qemu_mutex_unlock(&hdrv->thread.lock);
+
+    return n;
+}
+
+static int tpm_host_recv(TPMDriver *drv, uint8_t locty, uint32_t len)
+{
+    TPMHostDriver *hdrv = DO_UPCAST(TPMHostDriver, common, drv);
+    int n = 0;
+
+    drv->locty = locty;
+
+    qemu_mutex_lock(&hdrv->thread.lock);
+    switch (hdrv->recv_status) {
+        case STATUS_IN_PROGRESS:
+            break;
+        case STATUS_IDLE:
+            break;
+        case STATUS_DONE:
+            hdrv->recv_status = STATUS_IDLE;
+            n = hdrv->recv_len;
+            break;
+        default:
+            n = -1;
+            fprintf(stderr,
+                    "tpm host backend: internal error on recv status %d\n",
+                    hdrv->recv_status);
+            break;
+    }
+    qemu_mutex_unlock(&hdrv->thread.lock);
+
+    return n;
+}
+
+
+/* borrowed from qemu-char.c */
+static int unix_write(int fd, const uint8_t *buf, uint32_t len)
+{
+    int ret, len1;
+
+    len1 = len;
+    while (len1 > 0) {
+        ret = write(fd, buf, len1);
+        if (ret < 0) {
+            if (errno != EINTR && errno != EAGAIN)
+                return -1;
+        } else if (ret == 0) {
+            break;
+        } else {
+            buf  += ret;
+            len1 -= ret;
+        }
+    }
+    return len - len1;
+}
+
+static int unix_read(int fd, uint8_t *buf, uint32_t len)
+{
+    int ret, len1;
+    uint8_t *buf1;
+
+    len1 = len;
+    buf1 = buf;
+    while ((len1 > 0) && (ret = read(fd, buf1, len1)) != 0) {
+        if (ret < 0) {
+            if (errno != EINTR && errno != EAGAIN)
+                return -1;
+        } else {
+            buf1 += ret;
+            len1 -= ret;
+        }
+    }
+    return len - len1;
+}
+
+static void die2(int err, const char *what)
+{
+    fprintf(stderr, "%s failed: %s\n", what, strerror(err));
+    abort();
+}
+
+static void die(const char *what)
+{
+    die2(errno, what);
+}
+
+static void *tpm_host_thread(void *opaque)
+{
+    TPMHostDriver *drv = opaque;
+    TPMDriver     *s   = &drv->common;
+    sigset_t  set;
+    uint32_t  tpm_ret;
+    int ret;
+
+    /* block all signals */
+    if (sigfillset(&set)) {
+        die("sigfillset");
+    }
+    if (sigprocmask(SIG_BLOCK, &set, NULL)) {
+        die("sigprocmask");
+    }
+
+    qemu_mutex_lock(&drv->thread.lock);
+    while (1) {
+        qemu_cond_wait(&drv->thread.send_command, &drv->thread.lock);
+        drv->send_status = STATUS_IN_PROGRESS;
+        qemu_mutex_unlock(&drv->thread.lock);
+
+        DSHOW_BUFF(s->buf, "To TPM");
+
+        ret = unix_write(drv->fd, s->buf, drv->send_len);
+
+        qemu_mutex_lock(&drv->thread.lock);
+        drv->send_len    = ret;
+        drv->send_status = STATUS_DONE;
+
+        if (ret < 0) {
+            fprintf(stderr, "Error: while transmitting data to host tpm"
+                    ": %s (%i)\n",
+                    strerror(errno), errno);
+            continue;
+        }
+
+        drv->recv_status = STATUS_IN_PROGRESS;
+        qemu_mutex_unlock(&drv->thread.lock);
+
+        ret = unix_read(drv->fd, s->buf, drv->recv_len);
+
+        qemu_mutex_lock(&drv->thread.lock);
+        drv->recv_len    = ret;
+        drv->recv_status = STATUS_DONE;
+        drv->send_status = STATUS_IDLE;
+
+        if (ret < 0) {
+            fprintf(stderr, "Error: while reading data from host tpm"
+                    ": %s (%i)\n",
+                    strerror(errno), errno);
+            continue;
+        }
+
+        DSHOW_BUFF(s->buf, "From TPM");
+
+        tpm_ret = (s->buf[8])*256 + s->buf[9];
+        if (tpm_ret) {
+            DPRINTF("tpm command failed with error %d\n", tpm_ret);
+        } else {
+            DPRINTF("tpm command succeeded\n");
+        }
+    }
+
+    return NULL;
+}
+
+
+TPMDriver *qemu_tpm_host_open(QemuOpts *opts)
+{
+    TPMDriver      *drv = NULL;
+    TPMHostDriver *hdrv = NULL;
+    TPMThread *thread = NULL;
+    char *path = NULL;
+    int fd = -1;
+
+    hdrv = qemu_mallocz(sizeof(TPMHostDriver));
+    memset(hdrv, 0, sizeof(TPMHostDriver));
+    drv = &hdrv->common;
+
+    /* methods */
+    drv->send = tpm_host_send;
+    drv->recv = tpm_host_recv;
+
+    /* file open */
+    if (qemu_opt_get(opts, "path") == NULL) {
+        fprintf(stderr, "tpm: No path specified.\n");
+        goto fail;
+    }
+
+    path = qemu_strdup(qemu_opt_get(opts, "path"));
+    fd = open(path, O_RDWR);
+    if (fd < 0) {
+        fprintf(stderr, "Cannot open %s: %s (%i)\n",
+            path, strerror(errno), errno);
+        goto fail;
+    }
+    hdrv->fd = fd;
+
+    thread = &hdrv->thread;
+    qemu_mutex_init(&thread->lock);
+    qemu_cond_init( &thread->send_command);
+
+    qemu_thread_create(&thread->id, &tpm_host_thread, hdrv);
+
+    return drv;
+
+fail:
+    if (fd >= 0) {
+        close(fd);
+    }
+    qemu_free(hdrv);
+    return NULL;
+}
+
+
diff --git a/hw/tpm_int.h b/hw/tpm_int.h
index 7869a81..71a71f4 100644
--- a/hw/tpm_int.h
+++ b/hw/tpm_int.h
@@ -36,6 +36,9 @@ struct TPMDriver {
 
 TPMDriver *tpm_get_driver(const char *id);
 
+TPMDriver *qemu_tpm_host_open(QemuOpts *opts);
+
+
 #define TPM_MAX_PKT            4096
 #define TPM_MAX_PATH           4096
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH 4/5] Add configure script and command line options for TPM interface.
  2011-02-18 15:33 [Qemu-devel] [PATCH 0/5] TPM device emulation Andreas Niederl
                   ` (2 preceding siblings ...)
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 3/5] Add TPM host passthrough device backend Andreas Niederl
@ 2011-02-18 15:33 ` Andreas Niederl
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 5/5] Adapt TPM host backend to use threadlets Andreas Niederl
  4 siblings, 0 replies; 17+ messages in thread
From: Andreas Niederl @ 2011-02-18 15:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Niederl

Signed-off-by: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
---
 configure       |    9 +++++++++
 qemu-config.c   |   16 ++++++++++++++++
 qemu-config.h   |    1 +
 qemu-options.hx |    6 ++++++
 vl.c            |   22 ++++++++++++++++++++++
 5 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/configure b/configure
index a3f5345..7addec3 100755
--- a/configure
+++ b/configure
@@ -316,6 +316,7 @@ case "$cpu" in
   ;;
 esac
 
+tpm="no"
 # OS specific
 if check_define __linux__ ; then
   targetos="Linux"
@@ -455,6 +456,7 @@ Haiku)
   usb="linux"
   if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
     audio_possible_drivers="$audio_possible_drivers fmod"
+    tpm="yes"
   fi
 ;;
 esac
@@ -713,6 +715,8 @@ for opt do
   ;;
   --enable-vhost-net) vhost_net="yes"
   ;;
+  --disable-tpm) tpm="no"
+  ;;
   --*dir)
   ;;
   --disable-rbd) rbd="no"
@@ -914,6 +918,7 @@ echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
 echo "  --enable-spice           enable spice"
 echo "  --enable-rbd             enable building the rados block device (rbd)"
+echo "  --disable-tpm            disable tpm passthrough device emulation"
 echo ""
 echo "NOTE: The object files are built at the place where configure is launched"
 exit 1
@@ -2478,6 +2483,7 @@ echo "Trace output file $trace_file-<pid>"
 echo "spice support     $spice"
 echo "rbd support       $rbd"
 echo "xfsctl support    $xfs"
+echo "tpm support       $tpm"
 
 if test $sdl_too_old = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -2739,6 +2745,9 @@ fi
 if test "$fdatasync" = "yes" ; then
   echo "CONFIG_FDATASYNC=y" >> $config_host_mak
 fi
+if test "$tpm" = "yes" ; then
+  echo "CONFIG_TPM=y" >> $config_host_mak
+fi
 if test "$madvise" = "yes" ; then
   echo "CONFIG_MADVISE=y" >> $config_host_mak
 fi
diff --git a/qemu-config.c b/qemu-config.c
index 323d3c2..fe3a2ae 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -451,6 +451,22 @@ QemuOptsList qemu_option_rom_opts = {
     },
 };
 
+QemuOptsList qemu_tpm_opts = {
+    .name = "tpm",
+    .implied_opt_name = "type",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_tpm_opts.head),
+    .desc = {
+        {
+            .name = "type",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },
+        { /*End of list */ }
+    },
+};
+
 static QemuOptsList *vm_config_groups[32] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
diff --git a/qemu-config.h b/qemu-config.h
index 20d707f..eed9b3f 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -4,6 +4,7 @@
 extern QemuOptsList qemu_fsdev_opts;
 extern QemuOptsList qemu_virtfs_opts;
 extern QemuOptsList qemu_spice_opts;
+extern QemuOptsList qemu_tpm_opts;
 
 QemuOptsList *qemu_find_opts(const char *group);
 void qemu_add_opts(QemuOptsList *list);
diff --git a/qemu-options.hx b/qemu-options.hx
index 945edf3..cf4494d 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2339,6 +2339,12 @@ STEXI
 Specify a trace file to log output traces to.
 ETEXI
 #endif
+#ifdef CONFIG_TPM
+DEF("tpm", HAS_ARG, QEMU_OPTION_tpm,
+    "-tpm host,id=id,path=path\n"
+    "                enable TPM support and forward commands to the given TPM device file\n",
+    QEMU_ARCH_I386)
+#endif
 
 HXCOMM This is the last statement. Insert new options before this line!
 STEXI
diff --git a/vl.c b/vl.c
index f74f37a..4bafcce 100644
--- a/vl.c
+++ b/vl.c
@@ -1651,6 +1651,14 @@ static int fsdev_init_func(QemuOpts *opts, void *opaque)
 #endif
 
 #ifdef CONFIG_TPM
+static int tpm_init_func(QemuOpts *opts, void *opaque)
+{
+    int ret;
+    ret = qemu_tpm_add(opts);
+
+    return ret;
+}
+
 static int tpm_acpi_init_func(QemuOpts *opts, void *opaque)
 {
     int ret = 0;
@@ -1993,6 +2001,10 @@ int main(int argc, char **argv, char **envp)
     tb_size = 0;
     autostart= 1;
 
+#ifdef CONFIG_TPM
+    qemu_add_opts(&qemu_tpm_opts);
+#endif
+
     /* first pass of option parsing */
     optind = 1;
     while (optind < argc) {
@@ -2493,6 +2505,13 @@ int main(int argc, char **argv, char **envp)
                 qemu_free(arg_9p);
                 break;
             }
+            case QEMU_OPTION_tpm:
+               opts = qemu_opts_parse(qemu_find_opts("tpm"), optarg, 0);
+               if (!opts) {
+                   fprintf(stderr, "parse error: %s\n", optarg);
+                   exit(1);
+               }
+               break;
             case QEMU_OPTION_serial:
                 add_device_config(DEV_SERIAL, optarg);
                 default_serial = 0;
@@ -2881,6 +2900,9 @@ int main(int argc, char **argv, char **envp)
 #endif
 
 #ifdef CONFIG_TPM
+    if (qemu_opts_foreach(qemu_find_opts("tpm"), tpm_init_func, NULL, 1) != 0) {
+        exit(1);
+    }
     /* register TPM acpi table before machine->init is called */
     if (qemu_opts_foreach(qemu_find_opts("device"), tpm_acpi_init_func, NULL, 1) != 0) {
         exit(1);
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH 5/5] Adapt TPM host backend to use threadlets
  2011-02-18 15:33 [Qemu-devel] [PATCH 0/5] TPM device emulation Andreas Niederl
                   ` (3 preceding siblings ...)
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 4/5] Add configure script and command line options for TPM interface Andreas Niederl
@ 2011-02-18 15:33 ` Andreas Niederl
  4 siblings, 0 replies; 17+ messages in thread
From: Andreas Niederl @ 2011-02-18 15:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: Andreas Niederl

Signed-off-by: Andreas Niederl <andreas.niederl@iaik.tugraz.at>
---
 Makefile.objs         |    3 -
 hw/tpm_host_backend.c |  111 ++++++++++++++-----------------------------------
 2 files changed, 32 insertions(+), 82 deletions(-)

diff --git a/Makefile.objs b/Makefile.objs
index 55fd6b5..5209a9b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -285,9 +285,6 @@ hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
 
 # TPM passthrough device
 hw-obj-$(CONFIG_TPM) += tpm_tis.o tpm_backend.o tpm_host_backend.o
-ifndef CONFIG_THREAD
-common-obj-$(CONFIG_TPM) += qemu-thread.o
-endif
 
 ######################################################################
 # libdis
diff --git a/hw/tpm_host_backend.c b/hw/tpm_host_backend.c
index 4ae9deb..9204ede 100644
--- a/hw/tpm_host_backend.c
+++ b/hw/tpm_host_backend.c
@@ -20,17 +20,11 @@
 #include <signal.h>
 
 #include "qemu-common.h"
-#include "qemu-thread.h"
+#include "qemu-threadlet.h"
 
 #include "hw/tpm_int.h"
 
 
-typedef struct {
-    QemuThread id;
-    QemuMutex  lock;
-    QemuCond   send_command;
-} TPMThread;
-
 #define STATUS_DONE        (1 << 1)
 #define STATUS_IN_PROGRESS (1 << 0)
 #define STATUS_IDLE         0
@@ -38,7 +32,7 @@ typedef struct {
 typedef struct {
     TPMDriver common;
 
-    TPMThread thread;
+    ThreadletWork work;
 
     uint8_t   send_status;
     uint8_t   recv_status;
@@ -56,7 +50,6 @@ static int tpm_host_send(TPMDriver *drv, uint8_t locty, uint32_t len)
 
     drv->locty = locty;
 
-    qemu_mutex_lock(&hdrv->thread.lock);
     switch (hdrv->send_status) {
         case STATUS_IN_PROGRESS:
             break;
@@ -65,7 +58,7 @@ static int tpm_host_send(TPMDriver *drv, uint8_t locty, uint32_t len)
             hdrv->recv_len = TPM_MAX_PKT;
             /* asynchronous send */
             n = 1;
-            qemu_cond_signal( &hdrv->thread.send_command);
+            submit_work(&hdrv->work);
             break;
         case STATUS_DONE:
             n = hdrv->send_len;
@@ -78,7 +71,6 @@ static int tpm_host_send(TPMDriver *drv, uint8_t locty, uint32_t len)
                     hdrv->send_status);
             break;
     }
-    qemu_mutex_unlock(&hdrv->thread.lock);
 
     return n;
 }
@@ -90,7 +82,6 @@ static int tpm_host_recv(TPMDriver *drv, uint8_t locty, uint32_t len)
 
     drv->locty = locty;
 
-    qemu_mutex_lock(&hdrv->thread.lock);
     switch (hdrv->recv_status) {
         case STATUS_IN_PROGRESS:
             break;
@@ -107,7 +98,6 @@ static int tpm_host_recv(TPMDriver *drv, uint8_t locty, uint32_t len)
                     hdrv->recv_status);
             break;
     }
-    qemu_mutex_unlock(&hdrv->thread.lock);
 
     return n;
 }
@@ -153,82 +143,50 @@ static int unix_read(int fd, uint8_t *buf, uint32_t len)
     return len - len1;
 }
 
-static void die2(int err, const char *what)
-{
-    fprintf(stderr, "%s failed: %s\n", what, strerror(err));
-    abort();
-}
-
-static void die(const char *what)
+static void tpm_host_send_receive(ThreadletWork *work)
 {
-    die2(errno, what);
-}
-
-static void *tpm_host_thread(void *opaque)
-{
-    TPMHostDriver *drv = opaque;
+    TPMHostDriver *drv = container_of(work, TPMHostDriver, work);
     TPMDriver     *s   = &drv->common;
-    sigset_t  set;
     uint32_t  tpm_ret;
     int ret;
 
-    /* block all signals */
-    if (sigfillset(&set)) {
-        die("sigfillset");
-    }
-    if (sigprocmask(SIG_BLOCK, &set, NULL)) {
-        die("sigprocmask");
-    }
-
-    qemu_mutex_lock(&drv->thread.lock);
-    while (1) {
-        qemu_cond_wait(&drv->thread.send_command, &drv->thread.lock);
-        drv->send_status = STATUS_IN_PROGRESS;
-        qemu_mutex_unlock(&drv->thread.lock);
+    drv->send_status = STATUS_IN_PROGRESS;
 
-        DSHOW_BUFF(s->buf, "To TPM");
+    DSHOW_BUFF(s->buf, "To TPM");
 
-        ret = unix_write(drv->fd, s->buf, drv->send_len);
+    ret = unix_write(drv->fd, s->buf, drv->send_len);
 
-        qemu_mutex_lock(&drv->thread.lock);
-        drv->send_len    = ret;
-        drv->send_status = STATUS_DONE;
+    drv->send_len    = ret;
+    drv->send_status = STATUS_DONE;
 
-        if (ret < 0) {
-            fprintf(stderr, "Error: while transmitting data to host tpm"
-                    ": %s (%i)\n",
-                    strerror(errno), errno);
-            continue;
-        }
+    if (ret < 0) {
+      fprintf(stderr, "Error: while transmitting data to host tpm"
+          ": %s (%i)\n",
+          strerror(errno), errno);
+    }
 
-        drv->recv_status = STATUS_IN_PROGRESS;
-        qemu_mutex_unlock(&drv->thread.lock);
+    drv->recv_status = STATUS_IN_PROGRESS;
 
-        ret = unix_read(drv->fd, s->buf, drv->recv_len);
+    ret = unix_read(drv->fd, s->buf, drv->recv_len);
 
-        qemu_mutex_lock(&drv->thread.lock);
-        drv->recv_len    = ret;
-        drv->recv_status = STATUS_DONE;
-        drv->send_status = STATUS_IDLE;
+    drv->recv_len    = ret;
+    drv->recv_status = STATUS_DONE;
+    drv->send_status = STATUS_IDLE;
 
-        if (ret < 0) {
-            fprintf(stderr, "Error: while reading data from host tpm"
-                    ": %s (%i)\n",
-                    strerror(errno), errno);
-            continue;
-        }
+    if (ret < 0) {
+      fprintf(stderr, "Error: while reading data from host tpm"
+          ": %s (%i)\n",
+          strerror(errno), errno);
+    }
 
-        DSHOW_BUFF(s->buf, "From TPM");
+    DSHOW_BUFF(s->buf, "From TPM");
 
-        tpm_ret = (s->buf[8])*256 + s->buf[9];
-        if (tpm_ret) {
-            DPRINTF("tpm command failed with error %d\n", tpm_ret);
-        } else {
-            DPRINTF("tpm command succeeded\n");
-        }
+    tpm_ret = (s->buf[8])*256 + s->buf[9];
+    if (tpm_ret) {
+      DPRINTF("tpm command failed with error %d\n", tpm_ret);
+    } else {
+      DPRINTF("tpm command succeeded\n");
     }
-
-    return NULL;
 }
 
 
@@ -236,7 +194,6 @@ TPMDriver *qemu_tpm_host_open(QemuOpts *opts)
 {
     TPMDriver      *drv = NULL;
     TPMHostDriver *hdrv = NULL;
-    TPMThread *thread = NULL;
     char *path = NULL;
     int fd = -1;
 
@@ -263,11 +220,7 @@ TPMDriver *qemu_tpm_host_open(QemuOpts *opts)
     }
     hdrv->fd = fd;
 
-    thread = &hdrv->thread;
-    qemu_mutex_init(&thread->lock);
-    qemu_cond_init( &thread->send_command);
-
-    qemu_thread_create(&thread->id, &tpm_host_thread, hdrv);
+    hdrv->work.func = tpm_host_send_receive;
 
     return drv;
 
-- 
1.7.4.1

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface Andreas Niederl
@ 2011-02-18 16:37   ` Stefan Berger
  2011-02-18 17:37     ` Andreas Niederl
  2011-02-24 15:30     ` Andreas Niederl
  2011-02-18 21:03   ` Stefan Berger
  1 sibling, 2 replies; 17+ messages in thread
From: Stefan Berger @ 2011-02-18 16:37 UTC (permalink / raw)
  To: Andreas Niederl; +Cc: qemu-devel

On 02/18/2011 10:33 AM, Andreas Niederl wrote:
> This implementation is based on the TPM 1.2 interface for virtualized TPM
> devices from the Xen-4.0.0 ioemu-qemu-xen fork.
>
> A backend driver infrastructure is provided to be able to use different
> device backends.
>
> Signed-off-by: Andreas Niederl<andreas.niederl@iaik.tugraz.at>
>
> --- /dev/null
> +++ b/hw/tpm_tis.c
> @@ -0,0 +1,705 @@
> +/*
> + * tpm_tis.c - QEMU emulator for a 1.2 TPM with TIS interface
> + *
> + * Copyright (C) 2006 IBM Corporation
> + * Copyright (C) 2011 IAIK, Graz University of Technology
> + *
> + * Author: Stefan Berger<stefanb@us.ibm.com>
> + *         David Safford<safford@us.ibm.com>
> + *
> + * Author: Andreas Niederl<andreas.niederl@iaik.tugraz.at>
> + * Modified to use a separate TPM device backend
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation, version 2 of the
> + * License.
> + *
> + *
> + * Implementation of the TIS interface according to specs at
> + * https://www.trustedcomputinggroup.org/
> + *

I have a tpm_tis.c with major changes in it getting rid of the polling, 
closer to specs that passes a test suite and a registerable backend as 
well that has several more interface functions, due to support for 
snapshotting etc. Unfortunately it doesn't make much sense for me to 
post it since the backend is based on a library that's currently in the 
Fedora review process and nobody else could build or test it  -- unless 
there really was interest in reviewing at least some part of it.

It would certainly be desirable if your backend and mine could be 
accommodate.

     Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 2/5] Provide SSDT for enabled TPM device
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 2/5] Provide SSDT for enabled TPM device Andreas Niederl
@ 2011-02-18 17:02   ` Stefan Berger
  2011-02-21 16:55     ` Andreas Niederl
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Berger @ 2011-02-18 17:02 UTC (permalink / raw)
  To: Andreas Niederl; +Cc: qemu-devel

On 02/18/2011 10:33 AM, Andreas Niederl wrote:
> Signed-off-by: Andreas Niederl<andreas.niederl@iaik.tugraz.at>
> ---
>   Makefile.target |    3 +++
>   hw/acpi.c       |   28 ++++++++++++++++++++++++++++
>   hw/pc.h         |    1 +
>   hw/tpm.h        |    2 ++
>   hw/tpm_acpi.c   |   40 ++++++++++++++++++++++++++++++++++++++++
>   hw/tpm_ssdt.dsl |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   hw/tpm_ssdt.hex |   41 +++++++++++++++++++++++++++++++++++++++++
>   hw/tpm_tis.c    |    1 +
>   rules.mak       |    7 ++++++-
>   vl.c            |   23 +++++++++++++++++++++++
>   10 files changed, 200 insertions(+), 1 deletions(-)
>   create mode 100644 hw/tpm_acpi.c
>   create mode 100644 hw/tpm_ssdt.dsl
>   create mode 100644 hw/tpm_ssdt.hex
>
> diff --git a/Makefile.target b/Makefile.target
> index 5a0fd40..33ffe19 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -211,6 +211,9 @@ obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
>   # Inter-VM PCI shared memory
>   obj-$(CONFIG_KVM) += ivshmem.o
>
> +# TPM acpi support
> +obj-$(CONFIG_TPM) += tpm_acpi.o
> +
>   # Hardware support
>   obj-i386-y += vga.o
>   obj-i386-y += mc146818rtc.o i8259.o pc.o
> diff --git a/hw/acpi.c b/hw/acpi.c
> index 8071e7b..93656c5 100644
> --- a/hw/acpi.c
> +++ b/hw/acpi.c
> @@ -35,6 +35,34 @@ struct acpi_table_header
>   char *acpi_tables;
>   size_t acpi_tables_len;
>
> +
> +/*
> + * add a table directly (e.g. iasl C source output)
> + */
> +int acpi_table_add_raw(const char *t, uint32_t length)
> +{
> +    char *p;
> +
> +    if (!acpi_tables) {
> +        acpi_tables_len = sizeof(uint16_t);
> +        acpi_tables = qemu_mallocz(acpi_tables_len);
> +    }
> +    acpi_tables = qemu_realloc(acpi_tables,
> +                               acpi_tables_len + sizeof(uint16_t) + length);
> +    p = acpi_tables + acpi_tables_len;
> +    acpi_tables_len += sizeof(uint16_t) + length;
> +
> +    *(uint16_t*)p = cpu_to_le32(length);
> +    p += sizeof(uint16_t);
> +
> +    memcpy(p, t, length);
> +
> +    /* increase number of tables */
> +    (*(uint16_t*)acpi_tables) =
> +        cpu_to_le32(le32_to_cpu(*(uint16_t*)acpi_tables) + 1);
> +    return 0;
> +}
> +
Does it show up in Linux? I am trying to find the code that connects it 
to the RSDT, but don't see any.

     Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 16:37   ` Stefan Berger
@ 2011-02-18 17:37     ` Andreas Niederl
  2011-02-18 20:27       ` Stefan Berger
  2011-02-24 15:30     ` Andreas Niederl
  1 sibling, 1 reply; 17+ messages in thread
From: Andreas Niederl @ 2011-02-18 17:37 UTC (permalink / raw)
  To: Stefan Berger; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1398 bytes --]

On 02/18/2011 05:37 PM, Stefan Berger wrote:
> On 02/18/2011 10:33 AM, Andreas Niederl wrote:
>> This implementation is based on the TPM 1.2 interface for virtualized TPM
>> devices from the Xen-4.0.0 ioemu-qemu-xen fork.
>>
>> A backend driver infrastructure is provided to be able to use different
>> device backends.
[...]
> 
> I have a tpm_tis.c with major changes in it getting rid of the polling,
> closer to specs that passes a test suite and a registerable backend as
> well that has several more interface functions, due to support for
> snapshotting etc. Unfortunately it doesn't make much sense for me to
> post it since the backend is based on a library that's currently in the
> Fedora review process and nobody else could build or test it  -- unless
> there really was interest in reviewing at least some part of it.

So I'm guessing that this library is not publicly available right now?

Is this backend meant for integration into QEMU or does it run as
separate process?

How/Where could I integrate a passthrough backend like the one in this
patch series?


The polling code isn't really necessary for the host backend, I left it
there just in case it would be needed by such a socket interface as is
used in the Xen fork.


> It would certainly be desirable if your backend and mine could be
> accommodate.

Of course.


Regards,
Andreas


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 6163 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 17:37     ` Andreas Niederl
@ 2011-02-18 20:27       ` Stefan Berger
  2011-02-21 17:03         ` Andreas Niederl
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Berger @ 2011-02-18 20:27 UTC (permalink / raw)
  To: Andreas Niederl; +Cc: qemu-devel

On 02/18/2011 12:37 PM, Andreas Niederl wrote:
> On 02/18/2011 05:37 PM, Stefan Berger wrote:
>> On 02/18/2011 10:33 AM, Andreas Niederl wrote:
>>> This implementation is based on the TPM 1.2 interface for virtualized TPM
>>> devices from the Xen-4.0.0 ioemu-qemu-xen fork.
>>>
>>> A backend driver infrastructure is provided to be able to use different
>>> device backends.
> [...]
>> I have a tpm_tis.c with major changes in it getting rid of the polling,
>> closer to specs that passes a test suite and a registerable backend as
>> well that has several more interface functions, due to support for
>> snapshotting etc. Unfortunately it doesn't make much sense for me to
>> post it since the backend is based on a library that's currently in the
>> Fedora review process and nobody else could build or test it  -- unless
>> there really was interest in reviewing at least some part of it.
> So I'm guessing that this library is not publicly available right now?
Not via the fedora repository at least. So yum install does not work, yet.
> Is this backend meant for integration into QEMU or does it run as
> separate process?
>
The backend is meant for integration in Qemu. It runs as a thread.
> How/Where could I integrate a passthrough backend like the one in this
> patch series?
>
It's possible via similar mechanisms as you have, just the interface is 
bigger and main code calls into the interface at different times. I'd 
need to share the code with you.
> The polling code isn't really necessary for the host backend, I left it
> there just in case it would be needed by such a socket interface as is
> used in the Xen fork.
>
I don't think it's necessary to have it all. In the new code, the  
frontend delivers a request to the backend and provides a callback 
function for delivering the response back once received.

>> It would certainly be desirable if your backend and mine could be
>> accommodate.
> Of course.
>
Let's see how we do this.

   Stefan

> Regards,
> Andreas
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 15:33 ` [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface Andreas Niederl
  2011-02-18 16:37   ` Stefan Berger
@ 2011-02-18 21:03   ` Stefan Berger
  2011-02-21 17:13     ` Andreas Niederl
  1 sibling, 1 reply; 17+ messages in thread
From: Stefan Berger @ 2011-02-18 21:03 UTC (permalink / raw)
  To: qemu-devel

On 02/18/2011 10:33 AM, Andreas Niederl wrote:
> +
> +static const VMStateDescription vmstate_loc = {
> +    .name       = "loc",
> +    .version_id = 0,
> +    .fields     = (VMStateField []) {
> +        VMSTATE_UINT32(state, TPMLocality),
> +        VMSTATE_UINT32(inte,  TPMLocality),
> +        VMSTATE_UINT32(ints,  TPMLocality),
> +        VMSTATE_UINT8(access, TPMLocality),
> +        VMSTATE_UINT8(sts,    TPMLocality),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_tpm = {
> +    .name       = "tpm",
> +    .version_id = 0,
> +    .minimum_version_id     = 0,
> +    .minimum_version_id_old = 0,
> +    .pre_save   = tpm_pre_save,
> +    .fields     = (VMStateField []) {
> +        VMSTATE_UINT32(irq,    TPMState),
> +        VMSTATE_UINT32(offset, TPMState),
> +        VMSTATE_BUFFER(buf,    TPMState),
> +        VMSTATE_UINT8(  active_locty, TPMState),
> +        VMSTATE_UINT8(aborting_locty, TPMState),
> +        VMSTATE_UINT8(    next_locty, TPMState),
> +        VMSTATE_STRUCT_ARRAY(loc, TPMState, NUM_LOCALITIES, 0,
> +                             vmstate_loc, TPMLocality),
Here you are pointing to the above vmstate_loc ...
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +/*

> +
> +    vmstate_register(&dev->qdev, 1,&vmstate_tpm, s);
> +    for (i = 0; i<  NUM_LOCALITIES; i++) {
> +        vmstate_register(&dev->qdev, 1,&vmstate_loc,&s->loc[i]);
... here you are (again) registering the localities ...
> +    }
> +
> +    isa_init_irq(dev,&s->pic, isairq);
> +    s->irq = isairq;
> +
> +    iomem = cpu_register_io_memory(tis_readfn, tis_writefn, s,
> +            DEVICE_LITTLE_ENDIAN);
> +    cpu_register_physical_memory(TIS_ADDR_BASE,
> +            0x1000 * NUM_LOCALITIES, iomem);
> +
> +    s->poll_timer = qemu_new_timer(vm_clock, tis_poll_timer, s);
> +
> +    return 0;
> +}
> +
> +static void qdev_tpm_reset(DeviceState *dev)
> +{
> +    TPMState *s = DO_UPCAST(TPMState, dev.qdev, dev);
> +    tpm_reset(s);
> +}
> +
> +static ISADeviceInfo tpm_info = {
> +    .init          = tpm_init,
> +    .qdev.name     = "tpm",
> +    .qdev.desc     = "TPM TIS Interface",
> +    .qdev.size     = sizeof (TPMState),
> +    .qdev.vmsd     =&vmstate_tpm,
... and here you're pointing to vmstate_tpm, which was also registered 
above using

+
+    vmstate_register(&dev->qdev, 1,&vmstate_tpm, s);


Are you sure this is necessary? In my implementation I only have the 
qdev.vmsd set and need not explicitly use vmstate_register(). Aren't you 
writing the state two times if you do that?

    Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 2/5] Provide SSDT for enabled TPM device
  2011-02-18 17:02   ` Stefan Berger
@ 2011-02-21 16:55     ` Andreas Niederl
  0 siblings, 0 replies; 17+ messages in thread
From: Andreas Niederl @ 2011-02-21 16:55 UTC (permalink / raw)
  To: Stefan Berger; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 375 bytes --]

On 02/18/2011 06:02 PM, Stefan Berger wrote:
[...]
> Does it show up in Linux? I am trying to find the code that connects it
> to the RSDT, but don't see any.

Yes, it does.

QEMU can provide ACPI tables over a BIOS config I/O port.
SeaBIOS reads these in src/acpi.c:acpi_bios_init() and builds the RSDT
including the tables received from this port.


Andreas


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 6163 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 20:27       ` Stefan Berger
@ 2011-02-21 17:03         ` Andreas Niederl
  2011-02-22 16:47           ` Stefan Berger
  0 siblings, 1 reply; 17+ messages in thread
From: Andreas Niederl @ 2011-02-21 17:03 UTC (permalink / raw)
  To: Stefan Berger; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1529 bytes --]

On 02/18/2011 09:27 PM, Stefan Berger wrote:
> On 02/18/2011 12:37 PM, Andreas Niederl wrote:
[...]
>> So I'm guessing that this library is not publicly available right now?
> Not via the fedora repository at least. So yum install does not work, yet.

Is the source code available in a public version control repository?
If so, could you please provide a URI to it?


>> Is this backend meant for integration into QEMU or does it run as
>> separate process?
>>
> The backend is meant for integration in Qemu. It runs as a thread.

I see.
Has there already been an effort to integrate this with the main project?


>> How/Where could I integrate a passthrough backend like the one in this
>> patch series?
>>
> It's possible via similar mechanisms as you have, just the interface is
> bigger and main code calls into the interface at different times. I'd
> need to share the code with you.

I'd like to have a look at it.


>> The polling code isn't really necessary for the host backend, I left it
>> there just in case it would be needed by such a socket interface as is
>> used in the Xen fork.
>>
> I don't think it's necessary to have it all. In the new code, the 
> frontend delivers a request to the backend and provides a callback
> function for delivering the response back once received.

Sounds good.


>>> It would certainly be desirable if your backend and mine could be
>>> accommodate.
>> Of course.
>>
> Let's see how we do this.

That would be great.


Andreas


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 6163 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 21:03   ` Stefan Berger
@ 2011-02-21 17:13     ` Andreas Niederl
  0 siblings, 0 replies; 17+ messages in thread
From: Andreas Niederl @ 2011-02-21 17:13 UTC (permalink / raw)
  To: Stefan Berger; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 893 bytes --]

On 02/18/2011 10:03 PM, Stefan Berger wrote:
> On 02/18/2011 10:33 AM, Andreas Niederl wrote:
[...]
>> +static ISADeviceInfo tpm_info = {
>> +    .init          = tpm_init,
>> +    .qdev.name     = "tpm",
>> +    .qdev.desc     = "TPM TIS Interface",
>> +    .qdev.size     = sizeof (TPMState),
>> +    .qdev.vmsd     =&vmstate_tpm,
> ... and here you're pointing to vmstate_tpm, which was also registered
> above using
> 
> +
> +    vmstate_register(&dev->qdev, 1,&vmstate_tpm, s);
> 
> 
> Are you sure this is necessary? In my implementation I only have the
> qdev.vmsd set and need not explicitly use vmstate_register(). Aren't you
> writing the state two times if you do that?

You're right, apparently I've missed that vmstate_save_state operates
recursively on fields of type VMS_STRUCT.

Also, manual registration of vmstate_tpm is not necessary.


Andreas


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 6163 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-21 17:03         ` Andreas Niederl
@ 2011-02-22 16:47           ` Stefan Berger
  0 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2011-02-22 16:47 UTC (permalink / raw)
  To: qemu-devel, Andreas Niederl

On 02/21/2011 12:03 PM, Andreas Niederl wrote:
> On 02/18/2011 09:27 PM, Stefan Berger wrote:
>> On 02/18/2011 12:37 PM, Andreas Niederl wrote:
> [...]
>>> So I'm guessing that this library is not publicly available right now?
>> Not via the fedora repository at least. So yum install does not work, yet.
> Is the source code available in a public version control repository?
> If so, could you please provide a URI to it?
Here's the link to the review request including links to spec and source 
rpm:

https://bugzilla.redhat.com/show_bug.cgi?id=668052

>
>>> Is this backend meant for integration into QEMU or does it run as
>>> separate process?
>>>
>> The backend is meant for integration in Qemu. It runs as a thread.
> I see.
> Has there already been an effort to integrate this with the main project?
>
>
No. Since the library is not available yet I haven't posted the code for 
the TIS and backend, yet.
>>> How/Where could I integrate a passthrough backend like the one in this
>>> patch series?
>>>
>> It's possible via similar mechanisms as you have, just the interface is
>> bigger and main code calls into the interface at different times. I'd
>> need to share the code with you.
> I'd like to have a look at it.
>
Ok. I'll either share it here or via the mailing list. It may be later 
this week, though.

    Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-18 16:37   ` Stefan Berger
  2011-02-18 17:37     ` Andreas Niederl
@ 2011-02-24 15:30     ` Andreas Niederl
  2011-02-24 17:44       ` Stefan Berger
  1 sibling, 1 reply; 17+ messages in thread
From: Andreas Niederl @ 2011-02-24 15:30 UTC (permalink / raw)
  To: Stefan Berger; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1260 bytes --]

On 02/18/2011 05:37 PM, Stefan Berger wrote:
[...]
> I have a tpm_tis.c with major changes in it getting rid of the polling,
> closer to specs that passes a test suite and a registerable backend as
> well that has several more interface functions, due to support for
> snapshotting etc. Unfortunately it doesn't make much sense for me to
> post it since the backend is based on a library that's currently in the
> Fedora review process and nobody else could build or test it  -- unless
> there really was interest in reviewing at least some part of it.
> 
> It would certainly be desirable if your backend and mine could be
> accommodate.

I am looking for a rather soon integration of this functionality (at
least with my host passthrough backend) into the main project.

We could try to integrate your improved device emulation frontend along
with the infrastructure for using different backends while your library
is still being reviewed.
I would post my (rather simple) direct host passthrough backend along
with it, so testing can be done.

That way, we would have the better part of the TPM emulation framework
available in Qemu and you could post your library-based backend as soon
as it has finished its review.


Andreas


[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 6163 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface
  2011-02-24 15:30     ` Andreas Niederl
@ 2011-02-24 17:44       ` Stefan Berger
  0 siblings, 0 replies; 17+ messages in thread
From: Stefan Berger @ 2011-02-24 17:44 UTC (permalink / raw)
  To: Andreas Niederl; +Cc: qemu-devel

On 02/24/2011 10:30 AM, Andreas Niederl wrote:
> On 02/18/2011 05:37 PM, Stefan Berger wrote:
> [...]
>> I have a tpm_tis.c with major changes in it getting rid of the polling,
>> closer to specs that passes a test suite and a registerable backend as
>> well that has several more interface functions, due to support for
>> snapshotting etc. Unfortunately it doesn't make much sense for me to
>> post it since the backend is based on a library that's currently in the
>> Fedora review process and nobody else could build or test it  -- unless
>> there really was interest in reviewing at least some part of it.
>>
>> It would certainly be desirable if your backend and mine could be
>> accommodate.
> I am looking for a rather soon integration of this functionality (at
> least with my host passthrough backend) into the main project.
>
> We could try to integrate your improved device emulation frontend along
> with the infrastructure for using different backends while your library
> is still being reviewed.
> I would post my (rather simple) direct host passthrough backend along
> with it, so testing can be done.
>
> That way, we would have the better part of the TPM emulation framework
> available in Qemu and you could post your library-based backend as soon
> as it has finished its review.
I will post my patches soon.

    Stefan

>
> Andreas
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2011-02-24 19:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-02-18 15:33 [Qemu-devel] [PATCH 0/5] TPM device emulation Andreas Niederl
2011-02-18 15:33 ` [Qemu-devel] [PATCH 1/5] Add TPM 1.2 device interface Andreas Niederl
2011-02-18 16:37   ` Stefan Berger
2011-02-18 17:37     ` Andreas Niederl
2011-02-18 20:27       ` Stefan Berger
2011-02-21 17:03         ` Andreas Niederl
2011-02-22 16:47           ` Stefan Berger
2011-02-24 15:30     ` Andreas Niederl
2011-02-24 17:44       ` Stefan Berger
2011-02-18 21:03   ` Stefan Berger
2011-02-21 17:13     ` Andreas Niederl
2011-02-18 15:33 ` [Qemu-devel] [PATCH 2/5] Provide SSDT for enabled TPM device Andreas Niederl
2011-02-18 17:02   ` Stefan Berger
2011-02-21 16:55     ` Andreas Niederl
2011-02-18 15:33 ` [Qemu-devel] [PATCH 3/5] Add TPM host passthrough device backend Andreas Niederl
2011-02-18 15:33 ` [Qemu-devel] [PATCH 4/5] Add configure script and command line options for TPM interface Andreas Niederl
2011-02-18 15:33 ` [Qemu-devel] [PATCH 5/5] Adapt TPM host backend to use threadlets Andreas Niederl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).