All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups
@ 2018-01-19 14:10 Marc-André Lureau
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class Marc-André Lureau
                   ` (5 more replies)
  0 siblings, 6 replies; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-19 14:10 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanb, Marc-André Lureau

Hi,

This series cleans up a bit the TPM IO thread handling, allows to
report backend error to hw/frontend, and implements the CRB device. I
adapted a previously sent patch "tpm: extend TPM CRB with state
migration support" from Stefan, and included an old pending patch
"lookup cancel path" in the series to empty my TPM queue.

Comments welcome

Marc-André Lureau (4):
  tpm: lookup cancel path under tpm device class
  tpm: replace GThreadPool with AIO threadpool
  tpm: report backend request error
  tpm: add CRB device

Stefan Berger (1):
  tpm: extend TPM CRB with state migration support

 qapi/tpm.json                      |   5 +-
 include/hw/acpi/tpm.h              |  72 ++++++++
 include/sysemu/tpm.h               |   5 +-
 include/sysemu/tpm_backend.h       |  15 +-
 backends/tpm.c                     |  59 +++---
 hw/i386/acpi-build.c               |  34 +++-
 hw/tpm/tpm_crb.c                   | 357 +++++++++++++++++++++++++++++++++++++
 hw/tpm/tpm_emulator.c              |  21 +--
 hw/tpm/tpm_passthrough.c           |  65 ++++---
 hw/tpm/tpm_tis.c                   |   3 +-
 default-configs/i386-softmmu.mak   |   1 +
 default-configs/x86_64-softmmu.mak |   1 +
 hw/tpm/Makefile.objs               |   1 +
 13 files changed, 555 insertions(+), 84 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.c

-- 
2.16.0.rc1.1.gef27df75a1

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

* [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class
  2018-01-19 14:10 [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups Marc-André Lureau
@ 2018-01-19 14:11 ` Marc-André Lureau
  2018-01-19 14:32   ` Stefan Berger
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool Marc-André Lureau
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-19 14:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanb, Marc-André Lureau

Since Linux commit 313d21eeab9282e, tpm devices have their own device
class "tpm" and the cancel path must be looked up under
/sys/class/tpm/ instead of /sys/class/misc/.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/tpm/tpm_passthrough.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index 29142f38bb..f2563ac668 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -216,7 +216,8 @@ static size_t tpm_passthrough_get_buffer_size(TPMBackend *tb)
  * Unless path or file descriptor set has been provided by user,
  * determine the sysfs cancel file following kernel documentation
  * in Documentation/ABI/stable/sysfs-class-tpm.
- * From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel
+ * From /dev/tpm0 create /sys/class/tpm/tpm0/device/cancel
+ * before 4.0: /sys/class/misc/tpm0/device/cancel
  */
 static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
 {
@@ -227,26 +228,35 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
     if (tpm_pt->options->cancel_path) {
         fd = qemu_open(tpm_pt->options->cancel_path, O_WRONLY);
         if (fd < 0) {
-            error_report("Could not open TPM cancel path : %s",
+            error_report("tpm_passthrough: Could not open TPM cancel path: %s",
                          strerror(errno));
         }
         return fd;
     }
 
     dev = strrchr(tpm_pt->tpm_dev, '/');
-    if (dev) {
-        dev++;
-        if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel",
-                     dev) < sizeof(path)) {
-            fd = qemu_open(path, O_WRONLY);
-            if (fd < 0) {
-                error_report("tpm_passthrough: Could not open TPM cancel "
-                             "path %s : %s", path, strerror(errno));
+    if (!dev) {
+        error_report("tpm_passthrough: Bad TPM device path %s",
+                     tpm_pt->tpm_dev);
+        return -1;
+    }
+
+    dev++;
+    if (snprintf(path, sizeof(path), "/sys/class/tpm/%s/device/cancel",
+                 dev) < sizeof(path)) {
+        fd = qemu_open(path, O_WRONLY);
+        if (fd < 0) {
+            if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel",
+                         dev) < sizeof(path)) {
+                fd = qemu_open(path, O_WRONLY);
             }
         }
+    }
+
+    if (fd < 0) {
+        error_report("tpm_passthrough: Could not guess TPM cancel path");
     } else {
-       error_report("tpm_passthrough: Bad TPM device path %s",
-                    tpm_pt->tpm_dev);
+        tpm_pt->options->cancel_path = g_strdup(path);
     }
 
     return fd;
-- 
2.16.0.rc1.1.gef27df75a1

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

* [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool
  2018-01-19 14:10 [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups Marc-André Lureau
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class Marc-André Lureau
@ 2018-01-19 14:11 ` Marc-André Lureau
  2018-01-23 18:39   ` Stefan Berger
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 3/5] tpm: report backend request error Marc-André Lureau
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-19 14:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanb, Marc-André Lureau

The TPM backend uses a GThreadPool to handle IO in a seperate
thread. However, GThreadPool isn't integrated with Qemu main loops,
making it unnecessarily complicated to deal with.

Qemu has a AIO threadpool, that is better integrated with loops and
various IO functions, provides completion BH by default etc.

Remove the only user of GThreadPool from qemu, use AIO threadpool.

Note that the backend:
- no longer accepts queing multiple requests (unneeded so far)
- increase ref to itself when handling a command, for extra safety
- tpm_backend_thread_end() is renamed tpm_backend_finish_sync() and
will wait for completion of BH (request_completed), which will help
migration handling.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/sysemu/tpm_backend.h | 12 ++++++++--
 backends/tpm.c               | 52 +++++++++++++++++++++++---------------------
 2 files changed, 37 insertions(+), 27 deletions(-)

diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index 0d6c994a62..a69593e0cd 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -45,9 +45,8 @@ struct TPMBackend {
     /*< protected >*/
     TPMIf *tpmif;
     bool opened;
-    GThreadPool *thread_pool;
     bool had_startup_error;
-    QEMUBH *bh;
+    TPMBackendCmd *cmd;
 
     /* <public> */
     char *id;
@@ -196,6 +195,15 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
  */
 size_t tpm_backend_get_buffer_size(TPMBackend *s);
 
+/**
+ * tpm_backend_finish_sync:
+ * @s: the backend to call into
+ *
+ * Finish the pending command synchronously (this will call aio_poll()
+ * on qemu main AIOContext until it ends)
+ */
+void tpm_backend_finish_sync(TPMBackend *s);
+
 /**
  * tpm_backend_query_tpm:
  * @s: the backend
diff --git a/backends/tpm.c b/backends/tpm.c
index 91222c5164..143807aa37 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -19,30 +19,35 @@
 #include "sysemu/tpm.h"
 #include "qemu/thread.h"
 #include "qemu/main-loop.h"
+#include "block/thread-pool.h"
+#include "qemu/error-report.h"
 
-static void tpm_backend_request_completed_bh(void *opaque)
+static void tpm_backend_request_completed(void *opaque, int ret)
 {
     TPMBackend *s = TPM_BACKEND(opaque);
     TPMIfClass *tic = TPM_IF_GET_CLASS(s->tpmif);
 
     tic->request_completed(s->tpmif);
+
+    /* no need for atomic, as long the BQL is taken */
+    s->cmd = NULL;
+    object_unref(OBJECT(s));
 }
 
-static void tpm_backend_worker_thread(gpointer data, gpointer user_data)
+static int tpm_backend_worker_thread(gpointer data)
 {
-    TPMBackend *s = TPM_BACKEND(user_data);
+    TPMBackend *s = TPM_BACKEND(data);
     TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
 
-    k->handle_request(s, (TPMBackendCmd *)data);
+    k->handle_request(s, s->cmd);
 
-    qemu_bh_schedule(s->bh);
+    return 0;
 }
 
-static void tpm_backend_thread_end(TPMBackend *s)
+void tpm_backend_finish_sync(TPMBackend *s)
 {
-    if (s->thread_pool) {
-        g_thread_pool_free(s->thread_pool, FALSE, TRUE);
-        s->thread_pool = NULL;
+    while (s->cmd) {
+        aio_poll(qemu_get_aio_context(), true);
     }
 }
 
@@ -74,10 +79,7 @@ int tpm_backend_startup_tpm(TPMBackend *s, size_t buffersize)
     TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
 
     /* terminate a running TPM */
-    tpm_backend_thread_end(s);
-
-    s->thread_pool = g_thread_pool_new(tpm_backend_worker_thread, s, 1, TRUE,
-                                       NULL);
+    tpm_backend_finish_sync(s);
 
     res = k->startup_tpm ? k->startup_tpm(s, buffersize) : 0;
 
@@ -93,7 +95,17 @@ bool tpm_backend_had_startup_error(TPMBackend *s)
 
 void tpm_backend_deliver_request(TPMBackend *s, TPMBackendCmd *cmd)
 {
-    g_thread_pool_push(s->thread_pool, cmd, NULL);
+    ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
+
+    if (s->cmd != NULL) {
+        error_report("There is a TPM request pending");
+        return;
+    }
+
+    s->cmd = cmd;
+    object_ref(OBJECT(s));
+    thread_pool_submit_aio(pool, tpm_backend_worker_thread, s,
+                           tpm_backend_request_completed, s);
 }
 
 void tpm_backend_reset(TPMBackend *s)
@@ -104,7 +116,7 @@ void tpm_backend_reset(TPMBackend *s)
         k->reset(s);
     }
 
-    tpm_backend_thread_end(s);
+    tpm_backend_finish_sync(s);
 
     s->had_startup_error = false;
 }
@@ -159,28 +171,18 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s)
     return info;
 }
 
-static void tpm_backend_instance_init(Object *obj)
-{
-    TPMBackend *s = TPM_BACKEND(obj);
-
-    s->bh = qemu_bh_new(tpm_backend_request_completed_bh, s);
-}
-
 static void tpm_backend_instance_finalize(Object *obj)
 {
     TPMBackend *s = TPM_BACKEND(obj);
 
     object_unref(OBJECT(s->tpmif));
     g_free(s->id);
-    tpm_backend_thread_end(s);
-    qemu_bh_delete(s->bh);
 }
 
 static const TypeInfo tpm_backend_info = {
     .name = TYPE_TPM_BACKEND,
     .parent = TYPE_OBJECT,
     .instance_size = sizeof(TPMBackend),
-    .instance_init = tpm_backend_instance_init,
     .instance_finalize = tpm_backend_instance_finalize,
     .class_size = sizeof(TPMBackendClass),
     .abstract = true,
-- 
2.16.0.rc1.1.gef27df75a1

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

* [Qemu-devel] [PATCH v2 3/5] tpm: report backend request error
  2018-01-19 14:10 [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups Marc-André Lureau
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class Marc-André Lureau
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool Marc-André Lureau
@ 2018-01-19 14:11 ` Marc-André Lureau
  2018-01-19 14:57   ` Stefan Berger
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device Marc-André Lureau
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-19 14:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanb, Marc-André Lureau

Use an Error** for request to let the caller handle error reporting.

This will also allow to inform the frontend of a backend error.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 include/sysemu/tpm.h         |  2 +-
 include/sysemu/tpm_backend.h |  3 ++-
 backends/tpm.c               |  9 +++++++--
 hw/tpm/tpm_emulator.c        | 21 ++++++---------------
 hw/tpm/tpm_passthrough.c     | 31 +++++++++++++++----------------
 hw/tpm/tpm_tis.c             |  3 ++-
 6 files changed, 33 insertions(+), 36 deletions(-)

diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 852e02687c..ac04a9d4a2 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -41,7 +41,7 @@ typedef struct TPMIfClass {
     InterfaceClass parent_class;
 
     enum TpmModel model;
-    void (*request_completed)(TPMIf *obj);
+    void (*request_completed)(TPMIf *obj, int ret);
     enum TPMVersion (*get_version)(TPMIf *obj);
 } TPMIfClass;
 
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index a69593e0cd..7e166ef954 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -18,6 +18,7 @@
 #include "qapi-types.h"
 #include "qemu/option.h"
 #include "sysemu/tpm.h"
+#include "qapi/error.h"
 
 #define TYPE_TPM_BACKEND "tpm-backend"
 #define TPM_BACKEND(obj) \
@@ -84,7 +85,7 @@ struct TPMBackendClass {
 
     TpmTypeOptions *(*get_tpm_options)(TPMBackend *t);
 
-    void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd);
+    void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd, Error **errp);
 };
 
 /**
diff --git a/backends/tpm.c b/backends/tpm.c
index 143807aa37..d617ba7c52 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -27,7 +27,7 @@ static void tpm_backend_request_completed(void *opaque, int ret)
     TPMBackend *s = TPM_BACKEND(opaque);
     TPMIfClass *tic = TPM_IF_GET_CLASS(s->tpmif);
 
-    tic->request_completed(s->tpmif);
+    tic->request_completed(s->tpmif, ret);
 
     /* no need for atomic, as long the BQL is taken */
     s->cmd = NULL;
@@ -38,8 +38,13 @@ static int tpm_backend_worker_thread(gpointer data)
 {
     TPMBackend *s = TPM_BACKEND(data);
     TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+    Error *err = NULL;
 
-    k->handle_request(s, s->cmd);
+    k->handle_request(s, s->cmd, &err);
+    if (err) {
+        error_report_err(err);
+        return -1;
+    }
 
     return 0;
 }
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
index 35c78de5a9..52552af9f9 100644
--- a/hw/tpm/tpm_emulator.c
+++ b/hw/tpm/tpm_emulator.c
@@ -185,28 +185,19 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
     return 0;
 }
 
-static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd)
+static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
+                                        Error **errp)
 {
     TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
-    Error *err = NULL;
 
     DPRINTF("processing TPM command");
 
-    if (tpm_emulator_set_locality(tpm_emu, cmd->locty, &err) < 0) {
-        goto error;
-    }
-
-    if (tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
+    if (tpm_emulator_set_locality(tpm_emu, cmd->locty, errp) < 0 ||
+        tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
                                   cmd->out, cmd->out_len,
-                                  &cmd->selftest_done, &err) < 0) {
-        goto error;
+                                  &cmd->selftest_done, errp) < 0) {
+        tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
     }
-
-    return;
-
-error:
-    tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
-    error_report_err(err);
 }
 
 static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index f2563ac668..37dce15801 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -80,10 +80,11 @@ static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
     }
     return ret;
 }
-static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
-                                        const uint8_t *in, uint32_t in_len,
-                                        uint8_t *out, uint32_t out_len,
-                                        bool *selftest_done)
+
+static void tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
+                                         const uint8_t *in, uint32_t in_len,
+                                         uint8_t *out, uint32_t out_len,
+                                         bool *selftest_done, Error **errp)
 {
     ssize_t ret;
     bool is_selftest;
@@ -99,9 +100,8 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
     ret = qemu_write_full(tpm_pt->tpm_fd, in, in_len);
     if (ret != in_len) {
         if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
-            error_report("tpm_passthrough: error while transmitting data "
-                         "to TPM: %s (%i)",
-                         strerror(errno), errno);
+            error_setg_errno(errp, errno, "tpm_passthrough: error while "
+                             "transmitting data to TPM");
         }
         goto err_exit;
     }
@@ -111,15 +111,14 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
     ret = tpm_passthrough_unix_read(tpm_pt->tpm_fd, out, out_len);
     if (ret < 0) {
         if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
-            error_report("tpm_passthrough: error while reading data from "
-                         "TPM: %s (%i)",
-                         strerror(errno), errno);
+            error_setg_errno(errp, errno, "tpm_passthrough: error while "
+                             "reading data from TPM");
         }
     } else if (ret < sizeof(struct tpm_resp_hdr) ||
                be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
         ret = -1;
-        error_report("tpm_passthrough: received invalid response "
-                     "packet from TPM");
+        error_setg_errno(errp, errno, "tpm_passthrough: received invalid "
+                     "response packet from TPM");
     }
 
     if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) {
@@ -133,18 +132,18 @@ err_exit:
     }
 
     tpm_pt->tpm_executing = false;
-
-    return ret;
 }
 
-static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *cmd)
+static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
+                                           Error **errp)
 {
     TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
 
     DPRINTF("tpm_passthrough: processing command %p\n", cmd);
 
     tpm_passthrough_unix_tx_bufs(tpm_pt, cmd->in, cmd->in_len,
-                                 cmd->out, cmd->out_len, &cmd->selftest_done);
+                                 cmd->out, cmd->out_len, &cmd->selftest_done,
+                                 errp);
 }
 
 static void tpm_passthrough_reset(TPMBackend *tb)
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index 8b5eb01a2c..08f41d2707 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -393,7 +393,7 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
 /*
  * Callback from the TPM to indicate that the response was received.
  */
-static void tpm_tis_request_completed(TPMIf *ti)
+static void tpm_tis_request_completed(TPMIf *ti, int ret)
 {
     TPMState *s = TPM(ti);
     uint8_t locty = s->cmd.locty;
@@ -405,6 +405,7 @@ static void tpm_tis_request_completed(TPMIf *ti)
         }
     }
 
+    /* FIXME: report error if ret != 0 */
     tpm_tis_sts_set(&s->loc[locty],
                     TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
     s->loc[locty].state = TPM_TIS_STATE_COMPLETION;
-- 
2.16.0.rc1.1.gef27df75a1

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

* [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-19 14:10 [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups Marc-André Lureau
                   ` (2 preceding siblings ...)
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 3/5] tpm: report backend request error Marc-André Lureau
@ 2018-01-19 14:11 ` Marc-André Lureau
  2018-01-19 17:10   ` Stefan Berger
  2018-01-20 12:54   ` Philippe Mathieu-Daudé
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support Marc-André Lureau
  2018-01-19 14:36 ` [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups no-reply
  5 siblings, 2 replies; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-19 14:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: stefanb, Marc-André Lureau, Michael S. Tsirkin,
	Igor Mammedov, Paolo Bonzini, Richard Henderson, Eduardo Habkost,
	Marcel Apfelbaum, Eric Blake, Markus Armbruster

tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
Interface as defined in TCG PC Client Platform TPM Profile (PTP)
Specification Family “2.0” Level 00 Revision 01.03 v22.

The PTP allows device implementation to switch between TIS and CRB
model at run time, but given that CRB is a simpler device to
implement, I chose to implement it as a different device.

The device doesn't implement other locality than 0 for now (my laptop
TPM doesn't either, so I assume this isn't so bad)

The command/reply memory region is statically allocated after the CRB
registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
wonder if the BIOS could or should allocate it instead, or what size
to use, again this seems to fit well expectations)

The PTP doesn't specify a particular bus to put the device. So I added
it on the system bus directly, so it could hopefully be used easily on
a different platform than x86. Currently, it fails to init on piix,
because error_on_sysbus_device() check. The check may be changed in a
near future, see discussion on the qemu-devel ML.

Tested with some success with Linux upstream and Windows 10, seabios &
modified ovmf. The device is recognized and correctly transmit
command/response with passthrough & emu. However, we are missing PPI
ACPI part atm.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
 qapi/tpm.json                      |   5 +-
 include/hw/acpi/tpm.h              |  72 ++++++++
 include/sysemu/tpm.h               |   3 +
 hw/i386/acpi-build.c               |  34 +++-
 hw/tpm/tpm_crb.c                   | 327 +++++++++++++++++++++++++++++++++++++
 default-configs/i386-softmmu.mak   |   1 +
 default-configs/x86_64-softmmu.mak |   1 +
 hw/tpm/Makefile.objs               |   1 +
 8 files changed, 434 insertions(+), 10 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.c

diff --git a/qapi/tpm.json b/qapi/tpm.json
index 7093f268fb..d50deef5e9 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -11,10 +11,11 @@
 # An enumeration of TPM models
 #
 # @tpm-tis: TPM TIS model
+# @tpm-crb: TPM CRB model (since 2.12)
 #
 # Since: 1.5
 ##
-{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
+{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
 
 ##
 # @query-tpm-models:
@@ -28,7 +29,7 @@
 # Example:
 #
 # -> { "execute": "query-tpm-models" }
-# <- { "return": [ "tpm-tis" ] }
+# <- { "return": [ "tpm-tis", "tpm-crb" ] }
 #
 ##
 { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 6d516c6a7f..b0048515fa 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -16,11 +16,82 @@
 #ifndef HW_ACPI_TPM_H
 #define HW_ACPI_TPM_H
 
+#include "qemu/osdep.h"
+
 #define TPM_TIS_ADDR_BASE           0xFED40000
 #define TPM_TIS_ADDR_SIZE           0x5000
 
 #define TPM_TIS_IRQ                 5
 
+struct crb_regs {
+    union {
+        uint32_t reg;
+        struct {
+            unsigned tpm_established:1;
+            unsigned loc_assigned:1;
+            unsigned active_locality:3;
+            unsigned reserved:2;
+            unsigned tpm_reg_valid_sts:1;
+        } bits;
+    } loc_state;
+    uint32_t reserved1;
+    uint32_t loc_ctrl;
+    union {
+        uint32_t reg;
+        struct {
+            unsigned granted:1;
+            unsigned been_seized:1;
+        } bits;
+    } loc_sts;
+    uint8_t reserved2[32];
+    union {
+        uint64_t reg;
+        struct {
+            unsigned type:4;
+            unsigned version:4;
+            unsigned cap_locality:1;
+            unsigned cap_crb_idle_bypass:1;
+            unsigned reserved1:1;
+            unsigned cap_data_xfer_size_support:2;
+            unsigned cap_fifo:1;
+            unsigned cap_crb:1;
+            unsigned cap_if_res:2;
+            unsigned if_selector:2;
+            unsigned if_selector_lock:1;
+            unsigned reserved2:4;
+            unsigned rid:8;
+            unsigned vid:16;
+            unsigned did:16;
+        } bits;
+    } intf_id;
+    uint64_t ctrl_ext;
+
+    uint32_t ctrl_req;
+    union {
+        uint32_t reg;
+        struct {
+            unsigned tpm_sts:1;
+            unsigned tpm_idle:1;
+            unsigned reserved:30;
+        } bits;
+    } ctrl_sts;
+    uint32_t ctrl_cancel;
+    uint32_t ctrl_start;
+    uint32_t ctrl_int_enable;
+    uint32_t ctrl_int_sts;
+    uint32_t ctrl_cmd_size;
+    uint32_t ctrl_cmd_pa_low;
+    uint32_t ctrl_cmd_pa_high;
+    uint32_t ctrl_rsp_size;
+    uint64_t ctrl_rsp_pa;
+    uint8_t reserved3[0x10];
+} QEMU_PACKED;
+
+#define TPM_CRB_ADDR_BASE           0xFED40000
+#define TPM_CRB_ADDR_SIZE           0x1000
+#define TPM_CRB_ADDR_CTRL \
+    (TPM_CRB_ADDR_BASE + offsetof(struct crb_regs, ctrl_req))
+
 #define TPM_LOG_AREA_MINIMUM_SIZE   (64 * 1024)
 
 #define TPM_TCPA_ACPI_CLASS_CLIENT  0
@@ -30,5 +101,6 @@
 #define TPM2_ACPI_CLASS_SERVER      1
 
 #define TPM2_START_METHOD_MMIO      6
+#define TPM2_START_METHOD_CRB       7
 
 #endif /* HW_ACPI_TPM_H */
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index ac04a9d4a2..233b1a3fc3 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -46,9 +46,12 @@ typedef struct TPMIfClass {
 } TPMIfClass;
 
 #define TYPE_TPM_TIS                "tpm-tis"
+#define TYPE_TPM_CRB                "tpm-crb"
 
 #define TPM_IS_TIS(chr)                             \
     object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
+#define TPM_IS_CRB(chr)                             \
+    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
 
 /* returns NULL unless there is exactly one TPM device */
 static inline TPMIf *tpm_find(void)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index dc4b2b9ffe..ed78c4ed9f 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2224,6 +2224,22 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
             aml_append(sb_scope, scope);
         }
     }
+
+    if (TPM_IS_CRB(tpm_find())) {
+        dev = aml_device("TPM");
+        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+        crs = aml_resource_template();
+        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
+                                           TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
+        aml_append(dev, aml_name_decl("_CRS", crs));
+
+        method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+        aml_append(method, aml_return(aml_int(0x0f)));
+        aml_append(dev, method);
+
+        aml_append(sb_scope, dev);
+    }
+
     aml_append(dsdt, sb_scope);
 
     /* copy AML table into ACPI tables blob and patch header there */
@@ -2285,18 +2301,20 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
     if (TPM_IS_TIS(tpm_find())) {
         tpm2_ptr->control_area_address = cpu_to_le64(0);
         tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
-
-        tpm2_ptr->log_area_minimum_length =
-            cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
-
-        /* log area start address to be filled by Guest linker */
-        bios_linker_loader_add_pointer(linker,
-            ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
-            ACPI_BUILD_TPMLOG_FILE, 0);
+    } else if (TPM_IS_CRB(tpm_find())) {
+        tpm2_ptr->control_area_address = cpu_to_le64(TPM_CRB_ADDR_CTRL);
+        tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_CRB);
     } else {
         g_warn_if_reached();
     }
 
+    tpm2_ptr->log_area_minimum_length =
+        cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
+
+    /* log area start address to be filled by Guest linker */
+    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
+                                   log_addr_offset, log_addr_size,
+                                   ACPI_BUILD_TPMLOG_FILE, 0);
     build_header(linker, table_data,
                  (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL);
 }
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
new file mode 100644
index 0000000000..908ca18d92
--- /dev/null
+++ b/hw/tpm/tpm_crb.c
@@ -0,0 +1,327 @@
+/*
+ * tpm_crb.c - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2017 Red Hat, Inc.
+ *
+ * Authors:
+ *   Marc-André Lureau <marcandre.lureau@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+
+#include "qemu/osdep.h"
+
+#include "qemu-common.h"
+#include "qapi/error.h"
+#include "hw/sysbus.h"
+#include "exec/address-spaces.h"
+
+#include "hw/pci/pci_ids.h"
+#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_int.h"
+#include "tpm_util.h"
+
+typedef struct CRBState {
+    SysBusDevice parent_obj;
+
+    TPMBackend *tpmbe;
+    TPMBackendCmd cmd;
+    struct crb_regs regs;
+    MemoryRegion mmio;
+    MemoryRegion cmdmem;
+
+    size_t be_buffer_size;
+} CRBState;
+
+#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB)
+
+#define DEBUG_CRB 0
+
+#define DPRINTF(fmt, ...) do {                  \
+        if (DEBUG_CRB) {                        \
+            printf(fmt, ## __VA_ARGS__);        \
+        }                                       \
+    } while (0)
+
+#define CRB_ADDR_LOC_STATE offsetof(struct crb_regs, loc_state)
+#define CRB_ADDR_LOC_CTRL offsetof(struct crb_regs, loc_ctrl)
+#define CRB_ADDR_CTRL_REQ offsetof(struct crb_regs, ctrl_req)
+#define CRB_ADDR_CTRL_CANCEL offsetof(struct crb_regs, ctrl_cancel)
+#define CRB_ADDR_CTRL_START offsetof(struct crb_regs, ctrl_start)
+
+#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
+#define CRB_INTF_VERSION_CRB 0b1
+#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
+#define CRB_INTF_CAP_IDLE_FAST 0b0
+#define CRB_INTF_CAP_XFER_SIZE_64 0b11
+#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
+#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
+#define CRB_INTF_IF_SELECTOR_CRB 0b1
+#define CRB_INTF_IF_SELECTOR_UNLOCKED 0b0
+
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs))
+
+enum crb_loc_ctrl {
+    CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+    CRB_LOC_CTRL_RELINQUISH = BIT(1),
+    CRB_LOC_CTRL_SEIZE = BIT(2),
+    CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
+};
+
+enum crb_ctrl_req {
+    CRB_CTRL_REQ_CMD_READY = BIT(0),
+    CRB_CTRL_REQ_GO_IDLE = BIT(1),
+};
+
+enum crb_start {
+    CRB_START_INVOKE = BIT(0),
+};
+
+enum crb_cancel {
+    CRB_CANCEL_INVOKE = BIT(0),
+};
+
+static const char *addr_desc(unsigned off)
+{
+    struct crb_regs crb;
+
+    switch (off) {
+#define CASE(field)                                                 \
+    case offsetof(struct crb_regs, field) ...                       \
+        offsetof(struct crb_regs, field) + sizeof(crb.field) - 1:   \
+        return G_STRINGIFY(field);
+        CASE(loc_state);
+        CASE(reserved1);
+        CASE(loc_ctrl);
+        CASE(loc_sts);
+        CASE(reserved2);
+        CASE(intf_id);
+        CASE(ctrl_ext);
+        CASE(ctrl_req);
+        CASE(ctrl_sts);
+        CASE(ctrl_cancel);
+        CASE(ctrl_start);
+        CASE(ctrl_int_enable);
+        CASE(ctrl_int_sts);
+        CASE(ctrl_cmd_size);
+        CASE(ctrl_cmd_pa_low);
+        CASE(ctrl_cmd_pa_high);
+        CASE(ctrl_rsp_size);
+        CASE(ctrl_rsp_pa);
+#undef CASE
+    }
+    return NULL;
+}
+
+static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
+                                  unsigned size)
+{
+    CRBState *s = CRB(opaque);
+    DPRINTF("CRB read 0x%lx:%s len:%u\n",
+            addr, addr_desc(addr), size);
+    void *regs = (void *)&s->regs + addr;
+
+    switch (size) {
+    case 1:
+        return *(uint8_t *)regs;
+    case 2:
+        return *(uint16_t *)regs;
+    case 4:
+        return *(uint32_t *)regs;
+    default:
+        g_return_val_if_reached(-1);
+    }
+}
+
+static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
+                               uint64_t val, unsigned size)
+{
+    CRBState *s = CRB(opaque);
+    DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
+            addr, addr_desc(addr), size, val);
+
+    switch (addr) {
+    case CRB_ADDR_CTRL_REQ:
+        switch (val) {
+        case CRB_CTRL_REQ_CMD_READY:
+            s->regs.ctrl_sts.bits.tpm_idle = 0;
+            break;
+        case CRB_CTRL_REQ_GO_IDLE:
+            s->regs.ctrl_sts.bits.tpm_idle = 1;
+            break;
+        }
+        break;
+    case CRB_ADDR_CTRL_CANCEL:
+        if (val == CRB_CANCEL_INVOKE && s->regs.ctrl_start & CRB_START_INVOKE) {
+            tpm_backend_cancel_cmd(s->tpmbe);
+        }
+        break;
+    case CRB_ADDR_CTRL_START:
+        if (val == CRB_START_INVOKE &&
+            !(s->regs.ctrl_start & CRB_START_INVOKE)) {
+            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
+
+            s->regs.ctrl_start |= CRB_START_INVOKE;
+            s->cmd = (TPMBackendCmd) {
+                .in = mem,
+                .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
+                .out = mem,
+                .out_len = s->be_buffer_size,
+            };
+
+            tpm_backend_deliver_request(s->tpmbe, &s->cmd);
+        }
+        break;
+    case CRB_ADDR_LOC_CTRL:
+        switch (val) {
+        case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
+            /* not loc 3 or 4 */
+            break;
+        case CRB_LOC_CTRL_RELINQUISH:
+            break;
+        case CRB_LOC_CTRL_REQUEST_ACCESS:
+            s->regs.loc_sts.bits.granted = 1;
+            s->regs.loc_sts.bits.been_seized = 0;
+            s->regs.loc_state.bits.loc_assigned = 1;
+            s->regs.loc_state.bits.tpm_reg_valid_sts = 1;
+            break;
+        }
+        break;
+    }
+}
+
+static const MemoryRegionOps tpm_crb_memory_ops = {
+    .read = tpm_crb_mmio_read,
+    .write = tpm_crb_mmio_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 4,
+    },
+};
+
+static void tpm_crb_reset(DeviceState *dev)
+{
+    CRBState *s = CRB(dev);
+
+    tpm_backend_reset(s->tpmbe);
+
+    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
+                            CRB_CTRL_CMD_SIZE);
+
+    s->regs = (struct crb_regs) {
+        .intf_id.bits = {
+            .type = CRB_INTF_TYPE_CRB_ACTIVE,
+            .version = CRB_INTF_VERSION_CRB,
+            .cap_locality = CRB_INTF_CAP_LOCALITY_0_ONLY,
+            .cap_crb_idle_bypass = CRB_INTF_CAP_IDLE_FAST,
+            .cap_data_xfer_size_support = CRB_INTF_CAP_XFER_SIZE_64,
+            .cap_fifo = CRB_INTF_CAP_FIFO_NOT_SUPPORTED,
+            .cap_crb = CRB_INTF_CAP_CRB_SUPPORTED,
+            .cap_if_res = 0b0,
+            .if_selector = CRB_INTF_IF_SELECTOR_CRB,
+            .if_selector_lock = CRB_INTF_IF_SELECTOR_UNLOCKED,
+            .rid = 0b0001,
+            .vid = PCI_VENDOR_ID_IBM,
+            .did = 0b0001,
+        },
+        .ctrl_cmd_size = CRB_CTRL_CMD_SIZE,
+        .ctrl_cmd_pa_low = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
+        .ctrl_rsp_size = CRB_CTRL_CMD_SIZE,
+        .ctrl_rsp_pa = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
+    };
+
+    tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size);
+}
+
+static void tpm_crb_request_completed(TPMIf *ti, int ret)
+{
+    CRBState *s = CRB(ti);
+
+    s->regs.ctrl_start &= ~CRB_START_INVOKE;
+    if (ret != 0) {
+        s->regs.ctrl_sts.bits.tpm_sts = 1; /* fatal error */
+    }
+}
+
+static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
+{
+    CRBState *s = CRB(ti);
+
+    return tpm_backend_get_tpm_version(s->tpmbe);
+}
+
+static const VMStateDescription vmstate_tpm_crb = {
+    .name = "tpm-crb",
+    .unmigratable = 1,
+};
+
+static Property tpm_crb_properties[] = {
+    DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tpm_crb_realizefn(DeviceState *dev, Error **errp)
+{
+    CRBState *s = CRB(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    if (!tpm_find()) {
+        error_setg(errp, "at most one TPM device is permitted");
+        return;
+    }
+    if (!s->tpmbe) {
+        error_setg(errp, "'tpmdev' property is required");
+        return;
+    }
+
+    memory_region_init_io(&s->mmio, OBJECT(s), &tpm_crb_memory_ops, s,
+        "tpm-crb-mmio", sizeof(struct crb_regs));
+    memory_region_init_ram(&s->cmdmem, OBJECT(s),
+        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+
+    sysbus_init_mmio(sbd, &s->mmio);
+    sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE);
+    /* allocate ram in bios instead? */
+    memory_region_add_subregion(get_system_memory(),
+        TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), &s->cmdmem);
+}
+
+static void tpm_crb_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    TPMIfClass *tc = TPM_IF_CLASS(klass);
+
+    dc->realize = tpm_crb_realizefn;
+    dc->props = tpm_crb_properties;
+    dc->reset = tpm_crb_reset;
+    dc->vmsd  = &vmstate_tpm_crb;
+    dc->user_creatable = true;
+    tc->model = TPM_MODEL_TPM_CRB;
+    tc->get_version = tpm_crb_get_version;
+    tc->request_completed = tpm_crb_request_completed;
+}
+
+static const TypeInfo tpm_crb_info = {
+    .name = TYPE_TPM_CRB,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(CRBState),
+    .class_init  = tpm_crb_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_TPM_IF },
+        { }
+    }
+};
+
+static void tpm_crb_register(void)
+{
+    type_register_static(&tpm_crb_info);
+}
+
+type_init(tpm_crb_register)
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 95ac4b464a..ac27700e79 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=$(CONFIG_TPM)
+CONFIG_TPM_CRB=$(CONFIG_TPM)
 CONFIG_MC146818RTC=y
 CONFIG_PCI_PIIX=y
 CONFIG_WDT_IB700=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 0221236825..b2104ade19 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
 CONFIG_I8259=y
 CONFIG_PFLASH_CFI01=y
 CONFIG_TPM_TIS=$(CONFIG_TPM)
+CONFIG_TPM_CRB=$(CONFIG_TPM)
 CONFIG_MC146818RTC=y
 CONFIG_PCI_PIIX=y
 CONFIG_WDT_IB700=y
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index 7a93b24636..1dc9f8bf2c 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -1,4 +1,5 @@
 common-obj-y += tpm_util.o
 common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
+common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
 common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
 common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
-- 
2.16.0.rc1.1.gef27df75a1

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

* [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support
  2018-01-19 14:10 [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups Marc-André Lureau
                   ` (3 preceding siblings ...)
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device Marc-André Lureau
@ 2018-01-19 14:11 ` Marc-André Lureau
  2018-01-19 14:46   ` Stefan Berger
  2018-01-19 14:36 ` [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups no-reply
  5 siblings, 1 reply; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-19 14:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: stefanb, Marc-André Lureau

From: Stefan Berger <stefanb@linux.vnet.ibm.com>

We need to synchronize with the backend thread to make sure that a command
being processed by the external TPM emulator has completed and its
response been received. In case the bottom half did not run, we run the
function it is supposed to run.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
[ Marc-André - drop memory_region_get_ram_ptr(cmdmem) copy as it
  should be migrated already ]
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 hw/tpm/tpm_crb.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 908ca18d92..63d53384c5 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -257,9 +257,39 @@ static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
     return tpm_backend_get_tpm_version(s->tpmbe);
 }
 
+/* persistent state handling */
+
+static int tpm_crb_pre_save(void *opaque)
+{
+    CRBState *s = opaque;
+
+    tpm_backend_finish_sync(s->tpmbe);
+
+    return 0;
+}
+
 static const VMStateDescription vmstate_tpm_crb = {
     .name = "tpm-crb",
-    .unmigratable = 1,
+    .pre_save  = tpm_crb_pre_save,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(regs.loc_state.reg, CRBState),
+        VMSTATE_UINT32(regs.loc_ctrl, CRBState),
+        VMSTATE_UINT32(regs.loc_sts.reg, CRBState),
+        VMSTATE_UINT64(regs.intf_id.reg, CRBState),
+        VMSTATE_UINT64(regs.ctrl_ext, CRBState),
+        VMSTATE_UINT32(regs.ctrl_req, CRBState),
+        VMSTATE_UINT32(regs.ctrl_sts.reg, CRBState),
+        VMSTATE_UINT32(regs.ctrl_cancel, CRBState),
+        VMSTATE_UINT32(regs.ctrl_start, CRBState),
+        VMSTATE_UINT32(regs.ctrl_int_enable, CRBState),
+        VMSTATE_UINT32(regs.ctrl_int_sts, CRBState),
+        VMSTATE_UINT32(regs.ctrl_cmd_size, CRBState),
+        VMSTATE_UINT32(regs.ctrl_cmd_pa_low, CRBState),
+        VMSTATE_UINT32(regs.ctrl_rsp_size, CRBState),
+        VMSTATE_UINT64(regs.ctrl_rsp_pa, CRBState),
+
+        VMSTATE_END_OF_LIST(),
+    }
 };
 
 static Property tpm_crb_properties[] = {
-- 
2.16.0.rc1.1.gef27df75a1

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

* Re: [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class Marc-André Lureau
@ 2018-01-19 14:32   ` Stefan Berger
  0 siblings, 0 replies; 31+ messages in thread
From: Stefan Berger @ 2018-01-19 14:32 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel

On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
> Since Linux commit 313d21eeab9282e, tpm devices have their own device
> class "tpm" and the cancel path must be looked up under
> /sys/class/tpm/ instead of /sys/class/misc/.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>

> ---
>   hw/tpm/tpm_passthrough.c | 34 ++++++++++++++++++++++------------
>   1 file changed, 22 insertions(+), 12 deletions(-)
>
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index 29142f38bb..f2563ac668 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -216,7 +216,8 @@ static size_t tpm_passthrough_get_buffer_size(TPMBackend *tb)
>    * Unless path or file descriptor set has been provided by user,
>    * determine the sysfs cancel file following kernel documentation
>    * in Documentation/ABI/stable/sysfs-class-tpm.
> - * From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel
> + * From /dev/tpm0 create /sys/class/tpm/tpm0/device/cancel
> + * before 4.0: /sys/class/misc/tpm0/device/cancel
>    */
>   static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
>   {
> @@ -227,26 +228,35 @@ static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
>       if (tpm_pt->options->cancel_path) {
>           fd = qemu_open(tpm_pt->options->cancel_path, O_WRONLY);
>           if (fd < 0) {
> -            error_report("Could not open TPM cancel path : %s",
> +            error_report("tpm_passthrough: Could not open TPM cancel path: %s",
>                            strerror(errno));
>           }
>           return fd;
>       }
>
>       dev = strrchr(tpm_pt->tpm_dev, '/');
> -    if (dev) {
> -        dev++;
> -        if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel",
> -                     dev) < sizeof(path)) {
> -            fd = qemu_open(path, O_WRONLY);
> -            if (fd < 0) {
> -                error_report("tpm_passthrough: Could not open TPM cancel "
> -                             "path %s : %s", path, strerror(errno));
> +    if (!dev) {
> +        error_report("tpm_passthrough: Bad TPM device path %s",
> +                     tpm_pt->tpm_dev);
> +        return -1;
> +    }
> +
> +    dev++;
> +    if (snprintf(path, sizeof(path), "/sys/class/tpm/%s/device/cancel",
> +                 dev) < sizeof(path)) {
> +        fd = qemu_open(path, O_WRONLY);
> +        if (fd < 0) {
> +            if (snprintf(path, sizeof(path), "/sys/class/misc/%s/device/cancel",
> +                         dev) < sizeof(path)) {
> +                fd = qemu_open(path, O_WRONLY);
>               }
>           }
> +    }
> +
> +    if (fd < 0) {
> +        error_report("tpm_passthrough: Could not guess TPM cancel path");
>       } else {
> -       error_report("tpm_passthrough: Bad TPM device path %s",
> -                    tpm_pt->tpm_dev);
> +        tpm_pt->options->cancel_path = g_strdup(path);
>       }
>
>       return fd;

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

* Re: [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups
  2018-01-19 14:10 [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups Marc-André Lureau
                   ` (4 preceding siblings ...)
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support Marc-André Lureau
@ 2018-01-19 14:36 ` no-reply
  2018-01-19 14:56   ` Marc-Andre Lureau
  5 siblings, 1 reply; 31+ messages in thread
From: no-reply @ 2018-01-19 14:36 UTC (permalink / raw)
  To: marcandre.lureau; +Cc: famz, qemu-devel, stefanb

Hi,

This series failed docker-mingw@fedora build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

Type: series
Message-id: 20180119141105.29095-1-marcandre.lureau@redhat.com
Subject: [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups

=== TEST SCRIPT BEGIN ===
#!/bin/bash
set -e
git submodule update --init dtc
# Let docker tests dump environment info
export SHOW_ENV=1
export J=8
time make docker-test-mingw@fedora
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
a8cb8c7ef5 tpm: extend TPM CRB with state migration support
8a2b609952 tpm: add CRB device
c9daf3470d tpm: report backend request error
c3d6c6e43e tpm: replace GThreadPool with AIO threadpool
9dbfdf970f tpm: lookup cancel path under tpm device class

=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-m301zxts/src/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
  BUILD   fedora
  GEN     /var/tmp/patchew-tester-tmp-m301zxts/src/docker-src.2018-01-19-09.32.36.2536/qemu.tar
Cloning into '/var/tmp/patchew-tester-tmp-m301zxts/src/docker-src.2018-01-19-09.32.36.2536/qemu.tar.vroot'...
done.
Checking out files:  50% (2918/5737)   
Checking out files:  51% (2926/5737)   
Checking out files:  52% (2984/5737)   
Checking out files:  53% (3041/5737)   
Checking out files:  54% (3098/5737)   
Checking out files:  55% (3156/5737)   
Checking out files:  56% (3213/5737)   
Checking out files:  57% (3271/5737)   
Checking out files:  58% (3328/5737)   
Checking out files:  59% (3385/5737)   
Checking out files:  60% (3443/5737)   
Checking out files:  61% (3500/5737)   
Checking out files:  62% (3557/5737)   
Checking out files:  63% (3615/5737)   
Checking out files:  64% (3672/5737)   
Checking out files:  65% (3730/5737)   
Checking out files:  66% (3787/5737)   
Checking out files:  67% (3844/5737)   
Checking out files:  68% (3902/5737)   
Checking out files:  69% (3959/5737)   
Checking out files:  70% (4016/5737)   
Checking out files:  71% (4074/5737)   
Checking out files:  72% (4131/5737)   
Checking out files:  73% (4189/5737)   
Checking out files:  74% (4246/5737)   
Checking out files:  75% (4303/5737)   
Checking out files:  76% (4361/5737)   
Checking out files:  76% (4386/5737)   
Checking out files:  77% (4418/5737)   
Checking out files:  78% (4475/5737)   
Checking out files:  79% (4533/5737)   
Checking out files:  80% (4590/5737)   
Checking out files:  81% (4647/5737)   
Checking out files:  82% (4705/5737)   
Checking out files:  83% (4762/5737)   
Checking out files:  84% (4820/5737)   
Checking out files:  85% (4877/5737)   
Checking out files:  86% (4934/5737)   
Checking out files:  87% (4992/5737)   
Checking out files:  88% (5049/5737)   
Checking out files:  89% (5106/5737)   
Checking out files:  90% (5164/5737)   
Checking out files:  91% (5221/5737)   
Checking out files:  92% (5279/5737)   
Checking out files:  93% (5336/5737)   
Checking out files:  94% (5393/5737)   
Checking out files:  95% (5451/5737)   
Checking out files:  96% (5508/5737)   
Checking out files:  97% (5565/5737)   
Checking out files:  98% (5623/5737)   
Checking out files:  99% (5680/5737)   
Checking out files: 100% (5737/5737)   
Checking out files: 100% (5737/5737), done.
Your branch is up-to-date with 'origin/test'.
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-m301zxts/src/docker-src.2018-01-19-09.32.36.2536/qemu.tar.vroot/dtc'...
Submodule path 'dtc': checked out 'e54388015af1fb4bf04d0bca99caba1074d9cc42'
Submodule 'ui/keycodemapdb' (git://git.qemu.org/keycodemapdb.git) registered for path 'ui/keycodemapdb'
Cloning into '/var/tmp/patchew-tester-tmp-m301zxts/src/docker-src.2018-01-19-09.32.36.2536/qemu.tar.vroot/ui/keycodemapdb'...
Submodule path 'ui/keycodemapdb': checked out '10739aa26051a5d49d88132604539d3ed085e72e'
  COPY    RUNNER
    RUN test-mingw in qemu:fedora 
Packages installed:
PyYAML-3.11-13.fc25.x86_64
SDL-devel-1.2.15-21.fc24.x86_64
bc-1.06.95-16.fc24.x86_64
bison-3.0.4-4.fc24.x86_64
bzip2-1.0.6-21.fc25.x86_64
ccache-3.3.4-1.fc25.x86_64
clang-3.9.1-2.fc25.x86_64
findutils-4.6.0-8.fc25.x86_64
flex-2.6.0-3.fc25.x86_64
gcc-6.4.1-1.fc25.x86_64
gcc-c++-6.4.1-1.fc25.x86_64
gettext-0.19.8.1-3.fc25.x86_64
git-2.9.5-3.fc25.x86_64
glib2-devel-2.50.3-1.fc25.x86_64
hostname-3.15-8.fc25.x86_64
libaio-devel-0.3.110-6.fc24.x86_64
libasan-6.4.1-1.fc25.x86_64
libfdt-devel-1.4.2-1.fc25.x86_64
libubsan-6.4.1-1.fc25.x86_64
make-4.1-6.fc25.x86_64
mingw32-SDL-1.2.15-7.fc24.noarch
mingw32-bzip2-1.0.6-7.fc24.noarch
mingw32-curl-7.47.0-1.fc24.noarch
mingw32-glib2-2.50.3-1.fc25.noarch
mingw32-gmp-6.1.1-1.fc25.noarch
mingw32-gnutls-3.5.5-2.fc25.noarch
mingw32-gtk2-2.24.31-2.fc25.noarch
mingw32-gtk3-3.22.17-1.fc25.noarch
mingw32-libjpeg-turbo-1.5.1-1.fc25.noarch
mingw32-libpng-1.6.27-1.fc25.noarch
mingw32-libssh2-1.4.3-5.fc24.noarch
mingw32-libtasn1-4.9-1.fc25.noarch
mingw32-nettle-3.3-1.fc25.noarch
mingw32-pixman-0.34.0-1.fc25.noarch
mingw32-pkg-config-0.28-6.fc24.x86_64
mingw64-SDL-1.2.15-7.fc24.noarch
mingw64-bzip2-1.0.6-7.fc24.noarch
mingw64-curl-7.47.0-1.fc24.noarch
mingw64-glib2-2.50.3-1.fc25.noarch
mingw64-gmp-6.1.1-1.fc25.noarch
mingw64-gnutls-3.5.5-2.fc25.noarch
mingw64-gtk2-2.24.31-2.fc25.noarch
mingw64-gtk3-3.22.17-1.fc25.noarch
mingw64-libjpeg-turbo-1.5.1-1.fc25.noarch
mingw64-libpng-1.6.27-1.fc25.noarch
mingw64-libssh2-1.4.3-5.fc24.noarch
mingw64-libtasn1-4.9-1.fc25.noarch
mingw64-nettle-3.3-1.fc25.noarch
mingw64-pixman-0.34.0-1.fc25.noarch
mingw64-pkg-config-0.28-6.fc24.x86_64
nettle-devel-3.3-1.fc25.x86_64
package python2 is not installed
perl-5.24.3-389.fc25.x86_64
pixman-devel-0.34.0-2.fc24.x86_64
sparse-0.5.0-10.fc25.x86_64
tar-1.29-3.fc25.x86_64
which-2.21-1.fc25.x86_64
zlib-devel-1.2.8-10.fc24.x86_64

Environment variables:
PACKAGES=ccache gettext git tar PyYAML sparse flex bison python2 bzip2 hostname     glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel     gcc gcc-c++ clang make perl which bc findutils libaio-devel     nettle-devel libasan libubsan     mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config     mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1     mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2     mingw32-bzip2     mingw64-pixman mingw64-glib2 mingw64-gmp mingw64-SDL mingw64-pkg-config     mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1     mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2     mingw64-bzip2
HOSTNAME=91a02251742e
MAKEFLAGS= -j8
J=8
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
TARGET_LIST=
FGC=f25
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
DISTTAG=f25container
FEATURES=mingw clang pyyaml asan dtc
DEBUG=
_=/usr/bin/env

Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/tmp/qemu-test/install --cross-prefix=x86_64-w64-mingw32- --enable-trace-backends=simple --enable-gnutls --enable-nettle --enable-curl --enable-vnc --enable-bzip2 --enable-guest-agent --with-sdlabi=1.2 --with-gtkabi=2.0
Install prefix    /tmp/qemu-test/install
BIOS directory    /tmp/qemu-test/install
firmware path     /tmp/qemu-test/install/share/qemu-firmware
binary directory  /tmp/qemu-test/install
library directory /tmp/qemu-test/install/lib
module directory  /tmp/qemu-test/install/lib
libexec directory /tmp/qemu-test/install/libexec
include directory /tmp/qemu-test/install/include
config directory  /tmp/qemu-test/install
local state directory   queried at runtime
Windows SDK       no
Source path       /tmp/qemu-test/src
GIT binary        git
GIT submodules    
C compiler        x86_64-w64-mingw32-gcc
Host C compiler   cc
C++ compiler      x86_64-w64-mingw32-g++
Objective-C compiler clang
ARFLAGS           rv
CFLAGS            -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g 
QEMU_CFLAGS       -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/pixman-1  -I$(SRC_PATH)/dtc/libfdt -Werror -mms-bitfields -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/glib-2.0 -I/usr/x86_64-w64-mingw32/sys-root/mingw/lib/glib-2.0/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include  -m64 -mcx16 -mthreads -D__USE_MINGW_ANSI_STDIO=1 -DWIN32_LEAN_AND_MEAN -DWINVER=0x501 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes -Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes -fno-strict-aliasing -fno-common -fwrapv  -Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body -Wnested-externs -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers -Wold-style-declaration -Wold-style-definition -Wtype-limits -fstack-protector-strong -I/usr/x86_64-w64-mingw32/sys-root/mingw/include -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/p11-kit-1 -I/usr/x86_64-w64-mingw32/sys-root/mingw/include  -I/usr/x86_64-w64-mingw32/sys-root/mingw/include   -I/usr/x86_64-w64-mingw32/sys-root/mingw/include/libpng16 
LDFLAGS           -Wl,--nxcompat -Wl,--no-seh -Wl,--dynamicbase -Wl,--warn-common -m64 -g 
make              make
install           install
python            python -B
smbd              /usr/sbin/smbd
module support    no
host CPU          x86_64
host big endian   no
target list       x86_64-softmmu aarch64-softmmu
gprof enabled     no
sparse enabled    no
strip binaries    yes
profiler          no
static build      no
SDL support       yes (1.2.15)
GTK support       yes (2.24.31)
GTK GL support    no
VTE support       no 
TLS priority      NORMAL
GNUTLS support    yes
GNUTLS rnd        yes
libgcrypt         no
libgcrypt kdf     no
nettle            yes (3.3)
nettle kdf        yes
libtasn1          yes
curses support    no
virgl support     no
curl support      yes
mingw32 support   yes
Audio drivers     dsound
Block whitelist (rw) 
Block whitelist (ro) 
VirtFS support    no
Multipath support no
VNC support       yes
VNC SASL support  no
VNC JPEG support  yes
VNC PNG support   yes
xen support       no
brlapi support    no
bluez  support    no
Documentation     no
PIE               no
vde support       no
netmap support    no
Linux AIO support no
ATTR/XATTR support no
Install blobs     yes
KVM support       no
HAX support       yes
HVF support       no
TCG support       yes
TCG debug enabled no
TCG interpreter   no
malloc trim support no
RDMA support      no
fdt support       yes
preadv support    no
fdatasync         no
madvise           no
posix_madvise     no
libcap-ng support no
vhost-net support no
vhost-scsi support no
vhost-vsock support no
vhost-user support no
Trace backends    simple
Trace output file trace-<pid>
spice support     no 
rbd support       no
xfsctl support    no
smartcard support no
libusb            no
usb net redir     no
OpenGL support    no
OpenGL dmabufs    no
libiscsi support  no
libnfs support    no
build guest agent yes
QGA VSS support   no
QGA w32 disk info yes
QGA MSI support   no
seccomp support   no
coroutine backend win32
coroutine pool    yes
debug stack usage no
crypto afalg      no
GlusterFS support no
gcov              gcov
gcov enabled      no
TPM support       yes
libssh2 support   yes
TPM passthrough   no
TPM emulator      no
QOM debugging     yes
Live block migration yes
lzo support       no
snappy support    no
bzip2 support     yes
NUMA host support no
tcmalloc support  no
jemalloc support  no
avx2 optimization yes
replication support yes
VxHS block device no
capstone          no

WARNING: Use of GTK 2.0 is deprecated and will be removed in
WARNING: future releases. Please switch to using GTK 3.0
  GEN     x86_64-softmmu/config-devices.mak.tmp
  GEN     aarch64-softmmu/config-devices.mak.tmp
  GEN     config-host.h
  GEN     qemu-options.def
  GEN     qmp-commands.h
  GEN     qapi-types.h
  GEN     qapi-visit.h
  GEN     qapi-event.h
  GEN     x86_64-softmmu/config-devices.mak
  GEN     aarch64-softmmu/config-devices.mak
  GEN     qmp-marshal.c
  GEN     qapi-types.c
  GEN     qapi-visit.c
  GEN     qapi-event.c
  GEN     qmp-introspect.h
  GEN     qmp-introspect.c
  GEN     trace/generated-tcg-tracers.h
  GEN     trace/generated-helpers-wrappers.h
  GEN     trace/generated-helpers.h
  GEN     module_block.h
  GEN     trace/generated-helpers.c
  GEN     ui/input-keymap-linux-to-qcode.c
  GEN     ui/input-keymap-qcode-to-qnum.c
  GEN     ui/input-keymap-qnum-to-qcode.c
  GEN     ui/input-keymap-qcode-to-linux.c
  GEN     tests/test-qapi-types.h
  GEN     tests/test-qapi-visit.h
  GEN     tests/test-qmp-commands.h
  GEN     tests/test-qmp-introspect.h
  GEN     tests/test-qapi-event.h
  GEN     trace-root.h
  GEN     util/trace.h
  GEN     crypto/trace.h
  GEN     io/trace.h
  GEN     migration/trace.h
  GEN     block/trace.h
  GEN     chardev/trace.h
  GEN     hw/block/trace.h
  GEN     hw/block/dataplane/trace.h
  GEN     hw/char/trace.h
  GEN     hw/intc/trace.h
  GEN     hw/net/trace.h
  GEN     hw/virtio/trace.h
  GEN     hw/audio/trace.h
  GEN     hw/misc/trace.h
  GEN     hw/usb/trace.h
  GEN     hw/scsi/trace.h
  GEN     hw/nvram/trace.h
  GEN     hw/display/trace.h
  GEN     hw/input/trace.h
  GEN     hw/timer/trace.h
  GEN     hw/dma/trace.h
  GEN     hw/sparc/trace.h
  GEN     hw/sparc64/trace.h
  GEN     hw/sd/trace.h
  GEN     hw/isa/trace.h
  GEN     hw/mem/trace.h
  GEN     hw/i386/trace.h
  GEN     hw/i386/xen/trace.h
  GEN     hw/9pfs/trace.h
  GEN     hw/ppc/trace.h
  GEN     hw/pci/trace.h
  GEN     hw/s390x/trace.h
  GEN     hw/vfio/trace.h
  GEN     hw/acpi/trace.h
  GEN     hw/arm/trace.h
  GEN     hw/alpha/trace.h
  GEN     hw/xen/trace.h
  GEN     hw/ide/trace.h
  GEN     ui/trace.h
  GEN     audio/trace.h
  GEN     net/trace.h
  GEN     target/arm/trace.h
  GEN     target/i386/trace.h
  GEN     target/mips/trace.h
  GEN     target/sparc/trace.h
  GEN     target/s390x/trace.h
  GEN     target/ppc/trace.h
  GEN     qom/trace.h
  GEN     linux-user/trace.h
  GEN     qapi/trace.h
  GEN     accel/tcg/trace.h
  GEN     accel/kvm/trace.h
  GEN     nbd/trace.h
  GEN     scsi/trace.h
  GEN     trace-root.c
  GEN     util/trace.c
  GEN     crypto/trace.c
  GEN     io/trace.c
  GEN     migration/trace.c
  GEN     block/trace.c
  GEN     chardev/trace.c
  GEN     hw/block/trace.c
  GEN     hw/block/dataplane/trace.c
  GEN     hw/char/trace.c
  GEN     hw/intc/trace.c
  GEN     hw/net/trace.c
  GEN     hw/virtio/trace.c
  GEN     hw/audio/trace.c
  GEN     hw/misc/trace.c
  GEN     hw/usb/trace.c
  GEN     hw/scsi/trace.c
  GEN     hw/nvram/trace.c
  GEN     hw/display/trace.c
  GEN     hw/input/trace.c
  GEN     hw/timer/trace.c
  GEN     hw/dma/trace.c
  GEN     hw/sparc/trace.c
  GEN     hw/sparc64/trace.c
  GEN     hw/sd/trace.c
  GEN     hw/isa/trace.c
  GEN     hw/mem/trace.c
  GEN     hw/i386/trace.c
  GEN     hw/i386/xen/trace.c
  GEN     hw/9pfs/trace.c
  GEN     hw/ppc/trace.c
  GEN     hw/pci/trace.c
  GEN     hw/s390x/trace.c
  GEN     hw/vfio/trace.c
  GEN     hw/acpi/trace.c
  GEN     hw/arm/trace.c
  GEN     hw/alpha/trace.c
  GEN     hw/xen/trace.c
  GEN     hw/ide/trace.c
  GEN     ui/trace.c
  GEN     audio/trace.c
  GEN     net/trace.c
  GEN     target/arm/trace.c
  GEN     target/i386/trace.c
  GEN     target/mips/trace.c
  GEN     target/sparc/trace.c
  GEN     target/s390x/trace.c
  GEN     target/ppc/trace.c
  GEN     qom/trace.c
  GEN     linux-user/trace.c
  GEN     qapi/trace.c
  GEN     accel/tcg/trace.c
  GEN     accel/kvm/trace.c
  GEN     nbd/trace.c
  GEN     scsi/trace.c
  GEN     config-all-devices.mak
	 DEP /tmp/qemu-test/src/dtc/tests/dumptrees.c
	 DEP /tmp/qemu-test/src/dtc/tests/trees.S
	 DEP /tmp/qemu-test/src/dtc/tests/testutils.c
	 DEP /tmp/qemu-test/src/dtc/tests/value-labels.c
	 DEP /tmp/qemu-test/src/dtc/tests/asm_tree_dump.c
	 DEP /tmp/qemu-test/src/dtc/tests/truncated_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/check_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay_bad_fixup.c
	 DEP /tmp/qemu-test/src/dtc/tests/overlay.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/property_iterate.c
	 DEP /tmp/qemu-test/src/dtc/tests/integer-expressions.c
	 DEP /tmp/qemu-test/src/dtc/tests/utilfdt_test.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset_aliases.c
	 DEP /tmp/qemu-test/src/dtc/tests/add_subnode_with_nops.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_unordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.c
	 DEP /tmp/qemu-test/src/dtc/tests/dtb_reverse.c
	 DEP /tmp/qemu-test/src/dtc/tests/extra-terminating-null.c
	 DEP /tmp/qemu-test/src/dtc/tests/incbin.c
	 DEP /tmp/qemu-test/src/dtc/tests/boot-cpuid.c
	 DEP /tmp/qemu-test/src/dtc/tests/phandle_format.c
	 DEP /tmp/qemu-test/src/dtc/tests/path-references.c
	 DEP /tmp/qemu-test/src/dtc/tests/references.c
	 DEP /tmp/qemu-test/src/dtc/tests/string_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/propname_escapes.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop2.c
	 DEP /tmp/qemu-test/src/dtc/tests/appendprop1.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/del_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/set_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/rw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/open_pack.c
	 DEP /tmp/qemu-test/src/dtc/tests/nopulate.c
	 DEP /tmp/qemu-test/src/dtc/tests/mangle-layout.c
	 DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
	 DEP /tmp/qemu-test/src/dtc/tests/move_and_save.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/stringlist.c
	 DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
	 DEP /tmp/qemu-test/src/dtc/tests/addr_size_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/notfound.c
	 DEP /tmp/qemu-test/src/dtc/tests/sized_cells.c
	 DEP /tmp/qemu-test/src/dtc/tests/char_literal.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_check_compatible.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_alias.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_prop_value.c
	 DEP /tmp/qemu-test/src/dtc/tests/parent_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/supernode_atdepth_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_path.c
	 DEP /tmp/qemu-test/src/dtc/tests/getprop.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_phandle.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_name.c
	 DEP /tmp/qemu-test/src/dtc/tests/path_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/subnode_offset.c
	 DEP /tmp/qemu-test/src/dtc/tests/find_property.c
	 DEP /tmp/qemu-test/src/dtc/tests/root_node.c
	 DEP /tmp/qemu-test/src/dtc/tests/get_mem_rsv.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_overlay.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_addresses.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_empty_tree.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_strerror.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_sw.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_wip.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
	 DEP /tmp/qemu-test/src/dtc/util.c
	 DEP /tmp/qemu-test/src/dtc/libfdt/fdt_ro.c
	 DEP /tmp/qemu-test/src/dtc/fdtoverlay.c
	 DEP /tmp/qemu-test/src/dtc/fdtget.c
	 DEP /tmp/qemu-test/src/dtc/fdtput.c
	 DEP /tmp/qemu-test/src/dtc/fdtdump.c
	 LEX convert-dtsv0-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/srcpos.c
	 BISON dtc-parser.tab.c
	 LEX dtc-lexer.lex.c
	 DEP /tmp/qemu-test/src/dtc/treesource.c
	 DEP /tmp/qemu-test/src/dtc/livetree.c
	 DEP /tmp/qemu-test/src/dtc/fstree.c
	 DEP /tmp/qemu-test/src/dtc/flattree.c
	 DEP /tmp/qemu-test/src/dtc/dtc.c
	 DEP /tmp/qemu-test/src/dtc/data.c
	 DEP /tmp/qemu-test/src/dtc/checks.c
	 DEP convert-dtsv0-lexer.lex.c
	 DEP dtc-parser.tab.c
	 DEP dtc-lexer.lex.c
	CHK version_gen.h
	UPD version_gen.h
	 DEP /tmp/qemu-test/src/dtc/util.c
	 CC libfdt/fdt.o
	 CC libfdt/fdt_ro.o
	 CC libfdt/fdt_wip.o
	 CC libfdt/fdt_sw.o
	 CC libfdt/fdt_rw.o
	 CC libfdt/fdt_strerror.o
	 CC libfdt/fdt_empty_tree.o
	 CC libfdt/fdt_addresses.o
	 CC libfdt/fdt_overlay.o
	 AR libfdt/libfdt.a
x86_64-w64-mingw32-ar: creating libfdt/libfdt.a
a - libfdt/fdt.o
a - libfdt/fdt_ro.o
a - libfdt/fdt_wip.o
a - libfdt/fdt_sw.o
a - libfdt/fdt_rw.o
a - libfdt/fdt_strerror.o
a - libfdt/fdt_empty_tree.o
a - libfdt/fdt_addresses.o
a - libfdt/fdt_overlay.o
  RC      version.o
  GEN     qga/qapi-generated/qga-qapi-types.h
  GEN     qga/qapi-generated/qga-qapi-visit.h
  GEN     qga/qapi-generated/qga-qapi-types.c
  GEN     qga/qapi-generated/qga-qapi-visit.c
  GEN     qga/qapi-generated/qga-qmp-commands.h
  CC      qapi-types.o
  GEN     qga/qapi-generated/qga-qmp-marshal.c
  CC      qmp-introspect.o
  CC      qapi-visit.o
  CC      qapi/qapi-visit-core.o
  CC      qapi-event.o
  CC      qapi/qapi-dealloc-visitor.o
  CC      qapi/qobject-input-visitor.o
  CC      qapi/qobject-output-visitor.o
  CC      qapi/qmp-registry.o
  CC      qapi/qmp-dispatch.o
  CC      qapi/string-input-visitor.o
  CC      qapi/string-output-visitor.o
  CC      qapi/opts-visitor.o
  CC      qapi/qapi-clone-visitor.o
  CC      qapi/qmp-event.o
  CC      qapi/qapi-util.o
  CC      qobject/qnull.o
  CC      qobject/qnum.o
  CC      qobject/qstring.o
  CC      qobject/qdict.o
  CC      qobject/qlist.o
  CC      qobject/qbool.o
  CC      qobject/qlit.o
  CC      qobject/qjson.o
  CC      qobject/qobject.o
  CC      qobject/json-lexer.o
  CC      qobject/json-streamer.o
  CC      qobject/json-parser.o
  CC      trace/simple.o
  CC      trace/control.o
  CC      trace/qmp.o
  CC      util/osdep.o
  CC      util/cutils.o
  CC      util/unicode.o
  CC      util/qemu-timer-common.o
  CC      util/bufferiszero.o
  CC      util/lockcnt.o
  CC      util/aiocb.o
  CC      util/async.o
  CC      util/thread-pool.o
  CC      util/qemu-timer.o
  CC      util/main-loop.o
  CC      util/iohandler.o
  CC      util/aio-win32.o
  CC      util/event_notifier-win32.o
  CC      util/oslib-win32.o
  CC      util/qemu-thread-win32.o
  CC      util/envlist.o
  CC      util/path.o
  CC      util/module.o
  CC      util/host-utils.o
  CC      util/bitmap.o
  CC      util/bitops.o
  CC      util/hbitmap.o
  CC      util/fifo8.o
  CC      util/acl.o
  CC      util/cacheinfo.o
  CC      util/error.o
  CC      util/qemu-error.o
  CC      util/id.o
  CC      util/iov.o
  CC      util/qemu-config.o
  CC      util/qemu-sockets.o
  CC      util/uri.o
  CC      util/notify.o
  CC      util/qemu-option.o
  CC      util/qemu-progress.o
  CC      util/keyval.o
  CC      util/hexdump.o
  CC      util/crc32c.o
  CC      util/uuid.o
  CC      util/throttle.o
  CC      util/getauxval.o
  CC      util/readline.o
  CC      util/rcu.o
  CC      util/qemu-coroutine.o
  CC      util/qemu-coroutine-lock.o
  CC      util/qemu-coroutine-io.o
  CC      util/qemu-coroutine-sleep.o
  CC      util/coroutine-win32.o
  CC      util/buffer.o
  CC      util/timed-average.o
  CC      util/base64.o
  CC      util/log.o
  CC      util/pagesize.o
  CC      util/qdist.o
  CC      util/qht.o
  CC      util/range.o
  CC      util/stats64.o
  CC      util/systemd.o
  CC      trace-root.o
  CC      util/trace.o
  CC      crypto/trace.o
  CC      io/trace.o
  CC      migration/trace.o
  CC      block/trace.o
  CC      chardev/trace.o
  CC      hw/block/trace.o
  CC      hw/block/dataplane/trace.o
  CC      hw/char/trace.o
  CC      hw/intc/trace.o
  CC      hw/net/trace.o
  CC      hw/virtio/trace.o
  CC      hw/audio/trace.o
  CC      hw/misc/trace.o
  CC      hw/usb/trace.o
  CC      hw/scsi/trace.o
  CC      hw/nvram/trace.o
  CC      hw/display/trace.o
  CC      hw/input/trace.o
  CC      hw/timer/trace.o
  CC      hw/dma/trace.o
  CC      hw/sparc/trace.o
  CC      hw/sparc64/trace.o
  CC      hw/sd/trace.o
  CC      hw/isa/trace.o
  CC      hw/mem/trace.o
  CC      hw/i386/trace.o
  CC      hw/i386/xen/trace.o
  CC      hw/9pfs/trace.o
  CC      hw/ppc/trace.o
  CC      hw/pci/trace.o
  CC      hw/s390x/trace.o
  CC      hw/vfio/trace.o
  CC      hw/acpi/trace.o
  CC      hw/arm/trace.o
  CC      hw/alpha/trace.o
  CC      hw/xen/trace.o
  CC      hw/ide/trace.o
  CC      ui/trace.o
  CC      audio/trace.o
  CC      net/trace.o
  CC      target/arm/trace.o
  CC      target/i386/trace.o
  CC      target/mips/trace.o
  CC      target/sparc/trace.o
  CC      target/s390x/trace.o
  CC      target/ppc/trace.o
  CC      qom/trace.o
  CC      linux-user/trace.o
  CC      qapi/trace.o
  CC      accel/tcg/trace.o
  CC      accel/kvm/trace.o
  CC      nbd/trace.o
  CC      scsi/trace.o
  CC      crypto/pbkdf-stub.o
  CC      stubs/arch-query-cpu-def.o
  CC      stubs/arch-query-cpu-model-expansion.o
  CC      stubs/arch-query-cpu-model-comparison.o
  CC      stubs/arch-query-cpu-model-baseline.o
  CC      stubs/bdrv-next-monitor-owned.o
  CC      stubs/blk-commit-all.o
  CC      stubs/blockdev-close-all-bdrv-states.o
  CC      stubs/clock-warp.o
  CC      stubs/cpu-get-clock.o
  CC      stubs/cpu-get-icount.o
  CC      stubs/dump.o
  CC      stubs/error-printf.o
  CC      stubs/fdset.o
  CC      stubs/gdbstub.o
  CC      stubs/get-vm-name.o
  CC      stubs/iothread.o
  CC      stubs/iothread-lock.o
  CC      stubs/is-daemonized.o
  CC      stubs/machine-init-done.o
  CC      stubs/migr-blocker.o
  CC      stubs/change-state-handler.o
  CC      stubs/monitor.o
  CC      stubs/qtest.o
  CC      stubs/notify-event.o
  CC      stubs/replay.o
  CC      stubs/runstate-check.o
  CC      stubs/set-fd-handler.o
  CC      stubs/slirp.o
  CC      stubs/sysbus.o
  CC      stubs/tpm.o
  CC      stubs/trace-control.o
  CC      stubs/uuid.o
  CC      stubs/vm-stop.o
  CC      stubs/vmstate.o
  CC      stubs/fd-register.o
  CC      stubs/qmp_pc_dimm.o
  CC      stubs/target-monitor-defs.o
  CC      stubs/target-get-monitor-def.o
  CC      stubs/pc_madt_cpu_entry.o
  CC      stubs/vmgenid.o
  CC      stubs/xen-common.o
  CC      stubs/xen-hvm.o
  CC      stubs/pci-host-piix.o
  GEN     qemu-img-cmds.h
  CC      block.o
  CC      blockjob.o
  CC      qemu-io-cmds.o
  CC      replication.o
  CC      block/raw-format.o
  CC      block/qcow.o
  CC      block/vdi.o
  CC      block/vmdk.o
  CC      block/cloop.o
  CC      block/bochs.o
  CC      block/vpc.o
  CC      block/vvfat.o
  CC      block/dmg.o
  CC      block/qcow2.o
  CC      block/qcow2-refcount.o
  CC      block/qcow2-cluster.o
  CC      block/qcow2-snapshot.o
  CC      block/qcow2-cache.o
  CC      block/qcow2-bitmap.o
  CC      block/qed.o
  CC      block/qed-l2-cache.o
  CC      block/qed-table.o
  CC      block/qed-cluster.o
  CC      block/qed-check.o
  CC      block/vhdx.o
  CC      block/vhdx-endian.o
  CC      block/quorum.o
  CC      block/vhdx-log.o
  CC      block/parallels.o
  CC      block/blkdebug.o
  CC      block/blkverify.o
  CC      block/blkreplay.o
  CC      block/block-backend.o
  CC      block/snapshot.o
  CC      block/qapi.o
  CC      block/file-win32.o
  CC      block/win32-aio.o
  CC      block/null.o
  CC      block/mirror.o
  CC      block/commit.o
  CC      block/io.o
  CC      block/throttle-groups.o
  CC      block/nbd.o
  CC      block/nbd-client.o
  CC      block/sheepdog.o
  CC      block/accounting.o
  CC      block/dirty-bitmap.o
  CC      block/write-threshold.o
  CC      block/backup.o
  CC      block/replication.o
  CC      block/throttle.o
  CC      block/crypto.o
  CC      nbd/server.o
  CC      nbd/client.o
  CC      nbd/common.o
  CC      scsi/utils.o
  CC      block/curl.o
  CC      block/ssh.o
  CC      block/dmg-bz2.o
  CC      crypto/init.o
  CC      crypto/hash.o
  CC      crypto/hash-nettle.o
  CC      crypto/hmac.o
  CC      crypto/hmac-nettle.o
  CC      crypto/aes.o
  CC      crypto/desrfb.o
  CC      crypto/cipher.o
  CC      crypto/tlscreds.o
  CC      crypto/tlscredsanon.o
  CC      crypto/tlscredsx509.o
  CC      crypto/tlssession.o
  CC      crypto/secret.o
  CC      crypto/random-gnutls.o
  CC      crypto/pbkdf.o
  CC      crypto/pbkdf-nettle.o
  CC      crypto/ivgen.o
  CC      crypto/ivgen-essiv.o
  CC      crypto/ivgen-plain.o
  CC      crypto/ivgen-plain64.o
  CC      crypto/afsplit.o
  CC      crypto/xts.o
  CC      crypto/block.o
  CC      crypto/block-qcow.o
  CC      crypto/block-luks.o
  CC      io/channel.o
  CC      io/channel-buffer.o
  CC      io/channel-command.o
  CC      io/channel-file.o
  CC      io/channel-socket.o
  CC      io/channel-tls.o
  CC      io/channel-watch.o
  CC      io/channel-websock.o
  CC      io/channel-util.o
  CC      io/dns-resolver.o
  CC      io/net-listener.o
  CC      io/task.o
  CC      qom/object.o
  CC      qom/container.o
  CC      qom/qom-qobject.o
  CC      qom/object_interfaces.o
  CC      qemu-io.o
  CC      blockdev.o
  CC      blockdev-nbd.o
  CC      bootdevice.o
  CC      iothread.o
  CC      qdev-monitor.o
  CC      device-hotplug.o
  CC      os-win32.o
  CC      bt-host.o
  CC      bt-vhci.o
  CC      dma-helpers.o
  CC      vl.o
  CC      tpm.o
  CC      device_tree.o
  CC      qmp-marshal.o
  CC      qmp.o
  CC      hmp.o
  CC      cpus-common.o
  CC      audio/audio.o
  CC      audio/noaudio.o
  CC      audio/wavaudio.o
  CC      audio/mixeng.o
  CC      audio/sdlaudio.o
  CC      audio/dsoundaudio.o
  CC      audio/audio_win_int.o
  CC      audio/wavcapture.o
  CC      backends/rng.o
  CC      backends/rng-egd.o
  CC      backends/tpm.o
  CC      backends/hostmem.o
  CC      backends/hostmem-ram.o
  CC      backends/cryptodev.o
  CC      backends/cryptodev-builtin.o
  CC      block/stream.o
  CC      chardev/msmouse.o
  CC      chardev/wctablet.o
  CC      chardev/testdev.o
  CC      disas/arm.o
  CXX     disas/arm-a64.o
  CC      disas/i386.o
  CXX     disas/libvixl/vixl/utils.o
  CXX     disas/libvixl/vixl/compiler-intrinsics.o
  CXX     disas/libvixl/vixl/a64/instructions-a64.o
  CXX     disas/libvixl/vixl/a64/decoder-a64.o
  CXX     disas/libvixl/vixl/a64/disasm-a64.o
  CC      hw/acpi/core.o
  CC      hw/acpi/piix4.o
  CC      hw/acpi/pcihp.o
  CC      hw/acpi/ich9.o
  CC      hw/acpi/tco.o
  CC      hw/acpi/cpu_hotplug.o
  CC      hw/acpi/memory_hotplug.o
  CC      hw/acpi/cpu.o
  CC      hw/acpi/nvdimm.o
  CC      hw/acpi/vmgenid.o
  CC      hw/acpi/acpi_interface.o
  CC      hw/acpi/bios-linker-loader.o
  CC      hw/acpi/aml-build.o
  CC      hw/acpi/ipmi.o
  CC      hw/acpi/acpi-stub.o
  CC      hw/acpi/ipmi-stub.o
  CC      hw/audio/sb16.o
  CC      hw/audio/es1370.o
  CC      hw/audio/ac97.o
  CC      hw/audio/fmopl.o
  CC      hw/audio/adlib.o
  CC      hw/audio/gus.o
  CC      hw/audio/gusemu_hal.o
  CC      hw/audio/gusemu_mixer.o
  CC      hw/audio/cs4231a.o
  CC      hw/audio/intel-hda.o
  CC      hw/audio/hda-codec.o
  CC      hw/audio/pcspk.o
  CC      hw/audio/wm8750.o
  CC      hw/audio/pl041.o
  CC      hw/audio/lm4549.o
  CC      hw/audio/marvell_88w8618.o
  CC      hw/audio/soundhw.o
  CC      hw/block/block.o
  CC      hw/block/cdrom.o
  CC      hw/block/hd-geometry.o
  CC      hw/block/fdc.o
  CC      hw/block/m25p80.o
  CC      hw/block/nand.o
  CC      hw/block/pflash_cfi01.o
  CC      hw/block/pflash_cfi02.o
  CC      hw/block/ecc.o
  CC      hw/block/onenand.o
  CC      hw/block/nvme.o
  CC      hw/bt/core.o
  CC      hw/bt/l2cap.o
  CC      hw/bt/sdp.o
  CC      hw/bt/hci.o
  CC      hw/bt/hid.o
  CC      hw/bt/hci-csr.o
  CC      hw/char/ipoctal232.o
  CC      hw/char/parallel.o
  CC      hw/char/pl011.o
  CC      hw/char/serial.o
  CC      hw/char/serial-isa.o
  CC      hw/char/serial-pci.o
  CC      hw/char/virtio-console.o
  CC      hw/char/cadence_uart.o
  CC      hw/char/cmsdk-apb-uart.o
  CC      hw/char/debugcon.o
  CC      hw/char/imx_serial.o
  CC      hw/core/qdev.o
  CC      hw/core/qdev-properties.o
  CC      hw/core/bus.o
  CC      hw/core/reset.o
  CC      hw/core/fw-path-provider.o
  CC      hw/core/irq.o
  CC      hw/core/hotplug.o
  CC      hw/core/nmi.o
  CC      hw/core/stream.o
  CC      hw/core/ptimer.o
  CC      hw/core/sysbus.o
  CC      hw/core/machine.o
  CC      hw/core/loader.o
  CC      hw/core/qdev-properties-system.o
  CC      hw/core/register.o
  CC      hw/core/or-irq.o
  CC      hw/core/platform-bus.o
  CC      hw/cpu/core.o
  CC      hw/display/ads7846.o
  CC      hw/display/cirrus_vga.o
  CC      hw/display/pl110.o
  CC      hw/display/ssd0303.o
  CC      hw/display/ssd0323.o
  CC      hw/display/vga-pci.o
  CC      hw/display/vga-isa.o
  CC      hw/display/vmware_vga.o
  CC      hw/display/blizzard.o
  CC      hw/display/exynos4210_fimd.o
  CC      hw/display/framebuffer.o
  CC      hw/display/tc6393xb.o
  CC      hw/dma/pl080.o
  CC      hw/dma/pl330.o
  CC      hw/dma/i8257.o
  CC      hw/dma/xilinx_axidma.o
  CC      hw/dma/xlnx-zynq-devcfg.o
  CC      hw/gpio/max7310.o
  CC      hw/gpio/pl061.o
  CC      hw/gpio/zaurus.o
  CC      hw/gpio/gpio_key.o
  CC      hw/i2c/core.o
  CC      hw/i2c/smbus.o
  CC      hw/i2c/smbus_eeprom.o
  CC      hw/i2c/i2c-ddc.o
  CC      hw/i2c/versatile_i2c.o
  CC      hw/i2c/smbus_ich9.o
  CC      hw/i2c/pm_smbus.o
  CC      hw/i2c/bitbang_i2c.o
  CC      hw/i2c/exynos4210_i2c.o
  CC      hw/i2c/imx_i2c.o
  CC      hw/i2c/aspeed_i2c.o
  CC      hw/ide/core.o
  CC      hw/ide/atapi.o
  CC      hw/ide/qdev.o
  CC      hw/ide/pci.o
  CC      hw/ide/isa.o
  CC      hw/ide/piix.o
  CC      hw/ide/microdrive.o
  CC      hw/ide/ich.o
  CC      hw/ide/ahci-allwinner.o
  CC      hw/ide/ahci.o
  CC      hw/input/hid.o
  CC      hw/input/lm832x.o
  CC      hw/input/pckbd.o
  CC      hw/input/pl050.o
  CC      hw/input/ps2.o
  CC      hw/input/stellaris_input.o
  CC      hw/input/tsc2005.o
  CC      hw/input/virtio-input.o
  CC      hw/input/virtio-input-hid.o
  CC      hw/intc/i8259_common.o
  CC      hw/intc/i8259.o
  CC      hw/intc/pl190.o
  CC      hw/intc/imx_avic.o
  CC      hw/intc/realview_gic.o
  CC      hw/intc/ioapic_common.o
  CC      hw/intc/arm_gic_common.o
  CC      hw/intc/arm_gic.o
  CC      hw/intc/arm_gicv2m.o
  CC      hw/intc/arm_gicv3_common.o
  CC      hw/intc/arm_gicv3.o
  CC      hw/intc/arm_gicv3_dist.o
  CC      hw/intc/arm_gicv3_redist.o
  CC      hw/intc/arm_gicv3_its_common.o
  CC      hw/intc/intc.o
  CC      hw/ipack/ipack.o
  CC      hw/ipack/tpci200.o
  CC      hw/ipmi/ipmi.o
  CC      hw/ipmi/ipmi_bmc_sim.o
  CC      hw/ipmi/ipmi_bmc_extern.o
  CC      hw/ipmi/isa_ipmi_kcs.o
  CC      hw/ipmi/isa_ipmi_bt.o
  CC      hw/isa/isa-bus.o
  CC      hw/isa/apm.o
  CC      hw/mem/pc-dimm.o
  CC      hw/mem/nvdimm.o
  CC      hw/misc/applesmc.o
  CC      hw/misc/max111x.o
  CC      hw/misc/tmp105.o
  CC      hw/misc/tmp421.o
  CC      hw/misc/debugexit.o
  CC      hw/misc/sga.o
  CC      hw/misc/pc-testdev.o
  CC      hw/misc/pci-testdev.o
  CC      hw/misc/edu.o
  CC      hw/misc/unimp.o
  CC      hw/misc/vmcoreinfo.o
  CC      hw/misc/arm_l2x0.o
  CC      hw/misc/arm_integrator_debug.o
  CC      hw/misc/a9scu.o
  CC      hw/misc/arm11scu.o
  CC      hw/net/ne2000.o
  CC      hw/net/eepro100.o
  CC      hw/net/pcnet-pci.o
  CC      hw/net/pcnet.o
  CC      hw/net/e1000.o
  CC      hw/net/e1000x_common.o
  CC      hw/net/net_tx_pkt.o
  CC      hw/net/net_rx_pkt.o
  CC      hw/net/e1000e.o
  CC      hw/net/e1000e_core.o
  CC      hw/net/rtl8139.o
  CC      hw/net/vmxnet3.o
  CC      hw/net/smc91c111.o
  CC      hw/net/lan9118.o
  CC      hw/net/ne2000-isa.o
  CC      hw/net/xgmac.o
  CC      hw/net/xilinx_axienet.o
  CC      hw/net/allwinner_emac.o
  CC      hw/net/imx_fec.o
  CC      hw/net/cadence_gem.o
  CC      hw/net/stellaris_enet.o
  CC      hw/net/ftgmac100.o
  CC      hw/net/rocker/rocker.o
  CC      hw/net/rocker/rocker_fp.o
  CC      hw/net/rocker/rocker_desc.o
  CC      hw/net/rocker/rocker_world.o
  CC      hw/net/rocker/rocker_of_dpa.o
  CC      hw/nvram/eeprom93xx.o
  CC      hw/nvram/eeprom_at24c.o
  CC      hw/nvram/fw_cfg.o
  CC      hw/nvram/chrp_nvram.o
  CC      hw/pci-bridge/pci_bridge_dev.o
  CC      hw/pci-bridge/pcie_root_port.o
  CC      hw/pci-bridge/gen_pcie_root_port.o
  CC      hw/pci-bridge/pcie_pci_bridge.o
  CC      hw/pci-bridge/pci_expander_bridge.o
  CC      hw/pci-bridge/xio3130_upstream.o
  CC      hw/pci-bridge/xio3130_downstream.o
  CC      hw/pci-bridge/ioh3420.o
  CC      hw/pci-bridge/i82801b11.o
  CC      hw/pci-host/pam.o
  CC      hw/pci-host/versatile.o
  CC      hw/pci-host/piix.o
  CC      hw/pci-host/q35.o
  CC      hw/pci-host/gpex.o
  CC      hw/pci/pci.o
  CC      hw/pci/pci_bridge.o
  CC      hw/pci/msix.o
  CC      hw/pci/msi.o
  CC      hw/pci/shpc.o
  CC      hw/pci/slotid_cap.o
  CC      hw/pci/pci_host.o
  CC      hw/pci/pcie_host.o
  CC      hw/pci/pcie.o
  CC      hw/pci/pcie_aer.o
  CC      hw/pci/pcie_port.o
  CC      hw/pci/pci-stub.o
  CC      hw/pcmcia/pcmcia.o
  CC      hw/scsi/scsi-disk.o
  CC      hw/scsi/scsi-generic.o
  CC      hw/scsi/scsi-bus.o
  CC      hw/scsi/lsi53c895a.o
  CC      hw/scsi/mptsas.o
  CC      hw/scsi/mptconfig.o
  CC      hw/scsi/mptendian.o
  CC      hw/scsi/megasas.o
  CC      hw/scsi/vmw_pvscsi.o
  CC      hw/scsi/esp.o
  CC      hw/scsi/esp-pci.o
  CC      hw/sd/pl181.o
  CC      hw/sd/ssi-sd.o
  CC      hw/sd/sd.o
  CC      hw/sd/core.o
  CC      hw/sd/sdhci.o
  CC      hw/smbios/smbios.o
  CC      hw/smbios/smbios_type_38.o
  CC      hw/smbios/smbios-stub.o
  CC      hw/smbios/smbios_type_38-stub.o
  CC      hw/ssi/pl022.o
  CC      hw/ssi/ssi.o
  CC      hw/ssi/xilinx_spips.o
  CC      hw/ssi/aspeed_smc.o
  CC      hw/ssi/stm32f2xx_spi.o
  CC      hw/ssi/mss-spi.o
  CC      hw/timer/arm_timer.o
  CC      hw/timer/arm_mptimer.o
  CC      hw/timer/armv7m_systick.o
  CC      hw/timer/a9gtimer.o
  CC      hw/timer/cadence_ttc.o
  CC      hw/timer/ds1338.o
  CC      hw/timer/hpet.o
  CC      hw/timer/i8254_common.o
  CC      hw/timer/i8254.o
  CC      hw/timer/pl031.o
  CC      hw/timer/twl92230.o
  CC      hw/timer/imx_epit.o
  CC      hw/timer/imx_gpt.o
  CC      hw/timer/stm32f2xx_timer.o
  CC      hw/timer/aspeed_timer.o
  CC      hw/timer/cmsdk-apb-timer.o
  CC      hw/timer/mss-timer.o
  CC      hw/tpm/tpm_util.o
  CC      hw/tpm/tpm_tis.o
  CC      hw/tpm/tpm_crb.o
  CC      hw/usb/core.o
  CC      hw/usb/combined-packet.o
  CC      hw/usb/bus.o
  CC      hw/usb/libhw.o
  CC      hw/usb/desc.o
  CC      hw/usb/desc-msos.o
/tmp/qemu-test/src/hw/tpm/tpm_crb.c: In function 'tpm_crb_mmio_read':
/tmp/qemu-test/src/hw/tpm/tpm_crb.c:126:13: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'hwaddr {aka long long unsigned int}' [-Werror=format=]
     DPRINTF("CRB read 0x%lx:%s len:%u\n",
             ^
/tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
             printf(fmt, ## __VA_ARGS__);        \
                    ^~~
/tmp/qemu-test/src/hw/tpm/tpm_crb.c: In function 'tpm_crb_mmio_write':
/tmp/qemu-test/src/hw/tpm/tpm_crb.c:146:13: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'hwaddr {aka long long unsigned int}' [-Werror=format=]
     DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
             ^
/tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
             printf(fmt, ## __VA_ARGS__);        \
                    ^~~
/tmp/qemu-test/src/hw/tpm/tpm_crb.c:146:13: error: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'uint64_t {aka long long unsigned int}' [-Werror=format=]
     DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
             ^
/tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
             printf(fmt, ## __VA_ARGS__);        \
                    ^~~
cc1: all warnings being treated as errors
make: *** [hw/tpm/tpm_crb.o] Error 1
/tmp/qemu-test/src/rules.mak:66: recipe for target 'hw/tpm/tpm_crb.o' failed
make: *** Waiting for unfinished jobs....
Traceback (most recent call last):
  File "./tests/docker/docker.py", line 407, in <module>
    sys.exit(main())
  File "./tests/docker/docker.py", line 404, in main
    return args.cmdobj.run(args, argv)
  File "./tests/docker/docker.py", line 261, in run
    return Docker().run(argv, args.keep, quiet=args.quiet)
  File "./tests/docker/docker.py", line 229, in run
    quiet=quiet)
  File "./tests/docker/docker.py", line 147, in _do_check
    return subprocess.check_call(self._command + cmd, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 186, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['docker', 'run', '--label', 'com.qemu.instance.uuid=9e96c08afd2511e7b85952540069c830', '-u', '0', '--security-opt', 'seccomp=unconfined', '--rm', '--net=none', '-e', 'TARGET_LIST=', '-e', 'EXTRA_CONFIGURE_OPTS=', '-e', 'V=', '-e', 'J=8', '-e', 'DEBUG=', '-e', 'SHOW_ENV=1', '-e', 'CCACHE_DIR=/var/tmp/ccache', '-v', '/root/.cache/qemu-docker-ccache:/var/tmp/ccache:z', '-v', '/var/tmp/patchew-tester-tmp-m301zxts/src/docker-src.2018-01-19-09.32.36.2536:/var/tmp/qemu:z,ro', 'qemu:fedora', '/var/tmp/qemu/run', 'test-mingw']' returned non-zero exit status 2
make[1]: *** [tests/docker/Makefile.include:129: docker-run] Error 1
make: *** [tests/docker/Makefile.include:163: docker-run-test-mingw@fedora] Error 2

real	3m42.350s
user	0m4.070s
sys	0m2.993s
=== OUTPUT END ===

Test command exited with code: 2


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

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

* Re: [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support Marc-André Lureau
@ 2018-01-19 14:46   ` Stefan Berger
  2018-01-19 14:49     ` Marc-André Lureau
  0 siblings, 1 reply; 31+ messages in thread
From: Stefan Berger @ 2018-01-19 14:46 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel

On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
> From: Stefan Berger <stefanb@linux.vnet.ibm.com>
>
> We need to synchronize with the backend thread to make sure that a command
> being processed by the external TPM emulator has completed and its
> response been received. In case the bottom half did not run, we run the
> function it is supposed to run.
>
> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> [ Marc-André - drop memory_region_get_ram_ptr(cmdmem) copy as it
>    should be migrated already ]
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

I think we need to delay this until the PPI device has been added since 
this will extend the state of the CRB.


> ---
>   hw/tpm/tpm_crb.c | 32 +++++++++++++++++++++++++++++++-
>   1 file changed, 31 insertions(+), 1 deletion(-)
>
> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> index 908ca18d92..63d53384c5 100644
> --- a/hw/tpm/tpm_crb.c
> +++ b/hw/tpm/tpm_crb.c
> @@ -257,9 +257,39 @@ static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
>       return tpm_backend_get_tpm_version(s->tpmbe);
>   }
>
> +/* persistent state handling */
> +
> +static int tpm_crb_pre_save(void *opaque)
> +{
> +    CRBState *s = opaque;
> +
> +    tpm_backend_finish_sync(s->tpmbe);
> +
> +    return 0;
> +}
> +
>   static const VMStateDescription vmstate_tpm_crb = {
>       .name = "tpm-crb",
> -    .unmigratable = 1,
> +    .pre_save  = tpm_crb_pre_save,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_UINT32(regs.loc_state.reg, CRBState),
> +        VMSTATE_UINT32(regs.loc_ctrl, CRBState),
> +        VMSTATE_UINT32(regs.loc_sts.reg, CRBState),
> +        VMSTATE_UINT64(regs.intf_id.reg, CRBState),
> +        VMSTATE_UINT64(regs.ctrl_ext, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_req, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_sts.reg, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_cancel, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_start, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_int_enable, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_int_sts, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_cmd_size, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_cmd_pa_low, CRBState),
> +        VMSTATE_UINT32(regs.ctrl_rsp_size, CRBState),
> +        VMSTATE_UINT64(regs.ctrl_rsp_pa, CRBState),
> +
> +        VMSTATE_END_OF_LIST(),
> +    }
>   };
>
>   static Property tpm_crb_properties[] = {

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

* Re: [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support
  2018-01-19 14:46   ` Stefan Berger
@ 2018-01-19 14:49     ` Marc-André Lureau
  0 siblings, 0 replies; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-19 14:49 UTC (permalink / raw)
  To: Stefan Berger; +Cc: QEMU

Hi

On Fri, Jan 19, 2018 at 3:46 PM, Stefan Berger
<stefanb@linux.vnet.ibm.com> wrote:
> On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
>>
>> From: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>
>> We need to synchronize with the backend thread to make sure that a command
>> being processed by the external TPM emulator has completed and its
>> response been received. In case the bottom half did not run, we run the
>> function it is supposed to run.
>>
>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>> [ Marc-André - drop memory_region_get_ram_ptr(cmdmem) copy as it
>>    should be migrated already ]
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
>
> I think we need to delay this until the PPI device has been added since this
> will extend the state of the CRB.
>

That makes sense, I'll hand it back to you then :)

>
>
>> ---
>>   hw/tpm/tpm_crb.c | 32 +++++++++++++++++++++++++++++++-
>>   1 file changed, 31 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
>> index 908ca18d92..63d53384c5 100644
>> --- a/hw/tpm/tpm_crb.c
>> +++ b/hw/tpm/tpm_crb.c
>> @@ -257,9 +257,39 @@ static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
>>       return tpm_backend_get_tpm_version(s->tpmbe);
>>   }
>>
>> +/* persistent state handling */
>> +
>> +static int tpm_crb_pre_save(void *opaque)
>> +{
>> +    CRBState *s = opaque;
>> +
>> +    tpm_backend_finish_sync(s->tpmbe);
>> +
>> +    return 0;
>> +}
>> +
>>   static const VMStateDescription vmstate_tpm_crb = {
>>       .name = "tpm-crb",
>> -    .unmigratable = 1,
>> +    .pre_save  = tpm_crb_pre_save,
>> +    .fields      = (VMStateField[]) {
>> +        VMSTATE_UINT32(regs.loc_state.reg, CRBState),
>> +        VMSTATE_UINT32(regs.loc_ctrl, CRBState),
>> +        VMSTATE_UINT32(regs.loc_sts.reg, CRBState),
>> +        VMSTATE_UINT64(regs.intf_id.reg, CRBState),
>> +        VMSTATE_UINT64(regs.ctrl_ext, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_req, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_sts.reg, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_cancel, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_start, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_int_enable, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_int_sts, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_cmd_size, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_cmd_pa_low, CRBState),
>> +        VMSTATE_UINT32(regs.ctrl_rsp_size, CRBState),
>> +        VMSTATE_UINT64(regs.ctrl_rsp_pa, CRBState),
>> +
>> +        VMSTATE_END_OF_LIST(),
>> +    }
>>   };
>>
>>   static Property tpm_crb_properties[] = {
>
>
>
>



-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups
  2018-01-19 14:36 ` [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups no-reply
@ 2018-01-19 14:56   ` Marc-Andre Lureau
  2018-01-19 15:06     ` Stefan Berger
  0 siblings, 1 reply; 31+ messages in thread
From: Marc-Andre Lureau @ 2018-01-19 14:56 UTC (permalink / raw)
  To: qemu-devel; +Cc: marcandre, famz, stefanb

On Fri, Jan 19, 2018 at 3:36 PM,  <no-reply@patchew.org> wrote:
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c: In function 'tpm_crb_mmio_read':
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:126:13: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'hwaddr {aka long long unsigned int}' [-Werror=format=]
>      DPRINTF("CRB read 0x%lx:%s len:%u\n",
>              ^
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
>              printf(fmt, ## __VA_ARGS__);        \
>                     ^~~
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c: In function 'tpm_crb_mmio_write':
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:146:13: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'hwaddr {aka long long unsigned int}' [-Werror=format=]
>      DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
>              ^
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
>              printf(fmt, ## __VA_ARGS__);        \
>                     ^~~
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:146:13: error: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'uint64_t {aka long long unsigned int}' [-Werror=format=]
>      DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
>              ^
> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
>              printf(fmt, ## __VA_ARGS__);        \
>                     ^~~

This will fix it:
Stefan feel free to squash it if no further changes required

--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -123,7 +123,7 @@ static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
                                   unsigned size)
 {
     CRBState *s = CRB(opaque);
-    DPRINTF("CRB read 0x%lx:%s len:%u\n",
+    DPRINTF("CRB read 0x" TARGET_FMT_plx ":%s len:%u\n",
             addr, addr_desc(addr), size);
     void *regs = (void *)&s->regs + addr;

@@ -143,7 +143,7 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
                                uint64_t val, unsigned size)
 {
     CRBState *s = CRB(opaque);
-    DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
+    DPRINTF("CRB write 0x" TARGET_FMT_plx ":%s len:%u val:%" PRIu64 "\n",
             addr, addr_desc(addr), size, val);

     switch (addr) {

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

* Re: [Qemu-devel] [PATCH v2 3/5] tpm: report backend request error
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 3/5] tpm: report backend request error Marc-André Lureau
@ 2018-01-19 14:57   ` Stefan Berger
  0 siblings, 0 replies; 31+ messages in thread
From: Stefan Berger @ 2018-01-19 14:57 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel

On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
> Use an Error** for request to let the caller handle error reporting.
>
> This will also allow to inform the frontend of a backend error.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>

> ---
>   include/sysemu/tpm.h         |  2 +-
>   include/sysemu/tpm_backend.h |  3 ++-
>   backends/tpm.c               |  9 +++++++--
>   hw/tpm/tpm_emulator.c        | 21 ++++++---------------
>   hw/tpm/tpm_passthrough.c     | 31 +++++++++++++++----------------
>   hw/tpm/tpm_tis.c             |  3 ++-
>   6 files changed, 33 insertions(+), 36 deletions(-)
>
> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> index 852e02687c..ac04a9d4a2 100644
> --- a/include/sysemu/tpm.h
> +++ b/include/sysemu/tpm.h
> @@ -41,7 +41,7 @@ typedef struct TPMIfClass {
>       InterfaceClass parent_class;
>   
>       enum TpmModel model;
> -    void (*request_completed)(TPMIf *obj);
> +    void (*request_completed)(TPMIf *obj, int ret);
>       enum TPMVersion (*get_version)(TPMIf *obj);
>   } TPMIfClass;
>   
> diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
> index a69593e0cd..7e166ef954 100644
> --- a/include/sysemu/tpm_backend.h
> +++ b/include/sysemu/tpm_backend.h
> @@ -18,6 +18,7 @@
>   #include "qapi-types.h"
>   #include "qemu/option.h"
>   #include "sysemu/tpm.h"
> +#include "qapi/error.h"
>   
>   #define TYPE_TPM_BACKEND "tpm-backend"
>   #define TPM_BACKEND(obj) \
> @@ -84,7 +85,7 @@ struct TPMBackendClass {
>   
>       TpmTypeOptions *(*get_tpm_options)(TPMBackend *t);
>   
> -    void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd);
> +    void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd, Error **errp);
>   };
>   
>   /**
> diff --git a/backends/tpm.c b/backends/tpm.c
> index 143807aa37..d617ba7c52 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -27,7 +27,7 @@ static void tpm_backend_request_completed(void *opaque, int ret)
>       TPMBackend *s = TPM_BACKEND(opaque);
>       TPMIfClass *tic = TPM_IF_GET_CLASS(s->tpmif);
>   
> -    tic->request_completed(s->tpmif);
> +    tic->request_completed(s->tpmif, ret);
>   
>       /* no need for atomic, as long the BQL is taken */
>       s->cmd = NULL;
> @@ -38,8 +38,13 @@ static int tpm_backend_worker_thread(gpointer data)
>   {
>       TPMBackend *s = TPM_BACKEND(data);
>       TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
> +    Error *err = NULL;
>   
> -    k->handle_request(s, s->cmd);
> +    k->handle_request(s, s->cmd, &err);
> +    if (err) {
> +        error_report_err(err);
> +        return -1;
> +    }
>   
>       return 0;
>   }
> diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
> index 35c78de5a9..52552af9f9 100644
> --- a/hw/tpm/tpm_emulator.c
> +++ b/hw/tpm/tpm_emulator.c
> @@ -185,28 +185,19 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number,
>       return 0;
>   }
>   
> -static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd)
> +static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
> +                                        Error **errp)
>   {
>       TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
> -    Error *err = NULL;
>   
>       DPRINTF("processing TPM command");
>   
> -    if (tpm_emulator_set_locality(tpm_emu, cmd->locty, &err) < 0) {
> -        goto error;
> -    }
> -
> -    if (tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
> +    if (tpm_emulator_set_locality(tpm_emu, cmd->locty, errp) < 0 ||
> +        tpm_emulator_unix_tx_bufs(tpm_emu, cmd->in, cmd->in_len,
>                                     cmd->out, cmd->out_len,
> -                                  &cmd->selftest_done, &err) < 0) {
> -        goto error;
> +                                  &cmd->selftest_done, errp) < 0) {
> +        tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
>       }
> -
> -    return;
> -
> -error:
> -    tpm_util_write_fatal_error_response(cmd->out, cmd->out_len);
> -    error_report_err(err);
>   }
>   
>   static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index f2563ac668..37dce15801 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -80,10 +80,11 @@ static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
>       }
>       return ret;
>   }
> -static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
> -                                        const uint8_t *in, uint32_t in_len,
> -                                        uint8_t *out, uint32_t out_len,
> -                                        bool *selftest_done)
> +
> +static void tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
> +                                         const uint8_t *in, uint32_t in_len,
> +                                         uint8_t *out, uint32_t out_len,
> +                                         bool *selftest_done, Error **errp)
>   {
>       ssize_t ret;
>       bool is_selftest;
> @@ -99,9 +100,8 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
>       ret = qemu_write_full(tpm_pt->tpm_fd, in, in_len);
>       if (ret != in_len) {
>           if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
> -            error_report("tpm_passthrough: error while transmitting data "
> -                         "to TPM: %s (%i)",
> -                         strerror(errno), errno);
> +            error_setg_errno(errp, errno, "tpm_passthrough: error while "
> +                             "transmitting data to TPM");
>           }
>           goto err_exit;
>       }
> @@ -111,15 +111,14 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
>       ret = tpm_passthrough_unix_read(tpm_pt->tpm_fd, out, out_len);
>       if (ret < 0) {
>           if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
> -            error_report("tpm_passthrough: error while reading data from "
> -                         "TPM: %s (%i)",
> -                         strerror(errno), errno);
> +            error_setg_errno(errp, errno, "tpm_passthrough: error while "
> +                             "reading data from TPM");
>           }
>       } else if (ret < sizeof(struct tpm_resp_hdr) ||
>                  be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
>           ret = -1;
> -        error_report("tpm_passthrough: received invalid response "
> -                     "packet from TPM");
> +        error_setg_errno(errp, errno, "tpm_passthrough: received invalid "
> +                     "response packet from TPM");
>       }
>   
>       if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) {
> @@ -133,18 +132,18 @@ err_exit:
>       }
>   
>       tpm_pt->tpm_executing = false;
> -
> -    return ret;
>   }
>   
> -static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *cmd)
> +static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *cmd,
> +                                           Error **errp)
>   {
>       TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
>   
>       DPRINTF("tpm_passthrough: processing command %p\n", cmd);
>   
>       tpm_passthrough_unix_tx_bufs(tpm_pt, cmd->in, cmd->in_len,
> -                                 cmd->out, cmd->out_len, &cmd->selftest_done);
> +                                 cmd->out, cmd->out_len, &cmd->selftest_done,
> +                                 errp);
>   }
>   
>   static void tpm_passthrough_reset(TPMBackend *tb)
> diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
> index 8b5eb01a2c..08f41d2707 100644
> --- a/hw/tpm/tpm_tis.c
> +++ b/hw/tpm/tpm_tis.c
> @@ -393,7 +393,7 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
>   /*
>    * Callback from the TPM to indicate that the response was received.
>    */
> -static void tpm_tis_request_completed(TPMIf *ti)
> +static void tpm_tis_request_completed(TPMIf *ti, int ret)
>   {
>       TPMState *s = TPM(ti);
>       uint8_t locty = s->cmd.locty;
> @@ -405,6 +405,7 @@ static void tpm_tis_request_completed(TPMIf *ti)
>           }
>       }
>   
> +    /* FIXME: report error if ret != 0 */
>       tpm_tis_sts_set(&s->loc[locty],
>                       TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
>       s->loc[locty].state = TPM_TIS_STATE_COMPLETION;

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

* Re: [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups
  2018-01-19 14:56   ` Marc-Andre Lureau
@ 2018-01-19 15:06     ` Stefan Berger
  0 siblings, 0 replies; 31+ messages in thread
From: Stefan Berger @ 2018-01-19 15:06 UTC (permalink / raw)
  To: Marc-Andre Lureau, qemu-devel; +Cc: marcandre, famz

On 01/19/2018 09:56 AM, Marc-Andre Lureau wrote:
> On Fri, Jan 19, 2018 at 3:36 PM,  <no-reply@patchew.org> wrote:
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c: In function 'tpm_crb_mmio_read':
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:126:13: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'hwaddr {aka long long unsigned int}' [-Werror=format=]
>>       DPRINTF("CRB read 0x%lx:%s len:%u\n",
>>               ^
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
>>               printf(fmt, ## __VA_ARGS__);        \
>>                      ^~~
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c: In function 'tpm_crb_mmio_write':
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:146:13: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'hwaddr {aka long long unsigned int}' [-Werror=format=]
>>       DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
>>               ^
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
>>               printf(fmt, ## __VA_ARGS__);        \
>>                      ^~~
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:146:13: error: format '%lu' expects argument of type 'long unsigned int', but argument 5 has type 'uint64_t {aka long long unsigned int}' [-Werror=format=]
>>       DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
>>               ^
>> /tmp/qemu-test/src/hw/tpm/tpm_crb.c:48:20: note: in definition of macro 'DPRINTF'
>>               printf(fmt, ## __VA_ARGS__);        \
>>                      ^~~
> This will fix it:
> Stefan feel free to squash it if no further changes required

Will do. Thanks.

>
> --- a/hw/tpm/tpm_crb.c
> +++ b/hw/tpm/tpm_crb.c
> @@ -123,7 +123,7 @@ static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
>                                     unsigned size)
>   {
>       CRBState *s = CRB(opaque);
> -    DPRINTF("CRB read 0x%lx:%s len:%u\n",
> +    DPRINTF("CRB read 0x" TARGET_FMT_plx ":%s len:%u\n",
>               addr, addr_desc(addr), size);
>       void *regs = (void *)&s->regs + addr;
>
> @@ -143,7 +143,7 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
>                                  uint64_t val, unsigned size)
>   {
>       CRBState *s = CRB(opaque);
> -    DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
> +    DPRINTF("CRB write 0x" TARGET_FMT_plx ":%s len:%u val:%" PRIu64 "\n",
>               addr, addr_desc(addr), size, val);
>
>       switch (addr) {
>

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device Marc-André Lureau
@ 2018-01-19 17:10   ` Stefan Berger
  2018-01-19 18:42     ` Eduardo Habkost
  2018-01-20 12:54   ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 31+ messages in thread
From: Stefan Berger @ 2018-01-19 17:10 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: Michael S. Tsirkin, Igor Mammedov, Paolo Bonzini,
	Richard Henderson, Eduardo Habkost, Marcel Apfelbaum, Eric Blake,
	Markus Armbruster

On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
> Specification Family “2.0” Level 00 Revision 01.03 v22.
>
> The PTP allows device implementation to switch between TIS and CRB
> model at run time, but given that CRB is a simpler device to
> implement, I chose to implement it as a different device.
>
> The device doesn't implement other locality than 0 for now (my laptop
> TPM doesn't either, so I assume this isn't so bad)
>
> The command/reply memory region is statically allocated after the CRB
> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
> wonder if the BIOS could or should allocate it instead, or what size
> to use, again this seems to fit well expectations)

I removed this last sentence now. It's at the right location.

>
> The PTP doesn't specify a particular bus to put the device. So I added
> it on the system bus directly, so it could hopefully be used easily on
> a different platform than x86. Currently, it fails to init on piix,
> because error_on_sysbus_device() check. The check may be changed in a
> near future, see discussion on the qemu-devel ML.

I think this has to be solved. So I remove these last 2 sentences. I'll 
have to wait until that other patch series from Eduard is merged since 
it doesn't start yet.

    Stefan

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-19 17:10   ` Stefan Berger
@ 2018-01-19 18:42     ` Eduardo Habkost
  2018-01-19 21:56       ` Stefan Berger
  0 siblings, 1 reply; 31+ messages in thread
From: Eduardo Habkost @ 2018-01-19 18:42 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Marc-André Lureau, qemu-devel, Michael S. Tsirkin,
	Igor Mammedov, Paolo Bonzini, Richard Henderson,
	Marcel Apfelbaum, Eric Blake, Markus Armbruster

On Fri, Jan 19, 2018 at 12:10:03PM -0500, Stefan Berger wrote:
> On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
> > tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
> > Interface as defined in TCG PC Client Platform TPM Profile (PTP)
> > Specification Family “2.0” Level 00 Revision 01.03 v22.
> > 
> > The PTP allows device implementation to switch between TIS and CRB
> > model at run time, but given that CRB is a simpler device to
> > implement, I chose to implement it as a different device.
> > 
> > The device doesn't implement other locality than 0 for now (my laptop
> > TPM doesn't either, so I assume this isn't so bad)
> > 
> > The command/reply memory region is statically allocated after the CRB
> > registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
> > wonder if the BIOS could or should allocate it instead, or what size
> > to use, again this seems to fit well expectations)
> 
> I removed this last sentence now. It's at the right location.
> 
> > 
> > The PTP doesn't specify a particular bus to put the device. So I added
> > it on the system bus directly, so it could hopefully be used easily on
> > a different platform than x86. Currently, it fails to init on piix,
> > because error_on_sysbus_device() check. The check may be changed in a
> > near future, see discussion on the qemu-devel ML.
> 
> I think this has to be solved. So I remove these last 2 sentences. I'll have
> to wait until that other patch series from Eduard is merged since it doesn't
> start yet.

The series was just merged to master.  It's possible to make a
machine accept the new device using
machine_class_allow_dynamic_sysbus_dev(), now.

However, is it really necessary to make it a sysbus device?
Having bus-less devices was not possible in the past, but it is
possible today.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-19 18:42     ` Eduardo Habkost
@ 2018-01-19 21:56       ` Stefan Berger
  2018-01-20 11:08         ` Eduardo Habkost
  0 siblings, 1 reply; 31+ messages in thread
From: Stefan Berger @ 2018-01-19 21:56 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Marc-André Lureau, qemu-devel, Michael S. Tsirkin,
	Igor Mammedov, Paolo Bonzini, Richard Henderson,
	Marcel Apfelbaum, Eric Blake, Markus Armbruster

On 01/19/2018 01:42 PM, Eduardo Habkost wrote:
> On Fri, Jan 19, 2018 at 12:10:03PM -0500, Stefan Berger wrote:
>> On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>>
>>> The PTP allows device implementation to switch between TIS and CRB
>>> model at run time, but given that CRB is a simpler device to
>>> implement, I chose to implement it as a different device.
>>>
>>> The device doesn't implement other locality than 0 for now (my laptop
>>> TPM doesn't either, so I assume this isn't so bad)
>>>
>>> The command/reply memory region is statically allocated after the CRB
>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>>> wonder if the BIOS could or should allocate it instead, or what size
>>> to use, again this seems to fit well expectations)
>> I removed this last sentence now. It's at the right location.
>>
>>> The PTP doesn't specify a particular bus to put the device. So I added
>>> it on the system bus directly, so it could hopefully be used easily on
>>> a different platform than x86. Currently, it fails to init on piix,
>>> because error_on_sysbus_device() check. The check may be changed in a
>>> near future, see discussion on the qemu-devel ML.
>> I think this has to be solved. So I remove these last 2 sentences. I'll have
>> to wait until that other patch series from Eduard is merged since it doesn't
>> start yet.
> The series was just merged to master.  It's possible to make a
> machine accept the new device using
> machine_class_allow_dynamic_sysbus_dev(), now.

I saw that.
>
> However, is it really necessary to make it a sysbus device?
> Having bus-less devices was not possible in the past, but it is
> possible today.
>
What I don't like about it is the fact that I would have to use q35 if 
we only extend that machine type to allow this sysbus device. What is 
the reason that dynamic sysbus devices have to explicitly be allowed? If 
we don't need to limit this device to a certain machine type that may be 
more user friendly.

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-19 21:56       ` Stefan Berger
@ 2018-01-20 11:08         ` Eduardo Habkost
  0 siblings, 0 replies; 31+ messages in thread
From: Eduardo Habkost @ 2018-01-20 11:08 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Marc-André Lureau, qemu-devel, Michael S. Tsirkin,
	Igor Mammedov, Paolo Bonzini, Richard Henderson,
	Marcel Apfelbaum, Eric Blake, Markus Armbruster

On Fri, Jan 19, 2018 at 04:56:31PM -0500, Stefan Berger wrote:
> On 01/19/2018 01:42 PM, Eduardo Habkost wrote:
> > On Fri, Jan 19, 2018 at 12:10:03PM -0500, Stefan Berger wrote:
> > > On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
> > > > tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
> > > > Interface as defined in TCG PC Client Platform TPM Profile (PTP)
> > > > Specification Family “2.0” Level 00 Revision 01.03 v22.
> > > > 
> > > > The PTP allows device implementation to switch between TIS and CRB
> > > > model at run time, but given that CRB is a simpler device to
> > > > implement, I chose to implement it as a different device.
> > > > 
> > > > The device doesn't implement other locality than 0 for now (my laptop
> > > > TPM doesn't either, so I assume this isn't so bad)
> > > > 
> > > > The command/reply memory region is statically allocated after the CRB
> > > > registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
> > > > wonder if the BIOS could or should allocate it instead, or what size
> > > > to use, again this seems to fit well expectations)
> > > I removed this last sentence now. It's at the right location.
> > > 
> > > > The PTP doesn't specify a particular bus to put the device. So I added
> > > > it on the system bus directly, so it could hopefully be used easily on
> > > > a different platform than x86. Currently, it fails to init on piix,
> > > > because error_on_sysbus_device() check. The check may be changed in a
> > > > near future, see discussion on the qemu-devel ML.
> > > I think this has to be solved. So I remove these last 2 sentences. I'll have
> > > to wait until that other patch series from Eduard is merged since it doesn't
> > > start yet.
> > The series was just merged to master.  It's possible to make a
> > machine accept the new device using
> > machine_class_allow_dynamic_sysbus_dev(), now.
> 
> I saw that.
> > 
> > However, is it really necessary to make it a sysbus device?
> > Having bus-less devices was not possible in the past, but it is
> > possible today.
> > 
> What I don't like about it is the fact that I would have to use q35 if we
> only extend that machine type to allow this sysbus device. What is the
> reason that dynamic sysbus devices have to explicitly be allowed? If we
> don't need to limit this device to a certain machine type that may be more
> user friendly.

Most sysbus devices don't work unless they have additional
supporting machine code to wire them at the right addresses.
Devices that work without extra machine code (like *-iommu) are
the exception.

I think the last time I saw an explanation for this was at:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg439549.html

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device Marc-André Lureau
  2018-01-19 17:10   ` Stefan Berger
@ 2018-01-20 12:54   ` Philippe Mathieu-Daudé
  2018-01-21  5:46     ` Stefan Berger
  1 sibling, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-01-20 12:54 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, stefanb, Markus Armbruster,
	Paolo Bonzini, Igor Mammedov, Marcel Apfelbaum,
	Richard Henderson

On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
> Specification Family “2.0” Level 00 Revision 01.03 v22.
> 
> The PTP allows device implementation to switch between TIS and CRB
> model at run time, but given that CRB is a simpler device to
> implement, I chose to implement it as a different device.
> 
> The device doesn't implement other locality than 0 for now (my laptop
> TPM doesn't either, so I assume this isn't so bad)
> 
> The command/reply memory region is statically allocated after the CRB
> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
> wonder if the BIOS could or should allocate it instead, or what size
> to use, again this seems to fit well expectations)
> 
> The PTP doesn't specify a particular bus to put the device. So I added
> it on the system bus directly, so it could hopefully be used easily on
> a different platform than x86. Currently, it fails to init on piix,
> because error_on_sysbus_device() check. The check may be changed in a
> near future, see discussion on the qemu-devel ML.
> 
> Tested with some success with Linux upstream and Windows 10, seabios &
> modified ovmf. The device is recognized and correctly transmit
> command/response with passthrough & emu. However, we are missing PPI
> ACPI part atm.
> 
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> ---
>  qapi/tpm.json                      |   5 +-
>  include/hw/acpi/tpm.h              |  72 ++++++++
>  include/sysemu/tpm.h               |   3 +
>  hw/i386/acpi-build.c               |  34 +++-
>  hw/tpm/tpm_crb.c                   | 327 +++++++++++++++++++++++++++++++++++++
>  default-configs/i386-softmmu.mak   |   1 +
>  default-configs/x86_64-softmmu.mak |   1 +
>  hw/tpm/Makefile.objs               |   1 +
>  8 files changed, 434 insertions(+), 10 deletions(-)
>  create mode 100644 hw/tpm/tpm_crb.c
> 
> diff --git a/qapi/tpm.json b/qapi/tpm.json
> index 7093f268fb..d50deef5e9 100644
> --- a/qapi/tpm.json
> +++ b/qapi/tpm.json
> @@ -11,10 +11,11 @@
>  # An enumeration of TPM models
>  #
>  # @tpm-tis: TPM TIS model
> +# @tpm-crb: TPM CRB model (since 2.12)
>  #
>  # Since: 1.5
>  ##
> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>  
>  ##
>  # @query-tpm-models:
> @@ -28,7 +29,7 @@
>  # Example:
>  #
>  # -> { "execute": "query-tpm-models" }
> -# <- { "return": [ "tpm-tis" ] }
> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>  #
>  ##
>  { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
> index 6d516c6a7f..b0048515fa 100644
> --- a/include/hw/acpi/tpm.h
> +++ b/include/hw/acpi/tpm.h
> @@ -16,11 +16,82 @@
>  #ifndef HW_ACPI_TPM_H
>  #define HW_ACPI_TPM_H
>  
> +#include "qemu/osdep.h"
> +
>  #define TPM_TIS_ADDR_BASE           0xFED40000
>  #define TPM_TIS_ADDR_SIZE           0x5000
>  
>  #define TPM_TIS_IRQ                 5
>  
> +struct crb_regs {
> +    union {
> +        uint32_t reg;
> +        struct {
> +            unsigned tpm_established:1;
> +            unsigned loc_assigned:1;
> +            unsigned active_locality:3;
> +            unsigned reserved:2;
> +            unsigned tpm_reg_valid_sts:1;
> +        } bits;

I suppose this is little-endian layout, so this won't work on big-endian
hosts.

Can you add a qtest?

> +    } loc_state;
> +    uint32_t reserved1;
> +    uint32_t loc_ctrl;
> +    union {
> +        uint32_t reg;
> +        struct {
> +            unsigned granted:1;
> +            unsigned been_seized:1;
> +        } bits;


This is unclear where you expect those bits (right/left aligned).

Can you add an unnamed field to be more explicit?

i.e. without using struct if left alignment expected:

           unsigned granted:1, been_seized:1, :30;

> +    } loc_sts;
> +    uint8_t reserved2[32];
> +    union {
> +        uint64_t reg;
> +        struct {
> +            unsigned type:4;
> +            unsigned version:4;
> +            unsigned cap_locality:1;
> +            unsigned cap_crb_idle_bypass:1;
> +            unsigned reserved1:1;
> +            unsigned cap_data_xfer_size_support:2;
> +            unsigned cap_fifo:1;
> +            unsigned cap_crb:1;
> +            unsigned cap_if_res:2;
> +            unsigned if_selector:2;
> +            unsigned if_selector_lock:1;
> +            unsigned reserved2:4;
> +            unsigned rid:8;
> +            unsigned vid:16;
> +            unsigned did:16;
> +        } bits;
> +    } intf_id;
> +    uint64_t ctrl_ext;
> +
> +    uint32_t ctrl_req;
> +    union {
> +        uint32_t reg;
> +        struct {
> +            unsigned tpm_sts:1;
> +            unsigned tpm_idle:1;
> +            unsigned reserved:30;

Oh here you use 'reserved' to left align.

> +        } bits;
> +    } ctrl_sts;
> +    uint32_t ctrl_cancel;
> +    uint32_t ctrl_start;
> +    uint32_t ctrl_int_enable;
> +    uint32_t ctrl_int_sts;
> +    uint32_t ctrl_cmd_size;
> +    uint32_t ctrl_cmd_pa_low;
> +    uint32_t ctrl_cmd_pa_high;
> +    uint32_t ctrl_rsp_size;
> +    uint64_t ctrl_rsp_pa;
> +    uint8_t reserved3[0x10];
> +} QEMU_PACKED;
> +
> +#define TPM_CRB_ADDR_BASE           0xFED40000
> +#define TPM_CRB_ADDR_SIZE           0x1000
> +#define TPM_CRB_ADDR_CTRL \
> +    (TPM_CRB_ADDR_BASE + offsetof(struct crb_regs, ctrl_req))
> +
>  #define TPM_LOG_AREA_MINIMUM_SIZE   (64 * 1024)
>  
>  #define TPM_TCPA_ACPI_CLASS_CLIENT  0
> @@ -30,5 +101,6 @@
>  #define TPM2_ACPI_CLASS_SERVER      1
>  
>  #define TPM2_START_METHOD_MMIO      6
> +#define TPM2_START_METHOD_CRB       7
>  
>  #endif /* HW_ACPI_TPM_H */
> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> index ac04a9d4a2..233b1a3fc3 100644
> --- a/include/sysemu/tpm.h
> +++ b/include/sysemu/tpm.h
> @@ -46,9 +46,12 @@ typedef struct TPMIfClass {
>  } TPMIfClass;
>  
>  #define TYPE_TPM_TIS                "tpm-tis"
> +#define TYPE_TPM_CRB                "tpm-crb"
>  
>  #define TPM_IS_TIS(chr)                             \
>      object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
> +#define TPM_IS_CRB(chr)                             \
> +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
>  
>  /* returns NULL unless there is exactly one TPM device */
>  static inline TPMIf *tpm_find(void)
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index dc4b2b9ffe..ed78c4ed9f 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -2224,6 +2224,22 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>              aml_append(sb_scope, scope);
>          }
>      }
> +
> +    if (TPM_IS_CRB(tpm_find())) {
> +        dev = aml_device("TPM");
> +        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> +        crs = aml_resource_template();
> +        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> +                                           TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
> +        aml_append(dev, aml_name_decl("_CRS", crs));
> +
> +        method = aml_method("_STA", 0, AML_NOTSERIALIZED);
> +        aml_append(method, aml_return(aml_int(0x0f)));
> +        aml_append(dev, method);
> +
> +        aml_append(sb_scope, dev);
> +    }
> +
>      aml_append(dsdt, sb_scope);
>  
>      /* copy AML table into ACPI tables blob and patch header there */
> @@ -2285,18 +2301,20 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
>      if (TPM_IS_TIS(tpm_find())) {
>          tpm2_ptr->control_area_address = cpu_to_le64(0);
>          tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
> -
> -        tpm2_ptr->log_area_minimum_length =
> -            cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
> -
> -        /* log area start address to be filled by Guest linker */
> -        bios_linker_loader_add_pointer(linker,
> -            ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
> -            ACPI_BUILD_TPMLOG_FILE, 0);
> +    } else if (TPM_IS_CRB(tpm_find())) {
> +        tpm2_ptr->control_area_address = cpu_to_le64(TPM_CRB_ADDR_CTRL);
> +        tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_CRB);
>      } else {
>          g_warn_if_reached();
>      }
>  
> +    tpm2_ptr->log_area_minimum_length =
> +        cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
> +
> +    /* log area start address to be filled by Guest linker */
> +    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
> +                                   log_addr_offset, log_addr_size,
> +                                   ACPI_BUILD_TPMLOG_FILE, 0);
>      build_header(linker, table_data,
>                   (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL);
>  }
> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> new file mode 100644
> index 0000000000..908ca18d92
> --- /dev/null
> +++ b/hw/tpm/tpm_crb.c
> @@ -0,0 +1,327 @@
> +/*
> + * tpm_crb.c - QEMU's TPM CRB interface emulator
> + *
> + * Copyright (c) 2017 Red Hat, Inc.
> + *
> + * Authors:
> + *   Marc-André Lureau <marcandre.lureau@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + *
> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
> + * Family “2.0” Level 00 Revision 01.03 v22
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include "qemu-common.h"
> +#include "qapi/error.h"
> +#include "hw/sysbus.h"
> +#include "exec/address-spaces.h"
> +
> +#include "hw/pci/pci_ids.h"
> +#include "hw/acpi/tpm.h"
> +#include "sysemu/tpm_backend.h"
> +#include "tpm_int.h"
> +#include "tpm_util.h"
> +
> +typedef struct CRBState {
> +    SysBusDevice parent_obj;
> +
> +    TPMBackend *tpmbe;
> +    TPMBackendCmd cmd;
> +    struct crb_regs regs;
> +    MemoryRegion mmio;
> +    MemoryRegion cmdmem;
> +
> +    size_t be_buffer_size;
> +} CRBState;
> +
> +#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB)
> +
> +#define DEBUG_CRB 0
> +
> +#define DPRINTF(fmt, ...) do {                  \
> +        if (DEBUG_CRB) {                        \
> +            printf(fmt, ## __VA_ARGS__);        \
> +        }                                       \
> +    } while (0)
> +
> +#define CRB_ADDR_LOC_STATE offsetof(struct crb_regs, loc_state)
> +#define CRB_ADDR_LOC_CTRL offsetof(struct crb_regs, loc_ctrl)
> +#define CRB_ADDR_CTRL_REQ offsetof(struct crb_regs, ctrl_req)
> +#define CRB_ADDR_CTRL_CANCEL offsetof(struct crb_regs, ctrl_cancel)
> +#define CRB_ADDR_CTRL_START offsetof(struct crb_regs, ctrl_start)
> +
> +#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
> +#define CRB_INTF_VERSION_CRB 0b1
> +#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
> +#define CRB_INTF_CAP_IDLE_FAST 0b0
> +#define CRB_INTF_CAP_XFER_SIZE_64 0b11
> +#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
> +#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
> +#define CRB_INTF_IF_SELECTOR_CRB 0b1
> +#define CRB_INTF_IF_SELECTOR_UNLOCKED 0b0
> +
> +#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs))
> +
> +enum crb_loc_ctrl {
> +    CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
> +    CRB_LOC_CTRL_RELINQUISH = BIT(1),
> +    CRB_LOC_CTRL_SEIZE = BIT(2),
> +    CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
> +};
> +
> +enum crb_ctrl_req {
> +    CRB_CTRL_REQ_CMD_READY = BIT(0),
> +    CRB_CTRL_REQ_GO_IDLE = BIT(1),
> +};
> +
> +enum crb_start {
> +    CRB_START_INVOKE = BIT(0),
> +};
> +
> +enum crb_cancel {
> +    CRB_CANCEL_INVOKE = BIT(0),
> +};
> +
> +static const char *addr_desc(unsigned off)
> +{
> +    struct crb_regs crb;
> +
> +    switch (off) {
> +#define CASE(field)                                                 \
> +    case offsetof(struct crb_regs, field) ...                       \
> +        offsetof(struct crb_regs, field) + sizeof(crb.field) - 1:   \
> +        return G_STRINGIFY(field);
> +        CASE(loc_state);
> +        CASE(reserved1);
> +        CASE(loc_ctrl);
> +        CASE(loc_sts);
> +        CASE(reserved2);
> +        CASE(intf_id);
> +        CASE(ctrl_ext);
> +        CASE(ctrl_req);
> +        CASE(ctrl_sts);
> +        CASE(ctrl_cancel);
> +        CASE(ctrl_start);
> +        CASE(ctrl_int_enable);
> +        CASE(ctrl_int_sts);
> +        CASE(ctrl_cmd_size);
> +        CASE(ctrl_cmd_pa_low);
> +        CASE(ctrl_cmd_pa_high);
> +        CASE(ctrl_rsp_size);
> +        CASE(ctrl_rsp_pa);
> +#undef CASE
> +    }
> +    return NULL;
> +}
> +
> +static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
> +                                  unsigned size)
> +{
> +    CRBState *s = CRB(opaque);
> +    DPRINTF("CRB read 0x%lx:%s len:%u\n",
> +            addr, addr_desc(addr), size);
> +    void *regs = (void *)&s->regs + addr;
> +
> +    switch (size) {
> +    case 1:
> +        return *(uint8_t *)regs;
> +    case 2:
> +        return *(uint16_t *)regs;
> +    case 4:
> +        return *(uint32_t *)regs;
> +    default:
> +        g_return_val_if_reached(-1);
> +    }
> +}
> +
> +static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
> +                               uint64_t val, unsigned size)
> +{
> +    CRBState *s = CRB(opaque);
> +    DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
> +            addr, addr_desc(addr), size, val);
> +
> +    switch (addr) {
> +    case CRB_ADDR_CTRL_REQ:
> +        switch (val) {
> +        case CRB_CTRL_REQ_CMD_READY:
> +            s->regs.ctrl_sts.bits.tpm_idle = 0;
> +            break;
> +        case CRB_CTRL_REQ_GO_IDLE:
> +            s->regs.ctrl_sts.bits.tpm_idle = 1;
> +            break;
> +        }
> +        break;
> +    case CRB_ADDR_CTRL_CANCEL:
> +        if (val == CRB_CANCEL_INVOKE && s->regs.ctrl_start & CRB_START_INVOKE) {
> +            tpm_backend_cancel_cmd(s->tpmbe);
> +        }
> +        break;
> +    case CRB_ADDR_CTRL_START:
> +        if (val == CRB_START_INVOKE &&
> +            !(s->regs.ctrl_start & CRB_START_INVOKE)) {
> +            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
> +
> +            s->regs.ctrl_start |= CRB_START_INVOKE;
> +            s->cmd = (TPMBackendCmd) {
> +                .in = mem,
> +                .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
> +                .out = mem,
> +                .out_len = s->be_buffer_size,
> +            };
> +
> +            tpm_backend_deliver_request(s->tpmbe, &s->cmd);
> +        }
> +        break;
> +    case CRB_ADDR_LOC_CTRL:
> +        switch (val) {
> +        case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
> +            /* not loc 3 or 4 */
> +            break;
> +        case CRB_LOC_CTRL_RELINQUISH:
> +            break;
> +        case CRB_LOC_CTRL_REQUEST_ACCESS:
> +            s->regs.loc_sts.bits.granted = 1;
> +            s->regs.loc_sts.bits.been_seized = 0;
> +            s->regs.loc_state.bits.loc_assigned = 1;
> +            s->regs.loc_state.bits.tpm_reg_valid_sts = 1;
> +            break;
> +        }
> +        break;
> +    }
> +}
> +
> +static const MemoryRegionOps tpm_crb_memory_ops = {
> +    .read = tpm_crb_mmio_read,
> +    .write = tpm_crb_mmio_write,
> +    .endianness = DEVICE_LITTLE_ENDIAN,
> +    .valid = {
> +        .min_access_size = 1,
> +        .max_access_size = 4,
> +    },
> +};
> +
> +static void tpm_crb_reset(DeviceState *dev)
> +{
> +    CRBState *s = CRB(dev);
> +
> +    tpm_backend_reset(s->tpmbe);
> +
> +    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
> +                            CRB_CTRL_CMD_SIZE);
> +
> +    s->regs = (struct crb_regs) {
> +        .intf_id.bits = {
> +            .type = CRB_INTF_TYPE_CRB_ACTIVE,
> +            .version = CRB_INTF_VERSION_CRB,
> +            .cap_locality = CRB_INTF_CAP_LOCALITY_0_ONLY,
> +            .cap_crb_idle_bypass = CRB_INTF_CAP_IDLE_FAST,
> +            .cap_data_xfer_size_support = CRB_INTF_CAP_XFER_SIZE_64,
> +            .cap_fifo = CRB_INTF_CAP_FIFO_NOT_SUPPORTED,
> +            .cap_crb = CRB_INTF_CAP_CRB_SUPPORTED,
> +            .cap_if_res = 0b0,
> +            .if_selector = CRB_INTF_IF_SELECTOR_CRB,
> +            .if_selector_lock = CRB_INTF_IF_SELECTOR_UNLOCKED,
> +            .rid = 0b0001,
> +            .vid = PCI_VENDOR_ID_IBM,
> +            .did = 0b0001,
> +        },
> +        .ctrl_cmd_size = CRB_CTRL_CMD_SIZE,
> +        .ctrl_cmd_pa_low = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
> +        .ctrl_rsp_size = CRB_CTRL_CMD_SIZE,
> +        .ctrl_rsp_pa = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
> +    };
> +
> +    tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size);
> +}
> +
> +static void tpm_crb_request_completed(TPMIf *ti, int ret)
> +{
> +    CRBState *s = CRB(ti);
> +
> +    s->regs.ctrl_start &= ~CRB_START_INVOKE;
> +    if (ret != 0) {
> +        s->regs.ctrl_sts.bits.tpm_sts = 1; /* fatal error */
> +    }
> +}
> +
> +static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
> +{
> +    CRBState *s = CRB(ti);
> +
> +    return tpm_backend_get_tpm_version(s->tpmbe);
> +}
> +
> +static const VMStateDescription vmstate_tpm_crb = {
> +    .name = "tpm-crb",
> +    .unmigratable = 1,
> +};
> +
> +static Property tpm_crb_properties[] = {
> +    DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void tpm_crb_realizefn(DeviceState *dev, Error **errp)
> +{
> +    CRBState *s = CRB(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +
> +    if (!tpm_find()) {
> +        error_setg(errp, "at most one TPM device is permitted");
> +        return;
> +    }
> +    if (!s->tpmbe) {
> +        error_setg(errp, "'tpmdev' property is required");
> +        return;
> +    }
> +
> +    memory_region_init_io(&s->mmio, OBJECT(s), &tpm_crb_memory_ops, s,
> +        "tpm-crb-mmio", sizeof(struct crb_regs));
> +    memory_region_init_ram(&s->cmdmem, OBJECT(s),
> +        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
> +
> +    sysbus_init_mmio(sbd, &s->mmio);
> +    sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE);
> +    /* allocate ram in bios instead? */
> +    memory_region_add_subregion(get_system_memory(),
> +        TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), &s->cmdmem);
> +}
> +
> +static void tpm_crb_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    TPMIfClass *tc = TPM_IF_CLASS(klass);
> +
> +    dc->realize = tpm_crb_realizefn;
> +    dc->props = tpm_crb_properties;
> +    dc->reset = tpm_crb_reset;
> +    dc->vmsd  = &vmstate_tpm_crb;
> +    dc->user_creatable = true;
> +    tc->model = TPM_MODEL_TPM_CRB;
> +    tc->get_version = tpm_crb_get_version;
> +    tc->request_completed = tpm_crb_request_completed;
> +}
> +
> +static const TypeInfo tpm_crb_info = {
> +    .name = TYPE_TPM_CRB,
> +    .parent = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(CRBState),
> +    .class_init  = tpm_crb_class_init,
> +    .interfaces = (InterfaceInfo[]) {
> +        { TYPE_TPM_IF },
> +        { }
> +    }
> +};
> +
> +static void tpm_crb_register(void)
> +{
> +    type_register_static(&tpm_crb_info);
> +}
> +
> +type_init(tpm_crb_register)
> diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
> index 95ac4b464a..ac27700e79 100644
> --- a/default-configs/i386-softmmu.mak
> +++ b/default-configs/i386-softmmu.mak
> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>  CONFIG_I8259=y
>  CONFIG_PFLASH_CFI01=y
>  CONFIG_TPM_TIS=$(CONFIG_TPM)
> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>  CONFIG_MC146818RTC=y
>  CONFIG_PCI_PIIX=y
>  CONFIG_WDT_IB700=y
> diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
> index 0221236825..b2104ade19 100644
> --- a/default-configs/x86_64-softmmu.mak
> +++ b/default-configs/x86_64-softmmu.mak
> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>  CONFIG_I8259=y
>  CONFIG_PFLASH_CFI01=y
>  CONFIG_TPM_TIS=$(CONFIG_TPM)
> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>  CONFIG_MC146818RTC=y
>  CONFIG_PCI_PIIX=y
>  CONFIG_WDT_IB700=y
> diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
> index 7a93b24636..1dc9f8bf2c 100644
> --- a/hw/tpm/Makefile.objs
> +++ b/hw/tpm/Makefile.objs
> @@ -1,4 +1,5 @@
>  common-obj-y += tpm_util.o
>  common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
> +common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
>  common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
>  common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
> 

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-20 12:54   ` Philippe Mathieu-Daudé
@ 2018-01-21  5:46     ` Stefan Berger
  2018-01-21 19:24       ` Marc-Andre Lureau
  2018-01-21 22:50       ` Philippe Mathieu-Daudé
  0 siblings, 2 replies; 31+ messages in thread
From: Stefan Berger @ 2018-01-21  5:46 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Marc-André Lureau, qemu-devel
  Cc: Eduardo Habkost, Michael S. Tsirkin, Markus Armbruster,
	Paolo Bonzini, Igor Mammedov, Marcel Apfelbaum,
	Richard Henderson

On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>
>> The PTP allows device implementation to switch between TIS and CRB
>> model at run time, but given that CRB is a simpler device to
>> implement, I chose to implement it as a different device.
>>
>> The device doesn't implement other locality than 0 for now (my laptop
>> TPM doesn't either, so I assume this isn't so bad)
>>
>> The command/reply memory region is statically allocated after the CRB
>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>> wonder if the BIOS could or should allocate it instead, or what size
>> to use, again this seems to fit well expectations)
>>
>> The PTP doesn't specify a particular bus to put the device. So I added
>> it on the system bus directly, so it could hopefully be used easily on
>> a different platform than x86. Currently, it fails to init on piix,
>> because error_on_sysbus_device() check. The check may be changed in a
>> near future, see discussion on the qemu-devel ML.
>>
>> Tested with some success with Linux upstream and Windows 10, seabios &
>> modified ovmf. The device is recognized and correctly transmit
>> command/response with passthrough & emu. However, we are missing PPI
>> ACPI part atm.
>>
>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>> ---
>>   qapi/tpm.json                      |   5 +-
>>   include/hw/acpi/tpm.h              |  72 ++++++++
>>   include/sysemu/tpm.h               |   3 +
>>   hw/i386/acpi-build.c               |  34 +++-
>>   hw/tpm/tpm_crb.c                   | 327 +++++++++++++++++++++++++++++++++++++
>>   default-configs/i386-softmmu.mak   |   1 +
>>   default-configs/x86_64-softmmu.mak |   1 +
>>   hw/tpm/Makefile.objs               |   1 +
>>   8 files changed, 434 insertions(+), 10 deletions(-)
>>   create mode 100644 hw/tpm/tpm_crb.c
>>
>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>> index 7093f268fb..d50deef5e9 100644
>> --- a/qapi/tpm.json
>> +++ b/qapi/tpm.json
>> @@ -11,10 +11,11 @@
>>   # An enumeration of TPM models
>>   #
>>   # @tpm-tis: TPM TIS model
>> +# @tpm-crb: TPM CRB model (since 2.12)
>>   #
>>   # Since: 1.5
>>   ##
>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>>   
>>   ##
>>   # @query-tpm-models:
>> @@ -28,7 +29,7 @@
>>   # Example:
>>   #
>>   # -> { "execute": "query-tpm-models" }
>> -# <- { "return": [ "tpm-tis" ] }
>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>>   #
>>   ##
>>   { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>> index 6d516c6a7f..b0048515fa 100644
>> --- a/include/hw/acpi/tpm.h
>> +++ b/include/hw/acpi/tpm.h
>> @@ -16,11 +16,82 @@
>>   #ifndef HW_ACPI_TPM_H
>>   #define HW_ACPI_TPM_H
>>   
>> +#include "qemu/osdep.h"
>> +
>>   #define TPM_TIS_ADDR_BASE           0xFED40000
>>   #define TPM_TIS_ADDR_SIZE           0x5000
>>   
>>   #define TPM_TIS_IRQ                 5
>>   
>> +struct crb_regs {
>> +    union {
>> +        uint32_t reg;
>> +        struct {
>> +            unsigned tpm_established:1;
>> +            unsigned loc_assigned:1;
>> +            unsigned active_locality:3;
>> +            unsigned reserved:2;
>> +            unsigned tpm_reg_valid_sts:1;
>> +        } bits;
> I suppose this is little-endian layout, so this won't work on big-endian
> hosts.
>
> Can you add a qtest?
>
>> +    } loc_state;
>> +    uint32_t reserved1;
>> +    uint32_t loc_ctrl;
>> +    union {
>> +        uint32_t reg;
>> +        struct {
>> +            unsigned granted:1;
>> +            unsigned been_seized:1;
>> +        } bits;
>
> This is unclear where you expect those bits (right/left aligned).
>
> Can you add an unnamed field to be more explicit?
>
> i.e. without using struct if left alignment expected:
>
>             unsigned granted:1, been_seized:1, :30;


I got rid of all the bitfields and this patch here makes it work on a 
ppc64 big endian and also x86_64 host:

https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd

Regards,
     Stefan


>
>> +    } loc_sts;
>> +    uint8_t reserved2[32];
>> +    union {
>> +        uint64_t reg;
>> +        struct {
>> +            unsigned type:4;
>> +            unsigned version:4;
>> +            unsigned cap_locality:1;
>> +            unsigned cap_crb_idle_bypass:1;
>> +            unsigned reserved1:1;
>> +            unsigned cap_data_xfer_size_support:2;
>> +            unsigned cap_fifo:1;
>> +            unsigned cap_crb:1;
>> +            unsigned cap_if_res:2;
>> +            unsigned if_selector:2;
>> +            unsigned if_selector_lock:1;
>> +            unsigned reserved2:4;
>> +            unsigned rid:8;
>> +            unsigned vid:16;
>> +            unsigned did:16;
>> +        } bits;
>> +    } intf_id;
>> +    uint64_t ctrl_ext;
>> +
>> +    uint32_t ctrl_req;
>> +    union {
>> +        uint32_t reg;
>> +        struct {
>> +            unsigned tpm_sts:1;
>> +            unsigned tpm_idle:1;
>> +            unsigned reserved:30;
> Oh here you use 'reserved' to left align.
>
>> +        } bits;
>> +    } ctrl_sts;
>> +    uint32_t ctrl_cancel;
>> +    uint32_t ctrl_start;
>> +    uint32_t ctrl_int_enable;
>> +    uint32_t ctrl_int_sts;
>> +    uint32_t ctrl_cmd_size;
>> +    uint32_t ctrl_cmd_pa_low;
>> +    uint32_t ctrl_cmd_pa_high;
>> +    uint32_t ctrl_rsp_size;
>> +    uint64_t ctrl_rsp_pa;
>> +    uint8_t reserved3[0x10];
>> +} QEMU_PACKED;
>> +
>> +#define TPM_CRB_ADDR_BASE           0xFED40000
>> +#define TPM_CRB_ADDR_SIZE           0x1000
>> +#define TPM_CRB_ADDR_CTRL \
>> +    (TPM_CRB_ADDR_BASE + offsetof(struct crb_regs, ctrl_req))
>> +
>>   #define TPM_LOG_AREA_MINIMUM_SIZE   (64 * 1024)
>>   
>>   #define TPM_TCPA_ACPI_CLASS_CLIENT  0
>> @@ -30,5 +101,6 @@
>>   #define TPM2_ACPI_CLASS_SERVER      1
>>   
>>   #define TPM2_START_METHOD_MMIO      6
>> +#define TPM2_START_METHOD_CRB       7
>>   
>>   #endif /* HW_ACPI_TPM_H */
>> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
>> index ac04a9d4a2..233b1a3fc3 100644
>> --- a/include/sysemu/tpm.h
>> +++ b/include/sysemu/tpm.h
>> @@ -46,9 +46,12 @@ typedef struct TPMIfClass {
>>   } TPMIfClass;
>>   
>>   #define TYPE_TPM_TIS                "tpm-tis"
>> +#define TYPE_TPM_CRB                "tpm-crb"
>>   
>>   #define TPM_IS_TIS(chr)                             \
>>       object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
>> +#define TPM_IS_CRB(chr)                             \
>> +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
>>   
>>   /* returns NULL unless there is exactly one TPM device */
>>   static inline TPMIf *tpm_find(void)
>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>> index dc4b2b9ffe..ed78c4ed9f 100644
>> --- a/hw/i386/acpi-build.c
>> +++ b/hw/i386/acpi-build.c
>> @@ -2224,6 +2224,22 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>>               aml_append(sb_scope, scope);
>>           }
>>       }
>> +
>> +    if (TPM_IS_CRB(tpm_find())) {
>> +        dev = aml_device("TPM");
>> +        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
>> +        crs = aml_resource_template();
>> +        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
>> +                                           TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
>> +        aml_append(dev, aml_name_decl("_CRS", crs));
>> +
>> +        method = aml_method("_STA", 0, AML_NOTSERIALIZED);
>> +        aml_append(method, aml_return(aml_int(0x0f)));
>> +        aml_append(dev, method);
>> +
>> +        aml_append(sb_scope, dev);
>> +    }
>> +
>>       aml_append(dsdt, sb_scope);
>>   
>>       /* copy AML table into ACPI tables blob and patch header there */
>> @@ -2285,18 +2301,20 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
>>       if (TPM_IS_TIS(tpm_find())) {
>>           tpm2_ptr->control_area_address = cpu_to_le64(0);
>>           tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
>> -
>> -        tpm2_ptr->log_area_minimum_length =
>> -            cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
>> -
>> -        /* log area start address to be filled by Guest linker */
>> -        bios_linker_loader_add_pointer(linker,
>> -            ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
>> -            ACPI_BUILD_TPMLOG_FILE, 0);
>> +    } else if (TPM_IS_CRB(tpm_find())) {
>> +        tpm2_ptr->control_area_address = cpu_to_le64(TPM_CRB_ADDR_CTRL);
>> +        tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_CRB);
>>       } else {
>>           g_warn_if_reached();
>>       }
>>   
>> +    tpm2_ptr->log_area_minimum_length =
>> +        cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
>> +
>> +    /* log area start address to be filled by Guest linker */
>> +    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
>> +                                   log_addr_offset, log_addr_size,
>> +                                   ACPI_BUILD_TPMLOG_FILE, 0);
>>       build_header(linker, table_data,
>>                    (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL);
>>   }
>> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
>> new file mode 100644
>> index 0000000000..908ca18d92
>> --- /dev/null
>> +++ b/hw/tpm/tpm_crb.c
>> @@ -0,0 +1,327 @@
>> +/*
>> + * tpm_crb.c - QEMU's TPM CRB interface emulator
>> + *
>> + * Copyright (c) 2017 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *   Marc-André Lureau <marcandre.lureau@redhat.com>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + *
>> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
>> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
>> + * Family “2.0” Level 00 Revision 01.03 v22
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +
>> +#include "qemu-common.h"
>> +#include "qapi/error.h"
>> +#include "hw/sysbus.h"
>> +#include "exec/address-spaces.h"
>> +
>> +#include "hw/pci/pci_ids.h"
>> +#include "hw/acpi/tpm.h"
>> +#include "sysemu/tpm_backend.h"
>> +#include "tpm_int.h"
>> +#include "tpm_util.h"
>> +
>> +typedef struct CRBState {
>> +    SysBusDevice parent_obj;
>> +
>> +    TPMBackend *tpmbe;
>> +    TPMBackendCmd cmd;
>> +    struct crb_regs regs;
>> +    MemoryRegion mmio;
>> +    MemoryRegion cmdmem;
>> +
>> +    size_t be_buffer_size;
>> +} CRBState;
>> +
>> +#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB)
>> +
>> +#define DEBUG_CRB 0
>> +
>> +#define DPRINTF(fmt, ...) do {                  \
>> +        if (DEBUG_CRB) {                        \
>> +            printf(fmt, ## __VA_ARGS__);        \
>> +        }                                       \
>> +    } while (0)
>> +
>> +#define CRB_ADDR_LOC_STATE offsetof(struct crb_regs, loc_state)
>> +#define CRB_ADDR_LOC_CTRL offsetof(struct crb_regs, loc_ctrl)
>> +#define CRB_ADDR_CTRL_REQ offsetof(struct crb_regs, ctrl_req)
>> +#define CRB_ADDR_CTRL_CANCEL offsetof(struct crb_regs, ctrl_cancel)
>> +#define CRB_ADDR_CTRL_START offsetof(struct crb_regs, ctrl_start)
>> +
>> +#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
>> +#define CRB_INTF_VERSION_CRB 0b1
>> +#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
>> +#define CRB_INTF_CAP_IDLE_FAST 0b0
>> +#define CRB_INTF_CAP_XFER_SIZE_64 0b11
>> +#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
>> +#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
>> +#define CRB_INTF_IF_SELECTOR_CRB 0b1
>> +#define CRB_INTF_IF_SELECTOR_UNLOCKED 0b0
>> +
>> +#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs))
>> +
>> +enum crb_loc_ctrl {
>> +    CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
>> +    CRB_LOC_CTRL_RELINQUISH = BIT(1),
>> +    CRB_LOC_CTRL_SEIZE = BIT(2),
>> +    CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
>> +};
>> +
>> +enum crb_ctrl_req {
>> +    CRB_CTRL_REQ_CMD_READY = BIT(0),
>> +    CRB_CTRL_REQ_GO_IDLE = BIT(1),
>> +};
>> +
>> +enum crb_start {
>> +    CRB_START_INVOKE = BIT(0),
>> +};
>> +
>> +enum crb_cancel {
>> +    CRB_CANCEL_INVOKE = BIT(0),
>> +};
>> +
>> +static const char *addr_desc(unsigned off)
>> +{
>> +    struct crb_regs crb;
>> +
>> +    switch (off) {
>> +#define CASE(field)                                                 \
>> +    case offsetof(struct crb_regs, field) ...                       \
>> +        offsetof(struct crb_regs, field) + sizeof(crb.field) - 1:   \
>> +        return G_STRINGIFY(field);
>> +        CASE(loc_state);
>> +        CASE(reserved1);
>> +        CASE(loc_ctrl);
>> +        CASE(loc_sts);
>> +        CASE(reserved2);
>> +        CASE(intf_id);
>> +        CASE(ctrl_ext);
>> +        CASE(ctrl_req);
>> +        CASE(ctrl_sts);
>> +        CASE(ctrl_cancel);
>> +        CASE(ctrl_start);
>> +        CASE(ctrl_int_enable);
>> +        CASE(ctrl_int_sts);
>> +        CASE(ctrl_cmd_size);
>> +        CASE(ctrl_cmd_pa_low);
>> +        CASE(ctrl_cmd_pa_high);
>> +        CASE(ctrl_rsp_size);
>> +        CASE(ctrl_rsp_pa);
>> +#undef CASE
>> +    }
>> +    return NULL;
>> +}
>> +
>> +static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
>> +                                  unsigned size)
>> +{
>> +    CRBState *s = CRB(opaque);
>> +    DPRINTF("CRB read 0x%lx:%s len:%u\n",
>> +            addr, addr_desc(addr), size);
>> +    void *regs = (void *)&s->regs + addr;
>> +
>> +    switch (size) {
>> +    case 1:
>> +        return *(uint8_t *)regs;
>> +    case 2:
>> +        return *(uint16_t *)regs;
>> +    case 4:
>> +        return *(uint32_t *)regs;
>> +    default:
>> +        g_return_val_if_reached(-1);
>> +    }
>> +}
>> +
>> +static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
>> +                               uint64_t val, unsigned size)
>> +{
>> +    CRBState *s = CRB(opaque);
>> +    DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
>> +            addr, addr_desc(addr), size, val);
>> +
>> +    switch (addr) {
>> +    case CRB_ADDR_CTRL_REQ:
>> +        switch (val) {
>> +        case CRB_CTRL_REQ_CMD_READY:
>> +            s->regs.ctrl_sts.bits.tpm_idle = 0;
>> +            break;
>> +        case CRB_CTRL_REQ_GO_IDLE:
>> +            s->regs.ctrl_sts.bits.tpm_idle = 1;
>> +            break;
>> +        }
>> +        break;
>> +    case CRB_ADDR_CTRL_CANCEL:
>> +        if (val == CRB_CANCEL_INVOKE && s->regs.ctrl_start & CRB_START_INVOKE) {
>> +            tpm_backend_cancel_cmd(s->tpmbe);
>> +        }
>> +        break;
>> +    case CRB_ADDR_CTRL_START:
>> +        if (val == CRB_START_INVOKE &&
>> +            !(s->regs.ctrl_start & CRB_START_INVOKE)) {
>> +            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
>> +
>> +            s->regs.ctrl_start |= CRB_START_INVOKE;
>> +            s->cmd = (TPMBackendCmd) {
>> +                .in = mem,
>> +                .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
>> +                .out = mem,
>> +                .out_len = s->be_buffer_size,
>> +            };
>> +
>> +            tpm_backend_deliver_request(s->tpmbe, &s->cmd);
>> +        }
>> +        break;
>> +    case CRB_ADDR_LOC_CTRL:
>> +        switch (val) {
>> +        case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
>> +            /* not loc 3 or 4 */
>> +            break;
>> +        case CRB_LOC_CTRL_RELINQUISH:
>> +            break;
>> +        case CRB_LOC_CTRL_REQUEST_ACCESS:
>> +            s->regs.loc_sts.bits.granted = 1;
>> +            s->regs.loc_sts.bits.been_seized = 0;
>> +            s->regs.loc_state.bits.loc_assigned = 1;
>> +            s->regs.loc_state.bits.tpm_reg_valid_sts = 1;
>> +            break;
>> +        }
>> +        break;
>> +    }
>> +}
>> +
>> +static const MemoryRegionOps tpm_crb_memory_ops = {
>> +    .read = tpm_crb_mmio_read,
>> +    .write = tpm_crb_mmio_write,
>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>> +    .valid = {
>> +        .min_access_size = 1,
>> +        .max_access_size = 4,
>> +    },
>> +};
>> +
>> +static void tpm_crb_reset(DeviceState *dev)
>> +{
>> +    CRBState *s = CRB(dev);
>> +
>> +    tpm_backend_reset(s->tpmbe);
>> +
>> +    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
>> +                            CRB_CTRL_CMD_SIZE);
>> +
>> +    s->regs = (struct crb_regs) {
>> +        .intf_id.bits = {
>> +            .type = CRB_INTF_TYPE_CRB_ACTIVE,
>> +            .version = CRB_INTF_VERSION_CRB,
>> +            .cap_locality = CRB_INTF_CAP_LOCALITY_0_ONLY,
>> +            .cap_crb_idle_bypass = CRB_INTF_CAP_IDLE_FAST,
>> +            .cap_data_xfer_size_support = CRB_INTF_CAP_XFER_SIZE_64,
>> +            .cap_fifo = CRB_INTF_CAP_FIFO_NOT_SUPPORTED,
>> +            .cap_crb = CRB_INTF_CAP_CRB_SUPPORTED,
>> +            .cap_if_res = 0b0,
>> +            .if_selector = CRB_INTF_IF_SELECTOR_CRB,
>> +            .if_selector_lock = CRB_INTF_IF_SELECTOR_UNLOCKED,
>> +            .rid = 0b0001,
>> +            .vid = PCI_VENDOR_ID_IBM,
>> +            .did = 0b0001,
>> +        },
>> +        .ctrl_cmd_size = CRB_CTRL_CMD_SIZE,
>> +        .ctrl_cmd_pa_low = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
>> +        .ctrl_rsp_size = CRB_CTRL_CMD_SIZE,
>> +        .ctrl_rsp_pa = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
>> +    };
>> +
>> +    tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size);
>> +}
>> +
>> +static void tpm_crb_request_completed(TPMIf *ti, int ret)
>> +{
>> +    CRBState *s = CRB(ti);
>> +
>> +    s->regs.ctrl_start &= ~CRB_START_INVOKE;
>> +    if (ret != 0) {
>> +        s->regs.ctrl_sts.bits.tpm_sts = 1; /* fatal error */
>> +    }
>> +}
>> +
>> +static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
>> +{
>> +    CRBState *s = CRB(ti);
>> +
>> +    return tpm_backend_get_tpm_version(s->tpmbe);
>> +}
>> +
>> +static const VMStateDescription vmstate_tpm_crb = {
>> +    .name = "tpm-crb",
>> +    .unmigratable = 1,
>> +};
>> +
>> +static Property tpm_crb_properties[] = {
>> +    DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe),
>> +    DEFINE_PROP_END_OF_LIST(),
>> +};
>> +
>> +static void tpm_crb_realizefn(DeviceState *dev, Error **errp)
>> +{
>> +    CRBState *s = CRB(dev);
>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>> +
>> +    if (!tpm_find()) {
>> +        error_setg(errp, "at most one TPM device is permitted");
>> +        return;
>> +    }
>> +    if (!s->tpmbe) {
>> +        error_setg(errp, "'tpmdev' property is required");
>> +        return;
>> +    }
>> +
>> +    memory_region_init_io(&s->mmio, OBJECT(s), &tpm_crb_memory_ops, s,
>> +        "tpm-crb-mmio", sizeof(struct crb_regs));
>> +    memory_region_init_ram(&s->cmdmem, OBJECT(s),
>> +        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
>> +
>> +    sysbus_init_mmio(sbd, &s->mmio);
>> +    sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE);
>> +    /* allocate ram in bios instead? */
>> +    memory_region_add_subregion(get_system_memory(),
>> +        TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), &s->cmdmem);
>> +}
>> +
>> +static void tpm_crb_class_init(ObjectClass *klass, void *data)
>> +{
>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>> +    TPMIfClass *tc = TPM_IF_CLASS(klass);
>> +
>> +    dc->realize = tpm_crb_realizefn;
>> +    dc->props = tpm_crb_properties;
>> +    dc->reset = tpm_crb_reset;
>> +    dc->vmsd  = &vmstate_tpm_crb;
>> +    dc->user_creatable = true;
>> +    tc->model = TPM_MODEL_TPM_CRB;
>> +    tc->get_version = tpm_crb_get_version;
>> +    tc->request_completed = tpm_crb_request_completed;
>> +}
>> +
>> +static const TypeInfo tpm_crb_info = {
>> +    .name = TYPE_TPM_CRB,
>> +    .parent = TYPE_SYS_BUS_DEVICE,
>> +    .instance_size = sizeof(CRBState),
>> +    .class_init  = tpm_crb_class_init,
>> +    .interfaces = (InterfaceInfo[]) {
>> +        { TYPE_TPM_IF },
>> +        { }
>> +    }
>> +};
>> +
>> +static void tpm_crb_register(void)
>> +{
>> +    type_register_static(&tpm_crb_info);
>> +}
>> +
>> +type_init(tpm_crb_register)
>> diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
>> index 95ac4b464a..ac27700e79 100644
>> --- a/default-configs/i386-softmmu.mak
>> +++ b/default-configs/i386-softmmu.mak
>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>>   CONFIG_I8259=y
>>   CONFIG_PFLASH_CFI01=y
>>   CONFIG_TPM_TIS=$(CONFIG_TPM)
>> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>>   CONFIG_MC146818RTC=y
>>   CONFIG_PCI_PIIX=y
>>   CONFIG_WDT_IB700=y
>> diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
>> index 0221236825..b2104ade19 100644
>> --- a/default-configs/x86_64-softmmu.mak
>> +++ b/default-configs/x86_64-softmmu.mak
>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>>   CONFIG_I8259=y
>>   CONFIG_PFLASH_CFI01=y
>>   CONFIG_TPM_TIS=$(CONFIG_TPM)
>> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>>   CONFIG_MC146818RTC=y
>>   CONFIG_PCI_PIIX=y
>>   CONFIG_WDT_IB700=y
>> diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
>> index 7a93b24636..1dc9f8bf2c 100644
>> --- a/hw/tpm/Makefile.objs
>> +++ b/hw/tpm/Makefile.objs
>> @@ -1,4 +1,5 @@
>>   common-obj-y += tpm_util.o
>>   common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
>> +common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
>>   common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
>>   common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
>>

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-21  5:46     ` Stefan Berger
@ 2018-01-21 19:24       ` Marc-Andre Lureau
  2018-01-21 22:01         ` Stefan Berger
  2018-01-21 22:50       ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 31+ messages in thread
From: Marc-Andre Lureau @ 2018-01-21 19:24 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Philippe Mathieu-Daudé,
	Marc-André Lureau, qemu-devel, Eduardo Habkost,
	Michael S. Tsirkin, Markus Armbruster, Paolo Bonzini,
	Igor Mammedov, Marcel Apfelbaum, Richard Henderson

Hi

On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
<stefanb@linux.vnet.ibm.com> wrote:
> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>>
>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>>>
>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>>
>>> The PTP allows device implementation to switch between TIS and CRB
>>> model at run time, but given that CRB is a simpler device to
>>> implement, I chose to implement it as a different device.
>>>
>>> The device doesn't implement other locality than 0 for now (my laptop
>>> TPM doesn't either, so I assume this isn't so bad)
>>>
>>> The command/reply memory region is statically allocated after the CRB
>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>>> wonder if the BIOS could or should allocate it instead, or what size
>>> to use, again this seems to fit well expectations)
>>>
>>> The PTP doesn't specify a particular bus to put the device. So I added
>>> it on the system bus directly, so it could hopefully be used easily on
>>> a different platform than x86. Currently, it fails to init on piix,
>>> because error_on_sysbus_device() check. The check may be changed in a
>>> near future, see discussion on the qemu-devel ML.
>>>
>>> Tested with some success with Linux upstream and Windows 10, seabios &
>>> modified ovmf. The device is recognized and correctly transmit
>>> command/response with passthrough & emu. However, we are missing PPI
>>> ACPI part atm.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>> ---
>>>   qapi/tpm.json                      |   5 +-
>>>   include/hw/acpi/tpm.h              |  72 ++++++++
>>>   include/sysemu/tpm.h               |   3 +
>>>   hw/i386/acpi-build.c               |  34 +++-
>>>   hw/tpm/tpm_crb.c                   | 327
>>> +++++++++++++++++++++++++++++++++++++
>>>   default-configs/i386-softmmu.mak   |   1 +
>>>   default-configs/x86_64-softmmu.mak |   1 +
>>>   hw/tpm/Makefile.objs               |   1 +
>>>   8 files changed, 434 insertions(+), 10 deletions(-)
>>>   create mode 100644 hw/tpm/tpm_crb.c
>>>
>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>>> index 7093f268fb..d50deef5e9 100644
>>> --- a/qapi/tpm.json
>>> +++ b/qapi/tpm.json
>>> @@ -11,10 +11,11 @@
>>>   # An enumeration of TPM models
>>>   #
>>>   # @tpm-tis: TPM TIS model
>>> +# @tpm-crb: TPM CRB model (since 2.12)
>>>   #
>>>   # Since: 1.5
>>>   ##
>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>>>     ##
>>>   # @query-tpm-models:
>>> @@ -28,7 +29,7 @@
>>>   # Example:
>>>   #
>>>   # -> { "execute": "query-tpm-models" }
>>> -# <- { "return": [ "tpm-tis" ] }
>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>>>   #
>>>   ##
>>>   { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>>> index 6d516c6a7f..b0048515fa 100644
>>> --- a/include/hw/acpi/tpm.h
>>> +++ b/include/hw/acpi/tpm.h
>>> @@ -16,11 +16,82 @@
>>>   #ifndef HW_ACPI_TPM_H
>>>   #define HW_ACPI_TPM_H
>>>   +#include "qemu/osdep.h"
>>> +
>>>   #define TPM_TIS_ADDR_BASE           0xFED40000
>>>   #define TPM_TIS_ADDR_SIZE           0x5000
>>>     #define TPM_TIS_IRQ                 5
>>>   +struct crb_regs {
>>> +    union {
>>> +        uint32_t reg;
>>> +        struct {
>>> +            unsigned tpm_established:1;
>>> +            unsigned loc_assigned:1;
>>> +            unsigned active_locality:3;
>>> +            unsigned reserved:2;
>>> +            unsigned tpm_reg_valid_sts:1;
>>> +        } bits;
>>
>> I suppose this is little-endian layout, so this won't work on big-endian
>> hosts.
>>
>> Can you add a qtest?
>>
>>> +    } loc_state;
>>> +    uint32_t reserved1;
>>> +    uint32_t loc_ctrl;
>>> +    union {
>>> +        uint32_t reg;
>>> +        struct {
>>> +            unsigned granted:1;
>>> +            unsigned been_seized:1;
>>> +        } bits;
>>
>>
>> This is unclear where you expect those bits (right/left aligned).
>>
>> Can you add an unnamed field to be more explicit?
>>
>> i.e. without using struct if left alignment expected:
>>
>>             unsigned granted:1, been_seized:1, :30;
>
>
>
> I got rid of all the bitfields and this patch here makes it work on a ppc64
> big endian and also x86_64 host:
>
> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
>

Thank you Stefan! I am all for squashing this fix to the patch. You
should then add your signed-off to the commit.


> Regards,
>     Stefan
>
>
>
>>
>>> +    } loc_sts;
>>> +    uint8_t reserved2[32];
>>> +    union {
>>> +        uint64_t reg;
>>> +        struct {
>>> +            unsigned type:4;
>>> +            unsigned version:4;
>>> +            unsigned cap_locality:1;
>>> +            unsigned cap_crb_idle_bypass:1;
>>> +            unsigned reserved1:1;
>>> +            unsigned cap_data_xfer_size_support:2;
>>> +            unsigned cap_fifo:1;
>>> +            unsigned cap_crb:1;
>>> +            unsigned cap_if_res:2;
>>> +            unsigned if_selector:2;
>>> +            unsigned if_selector_lock:1;
>>> +            unsigned reserved2:4;
>>> +            unsigned rid:8;
>>> +            unsigned vid:16;
>>> +            unsigned did:16;
>>> +        } bits;
>>> +    } intf_id;
>>> +    uint64_t ctrl_ext;
>>> +
>>> +    uint32_t ctrl_req;
>>> +    union {
>>> +        uint32_t reg;
>>> +        struct {
>>> +            unsigned tpm_sts:1;
>>> +            unsigned tpm_idle:1;
>>> +            unsigned reserved:30;
>>
>> Oh here you use 'reserved' to left align.
>>
>>> +        } bits;
>>> +    } ctrl_sts;
>>> +    uint32_t ctrl_cancel;
>>> +    uint32_t ctrl_start;
>>> +    uint32_t ctrl_int_enable;
>>> +    uint32_t ctrl_int_sts;
>>> +    uint32_t ctrl_cmd_size;
>>> +    uint32_t ctrl_cmd_pa_low;
>>> +    uint32_t ctrl_cmd_pa_high;
>>> +    uint32_t ctrl_rsp_size;
>>> +    uint64_t ctrl_rsp_pa;
>>> +    uint8_t reserved3[0x10];
>>> +} QEMU_PACKED;
>>> +
>>> +#define TPM_CRB_ADDR_BASE           0xFED40000
>>> +#define TPM_CRB_ADDR_SIZE           0x1000
>>> +#define TPM_CRB_ADDR_CTRL \
>>> +    (TPM_CRB_ADDR_BASE + offsetof(struct crb_regs, ctrl_req))
>>> +
>>>   #define TPM_LOG_AREA_MINIMUM_SIZE   (64 * 1024)
>>>     #define TPM_TCPA_ACPI_CLASS_CLIENT  0
>>> @@ -30,5 +101,6 @@
>>>   #define TPM2_ACPI_CLASS_SERVER      1
>>>     #define TPM2_START_METHOD_MMIO      6
>>> +#define TPM2_START_METHOD_CRB       7
>>>     #endif /* HW_ACPI_TPM_H */
>>> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
>>> index ac04a9d4a2..233b1a3fc3 100644
>>> --- a/include/sysemu/tpm.h
>>> +++ b/include/sysemu/tpm.h
>>> @@ -46,9 +46,12 @@ typedef struct TPMIfClass {
>>>   } TPMIfClass;
>>>     #define TYPE_TPM_TIS                "tpm-tis"
>>> +#define TYPE_TPM_CRB                "tpm-crb"
>>>     #define TPM_IS_TIS(chr)                             \
>>>       object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
>>> +#define TPM_IS_CRB(chr)                             \
>>> +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
>>>     /* returns NULL unless there is exactly one TPM device */
>>>   static inline TPMIf *tpm_find(void)
>>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>>> index dc4b2b9ffe..ed78c4ed9f 100644
>>> --- a/hw/i386/acpi-build.c
>>> +++ b/hw/i386/acpi-build.c
>>> @@ -2224,6 +2224,22 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
>>>               aml_append(sb_scope, scope);
>>>           }
>>>       }
>>> +
>>> +    if (TPM_IS_CRB(tpm_find())) {
>>> +        dev = aml_device("TPM");
>>> +        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
>>> +        crs = aml_resource_template();
>>> +        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
>>> +                                           TPM_CRB_ADDR_SIZE,
>>> AML_READ_WRITE));
>>> +        aml_append(dev, aml_name_decl("_CRS", crs));
>>> +
>>> +        method = aml_method("_STA", 0, AML_NOTSERIALIZED);
>>> +        aml_append(method, aml_return(aml_int(0x0f)));
>>> +        aml_append(dev, method);
>>> +
>>> +        aml_append(sb_scope, dev);
>>> +    }
>>> +
>>>       aml_append(dsdt, sb_scope);
>>>         /* copy AML table into ACPI tables blob and patch header there */
>>> @@ -2285,18 +2301,20 @@ build_tpm2(GArray *table_data, BIOSLinker
>>> *linker, GArray *tcpalog)
>>>       if (TPM_IS_TIS(tpm_find())) {
>>>           tpm2_ptr->control_area_address = cpu_to_le64(0);
>>>           tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
>>> -
>>> -        tpm2_ptr->log_area_minimum_length =
>>> -            cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
>>> -
>>> -        /* log area start address to be filled by Guest linker */
>>> -        bios_linker_loader_add_pointer(linker,
>>> -            ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
>>> -            ACPI_BUILD_TPMLOG_FILE, 0);
>>> +    } else if (TPM_IS_CRB(tpm_find())) {
>>> +        tpm2_ptr->control_area_address = cpu_to_le64(TPM_CRB_ADDR_CTRL);
>>> +        tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_CRB);
>>>       } else {
>>>           g_warn_if_reached();
>>>       }
>>>   +    tpm2_ptr->log_area_minimum_length =
>>> +        cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
>>> +
>>> +    /* log area start address to be filled by Guest linker */
>>> +    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
>>> +                                   log_addr_offset, log_addr_size,
>>> +                                   ACPI_BUILD_TPMLOG_FILE, 0);
>>>       build_header(linker, table_data,
>>>                    (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL,
>>> NULL);
>>>   }
>>> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
>>> new file mode 100644
>>> index 0000000000..908ca18d92
>>> --- /dev/null
>>> +++ b/hw/tpm/tpm_crb.c
>>> @@ -0,0 +1,327 @@
>>> +/*
>>> + * tpm_crb.c - QEMU's TPM CRB interface emulator
>>> + *
>>> + * Copyright (c) 2017 Red Hat, Inc.
>>> + *
>>> + * Authors:
>>> + *   Marc-André Lureau <marcandre.lureau@redhat.com>
>>> + *
>>> + * This work is licensed under the terms of the GNU GPL, version 2 or
>>> later.
>>> + * See the COPYING file in the top-level directory.
>>> + *
>>> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>> Interface
>>> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
>>> + * Family “2.0” Level 00 Revision 01.03 v22
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +
>>> +#include "qemu-common.h"
>>> +#include "qapi/error.h"
>>> +#include "hw/sysbus.h"
>>> +#include "exec/address-spaces.h"
>>> +
>>> +#include "hw/pci/pci_ids.h"
>>> +#include "hw/acpi/tpm.h"
>>> +#include "sysemu/tpm_backend.h"
>>> +#include "tpm_int.h"
>>> +#include "tpm_util.h"
>>> +
>>> +typedef struct CRBState {
>>> +    SysBusDevice parent_obj;
>>> +
>>> +    TPMBackend *tpmbe;
>>> +    TPMBackendCmd cmd;
>>> +    struct crb_regs regs;
>>> +    MemoryRegion mmio;
>>> +    MemoryRegion cmdmem;
>>> +
>>> +    size_t be_buffer_size;
>>> +} CRBState;
>>> +
>>> +#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB)
>>> +
>>> +#define DEBUG_CRB 0
>>> +
>>> +#define DPRINTF(fmt, ...) do {                  \
>>> +        if (DEBUG_CRB) {                        \
>>> +            printf(fmt, ## __VA_ARGS__);        \
>>> +        }                                       \
>>> +    } while (0)
>>> +
>>> +#define CRB_ADDR_LOC_STATE offsetof(struct crb_regs, loc_state)
>>> +#define CRB_ADDR_LOC_CTRL offsetof(struct crb_regs, loc_ctrl)
>>> +#define CRB_ADDR_CTRL_REQ offsetof(struct crb_regs, ctrl_req)
>>> +#define CRB_ADDR_CTRL_CANCEL offsetof(struct crb_regs, ctrl_cancel)
>>> +#define CRB_ADDR_CTRL_START offsetof(struct crb_regs, ctrl_start)
>>> +
>>> +#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
>>> +#define CRB_INTF_VERSION_CRB 0b1
>>> +#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
>>> +#define CRB_INTF_CAP_IDLE_FAST 0b0
>>> +#define CRB_INTF_CAP_XFER_SIZE_64 0b11
>>> +#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
>>> +#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
>>> +#define CRB_INTF_IF_SELECTOR_CRB 0b1
>>> +#define CRB_INTF_IF_SELECTOR_UNLOCKED 0b0
>>> +
>>> +#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs))
>>> +
>>> +enum crb_loc_ctrl {
>>> +    CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
>>> +    CRB_LOC_CTRL_RELINQUISH = BIT(1),
>>> +    CRB_LOC_CTRL_SEIZE = BIT(2),
>>> +    CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
>>> +};
>>> +
>>> +enum crb_ctrl_req {
>>> +    CRB_CTRL_REQ_CMD_READY = BIT(0),
>>> +    CRB_CTRL_REQ_GO_IDLE = BIT(1),
>>> +};
>>> +
>>> +enum crb_start {
>>> +    CRB_START_INVOKE = BIT(0),
>>> +};
>>> +
>>> +enum crb_cancel {
>>> +    CRB_CANCEL_INVOKE = BIT(0),
>>> +};
>>> +
>>> +static const char *addr_desc(unsigned off)
>>> +{
>>> +    struct crb_regs crb;
>>> +
>>> +    switch (off) {
>>> +#define CASE(field)                                                 \
>>> +    case offsetof(struct crb_regs, field) ...                       \
>>> +        offsetof(struct crb_regs, field) + sizeof(crb.field) - 1:   \
>>> +        return G_STRINGIFY(field);
>>> +        CASE(loc_state);
>>> +        CASE(reserved1);
>>> +        CASE(loc_ctrl);
>>> +        CASE(loc_sts);
>>> +        CASE(reserved2);
>>> +        CASE(intf_id);
>>> +        CASE(ctrl_ext);
>>> +        CASE(ctrl_req);
>>> +        CASE(ctrl_sts);
>>> +        CASE(ctrl_cancel);
>>> +        CASE(ctrl_start);
>>> +        CASE(ctrl_int_enable);
>>> +        CASE(ctrl_int_sts);
>>> +        CASE(ctrl_cmd_size);
>>> +        CASE(ctrl_cmd_pa_low);
>>> +        CASE(ctrl_cmd_pa_high);
>>> +        CASE(ctrl_rsp_size);
>>> +        CASE(ctrl_rsp_pa);
>>> +#undef CASE
>>> +    }
>>> +    return NULL;
>>> +}
>>> +
>>> +static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
>>> +                                  unsigned size)
>>> +{
>>> +    CRBState *s = CRB(opaque);
>>> +    DPRINTF("CRB read 0x%lx:%s len:%u\n",
>>> +            addr, addr_desc(addr), size);
>>> +    void *regs = (void *)&s->regs + addr;
>>> +
>>> +    switch (size) {
>>> +    case 1:
>>> +        return *(uint8_t *)regs;
>>> +    case 2:
>>> +        return *(uint16_t *)regs;
>>> +    case 4:
>>> +        return *(uint32_t *)regs;
>>> +    default:
>>> +        g_return_val_if_reached(-1);
>>> +    }
>>> +}
>>> +
>>> +static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
>>> +                               uint64_t val, unsigned size)
>>> +{
>>> +    CRBState *s = CRB(opaque);
>>> +    DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
>>> +            addr, addr_desc(addr), size, val);
>>> +
>>> +    switch (addr) {
>>> +    case CRB_ADDR_CTRL_REQ:
>>> +        switch (val) {
>>> +        case CRB_CTRL_REQ_CMD_READY:
>>> +            s->regs.ctrl_sts.bits.tpm_idle = 0;
>>> +            break;
>>> +        case CRB_CTRL_REQ_GO_IDLE:
>>> +            s->regs.ctrl_sts.bits.tpm_idle = 1;
>>> +            break;
>>> +        }
>>> +        break;
>>> +    case CRB_ADDR_CTRL_CANCEL:
>>> +        if (val == CRB_CANCEL_INVOKE && s->regs.ctrl_start &
>>> CRB_START_INVOKE) {
>>> +            tpm_backend_cancel_cmd(s->tpmbe);
>>> +        }
>>> +        break;
>>> +    case CRB_ADDR_CTRL_START:
>>> +        if (val == CRB_START_INVOKE &&
>>> +            !(s->regs.ctrl_start & CRB_START_INVOKE)) {
>>> +            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
>>> +
>>> +            s->regs.ctrl_start |= CRB_START_INVOKE;
>>> +            s->cmd = (TPMBackendCmd) {
>>> +                .in = mem,
>>> +                .in_len = MIN(tpm_cmd_get_size(mem), s->be_buffer_size),
>>> +                .out = mem,
>>> +                .out_len = s->be_buffer_size,
>>> +            };
>>> +
>>> +            tpm_backend_deliver_request(s->tpmbe, &s->cmd);
>>> +        }
>>> +        break;
>>> +    case CRB_ADDR_LOC_CTRL:
>>> +        switch (val) {
>>> +        case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
>>> +            /* not loc 3 or 4 */
>>> +            break;
>>> +        case CRB_LOC_CTRL_RELINQUISH:
>>> +            break;
>>> +        case CRB_LOC_CTRL_REQUEST_ACCESS:
>>> +            s->regs.loc_sts.bits.granted = 1;
>>> +            s->regs.loc_sts.bits.been_seized = 0;
>>> +            s->regs.loc_state.bits.loc_assigned = 1;
>>> +            s->regs.loc_state.bits.tpm_reg_valid_sts = 1;
>>> +            break;
>>> +        }
>>> +        break;
>>> +    }
>>> +}
>>> +
>>> +static const MemoryRegionOps tpm_crb_memory_ops = {
>>> +    .read = tpm_crb_mmio_read,
>>> +    .write = tpm_crb_mmio_write,
>>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>>> +    .valid = {
>>> +        .min_access_size = 1,
>>> +        .max_access_size = 4,
>>> +    },
>>> +};
>>> +
>>> +static void tpm_crb_reset(DeviceState *dev)
>>> +{
>>> +    CRBState *s = CRB(dev);
>>> +
>>> +    tpm_backend_reset(s->tpmbe);
>>> +
>>> +    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
>>> +                            CRB_CTRL_CMD_SIZE);
>>> +
>>> +    s->regs = (struct crb_regs) {
>>> +        .intf_id.bits = {
>>> +            .type = CRB_INTF_TYPE_CRB_ACTIVE,
>>> +            .version = CRB_INTF_VERSION_CRB,
>>> +            .cap_locality = CRB_INTF_CAP_LOCALITY_0_ONLY,
>>> +            .cap_crb_idle_bypass = CRB_INTF_CAP_IDLE_FAST,
>>> +            .cap_data_xfer_size_support = CRB_INTF_CAP_XFER_SIZE_64,
>>> +            .cap_fifo = CRB_INTF_CAP_FIFO_NOT_SUPPORTED,
>>> +            .cap_crb = CRB_INTF_CAP_CRB_SUPPORTED,
>>> +            .cap_if_res = 0b0,
>>> +            .if_selector = CRB_INTF_IF_SELECTOR_CRB,
>>> +            .if_selector_lock = CRB_INTF_IF_SELECTOR_UNLOCKED,
>>> +            .rid = 0b0001,
>>> +            .vid = PCI_VENDOR_ID_IBM,
>>> +            .did = 0b0001,
>>> +        },
>>> +        .ctrl_cmd_size = CRB_CTRL_CMD_SIZE,
>>> +        .ctrl_cmd_pa_low = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
>>> +        .ctrl_rsp_size = CRB_CTRL_CMD_SIZE,
>>> +        .ctrl_rsp_pa = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
>>> +    };
>>> +
>>> +    tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size);
>>> +}
>>> +
>>> +static void tpm_crb_request_completed(TPMIf *ti, int ret)
>>> +{
>>> +    CRBState *s = CRB(ti);
>>> +
>>> +    s->regs.ctrl_start &= ~CRB_START_INVOKE;
>>> +    if (ret != 0) {
>>> +        s->regs.ctrl_sts.bits.tpm_sts = 1; /* fatal error */
>>> +    }
>>> +}
>>> +
>>> +static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
>>> +{
>>> +    CRBState *s = CRB(ti);
>>> +
>>> +    return tpm_backend_get_tpm_version(s->tpmbe);
>>> +}
>>> +
>>> +static const VMStateDescription vmstate_tpm_crb = {
>>> +    .name = "tpm-crb",
>>> +    .unmigratable = 1,
>>> +};
>>> +
>>> +static Property tpm_crb_properties[] = {
>>> +    DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe),
>>> +    DEFINE_PROP_END_OF_LIST(),
>>> +};
>>> +
>>> +static void tpm_crb_realizefn(DeviceState *dev, Error **errp)
>>> +{
>>> +    CRBState *s = CRB(dev);
>>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>> +
>>> +    if (!tpm_find()) {
>>> +        error_setg(errp, "at most one TPM device is permitted");
>>> +        return;
>>> +    }
>>> +    if (!s->tpmbe) {
>>> +        error_setg(errp, "'tpmdev' property is required");
>>> +        return;
>>> +    }
>>> +
>>> +    memory_region_init_io(&s->mmio, OBJECT(s), &tpm_crb_memory_ops, s,
>>> +        "tpm-crb-mmio", sizeof(struct crb_regs));
>>> +    memory_region_init_ram(&s->cmdmem, OBJECT(s),
>>> +        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
>>> +
>>> +    sysbus_init_mmio(sbd, &s->mmio);
>>> +    sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE);
>>> +    /* allocate ram in bios instead? */
>>> +    memory_region_add_subregion(get_system_memory(),
>>> +        TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), &s->cmdmem);
>>> +}
>>> +
>>> +static void tpm_crb_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +    TPMIfClass *tc = TPM_IF_CLASS(klass);
>>> +
>>> +    dc->realize = tpm_crb_realizefn;
>>> +    dc->props = tpm_crb_properties;
>>> +    dc->reset = tpm_crb_reset;
>>> +    dc->vmsd  = &vmstate_tpm_crb;
>>> +    dc->user_creatable = true;
>>> +    tc->model = TPM_MODEL_TPM_CRB;
>>> +    tc->get_version = tpm_crb_get_version;
>>> +    tc->request_completed = tpm_crb_request_completed;
>>> +}
>>> +
>>> +static const TypeInfo tpm_crb_info = {
>>> +    .name = TYPE_TPM_CRB,
>>> +    .parent = TYPE_SYS_BUS_DEVICE,
>>> +    .instance_size = sizeof(CRBState),
>>> +    .class_init  = tpm_crb_class_init,
>>> +    .interfaces = (InterfaceInfo[]) {
>>> +        { TYPE_TPM_IF },
>>> +        { }
>>> +    }
>>> +};
>>> +
>>> +static void tpm_crb_register(void)
>>> +{
>>> +    type_register_static(&tpm_crb_info);
>>> +}
>>> +
>>> +type_init(tpm_crb_register)
>>> diff --git a/default-configs/i386-softmmu.mak
>>> b/default-configs/i386-softmmu.mak
>>> index 95ac4b464a..ac27700e79 100644
>>> --- a/default-configs/i386-softmmu.mak
>>> +++ b/default-configs/i386-softmmu.mak
>>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>>>   CONFIG_I8259=y
>>>   CONFIG_PFLASH_CFI01=y
>>>   CONFIG_TPM_TIS=$(CONFIG_TPM)
>>> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>>>   CONFIG_MC146818RTC=y
>>>   CONFIG_PCI_PIIX=y
>>>   CONFIG_WDT_IB700=y
>>> diff --git a/default-configs/x86_64-softmmu.mak
>>> b/default-configs/x86_64-softmmu.mak
>>> index 0221236825..b2104ade19 100644
>>> --- a/default-configs/x86_64-softmmu.mak
>>> +++ b/default-configs/x86_64-softmmu.mak
>>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>>>   CONFIG_I8259=y
>>>   CONFIG_PFLASH_CFI01=y
>>>   CONFIG_TPM_TIS=$(CONFIG_TPM)
>>> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>>>   CONFIG_MC146818RTC=y
>>>   CONFIG_PCI_PIIX=y
>>>   CONFIG_WDT_IB700=y
>>> diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
>>> index 7a93b24636..1dc9f8bf2c 100644
>>> --- a/hw/tpm/Makefile.objs
>>> +++ b/hw/tpm/Makefile.objs
>>> @@ -1,4 +1,5 @@
>>>   common-obj-y += tpm_util.o
>>>   common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
>>> +common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
>>>   common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
>>>   common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
>>>
>

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-21 19:24       ` Marc-Andre Lureau
@ 2018-01-21 22:01         ` Stefan Berger
  2018-01-22 15:08           ` Marc-Andre Lureau
  0 siblings, 1 reply; 31+ messages in thread
From: Stefan Berger @ 2018-01-21 22:01 UTC (permalink / raw)
  To: Marc-Andre Lureau
  Cc: Eduardo Habkost, Michael S. Tsirkin, qemu-devel,
	Markus Armbruster, Philippe Mathieu-Daudé,
	Igor Mammedov, Paolo Bonzini, Marcel Apfelbaum,
	Marc-André Lureau, Richard Henderson

On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
> Hi
>
> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
> <stefanb@linux.vnet.ibm.com> wrote:
>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>>>
>>>> The PTP allows device implementation to switch between TIS and CRB
>>>> model at run time, but given that CRB is a simpler device to
>>>> implement, I chose to implement it as a different device.
>>>>
>>>> The device doesn't implement other locality than 0 for now (my laptop
>>>> TPM doesn't either, so I assume this isn't so bad)
>>>>
>>>> The command/reply memory region is statically allocated after the CRB
>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>>>> wonder if the BIOS could or should allocate it instead, or what size
>>>> to use, again this seems to fit well expectations)
>>>>
>>>> The PTP doesn't specify a particular bus to put the device. So I added
>>>> it on the system bus directly, so it could hopefully be used easily on
>>>> a different platform than x86. Currently, it fails to init on piix,
>>>> because error_on_sysbus_device() check. The check may be changed in a
>>>> near future, see discussion on the qemu-devel ML.
>>>>
>>>> Tested with some success with Linux upstream and Windows 10, seabios &
>>>> modified ovmf. The device is recognized and correctly transmit
>>>> command/response with passthrough & emu. However, we are missing PPI
>>>> ACPI part atm.
>>>>
>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>> ---
>>>>    qapi/tpm.json                      |   5 +-
>>>>    include/hw/acpi/tpm.h              |  72 ++++++++
>>>>    include/sysemu/tpm.h               |   3 +
>>>>    hw/i386/acpi-build.c               |  34 +++-
>>>>    hw/tpm/tpm_crb.c                   | 327
>>>> +++++++++++++++++++++++++++++++++++++
>>>>    default-configs/i386-softmmu.mak   |   1 +
>>>>    default-configs/x86_64-softmmu.mak |   1 +
>>>>    hw/tpm/Makefile.objs               |   1 +
>>>>    8 files changed, 434 insertions(+), 10 deletions(-)
>>>>    create mode 100644 hw/tpm/tpm_crb.c
>>>>
>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>>>> index 7093f268fb..d50deef5e9 100644
>>>> --- a/qapi/tpm.json
>>>> +++ b/qapi/tpm.json
>>>> @@ -11,10 +11,11 @@
>>>>    # An enumeration of TPM models
>>>>    #
>>>>    # @tpm-tis: TPM TIS model
>>>> +# @tpm-crb: TPM CRB model (since 2.12)
>>>>    #
>>>>    # Since: 1.5
>>>>    ##
>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>>>>      ##
>>>>    # @query-tpm-models:
>>>> @@ -28,7 +29,7 @@
>>>>    # Example:
>>>>    #
>>>>    # -> { "execute": "query-tpm-models" }
>>>> -# <- { "return": [ "tpm-tis" ] }
>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>>>>    #
>>>>    ##
>>>>    { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>>>> index 6d516c6a7f..b0048515fa 100644
>>>> --- a/include/hw/acpi/tpm.h
>>>> +++ b/include/hw/acpi/tpm.h
>>>> @@ -16,11 +16,82 @@
>>>>    #ifndef HW_ACPI_TPM_H
>>>>    #define HW_ACPI_TPM_H
>>>>    +#include "qemu/osdep.h"
>>>> +
>>>>    #define TPM_TIS_ADDR_BASE           0xFED40000
>>>>    #define TPM_TIS_ADDR_SIZE           0x5000
>>>>      #define TPM_TIS_IRQ                 5
>>>>    +struct crb_regs {
>>>> +    union {
>>>> +        uint32_t reg;
>>>> +        struct {
>>>> +            unsigned tpm_established:1;
>>>> +            unsigned loc_assigned:1;
>>>> +            unsigned active_locality:3;
>>>> +            unsigned reserved:2;
>>>> +            unsigned tpm_reg_valid_sts:1;
>>>> +        } bits;
>>> I suppose this is little-endian layout, so this won't work on big-endian
>>> hosts.
>>>
>>> Can you add a qtest?
>>>
>>>> +    } loc_state;
>>>> +    uint32_t reserved1;
>>>> +    uint32_t loc_ctrl;
>>>> +    union {
>>>> +        uint32_t reg;
>>>> +        struct {
>>>> +            unsigned granted:1;
>>>> +            unsigned been_seized:1;
>>>> +        } bits;
>>>
>>> This is unclear where you expect those bits (right/left aligned).
>>>
>>> Can you add an unnamed field to be more explicit?
>>>
>>> i.e. without using struct if left alignment expected:
>>>
>>>              unsigned granted:1, been_seized:1, :30;
>>
>>
>> I got rid of all the bitfields and this patch here makes it work on a ppc64
>> big endian and also x86_64 host:
>>
>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
>>
> Thank you Stefan! I am all for squashing this fix to the patch. You
> should then add your signed-off to the commit.

I'll do that.

The TIS is an ISA Device and the CRB is similar. Considering the 
complications with the sysbus devices where one has to explicitly allow 
it for a certain machine type, I would advocate to convert the CRB to an 
ISA device. A patch that does that is this one:

https://github.com/stefanberger/qemu-tpm/commit/08c61bd666f82084c42621f4285bcac08fb4f713

     Stefan

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-21  5:46     ` Stefan Berger
  2018-01-21 19:24       ` Marc-Andre Lureau
@ 2018-01-21 22:50       ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2018-01-21 22:50 UTC (permalink / raw)
  To: Stefan Berger, Marc-André Lureau, Alistair Francis
  Cc: qemu-devel, Eduardo Habkost, Michael S. Tsirkin,
	Markus Armbruster, Paolo Bonzini, Igor Mammedov,
	Marcel Apfelbaum, Richard Henderson

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

On 01/21/2018 02:46 AM, Stefan Berger wrote:
> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>>
>>> The PTP allows device implementation to switch between TIS and CRB
>>> model at run time, but given that CRB is a simpler device to
>>> implement, I chose to implement it as a different device.
>>>
>>> The device doesn't implement other locality than 0 for now (my laptop
>>> TPM doesn't either, so I assume this isn't so bad)
>>>
>>> The command/reply memory region is statically allocated after the CRB
>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>>> wonder if the BIOS could or should allocate it instead, or what size
>>> to use, again this seems to fit well expectations)
>>>
>>> The PTP doesn't specify a particular bus to put the device. So I added
>>> it on the system bus directly, so it could hopefully be used easily on
>>> a different platform than x86. Currently, it fails to init on piix,
>>> because error_on_sysbus_device() check. The check may be changed in a
>>> near future, see discussion on the qemu-devel ML.
>>>
>>> Tested with some success with Linux upstream and Windows 10, seabios &
>>> modified ovmf. The device is recognized and correctly transmit
>>> command/response with passthrough & emu. However, we are missing PPI
>>> ACPI part atm.
>>>
>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>> ---
>>>   qapi/tpm.json                      |   5 +-
>>>   include/hw/acpi/tpm.h              |  72 ++++++++
>>>   include/sysemu/tpm.h               |   3 +
>>>   hw/i386/acpi-build.c               |  34 +++-
>>>   hw/tpm/tpm_crb.c                   | 327
>>> +++++++++++++++++++++++++++++++++++++
>>>   default-configs/i386-softmmu.mak   |   1 +
>>>   default-configs/x86_64-softmmu.mak |   1 +
>>>   hw/tpm/Makefile.objs               |   1 +
>>>   8 files changed, 434 insertions(+), 10 deletions(-)
>>>   create mode 100644 hw/tpm/tpm_crb.c
>>>
>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>>> index 7093f268fb..d50deef5e9 100644
>>> --- a/qapi/tpm.json
>>> +++ b/qapi/tpm.json
>>> @@ -11,10 +11,11 @@
>>>   # An enumeration of TPM models
>>>   #
>>>   # @tpm-tis: TPM TIS model
>>> +# @tpm-crb: TPM CRB model (since 2.12)
>>>   #
>>>   # Since: 1.5
>>>   ##
>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>>>     ##
>>>   # @query-tpm-models:
>>> @@ -28,7 +29,7 @@
>>>   # Example:
>>>   #
>>>   # -> { "execute": "query-tpm-models" }
>>> -# <- { "return": [ "tpm-tis" ] }
>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>>>   #
>>>   ##
>>>   { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>>> index 6d516c6a7f..b0048515fa 100644
>>> --- a/include/hw/acpi/tpm.h
>>> +++ b/include/hw/acpi/tpm.h
>>> @@ -16,11 +16,82 @@
>>>   #ifndef HW_ACPI_TPM_H
>>>   #define HW_ACPI_TPM_H
>>>   +#include "qemu/osdep.h"
>>> +
>>>   #define TPM_TIS_ADDR_BASE           0xFED40000
>>>   #define TPM_TIS_ADDR_SIZE           0x5000
>>>     #define TPM_TIS_IRQ                 5
>>>   +struct crb_regs {
>>> +    union {
>>> +        uint32_t reg;
>>> +        struct {
>>> +            unsigned tpm_established:1;
>>> +            unsigned loc_assigned:1;
>>> +            unsigned active_locality:3;
>>> +            unsigned reserved:2;
>>> +            unsigned tpm_reg_valid_sts:1;
>>> +        } bits;
>> I suppose this is little-endian layout, so this won't work on big-endian
>> hosts.
>>
>> Can you add a qtest?
>>
>>> +    } loc_state;
>>> +    uint32_t reserved1;
>>> +    uint32_t loc_ctrl;
>>> +    union {
>>> +        uint32_t reg;
>>> +        struct {
>>> +            unsigned granted:1;
>>> +            unsigned been_seized:1;
>>> +        } bits;
>>
>> This is unclear where you expect those bits (right/left aligned).
>>
>> Can you add an unnamed field to be more explicit?
>>
>> i.e. without using struct if left alignment expected:
>>
>>             unsigned granted:1, been_seized:1, :30;
> 
> 
> I got rid of all the bitfields and this patch here makes it work on a
> ppc64 big endian and also x86_64 host:
> 
> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd

Thanks!

Looking at your tree, I recommend you to have a look at the
"hw/registerfields.h" API, you might find it simpler when it
comes to add bitfields #defines and checks, moreover when you
have specs available in a parsable form, since you can easily
script and auto-generate.

Alistair, thinking about it I'm not sure you already have a such
template available, but if you do we might add it in the
scripts/modules/ directory, then I can add doc and examples.

> 
> 
> Regards,
>     Stefan
> 
> 
>>
>>> +    } loc_sts;
>>> +    uint8_t reserved2[32];
>>> +    union {
>>> +        uint64_t reg;
>>> +        struct {
>>> +            unsigned type:4;
>>> +            unsigned version:4;
>>> +            unsigned cap_locality:1;
>>> +            unsigned cap_crb_idle_bypass:1;
>>> +            unsigned reserved1:1;
>>> +            unsigned cap_data_xfer_size_support:2;
>>> +            unsigned cap_fifo:1;
>>> +            unsigned cap_crb:1;
>>> +            unsigned cap_if_res:2;
>>> +            unsigned if_selector:2;
>>> +            unsigned if_selector_lock:1;
>>> +            unsigned reserved2:4;
>>> +            unsigned rid:8;
>>> +            unsigned vid:16;
>>> +            unsigned did:16;
>>> +        } bits;
>>> +    } intf_id;
>>> +    uint64_t ctrl_ext;
>>> +
>>> +    uint32_t ctrl_req;
>>> +    union {
>>> +        uint32_t reg;
>>> +        struct {
>>> +            unsigned tpm_sts:1;
>>> +            unsigned tpm_idle:1;
>>> +            unsigned reserved:30;
>> Oh here you use 'reserved' to left align.
>>
>>> +        } bits;
>>> +    } ctrl_sts;
>>> +    uint32_t ctrl_cancel;
>>> +    uint32_t ctrl_start;
>>> +    uint32_t ctrl_int_enable;
>>> +    uint32_t ctrl_int_sts;
>>> +    uint32_t ctrl_cmd_size;
>>> +    uint32_t ctrl_cmd_pa_low;
>>> +    uint32_t ctrl_cmd_pa_high;
>>> +    uint32_t ctrl_rsp_size;
>>> +    uint64_t ctrl_rsp_pa;
>>> +    uint8_t reserved3[0x10];
>>> +} QEMU_PACKED;
>>> +
>>> +#define TPM_CRB_ADDR_BASE           0xFED40000
>>> +#define TPM_CRB_ADDR_SIZE           0x1000
>>> +#define TPM_CRB_ADDR_CTRL \
>>> +    (TPM_CRB_ADDR_BASE + offsetof(struct crb_regs, ctrl_req))
>>> +
>>>   #define TPM_LOG_AREA_MINIMUM_SIZE   (64 * 1024)
>>>     #define TPM_TCPA_ACPI_CLASS_CLIENT  0
>>> @@ -30,5 +101,6 @@
>>>   #define TPM2_ACPI_CLASS_SERVER      1
>>>     #define TPM2_START_METHOD_MMIO      6
>>> +#define TPM2_START_METHOD_CRB       7
>>>     #endif /* HW_ACPI_TPM_H */
>>> diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
>>> index ac04a9d4a2..233b1a3fc3 100644
>>> --- a/include/sysemu/tpm.h
>>> +++ b/include/sysemu/tpm.h
>>> @@ -46,9 +46,12 @@ typedef struct TPMIfClass {
>>>   } TPMIfClass;
>>>     #define TYPE_TPM_TIS                "tpm-tis"
>>> +#define TYPE_TPM_CRB                "tpm-crb"
>>>     #define TPM_IS_TIS(chr)                             \
>>>       object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
>>> +#define TPM_IS_CRB(chr)                             \
>>> +    object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
>>>     /* returns NULL unless there is exactly one TPM device */
>>>   static inline TPMIf *tpm_find(void)
>>> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
>>> index dc4b2b9ffe..ed78c4ed9f 100644
>>> --- a/hw/i386/acpi-build.c
>>> +++ b/hw/i386/acpi-build.c
>>> @@ -2224,6 +2224,22 @@ build_dsdt(GArray *table_data, BIOSLinker
>>> *linker,
>>>               aml_append(sb_scope, scope);
>>>           }
>>>       }
>>> +
>>> +    if (TPM_IS_CRB(tpm_find())) {
>>> +        dev = aml_device("TPM");
>>> +        aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
>>> +        crs = aml_resource_template();
>>> +        aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
>>> +                                           TPM_CRB_ADDR_SIZE,
>>> AML_READ_WRITE));
>>> +        aml_append(dev, aml_name_decl("_CRS", crs));
>>> +
>>> +        method = aml_method("_STA", 0, AML_NOTSERIALIZED);
>>> +        aml_append(method, aml_return(aml_int(0x0f)));
>>> +        aml_append(dev, method);
>>> +
>>> +        aml_append(sb_scope, dev);
>>> +    }
>>> +
>>>       aml_append(dsdt, sb_scope);
>>>         /* copy AML table into ACPI tables blob and patch header
>>> there */
>>> @@ -2285,18 +2301,20 @@ build_tpm2(GArray *table_data, BIOSLinker
>>> *linker, GArray *tcpalog)
>>>       if (TPM_IS_TIS(tpm_find())) {
>>>           tpm2_ptr->control_area_address = cpu_to_le64(0);
>>>           tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
>>> -
>>> -        tpm2_ptr->log_area_minimum_length =
>>> -            cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
>>> -
>>> -        /* log area start address to be filled by Guest linker */
>>> -        bios_linker_loader_add_pointer(linker,
>>> -            ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
>>> -            ACPI_BUILD_TPMLOG_FILE, 0);
>>> +    } else if (TPM_IS_CRB(tpm_find())) {
>>> +        tpm2_ptr->control_area_address =
>>> cpu_to_le64(TPM_CRB_ADDR_CTRL);
>>> +        tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_CRB);
>>>       } else {
>>>           g_warn_if_reached();
>>>       }
>>>   +    tpm2_ptr->log_area_minimum_length =
>>> +        cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
>>> +
>>> +    /* log area start address to be filled by Guest linker */
>>> +    bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
>>> +                                   log_addr_offset, log_addr_size,
>>> +                                   ACPI_BUILD_TPMLOG_FILE, 0);
>>>       build_header(linker, table_data,
>>>                    (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4,
>>> NULL, NULL);
>>>   }
>>> diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
>>> new file mode 100644
>>> index 0000000000..908ca18d92
>>> --- /dev/null
>>> +++ b/hw/tpm/tpm_crb.c
>>> @@ -0,0 +1,327 @@
>>> +/*
>>> + * tpm_crb.c - QEMU's TPM CRB interface emulator
>>> + *
>>> + * Copyright (c) 2017 Red Hat, Inc.
>>> + *
>>> + * Authors:
>>> + *   Marc-André Lureau <marcandre.lureau@redhat.com>
>>> + *
>>> + * This work is licensed under the terms of the GNU GPL, version 2
>>> or later.
>>> + * See the COPYING file in the top-level directory.
>>> + *
>>> + * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>> Interface
>>> + * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
>>> + * Family “2.0” Level 00 Revision 01.03 v22
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +
>>> +#include "qemu-common.h"
>>> +#include "qapi/error.h"
>>> +#include "hw/sysbus.h"
>>> +#include "exec/address-spaces.h"
>>> +
>>> +#include "hw/pci/pci_ids.h"
>>> +#include "hw/acpi/tpm.h"
>>> +#include "sysemu/tpm_backend.h"
>>> +#include "tpm_int.h"
>>> +#include "tpm_util.h"
>>> +
>>> +typedef struct CRBState {
>>> +    SysBusDevice parent_obj;
>>> +
>>> +    TPMBackend *tpmbe;
>>> +    TPMBackendCmd cmd;
>>> +    struct crb_regs regs;
>>> +    MemoryRegion mmio;
>>> +    MemoryRegion cmdmem;
>>> +
>>> +    size_t be_buffer_size;
>>> +} CRBState;
>>> +
>>> +#define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB)
>>> +
>>> +#define DEBUG_CRB 0
>>> +
>>> +#define DPRINTF(fmt, ...) do {                  \
>>> +        if (DEBUG_CRB) {                        \
>>> +            printf(fmt, ## __VA_ARGS__);        \
>>> +        }                                       \
>>> +    } while (0)
>>> +
>>> +#define CRB_ADDR_LOC_STATE offsetof(struct crb_regs, loc_state)
>>> +#define CRB_ADDR_LOC_CTRL offsetof(struct crb_regs, loc_ctrl)
>>> +#define CRB_ADDR_CTRL_REQ offsetof(struct crb_regs, ctrl_req)
>>> +#define CRB_ADDR_CTRL_CANCEL offsetof(struct crb_regs, ctrl_cancel)
>>> +#define CRB_ADDR_CTRL_START offsetof(struct crb_regs, ctrl_start)
>>> +
>>> +#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
>>> +#define CRB_INTF_VERSION_CRB 0b1
>>> +#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
>>> +#define CRB_INTF_CAP_IDLE_FAST 0b0
>>> +#define CRB_INTF_CAP_XFER_SIZE_64 0b11
>>> +#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
>>> +#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
>>> +#define CRB_INTF_IF_SELECTOR_CRB 0b1
>>> +#define CRB_INTF_IF_SELECTOR_UNLOCKED 0b0
>>> +
>>> +#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs))
>>> +
>>> +enum crb_loc_ctrl {
>>> +    CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
>>> +    CRB_LOC_CTRL_RELINQUISH = BIT(1),
>>> +    CRB_LOC_CTRL_SEIZE = BIT(2),
>>> +    CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
>>> +};
>>> +
>>> +enum crb_ctrl_req {
>>> +    CRB_CTRL_REQ_CMD_READY = BIT(0),
>>> +    CRB_CTRL_REQ_GO_IDLE = BIT(1),
>>> +};
>>> +
>>> +enum crb_start {
>>> +    CRB_START_INVOKE = BIT(0),
>>> +};
>>> +
>>> +enum crb_cancel {
>>> +    CRB_CANCEL_INVOKE = BIT(0),
>>> +};
>>> +
>>> +static const char *addr_desc(unsigned off)
>>> +{
>>> +    struct crb_regs crb;
>>> +
>>> +    switch (off) {
>>> +#define CASE(field)                                                 \
>>> +    case offsetof(struct crb_regs, field) ...                       \
>>> +        offsetof(struct crb_regs, field) + sizeof(crb.field) - 1:   \
>>> +        return G_STRINGIFY(field);
>>> +        CASE(loc_state);
>>> +        CASE(reserved1);
>>> +        CASE(loc_ctrl);
>>> +        CASE(loc_sts);
>>> +        CASE(reserved2);
>>> +        CASE(intf_id);
>>> +        CASE(ctrl_ext);
>>> +        CASE(ctrl_req);
>>> +        CASE(ctrl_sts);
>>> +        CASE(ctrl_cancel);
>>> +        CASE(ctrl_start);
>>> +        CASE(ctrl_int_enable);
>>> +        CASE(ctrl_int_sts);
>>> +        CASE(ctrl_cmd_size);
>>> +        CASE(ctrl_cmd_pa_low);
>>> +        CASE(ctrl_cmd_pa_high);
>>> +        CASE(ctrl_rsp_size);
>>> +        CASE(ctrl_rsp_pa);
>>> +#undef CASE
>>> +    }
>>> +    return NULL;
>>> +}
>>> +
>>> +static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
>>> +                                  unsigned size)
>>> +{
>>> +    CRBState *s = CRB(opaque);
>>> +    DPRINTF("CRB read 0x%lx:%s len:%u\n",
>>> +            addr, addr_desc(addr), size);
>>> +    void *regs = (void *)&s->regs + addr;
>>> +
>>> +    switch (size) {
>>> +    case 1:
>>> +        return *(uint8_t *)regs;
>>> +    case 2:
>>> +        return *(uint16_t *)regs;
>>> +    case 4:
>>> +        return *(uint32_t *)regs;
>>> +    default:
>>> +        g_return_val_if_reached(-1);
>>> +    }
>>> +}
>>> +
>>> +static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
>>> +                               uint64_t val, unsigned size)
>>> +{
>>> +    CRBState *s = CRB(opaque);
>>> +    DPRINTF("CRB write 0x%lx:%s len:%u val:%lu\n",
>>> +            addr, addr_desc(addr), size, val);
>>> +
>>> +    switch (addr) {
>>> +    case CRB_ADDR_CTRL_REQ:
>>> +        switch (val) {
>>> +        case CRB_CTRL_REQ_CMD_READY:
>>> +            s->regs.ctrl_sts.bits.tpm_idle = 0;
>>> +            break;
>>> +        case CRB_CTRL_REQ_GO_IDLE:
>>> +            s->regs.ctrl_sts.bits.tpm_idle = 1;
>>> +            break;
>>> +        }
>>> +        break;
>>> +    case CRB_ADDR_CTRL_CANCEL:
>>> +        if (val == CRB_CANCEL_INVOKE && s->regs.ctrl_start &
>>> CRB_START_INVOKE) {
>>> +            tpm_backend_cancel_cmd(s->tpmbe);
>>> +        }
>>> +        break;
>>> +    case CRB_ADDR_CTRL_START:
>>> +        if (val == CRB_START_INVOKE &&
>>> +            !(s->regs.ctrl_start & CRB_START_INVOKE)) {
>>> +            void *mem = memory_region_get_ram_ptr(&s->cmdmem);
>>> +
>>> +            s->regs.ctrl_start |= CRB_START_INVOKE;
>>> +            s->cmd = (TPMBackendCmd) {
>>> +                .in = mem,
>>> +                .in_len = MIN(tpm_cmd_get_size(mem),
>>> s->be_buffer_size),
>>> +                .out = mem,
>>> +                .out_len = s->be_buffer_size,
>>> +            };
>>> +
>>> +            tpm_backend_deliver_request(s->tpmbe, &s->cmd);
>>> +        }
>>> +        break;
>>> +    case CRB_ADDR_LOC_CTRL:
>>> +        switch (val) {
>>> +        case CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT:
>>> +            /* not loc 3 or 4 */
>>> +            break;
>>> +        case CRB_LOC_CTRL_RELINQUISH:
>>> +            break;
>>> +        case CRB_LOC_CTRL_REQUEST_ACCESS:
>>> +            s->regs.loc_sts.bits.granted = 1;
>>> +            s->regs.loc_sts.bits.been_seized = 0;
>>> +            s->regs.loc_state.bits.loc_assigned = 1;
>>> +            s->regs.loc_state.bits.tpm_reg_valid_sts = 1;
>>> +            break;
>>> +        }
>>> +        break;
>>> +    }
>>> +}
>>> +
>>> +static const MemoryRegionOps tpm_crb_memory_ops = {
>>> +    .read = tpm_crb_mmio_read,
>>> +    .write = tpm_crb_mmio_write,
>>> +    .endianness = DEVICE_LITTLE_ENDIAN,
>>> +    .valid = {
>>> +        .min_access_size = 1,
>>> +        .max_access_size = 4,
>>> +    },
>>> +};
>>> +
>>> +static void tpm_crb_reset(DeviceState *dev)
>>> +{
>>> +    CRBState *s = CRB(dev);
>>> +
>>> +    tpm_backend_reset(s->tpmbe);
>>> +
>>> +    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
>>> +                            CRB_CTRL_CMD_SIZE);
>>> +
>>> +    s->regs = (struct crb_regs) {
>>> +        .intf_id.bits = {
>>> +            .type = CRB_INTF_TYPE_CRB_ACTIVE,
>>> +            .version = CRB_INTF_VERSION_CRB,
>>> +            .cap_locality = CRB_INTF_CAP_LOCALITY_0_ONLY,
>>> +            .cap_crb_idle_bypass = CRB_INTF_CAP_IDLE_FAST,
>>> +            .cap_data_xfer_size_support = CRB_INTF_CAP_XFER_SIZE_64,
>>> +            .cap_fifo = CRB_INTF_CAP_FIFO_NOT_SUPPORTED,
>>> +            .cap_crb = CRB_INTF_CAP_CRB_SUPPORTED,
>>> +            .cap_if_res = 0b0,
>>> +            .if_selector = CRB_INTF_IF_SELECTOR_CRB,
>>> +            .if_selector_lock = CRB_INTF_IF_SELECTOR_UNLOCKED,
>>> +            .rid = 0b0001,
>>> +            .vid = PCI_VENDOR_ID_IBM,
>>> +            .did = 0b0001,
>>> +        },
>>> +        .ctrl_cmd_size = CRB_CTRL_CMD_SIZE,
>>> +        .ctrl_cmd_pa_low = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
>>> +        .ctrl_rsp_size = CRB_CTRL_CMD_SIZE,
>>> +        .ctrl_rsp_pa = TPM_CRB_ADDR_BASE + sizeof(struct crb_regs),
>>> +    };
>>> +
>>> +    tpm_backend_startup_tpm(s->tpmbe, s->be_buffer_size);
>>> +}
>>> +
>>> +static void tpm_crb_request_completed(TPMIf *ti, int ret)
>>> +{
>>> +    CRBState *s = CRB(ti);
>>> +
>>> +    s->regs.ctrl_start &= ~CRB_START_INVOKE;
>>> +    if (ret != 0) {
>>> +        s->regs.ctrl_sts.bits.tpm_sts = 1; /* fatal error */
>>> +    }
>>> +}
>>> +
>>> +static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
>>> +{
>>> +    CRBState *s = CRB(ti);
>>> +
>>> +    return tpm_backend_get_tpm_version(s->tpmbe);
>>> +}
>>> +
>>> +static const VMStateDescription vmstate_tpm_crb = {
>>> +    .name = "tpm-crb",
>>> +    .unmigratable = 1,
>>> +};
>>> +
>>> +static Property tpm_crb_properties[] = {
>>> +    DEFINE_PROP_TPMBE("tpmdev", CRBState, tpmbe),
>>> +    DEFINE_PROP_END_OF_LIST(),
>>> +};
>>> +
>>> +static void tpm_crb_realizefn(DeviceState *dev, Error **errp)
>>> +{
>>> +    CRBState *s = CRB(dev);
>>> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>> +
>>> +    if (!tpm_find()) {
>>> +        error_setg(errp, "at most one TPM device is permitted");
>>> +        return;
>>> +    }
>>> +    if (!s->tpmbe) {
>>> +        error_setg(errp, "'tpmdev' property is required");
>>> +        return;
>>> +    }
>>> +
>>> +    memory_region_init_io(&s->mmio, OBJECT(s), &tpm_crb_memory_ops, s,
>>> +        "tpm-crb-mmio", sizeof(struct crb_regs));
>>> +    memory_region_init_ram(&s->cmdmem, OBJECT(s),
>>> +        "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
>>> +
>>> +    sysbus_init_mmio(sbd, &s->mmio);
>>> +    sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE);
>>> +    /* allocate ram in bios instead? */
>>> +    memory_region_add_subregion(get_system_memory(),
>>> +        TPM_CRB_ADDR_BASE + sizeof(struct crb_regs), &s->cmdmem);
>>> +}
>>> +
>>> +static void tpm_crb_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +    TPMIfClass *tc = TPM_IF_CLASS(klass);
>>> +
>>> +    dc->realize = tpm_crb_realizefn;
>>> +    dc->props = tpm_crb_properties;
>>> +    dc->reset = tpm_crb_reset;
>>> +    dc->vmsd  = &vmstate_tpm_crb;
>>> +    dc->user_creatable = true;
>>> +    tc->model = TPM_MODEL_TPM_CRB;
>>> +    tc->get_version = tpm_crb_get_version;
>>> +    tc->request_completed = tpm_crb_request_completed;
>>> +}
>>> +
>>> +static const TypeInfo tpm_crb_info = {
>>> +    .name = TYPE_TPM_CRB,
>>> +    .parent = TYPE_SYS_BUS_DEVICE,
>>> +    .instance_size = sizeof(CRBState),
>>> +    .class_init  = tpm_crb_class_init,
>>> +    .interfaces = (InterfaceInfo[]) {
>>> +        { TYPE_TPM_IF },
>>> +        { }
>>> +    }
>>> +};
>>> +
>>> +static void tpm_crb_register(void)
>>> +{
>>> +    type_register_static(&tpm_crb_info);
>>> +}
>>> +
>>> +type_init(tpm_crb_register)
>>> diff --git a/default-configs/i386-softmmu.mak
>>> b/default-configs/i386-softmmu.mak
>>> index 95ac4b464a..ac27700e79 100644
>>> --- a/default-configs/i386-softmmu.mak
>>> +++ b/default-configs/i386-softmmu.mak
>>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>>>   CONFIG_I8259=y
>>>   CONFIG_PFLASH_CFI01=y
>>>   CONFIG_TPM_TIS=$(CONFIG_TPM)
>>> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>>>   CONFIG_MC146818RTC=y
>>>   CONFIG_PCI_PIIX=y
>>>   CONFIG_WDT_IB700=y
>>> diff --git a/default-configs/x86_64-softmmu.mak
>>> b/default-configs/x86_64-softmmu.mak
>>> index 0221236825..b2104ade19 100644
>>> --- a/default-configs/x86_64-softmmu.mak
>>> +++ b/default-configs/x86_64-softmmu.mak
>>> @@ -37,6 +37,7 @@ CONFIG_APPLESMC=y
>>>   CONFIG_I8259=y
>>>   CONFIG_PFLASH_CFI01=y
>>>   CONFIG_TPM_TIS=$(CONFIG_TPM)
>>> +CONFIG_TPM_CRB=$(CONFIG_TPM)
>>>   CONFIG_MC146818RTC=y
>>>   CONFIG_PCI_PIIX=y
>>>   CONFIG_WDT_IB700=y
>>> diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
>>> index 7a93b24636..1dc9f8bf2c 100644
>>> --- a/hw/tpm/Makefile.objs
>>> +++ b/hw/tpm/Makefile.objs
>>> @@ -1,4 +1,5 @@
>>>   common-obj-y += tpm_util.o
>>>   common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
>>> +common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
>>>   common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
>>>   common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
>>>
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-21 22:01         ` Stefan Berger
@ 2018-01-22 15:08           ` Marc-Andre Lureau
  2018-01-22 15:47             ` Stefan Berger
  2018-01-22 17:25             ` Eduardo Habkost
  0 siblings, 2 replies; 31+ messages in thread
From: Marc-Andre Lureau @ 2018-01-22 15:08 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Eduardo Habkost, Michael S. Tsirkin, qemu-devel,
	Markus Armbruster, Philippe Mathieu-Daudé,
	Igor Mammedov, Paolo Bonzini, Marcel Apfelbaum,
	Marc-André Lureau, Richard Henderson

Hi

On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
<stefanb@linux.vnet.ibm.com> wrote:
> On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
>>
>> Hi
>>
>> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
>> <stefanb@linux.vnet.ibm.com> wrote:
>>>
>>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>>>>
>>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>>>>>
>>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>>>>
>>>>> The PTP allows device implementation to switch between TIS and CRB
>>>>> model at run time, but given that CRB is a simpler device to
>>>>> implement, I chose to implement it as a different device.
>>>>>
>>>>> The device doesn't implement other locality than 0 for now (my laptop
>>>>> TPM doesn't either, so I assume this isn't so bad)
>>>>>
>>>>> The command/reply memory region is statically allocated after the CRB
>>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>>>>> wonder if the BIOS could or should allocate it instead, or what size
>>>>> to use, again this seems to fit well expectations)
>>>>>
>>>>> The PTP doesn't specify a particular bus to put the device. So I added
>>>>> it on the system bus directly, so it could hopefully be used easily on
>>>>> a different platform than x86. Currently, it fails to init on piix,
>>>>> because error_on_sysbus_device() check. The check may be changed in a
>>>>> near future, see discussion on the qemu-devel ML.
>>>>>
>>>>> Tested with some success with Linux upstream and Windows 10, seabios &
>>>>> modified ovmf. The device is recognized and correctly transmit
>>>>> command/response with passthrough & emu. However, we are missing PPI
>>>>> ACPI part atm.
>>>>>
>>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>>> ---
>>>>>    qapi/tpm.json                      |   5 +-
>>>>>    include/hw/acpi/tpm.h              |  72 ++++++++
>>>>>    include/sysemu/tpm.h               |   3 +
>>>>>    hw/i386/acpi-build.c               |  34 +++-
>>>>>    hw/tpm/tpm_crb.c                   | 327
>>>>> +++++++++++++++++++++++++++++++++++++
>>>>>    default-configs/i386-softmmu.mak   |   1 +
>>>>>    default-configs/x86_64-softmmu.mak |   1 +
>>>>>    hw/tpm/Makefile.objs               |   1 +
>>>>>    8 files changed, 434 insertions(+), 10 deletions(-)
>>>>>    create mode 100644 hw/tpm/tpm_crb.c
>>>>>
>>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>>>>> index 7093f268fb..d50deef5e9 100644
>>>>> --- a/qapi/tpm.json
>>>>> +++ b/qapi/tpm.json
>>>>> @@ -11,10 +11,11 @@
>>>>>    # An enumeration of TPM models
>>>>>    #
>>>>>    # @tpm-tis: TPM TIS model
>>>>> +# @tpm-crb: TPM CRB model (since 2.12)
>>>>>    #
>>>>>    # Since: 1.5
>>>>>    ##
>>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>>>>>      ##
>>>>>    # @query-tpm-models:
>>>>> @@ -28,7 +29,7 @@
>>>>>    # Example:
>>>>>    #
>>>>>    # -> { "execute": "query-tpm-models" }
>>>>> -# <- { "return": [ "tpm-tis" ] }
>>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>>>>>    #
>>>>>    ##
>>>>>    { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>>>>> index 6d516c6a7f..b0048515fa 100644
>>>>> --- a/include/hw/acpi/tpm.h
>>>>> +++ b/include/hw/acpi/tpm.h
>>>>> @@ -16,11 +16,82 @@
>>>>>    #ifndef HW_ACPI_TPM_H
>>>>>    #define HW_ACPI_TPM_H
>>>>>    +#include "qemu/osdep.h"
>>>>> +
>>>>>    #define TPM_TIS_ADDR_BASE           0xFED40000
>>>>>    #define TPM_TIS_ADDR_SIZE           0x5000
>>>>>      #define TPM_TIS_IRQ                 5
>>>>>    +struct crb_regs {
>>>>> +    union {
>>>>> +        uint32_t reg;
>>>>> +        struct {
>>>>> +            unsigned tpm_established:1;
>>>>> +            unsigned loc_assigned:1;
>>>>> +            unsigned active_locality:3;
>>>>> +            unsigned reserved:2;
>>>>> +            unsigned tpm_reg_valid_sts:1;
>>>>> +        } bits;
>>>>
>>>> I suppose this is little-endian layout, so this won't work on big-endian
>>>> hosts.
>>>>
>>>> Can you add a qtest?
>>>>
>>>>> +    } loc_state;
>>>>> +    uint32_t reserved1;
>>>>> +    uint32_t loc_ctrl;
>>>>> +    union {
>>>>> +        uint32_t reg;
>>>>> +        struct {
>>>>> +            unsigned granted:1;
>>>>> +            unsigned been_seized:1;
>>>>> +        } bits;
>>>>
>>>>
>>>> This is unclear where you expect those bits (right/left aligned).
>>>>
>>>> Can you add an unnamed field to be more explicit?
>>>>
>>>> i.e. without using struct if left alignment expected:
>>>>
>>>>              unsigned granted:1, been_seized:1, :30;
>>>
>>>
>>>
>>> I got rid of all the bitfields and this patch here makes it work on a
>>> ppc64
>>> big endian and also x86_64 host:
>>>
>>>
>>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
>>>
>> Thank you Stefan! I am all for squashing this fix to the patch. You
>> should then add your signed-off to the commit.
>
>
> I'll do that.
>
> The TIS is an ISA Device and the CRB is similar. Considering the

How much similarity is there between TIS and CRB is there? The two
devices look quite different to me, CRB is way simpler it seems. Or is
the CRB implementation just lacking many bells and whistles that TIS
has? Should we consider merging CRB in TIS?

> complications with the sysbus devices where one has to explicitly allow it
> for a certain machine type, I would advocate to convert the CRB to an ISA
> device. A patch that does that is this one:

If it's only for that reason (an explicit enable), I would rather keep
it on the system bus. Or should it be on an LPC bus?

Eduardo, what do you think?

Thanks

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-22 15:08           ` Marc-Andre Lureau
@ 2018-01-22 15:47             ` Stefan Berger
  2018-01-22 16:57               ` Marc-André Lureau
  2018-01-22 17:25             ` Eduardo Habkost
  1 sibling, 1 reply; 31+ messages in thread
From: Stefan Berger @ 2018-01-22 15:47 UTC (permalink / raw)
  To: Marc-Andre Lureau
  Cc: Eduardo Habkost, Michael S. Tsirkin, qemu-devel,
	Markus Armbruster, Philippe Mathieu-Daudé,
	Igor Mammedov, Paolo Bonzini, Marcel Apfelbaum,
	Marc-André Lureau, Richard Henderson

On 01/22/2018 10:08 AM, Marc-Andre Lureau wrote:
> Hi
>
> On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
> <stefanb@linux.vnet.ibm.com> wrote:
>> On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
>>> Hi
>>>
>>> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
>>> <stefanb@linux.vnet.ibm.com> wrote:
>>>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>>>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>>>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>>>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>>>>>
>>>>>> The PTP allows device implementation to switch between TIS and CRB
>>>>>> model at run time, but given that CRB is a simpler device to
>>>>>> implement, I chose to implement it as a different device.
>>>>>>
>>>>>> The device doesn't implement other locality than 0 for now (my laptop
>>>>>> TPM doesn't either, so I assume this isn't so bad)
>>>>>>
>>>>>> The command/reply memory region is statically allocated after the CRB
>>>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>>>>>> wonder if the BIOS could or should allocate it instead, or what size
>>>>>> to use, again this seems to fit well expectations)
>>>>>>
>>>>>> The PTP doesn't specify a particular bus to put the device. So I added
>>>>>> it on the system bus directly, so it could hopefully be used easily on
>>>>>> a different platform than x86. Currently, it fails to init on piix,
>>>>>> because error_on_sysbus_device() check. The check may be changed in a
>>>>>> near future, see discussion on the qemu-devel ML.
>>>>>>
>>>>>> Tested with some success with Linux upstream and Windows 10, seabios &
>>>>>> modified ovmf. The device is recognized and correctly transmit
>>>>>> command/response with passthrough & emu. However, we are missing PPI
>>>>>> ACPI part atm.
>>>>>>
>>>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>>>> ---
>>>>>>     qapi/tpm.json                      |   5 +-
>>>>>>     include/hw/acpi/tpm.h              |  72 ++++++++
>>>>>>     include/sysemu/tpm.h               |   3 +
>>>>>>     hw/i386/acpi-build.c               |  34 +++-
>>>>>>     hw/tpm/tpm_crb.c                   | 327
>>>>>> +++++++++++++++++++++++++++++++++++++
>>>>>>     default-configs/i386-softmmu.mak   |   1 +
>>>>>>     default-configs/x86_64-softmmu.mak |   1 +
>>>>>>     hw/tpm/Makefile.objs               |   1 +
>>>>>>     8 files changed, 434 insertions(+), 10 deletions(-)
>>>>>>     create mode 100644 hw/tpm/tpm_crb.c
>>>>>>
>>>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>>>>>> index 7093f268fb..d50deef5e9 100644
>>>>>> --- a/qapi/tpm.json
>>>>>> +++ b/qapi/tpm.json
>>>>>> @@ -11,10 +11,11 @@
>>>>>>     # An enumeration of TPM models
>>>>>>     #
>>>>>>     # @tpm-tis: TPM TIS model
>>>>>> +# @tpm-crb: TPM CRB model (since 2.12)
>>>>>>     #
>>>>>>     # Since: 1.5
>>>>>>     ##
>>>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>>>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>>>>>>       ##
>>>>>>     # @query-tpm-models:
>>>>>> @@ -28,7 +29,7 @@
>>>>>>     # Example:
>>>>>>     #
>>>>>>     # -> { "execute": "query-tpm-models" }
>>>>>> -# <- { "return": [ "tpm-tis" ] }
>>>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>>>>>>     #
>>>>>>     ##
>>>>>>     { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>>>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>>>>>> index 6d516c6a7f..b0048515fa 100644
>>>>>> --- a/include/hw/acpi/tpm.h
>>>>>> +++ b/include/hw/acpi/tpm.h
>>>>>> @@ -16,11 +16,82 @@
>>>>>>     #ifndef HW_ACPI_TPM_H
>>>>>>     #define HW_ACPI_TPM_H
>>>>>>     +#include "qemu/osdep.h"
>>>>>> +
>>>>>>     #define TPM_TIS_ADDR_BASE           0xFED40000
>>>>>>     #define TPM_TIS_ADDR_SIZE           0x5000
>>>>>>       #define TPM_TIS_IRQ                 5
>>>>>>     +struct crb_regs {
>>>>>> +    union {
>>>>>> +        uint32_t reg;
>>>>>> +        struct {
>>>>>> +            unsigned tpm_established:1;
>>>>>> +            unsigned loc_assigned:1;
>>>>>> +            unsigned active_locality:3;
>>>>>> +            unsigned reserved:2;
>>>>>> +            unsigned tpm_reg_valid_sts:1;
>>>>>> +        } bits;
>>>>> I suppose this is little-endian layout, so this won't work on big-endian
>>>>> hosts.
>>>>>
>>>>> Can you add a qtest?
>>>>>
>>>>>> +    } loc_state;
>>>>>> +    uint32_t reserved1;
>>>>>> +    uint32_t loc_ctrl;
>>>>>> +    union {
>>>>>> +        uint32_t reg;
>>>>>> +        struct {
>>>>>> +            unsigned granted:1;
>>>>>> +            unsigned been_seized:1;
>>>>>> +        } bits;
>>>>>
>>>>> This is unclear where you expect those bits (right/left aligned).
>>>>>
>>>>> Can you add an unnamed field to be more explicit?
>>>>>
>>>>> i.e. without using struct if left alignment expected:
>>>>>
>>>>>               unsigned granted:1, been_seized:1, :30;
>>>>
>>>>
>>>> I got rid of all the bitfields and this patch here makes it work on a
>>>> ppc64
>>>> big endian and also x86_64 host:
>>>>
>>>>
>>>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
>>>>
>>> Thank you Stefan! I am all for squashing this fix to the patch. You
>>> should then add your signed-off to the commit.
>>
>> I'll do that.
>>
>> The TIS is an ISA Device and the CRB is similar. Considering the
> How much similarity is there between TIS and CRB is there? The two
> devices look quite different to me, CRB is way simpler it seems. Or is
> the CRB implementation just lacking many bells and whistles that TIS
> has? Should we consider merging CRB in TIS?

That is the question. It would be a pain for users to have to choose the 
interface. Basically TIS and CRB can be implemented in a single device 
and let the software choose the interface following flags that are set 
by the interface advertising whether it offers TIS and/or CRB. Maybe we 
could keep the CRB code in a separate file and, upon choosing the CRB 
interface call into CRB functions rather than TIS functions.


>
>> complications with the sysbus devices where one has to explicitly allow it
>> for a certain machine type, I would advocate to convert the CRB to an ISA
>> device. A patch that does that is this one:
> If it's only for that reason (an explicit enable), I would rather keep
> it on the system bus. Or should it be on an LPC bus?

I do not think there's an LPC bus. Merging the code into the TIS would 
put the whoe device on the ISA Bus per current TIS implementation.

>
> Eduardo, what do you think?
>
> Thanks
>

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-22 15:47             ` Stefan Berger
@ 2018-01-22 16:57               ` Marc-André Lureau
  0 siblings, 0 replies; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-22 16:57 UTC (permalink / raw)
  To: Stefan Berger
  Cc: Eduardo Habkost, Michael S. Tsirkin, qemu-devel,
	Markus Armbruster, Paolo Bonzini, Marcel Apfelbaum,
	Igor Mammedov, Richard Henderson, Philippe Mathieu-Daudé

On Mon, Jan 22, 2018 at 4:47 PM, Stefan Berger
<stefanb@linux.vnet.ibm.com> wrote:
> On 01/22/2018 10:08 AM, Marc-Andre Lureau wrote:
>>
>> Hi
>>
>> On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
>> <stefanb@linux.vnet.ibm.com> wrote:
>>>
>>> On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
>>>>
>>>> Hi
>>>>
>>>> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
>>>> <stefanb@linux.vnet.ibm.com> wrote:
>>>>>
>>>>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>>>>>>
>>>>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>>>>>>>
>>>>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>>>>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>>>>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>>>>>>>
>>>>>>> The PTP allows device implementation to switch between TIS and CRB
>>>>>>> model at run time, but given that CRB is a simpler device to
>>>>>>> implement, I chose to implement it as a different device.
>>>>>>>
>>>>>>> The device doesn't implement other locality than 0 for now (my laptop
>>>>>>> TPM doesn't either, so I assume this isn't so bad)
>>>>>>>
>>>>>>> The command/reply memory region is statically allocated after the CRB
>>>>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>>>>>>> wonder if the BIOS could or should allocate it instead, or what size
>>>>>>> to use, again this seems to fit well expectations)
>>>>>>>
>>>>>>> The PTP doesn't specify a particular bus to put the device. So I
>>>>>>> added
>>>>>>> it on the system bus directly, so it could hopefully be used easily
>>>>>>> on
>>>>>>> a different platform than x86. Currently, it fails to init on piix,
>>>>>>> because error_on_sysbus_device() check. The check may be changed in a
>>>>>>> near future, see discussion on the qemu-devel ML.
>>>>>>>
>>>>>>> Tested with some success with Linux upstream and Windows 10, seabios
>>>>>>> &
>>>>>>> modified ovmf. The device is recognized and correctly transmit
>>>>>>> command/response with passthrough & emu. However, we are missing PPI
>>>>>>> ACPI part atm.
>>>>>>>
>>>>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>>>>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>>>>>>> ---
>>>>>>>     qapi/tpm.json                      |   5 +-
>>>>>>>     include/hw/acpi/tpm.h              |  72 ++++++++
>>>>>>>     include/sysemu/tpm.h               |   3 +
>>>>>>>     hw/i386/acpi-build.c               |  34 +++-
>>>>>>>     hw/tpm/tpm_crb.c                   | 327
>>>>>>> +++++++++++++++++++++++++++++++++++++
>>>>>>>     default-configs/i386-softmmu.mak   |   1 +
>>>>>>>     default-configs/x86_64-softmmu.mak |   1 +
>>>>>>>     hw/tpm/Makefile.objs               |   1 +
>>>>>>>     8 files changed, 434 insertions(+), 10 deletions(-)
>>>>>>>     create mode 100644 hw/tpm/tpm_crb.c
>>>>>>>
>>>>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>>>>>>> index 7093f268fb..d50deef5e9 100644
>>>>>>> --- a/qapi/tpm.json
>>>>>>> +++ b/qapi/tpm.json
>>>>>>> @@ -11,10 +11,11 @@
>>>>>>>     # An enumeration of TPM models
>>>>>>>     #
>>>>>>>     # @tpm-tis: TPM TIS model
>>>>>>> +# @tpm-crb: TPM CRB model (since 2.12)
>>>>>>>     #
>>>>>>>     # Since: 1.5
>>>>>>>     ##
>>>>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>>>>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>>>>>>>       ##
>>>>>>>     # @query-tpm-models:
>>>>>>> @@ -28,7 +29,7 @@
>>>>>>>     # Example:
>>>>>>>     #
>>>>>>>     # -> { "execute": "query-tpm-models" }
>>>>>>> -# <- { "return": [ "tpm-tis" ] }
>>>>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>>>>>>>     #
>>>>>>>     ##
>>>>>>>     { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>>>>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>>>>>>> index 6d516c6a7f..b0048515fa 100644
>>>>>>> --- a/include/hw/acpi/tpm.h
>>>>>>> +++ b/include/hw/acpi/tpm.h
>>>>>>> @@ -16,11 +16,82 @@
>>>>>>>     #ifndef HW_ACPI_TPM_H
>>>>>>>     #define HW_ACPI_TPM_H
>>>>>>>     +#include "qemu/osdep.h"
>>>>>>> +
>>>>>>>     #define TPM_TIS_ADDR_BASE           0xFED40000
>>>>>>>     #define TPM_TIS_ADDR_SIZE           0x5000
>>>>>>>       #define TPM_TIS_IRQ                 5
>>>>>>>     +struct crb_regs {
>>>>>>> +    union {
>>>>>>> +        uint32_t reg;
>>>>>>> +        struct {
>>>>>>> +            unsigned tpm_established:1;
>>>>>>> +            unsigned loc_assigned:1;
>>>>>>> +            unsigned active_locality:3;
>>>>>>> +            unsigned reserved:2;
>>>>>>> +            unsigned tpm_reg_valid_sts:1;
>>>>>>> +        } bits;
>>>>>>
>>>>>> I suppose this is little-endian layout, so this won't work on
>>>>>> big-endian
>>>>>> hosts.
>>>>>>
>>>>>> Can you add a qtest?
>>>>>>
>>>>>>> +    } loc_state;
>>>>>>> +    uint32_t reserved1;
>>>>>>> +    uint32_t loc_ctrl;
>>>>>>> +    union {
>>>>>>> +        uint32_t reg;
>>>>>>> +        struct {
>>>>>>> +            unsigned granted:1;
>>>>>>> +            unsigned been_seized:1;
>>>>>>> +        } bits;
>>>>>>
>>>>>>
>>>>>> This is unclear where you expect those bits (right/left aligned).
>>>>>>
>>>>>> Can you add an unnamed field to be more explicit?
>>>>>>
>>>>>> i.e. without using struct if left alignment expected:
>>>>>>
>>>>>>               unsigned granted:1, been_seized:1, :30;
>>>>>
>>>>>
>>>>>
>>>>> I got rid of all the bitfields and this patch here makes it work on a
>>>>> ppc64
>>>>> big endian and also x86_64 host:
>>>>>
>>>>>
>>>>>
>>>>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
>>>>>
>>>> Thank you Stefan! I am all for squashing this fix to the patch. You
>>>> should then add your signed-off to the commit.
>>>
>>>
>>> I'll do that.
>>>
>>> The TIS is an ISA Device and the CRB is similar. Considering the
>>
>> How much similarity is there between TIS and CRB is there? The two
>> devices look quite different to me, CRB is way simpler it seems. Or is
>> the CRB implementation just lacking many bells and whistles that TIS
>> has? Should we consider merging CRB in TIS?
>
>
> That is the question. It would be a pain for users to have to choose the
> interface. Basically TIS and CRB can be implemented in a single device and
> let the software choose the interface following flags that are set by the
> interface advertising whether it offers TIS and/or CRB. Maybe we could keep
> the CRB code in a separate file and, upon choosing the CRB interface call
> into CRB functions rather than TIS functions.

Afaik, most people want to use TPM2, either with Linux or Windows, and
CRB fits that job better at least on Windows. So unless TPM 1.2 and
legacy OS is required, I would recommend to use CRB only.

If there is a need to grow dynamic TIS/CRB switching, I would teach
the existing TIS device to call into CRB, as you proposed. In the
meantime, I think it's best to have a simple CRB-only device that is
known to work with latest Linux & Windows.




-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-22 15:08           ` Marc-Andre Lureau
  2018-01-22 15:47             ` Stefan Berger
@ 2018-01-22 17:25             ` Eduardo Habkost
  2018-01-22 17:32               ` Marc-André Lureau
  1 sibling, 1 reply; 31+ messages in thread
From: Eduardo Habkost @ 2018-01-22 17:25 UTC (permalink / raw)
  To: Marc-Andre Lureau
  Cc: Stefan Berger, Michael S. Tsirkin, qemu-devel, Markus Armbruster,
	Philippe Mathieu-Daudé,
	Igor Mammedov, Paolo Bonzini, Marcel Apfelbaum,
	Marc-André Lureau, Richard Henderson

On Mon, Jan 22, 2018 at 04:08:30PM +0100, Marc-Andre Lureau wrote:
> Hi
> 
> On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
> <stefanb@linux.vnet.ibm.com> wrote:
> > On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
> >>
> >> Hi
> >>
> >> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
> >> <stefanb@linux.vnet.ibm.com> wrote:
> >>>
> >>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
> >>>>
> >>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
> >>>>>
> >>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
> >>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
> >>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
> >>>>>
> >>>>> The PTP allows device implementation to switch between TIS and CRB
> >>>>> model at run time, but given that CRB is a simpler device to
> >>>>> implement, I chose to implement it as a different device.
> >>>>>
> >>>>> The device doesn't implement other locality than 0 for now (my laptop
> >>>>> TPM doesn't either, so I assume this isn't so bad)
> >>>>>
> >>>>> The command/reply memory region is statically allocated after the CRB
> >>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
> >>>>> wonder if the BIOS could or should allocate it instead, or what size
> >>>>> to use, again this seems to fit well expectations)
> >>>>>
> >>>>> The PTP doesn't specify a particular bus to put the device. So I added
> >>>>> it on the system bus directly, so it could hopefully be used easily on
> >>>>> a different platform than x86. Currently, it fails to init on piix,
> >>>>> because error_on_sysbus_device() check. The check may be changed in a
> >>>>> near future, see discussion on the qemu-devel ML.
> >>>>>
> >>>>> Tested with some success with Linux upstream and Windows 10, seabios &
> >>>>> modified ovmf. The device is recognized and correctly transmit
> >>>>> command/response with passthrough & emu. However, we are missing PPI
> >>>>> ACPI part atm.
> >>>>>
> >>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >>>>> ---
> >>>>>    qapi/tpm.json                      |   5 +-
> >>>>>    include/hw/acpi/tpm.h              |  72 ++++++++
> >>>>>    include/sysemu/tpm.h               |   3 +
> >>>>>    hw/i386/acpi-build.c               |  34 +++-
> >>>>>    hw/tpm/tpm_crb.c                   | 327
> >>>>> +++++++++++++++++++++++++++++++++++++
> >>>>>    default-configs/i386-softmmu.mak   |   1 +
> >>>>>    default-configs/x86_64-softmmu.mak |   1 +
> >>>>>    hw/tpm/Makefile.objs               |   1 +
> >>>>>    8 files changed, 434 insertions(+), 10 deletions(-)
> >>>>>    create mode 100644 hw/tpm/tpm_crb.c
> >>>>>
> >>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
> >>>>> index 7093f268fb..d50deef5e9 100644
> >>>>> --- a/qapi/tpm.json
> >>>>> +++ b/qapi/tpm.json
> >>>>> @@ -11,10 +11,11 @@
> >>>>>    # An enumeration of TPM models
> >>>>>    #
> >>>>>    # @tpm-tis: TPM TIS model
> >>>>> +# @tpm-crb: TPM CRB model (since 2.12)
> >>>>>    #
> >>>>>    # Since: 1.5
> >>>>>    ##
> >>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
> >>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
> >>>>>      ##
> >>>>>    # @query-tpm-models:
> >>>>> @@ -28,7 +29,7 @@
> >>>>>    # Example:
> >>>>>    #
> >>>>>    # -> { "execute": "query-tpm-models" }
> >>>>> -# <- { "return": [ "tpm-tis" ] }
> >>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
> >>>>>    #
> >>>>>    ##
> >>>>>    { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
> >>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
> >>>>> index 6d516c6a7f..b0048515fa 100644
> >>>>> --- a/include/hw/acpi/tpm.h
> >>>>> +++ b/include/hw/acpi/tpm.h
> >>>>> @@ -16,11 +16,82 @@
> >>>>>    #ifndef HW_ACPI_TPM_H
> >>>>>    #define HW_ACPI_TPM_H
> >>>>>    +#include "qemu/osdep.h"
> >>>>> +
> >>>>>    #define TPM_TIS_ADDR_BASE           0xFED40000
> >>>>>    #define TPM_TIS_ADDR_SIZE           0x5000
> >>>>>      #define TPM_TIS_IRQ                 5
> >>>>>    +struct crb_regs {
> >>>>> +    union {
> >>>>> +        uint32_t reg;
> >>>>> +        struct {
> >>>>> +            unsigned tpm_established:1;
> >>>>> +            unsigned loc_assigned:1;
> >>>>> +            unsigned active_locality:3;
> >>>>> +            unsigned reserved:2;
> >>>>> +            unsigned tpm_reg_valid_sts:1;
> >>>>> +        } bits;
> >>>>
> >>>> I suppose this is little-endian layout, so this won't work on big-endian
> >>>> hosts.
> >>>>
> >>>> Can you add a qtest?
> >>>>
> >>>>> +    } loc_state;
> >>>>> +    uint32_t reserved1;
> >>>>> +    uint32_t loc_ctrl;
> >>>>> +    union {
> >>>>> +        uint32_t reg;
> >>>>> +        struct {
> >>>>> +            unsigned granted:1;
> >>>>> +            unsigned been_seized:1;
> >>>>> +        } bits;
> >>>>
> >>>>
> >>>> This is unclear where you expect those bits (right/left aligned).
> >>>>
> >>>> Can you add an unnamed field to be more explicit?
> >>>>
> >>>> i.e. without using struct if left alignment expected:
> >>>>
> >>>>              unsigned granted:1, been_seized:1, :30;
> >>>
> >>>
> >>>
> >>> I got rid of all the bitfields and this patch here makes it work on a
> >>> ppc64
> >>> big endian and also x86_64 host:
> >>>
> >>>
> >>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
> >>>
> >> Thank you Stefan! I am all for squashing this fix to the patch. You
> >> should then add your signed-off to the commit.
> >
> >
> > I'll do that.
> >
> > The TIS is an ISA Device and the CRB is similar. Considering the
> 
> How much similarity is there between TIS and CRB is there? The two
> devices look quite different to me, CRB is way simpler it seems. Or is
> the CRB implementation just lacking many bells and whistles that TIS
> has? Should we consider merging CRB in TIS?
> 
> > complications with the sysbus devices where one has to explicitly allow it
> > for a certain machine type, I would advocate to convert the CRB to an ISA
> > device. A patch that does that is this one:
> 
> If it's only for that reason (an explicit enable), I would rather keep
> it on the system bus. Or should it be on an LPC bus?
> 
> Eduardo, what do you think?

Everything about sysbus is exceptional and confusing, so I would
prefer to avoid using sysbus every time we have an alternative.
If tpm-tis is already an ISA device, what are the reasons to not
use ISA for tpm-crb too?

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-22 17:25             ` Eduardo Habkost
@ 2018-01-22 17:32               ` Marc-André Lureau
  2018-01-22 17:47                 ` Eduardo Habkost
  0 siblings, 1 reply; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-22 17:32 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Michael S. Tsirkin, qemu-devel, Stefan Berger, Markus Armbruster,
	Philippe Mathieu-Daudé,
	Paolo Bonzini, Marcel Apfelbaum, Igor Mammedov,
	Richard Henderson

Hi

On Mon, Jan 22, 2018 at 6:25 PM, Eduardo Habkost <ehabkost@redhat.com> wrote:
> On Mon, Jan 22, 2018 at 04:08:30PM +0100, Marc-Andre Lureau wrote:
>> Hi
>>
>> On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
>> <stefanb@linux.vnet.ibm.com> wrote:
>> > On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
>> >>
>> >> Hi
>> >>
>> >> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
>> >> <stefanb@linux.vnet.ibm.com> wrote:
>> >>>
>> >>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>> >>>>
>> >>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>> >>>>>
>> >>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>> >>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>> >>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>> >>>>>
>> >>>>> The PTP allows device implementation to switch between TIS and CRB
>> >>>>> model at run time, but given that CRB is a simpler device to
>> >>>>> implement, I chose to implement it as a different device.
>> >>>>>
>> >>>>> The device doesn't implement other locality than 0 for now (my laptop
>> >>>>> TPM doesn't either, so I assume this isn't so bad)
>> >>>>>
>> >>>>> The command/reply memory region is statically allocated after the CRB
>> >>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>> >>>>> wonder if the BIOS could or should allocate it instead, or what size
>> >>>>> to use, again this seems to fit well expectations)
>> >>>>>
>> >>>>> The PTP doesn't specify a particular bus to put the device. So I added
>> >>>>> it on the system bus directly, so it could hopefully be used easily on
>> >>>>> a different platform than x86. Currently, it fails to init on piix,
>> >>>>> because error_on_sysbus_device() check. The check may be changed in a
>> >>>>> near future, see discussion on the qemu-devel ML.
>> >>>>>
>> >>>>> Tested with some success with Linux upstream and Windows 10, seabios &
>> >>>>> modified ovmf. The device is recognized and correctly transmit
>> >>>>> command/response with passthrough & emu. However, we are missing PPI
>> >>>>> ACPI part atm.
>> >>>>>
>> >>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> >>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>> >>>>> ---
>> >>>>>    qapi/tpm.json                      |   5 +-
>> >>>>>    include/hw/acpi/tpm.h              |  72 ++++++++
>> >>>>>    include/sysemu/tpm.h               |   3 +
>> >>>>>    hw/i386/acpi-build.c               |  34 +++-
>> >>>>>    hw/tpm/tpm_crb.c                   | 327
>> >>>>> +++++++++++++++++++++++++++++++++++++
>> >>>>>    default-configs/i386-softmmu.mak   |   1 +
>> >>>>>    default-configs/x86_64-softmmu.mak |   1 +
>> >>>>>    hw/tpm/Makefile.objs               |   1 +
>> >>>>>    8 files changed, 434 insertions(+), 10 deletions(-)
>> >>>>>    create mode 100644 hw/tpm/tpm_crb.c
>> >>>>>
>> >>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>> >>>>> index 7093f268fb..d50deef5e9 100644
>> >>>>> --- a/qapi/tpm.json
>> >>>>> +++ b/qapi/tpm.json
>> >>>>> @@ -11,10 +11,11 @@
>> >>>>>    # An enumeration of TPM models
>> >>>>>    #
>> >>>>>    # @tpm-tis: TPM TIS model
>> >>>>> +# @tpm-crb: TPM CRB model (since 2.12)
>> >>>>>    #
>> >>>>>    # Since: 1.5
>> >>>>>    ##
>> >>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>> >>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>> >>>>>      ##
>> >>>>>    # @query-tpm-models:
>> >>>>> @@ -28,7 +29,7 @@
>> >>>>>    # Example:
>> >>>>>    #
>> >>>>>    # -> { "execute": "query-tpm-models" }
>> >>>>> -# <- { "return": [ "tpm-tis" ] }
>> >>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>> >>>>>    #
>> >>>>>    ##
>> >>>>>    { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>> >>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>> >>>>> index 6d516c6a7f..b0048515fa 100644
>> >>>>> --- a/include/hw/acpi/tpm.h
>> >>>>> +++ b/include/hw/acpi/tpm.h
>> >>>>> @@ -16,11 +16,82 @@
>> >>>>>    #ifndef HW_ACPI_TPM_H
>> >>>>>    #define HW_ACPI_TPM_H
>> >>>>>    +#include "qemu/osdep.h"
>> >>>>> +
>> >>>>>    #define TPM_TIS_ADDR_BASE           0xFED40000
>> >>>>>    #define TPM_TIS_ADDR_SIZE           0x5000
>> >>>>>      #define TPM_TIS_IRQ                 5
>> >>>>>    +struct crb_regs {
>> >>>>> +    union {
>> >>>>> +        uint32_t reg;
>> >>>>> +        struct {
>> >>>>> +            unsigned tpm_established:1;
>> >>>>> +            unsigned loc_assigned:1;
>> >>>>> +            unsigned active_locality:3;
>> >>>>> +            unsigned reserved:2;
>> >>>>> +            unsigned tpm_reg_valid_sts:1;
>> >>>>> +        } bits;
>> >>>>
>> >>>> I suppose this is little-endian layout, so this won't work on big-endian
>> >>>> hosts.
>> >>>>
>> >>>> Can you add a qtest?
>> >>>>
>> >>>>> +    } loc_state;
>> >>>>> +    uint32_t reserved1;
>> >>>>> +    uint32_t loc_ctrl;
>> >>>>> +    union {
>> >>>>> +        uint32_t reg;
>> >>>>> +        struct {
>> >>>>> +            unsigned granted:1;
>> >>>>> +            unsigned been_seized:1;
>> >>>>> +        } bits;
>> >>>>
>> >>>>
>> >>>> This is unclear where you expect those bits (right/left aligned).
>> >>>>
>> >>>> Can you add an unnamed field to be more explicit?
>> >>>>
>> >>>> i.e. without using struct if left alignment expected:
>> >>>>
>> >>>>              unsigned granted:1, been_seized:1, :30;
>> >>>
>> >>>
>> >>>
>> >>> I got rid of all the bitfields and this patch here makes it work on a
>> >>> ppc64
>> >>> big endian and also x86_64 host:
>> >>>
>> >>>
>> >>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
>> >>>
>> >> Thank you Stefan! I am all for squashing this fix to the patch. You
>> >> should then add your signed-off to the commit.
>> >
>> >
>> > I'll do that.
>> >
>> > The TIS is an ISA Device and the CRB is similar. Considering the
>>
>> How much similarity is there between TIS and CRB is there? The two
>> devices look quite different to me, CRB is way simpler it seems. Or is
>> the CRB implementation just lacking many bells and whistles that TIS
>> has? Should we consider merging CRB in TIS?
>>
>> > complications with the sysbus devices where one has to explicitly allow it
>> > for a certain machine type, I would advocate to convert the CRB to an ISA
>> > device. A patch that does that is this one:
>>
>> If it's only for that reason (an explicit enable), I would rather keep
>> it on the system bus. Or should it be on an LPC bus?
>>
>> Eduardo, what do you think?
>
> Everything about sysbus is exceptional and confusing, so I would
> prefer to avoid using sysbus every time we have an alternative.
> If tpm-tis is already an ISA device, what are the reasons to not
> use ISA for tpm-crb too?

I was hoping this would make the device more portable (especially on
arm) and avoid using legacy bus or resources.

Putting it on ISA doesn't reflect better what a real hardware is like,
or does it?

-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-22 17:32               ` Marc-André Lureau
@ 2018-01-22 17:47                 ` Eduardo Habkost
  2018-01-22 18:15                   ` Marc-André Lureau
  0 siblings, 1 reply; 31+ messages in thread
From: Eduardo Habkost @ 2018-01-22 17:47 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: Michael S. Tsirkin, qemu-devel, Stefan Berger, Markus Armbruster,
	Philippe Mathieu-Daudé,
	Paolo Bonzini, Marcel Apfelbaum, Igor Mammedov,
	Richard Henderson

On Mon, Jan 22, 2018 at 06:32:37PM +0100, Marc-André Lureau wrote:
> Hi
> 
> On Mon, Jan 22, 2018 at 6:25 PM, Eduardo Habkost <ehabkost@redhat.com> wrote:
> > On Mon, Jan 22, 2018 at 04:08:30PM +0100, Marc-Andre Lureau wrote:
> >> Hi
> >>
> >> On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
> >> <stefanb@linux.vnet.ibm.com> wrote:
> >> > On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
> >> >>
> >> >> Hi
> >> >>
> >> >> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
> >> >> <stefanb@linux.vnet.ibm.com> wrote:
> >> >>>
> >> >>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
> >> >>>>
> >> >>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
> >> >>>>>
> >> >>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
> >> >>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
> >> >>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
> >> >>>>>
> >> >>>>> The PTP allows device implementation to switch between TIS and CRB
> >> >>>>> model at run time, but given that CRB is a simpler device to
> >> >>>>> implement, I chose to implement it as a different device.
> >> >>>>>
> >> >>>>> The device doesn't implement other locality than 0 for now (my laptop
> >> >>>>> TPM doesn't either, so I assume this isn't so bad)
> >> >>>>>
> >> >>>>> The command/reply memory region is statically allocated after the CRB
> >> >>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
> >> >>>>> wonder if the BIOS could or should allocate it instead, or what size
> >> >>>>> to use, again this seems to fit well expectations)
> >> >>>>>
> >> >>>>> The PTP doesn't specify a particular bus to put the device. So I added
> >> >>>>> it on the system bus directly, so it could hopefully be used easily on
> >> >>>>> a different platform than x86. Currently, it fails to init on piix,
> >> >>>>> because error_on_sysbus_device() check. The check may be changed in a
> >> >>>>> near future, see discussion on the qemu-devel ML.
> >> >>>>>
> >> >>>>> Tested with some success with Linux upstream and Windows 10, seabios &
> >> >>>>> modified ovmf. The device is recognized and correctly transmit
> >> >>>>> command/response with passthrough & emu. However, we are missing PPI
> >> >>>>> ACPI part atm.
> >> >>>>>
> >> >>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >> >>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >> >>>>> ---
> >> >>>>>    qapi/tpm.json                      |   5 +-
> >> >>>>>    include/hw/acpi/tpm.h              |  72 ++++++++
> >> >>>>>    include/sysemu/tpm.h               |   3 +
> >> >>>>>    hw/i386/acpi-build.c               |  34 +++-
> >> >>>>>    hw/tpm/tpm_crb.c                   | 327
> >> >>>>> +++++++++++++++++++++++++++++++++++++
> >> >>>>>    default-configs/i386-softmmu.mak   |   1 +
> >> >>>>>    default-configs/x86_64-softmmu.mak |   1 +
> >> >>>>>    hw/tpm/Makefile.objs               |   1 +
> >> >>>>>    8 files changed, 434 insertions(+), 10 deletions(-)
> >> >>>>>    create mode 100644 hw/tpm/tpm_crb.c
> >> >>>>>
> >> >>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
> >> >>>>> index 7093f268fb..d50deef5e9 100644
> >> >>>>> --- a/qapi/tpm.json
> >> >>>>> +++ b/qapi/tpm.json
> >> >>>>> @@ -11,10 +11,11 @@
> >> >>>>>    # An enumeration of TPM models
> >> >>>>>    #
> >> >>>>>    # @tpm-tis: TPM TIS model
> >> >>>>> +# @tpm-crb: TPM CRB model (since 2.12)
> >> >>>>>    #
> >> >>>>>    # Since: 1.5
> >> >>>>>    ##
> >> >>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
> >> >>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
> >> >>>>>      ##
> >> >>>>>    # @query-tpm-models:
> >> >>>>> @@ -28,7 +29,7 @@
> >> >>>>>    # Example:
> >> >>>>>    #
> >> >>>>>    # -> { "execute": "query-tpm-models" }
> >> >>>>> -# <- { "return": [ "tpm-tis" ] }
> >> >>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
> >> >>>>>    #
> >> >>>>>    ##
> >> >>>>>    { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
> >> >>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
> >> >>>>> index 6d516c6a7f..b0048515fa 100644
> >> >>>>> --- a/include/hw/acpi/tpm.h
> >> >>>>> +++ b/include/hw/acpi/tpm.h
> >> >>>>> @@ -16,11 +16,82 @@
> >> >>>>>    #ifndef HW_ACPI_TPM_H
> >> >>>>>    #define HW_ACPI_TPM_H
> >> >>>>>    +#include "qemu/osdep.h"
> >> >>>>> +
> >> >>>>>    #define TPM_TIS_ADDR_BASE           0xFED40000
> >> >>>>>    #define TPM_TIS_ADDR_SIZE           0x5000
> >> >>>>>      #define TPM_TIS_IRQ                 5
> >> >>>>>    +struct crb_regs {
> >> >>>>> +    union {
> >> >>>>> +        uint32_t reg;
> >> >>>>> +        struct {
> >> >>>>> +            unsigned tpm_established:1;
> >> >>>>> +            unsigned loc_assigned:1;
> >> >>>>> +            unsigned active_locality:3;
> >> >>>>> +            unsigned reserved:2;
> >> >>>>> +            unsigned tpm_reg_valid_sts:1;
> >> >>>>> +        } bits;
> >> >>>>
> >> >>>> I suppose this is little-endian layout, so this won't work on big-endian
> >> >>>> hosts.
> >> >>>>
> >> >>>> Can you add a qtest?
> >> >>>>
> >> >>>>> +    } loc_state;
> >> >>>>> +    uint32_t reserved1;
> >> >>>>> +    uint32_t loc_ctrl;
> >> >>>>> +    union {
> >> >>>>> +        uint32_t reg;
> >> >>>>> +        struct {
> >> >>>>> +            unsigned granted:1;
> >> >>>>> +            unsigned been_seized:1;
> >> >>>>> +        } bits;
> >> >>>>
> >> >>>>
> >> >>>> This is unclear where you expect those bits (right/left aligned).
> >> >>>>
> >> >>>> Can you add an unnamed field to be more explicit?
> >> >>>>
> >> >>>> i.e. without using struct if left alignment expected:
> >> >>>>
> >> >>>>              unsigned granted:1, been_seized:1, :30;
> >> >>>
> >> >>>
> >> >>>
> >> >>> I got rid of all the bitfields and this patch here makes it work on a
> >> >>> ppc64
> >> >>> big endian and also x86_64 host:
> >> >>>
> >> >>>
> >> >>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
> >> >>>
> >> >> Thank you Stefan! I am all for squashing this fix to the patch. You
> >> >> should then add your signed-off to the commit.
> >> >
> >> >
> >> > I'll do that.
> >> >
> >> > The TIS is an ISA Device and the CRB is similar. Considering the
> >>
> >> How much similarity is there between TIS and CRB is there? The two
> >> devices look quite different to me, CRB is way simpler it seems. Or is
> >> the CRB implementation just lacking many bells and whistles that TIS
> >> has? Should we consider merging CRB in TIS?
> >>
> >> > complications with the sysbus devices where one has to explicitly allow it
> >> > for a certain machine type, I would advocate to convert the CRB to an ISA
> >> > device. A patch that does that is this one:
> >>
> >> If it's only for that reason (an explicit enable), I would rather keep
> >> it on the system bus. Or should it be on an LPC bus?
> >>
> >> Eduardo, what do you think?
> >
> > Everything about sysbus is exceptional and confusing, so I would
> > prefer to avoid using sysbus every time we have an alternative.
> > If tpm-tis is already an ISA device, what are the reasons to not
> > use ISA for tpm-crb too?
> 
> I was hoping this would make the device more portable (especially on
> arm) and avoid using legacy bus or resources.
> 
> Putting it on ISA doesn't reflect better what a real hardware is like,
> or does it?

I don't know what the hardware interface for those devices look
like, the documentation I found for TPM-CRB seem to be purely for
the software interface.

Is there a reason to make it a sysbus device instead of a
bus-less device, then?

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-22 17:47                 ` Eduardo Habkost
@ 2018-01-22 18:15                   ` Marc-André Lureau
  2018-01-22 19:22                     ` Eduardo Habkost
  0 siblings, 1 reply; 31+ messages in thread
From: Marc-André Lureau @ 2018-01-22 18:15 UTC (permalink / raw)
  To: Eduardo Habkost
  Cc: Michael S. Tsirkin, qemu-devel, Stefan Berger, Markus Armbruster,
	Philippe Mathieu-Daudé,
	Paolo Bonzini, Marcel Apfelbaum, Igor Mammedov,
	Richard Henderson

Hi

On Mon, Jan 22, 2018 at 6:47 PM, Eduardo Habkost <ehabkost@redhat.com> wrote:
> On Mon, Jan 22, 2018 at 06:32:37PM +0100, Marc-André Lureau wrote:
>> Hi
>>
>> On Mon, Jan 22, 2018 at 6:25 PM, Eduardo Habkost <ehabkost@redhat.com> wrote:
>> > On Mon, Jan 22, 2018 at 04:08:30PM +0100, Marc-Andre Lureau wrote:
>> >> Hi
>> >>
>> >> On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
>> >> <stefanb@linux.vnet.ibm.com> wrote:
>> >> > On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
>> >> >>
>> >> >> Hi
>> >> >>
>> >> >> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
>> >> >> <stefanb@linux.vnet.ibm.com> wrote:
>> >> >>>
>> >> >>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
>> >> >>>>
>> >> >>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
>> >> >>>>>
>> >> >>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
>> >> >>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
>> >> >>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
>> >> >>>>>
>> >> >>>>> The PTP allows device implementation to switch between TIS and CRB
>> >> >>>>> model at run time, but given that CRB is a simpler device to
>> >> >>>>> implement, I chose to implement it as a different device.
>> >> >>>>>
>> >> >>>>> The device doesn't implement other locality than 0 for now (my laptop
>> >> >>>>> TPM doesn't either, so I assume this isn't so bad)
>> >> >>>>>
>> >> >>>>> The command/reply memory region is statically allocated after the CRB
>> >> >>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
>> >> >>>>> wonder if the BIOS could or should allocate it instead, or what size
>> >> >>>>> to use, again this seems to fit well expectations)
>> >> >>>>>
>> >> >>>>> The PTP doesn't specify a particular bus to put the device. So I added
>> >> >>>>> it on the system bus directly, so it could hopefully be used easily on
>> >> >>>>> a different platform than x86. Currently, it fails to init on piix,
>> >> >>>>> because error_on_sysbus_device() check. The check may be changed in a
>> >> >>>>> near future, see discussion on the qemu-devel ML.
>> >> >>>>>
>> >> >>>>> Tested with some success with Linux upstream and Windows 10, seabios &
>> >> >>>>> modified ovmf. The device is recognized and correctly transmit
>> >> >>>>> command/response with passthrough & emu. However, we are missing PPI
>> >> >>>>> ACPI part atm.
>> >> >>>>>
>> >> >>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>> >> >>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
>> >> >>>>> ---
>> >> >>>>>    qapi/tpm.json                      |   5 +-
>> >> >>>>>    include/hw/acpi/tpm.h              |  72 ++++++++
>> >> >>>>>    include/sysemu/tpm.h               |   3 +
>> >> >>>>>    hw/i386/acpi-build.c               |  34 +++-
>> >> >>>>>    hw/tpm/tpm_crb.c                   | 327
>> >> >>>>> +++++++++++++++++++++++++++++++++++++
>> >> >>>>>    default-configs/i386-softmmu.mak   |   1 +
>> >> >>>>>    default-configs/x86_64-softmmu.mak |   1 +
>> >> >>>>>    hw/tpm/Makefile.objs               |   1 +
>> >> >>>>>    8 files changed, 434 insertions(+), 10 deletions(-)
>> >> >>>>>    create mode 100644 hw/tpm/tpm_crb.c
>> >> >>>>>
>> >> >>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
>> >> >>>>> index 7093f268fb..d50deef5e9 100644
>> >> >>>>> --- a/qapi/tpm.json
>> >> >>>>> +++ b/qapi/tpm.json
>> >> >>>>> @@ -11,10 +11,11 @@
>> >> >>>>>    # An enumeration of TPM models
>> >> >>>>>    #
>> >> >>>>>    # @tpm-tis: TPM TIS model
>> >> >>>>> +# @tpm-crb: TPM CRB model (since 2.12)
>> >> >>>>>    #
>> >> >>>>>    # Since: 1.5
>> >> >>>>>    ##
>> >> >>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
>> >> >>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
>> >> >>>>>      ##
>> >> >>>>>    # @query-tpm-models:
>> >> >>>>> @@ -28,7 +29,7 @@
>> >> >>>>>    # Example:
>> >> >>>>>    #
>> >> >>>>>    # -> { "execute": "query-tpm-models" }
>> >> >>>>> -# <- { "return": [ "tpm-tis" ] }
>> >> >>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
>> >> >>>>>    #
>> >> >>>>>    ##
>> >> >>>>>    { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
>> >> >>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
>> >> >>>>> index 6d516c6a7f..b0048515fa 100644
>> >> >>>>> --- a/include/hw/acpi/tpm.h
>> >> >>>>> +++ b/include/hw/acpi/tpm.h
>> >> >>>>> @@ -16,11 +16,82 @@
>> >> >>>>>    #ifndef HW_ACPI_TPM_H
>> >> >>>>>    #define HW_ACPI_TPM_H
>> >> >>>>>    +#include "qemu/osdep.h"
>> >> >>>>> +
>> >> >>>>>    #define TPM_TIS_ADDR_BASE           0xFED40000
>> >> >>>>>    #define TPM_TIS_ADDR_SIZE           0x5000
>> >> >>>>>      #define TPM_TIS_IRQ                 5
>> >> >>>>>    +struct crb_regs {
>> >> >>>>> +    union {
>> >> >>>>> +        uint32_t reg;
>> >> >>>>> +        struct {
>> >> >>>>> +            unsigned tpm_established:1;
>> >> >>>>> +            unsigned loc_assigned:1;
>> >> >>>>> +            unsigned active_locality:3;
>> >> >>>>> +            unsigned reserved:2;
>> >> >>>>> +            unsigned tpm_reg_valid_sts:1;
>> >> >>>>> +        } bits;
>> >> >>>>
>> >> >>>> I suppose this is little-endian layout, so this won't work on big-endian
>> >> >>>> hosts.
>> >> >>>>
>> >> >>>> Can you add a qtest?
>> >> >>>>
>> >> >>>>> +    } loc_state;
>> >> >>>>> +    uint32_t reserved1;
>> >> >>>>> +    uint32_t loc_ctrl;
>> >> >>>>> +    union {
>> >> >>>>> +        uint32_t reg;
>> >> >>>>> +        struct {
>> >> >>>>> +            unsigned granted:1;
>> >> >>>>> +            unsigned been_seized:1;
>> >> >>>>> +        } bits;
>> >> >>>>
>> >> >>>>
>> >> >>>> This is unclear where you expect those bits (right/left aligned).
>> >> >>>>
>> >> >>>> Can you add an unnamed field to be more explicit?
>> >> >>>>
>> >> >>>> i.e. without using struct if left alignment expected:
>> >> >>>>
>> >> >>>>              unsigned granted:1, been_seized:1, :30;
>> >> >>>
>> >> >>>
>> >> >>>
>> >> >>> I got rid of all the bitfields and this patch here makes it work on a
>> >> >>> ppc64
>> >> >>> big endian and also x86_64 host:
>> >> >>>
>> >> >>>
>> >> >>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
>> >> >>>
>> >> >> Thank you Stefan! I am all for squashing this fix to the patch. You
>> >> >> should then add your signed-off to the commit.
>> >> >
>> >> >
>> >> > I'll do that.
>> >> >
>> >> > The TIS is an ISA Device and the CRB is similar. Considering the
>> >>
>> >> How much similarity is there between TIS and CRB is there? The two
>> >> devices look quite different to me, CRB is way simpler it seems. Or is
>> >> the CRB implementation just lacking many bells and whistles that TIS
>> >> has? Should we consider merging CRB in TIS?
>> >>
>> >> > complications with the sysbus devices where one has to explicitly allow it
>> >> > for a certain machine type, I would advocate to convert the CRB to an ISA
>> >> > device. A patch that does that is this one:
>> >>
>> >> If it's only for that reason (an explicit enable), I would rather keep
>> >> it on the system bus. Or should it be on an LPC bus?
>> >>
>> >> Eduardo, what do you think?
>> >
>> > Everything about sysbus is exceptional and confusing, so I would
>> > prefer to avoid using sysbus every time we have an alternative.
>> > If tpm-tis is already an ISA device, what are the reasons to not
>> > use ISA for tpm-crb too?
>>
>> I was hoping this would make the device more portable (especially on
>> arm) and avoid using legacy bus or resources.
>>
>> Putting it on ISA doesn't reflect better what a real hardware is like,
>> or does it?
>
> I don't know what the hardware interface for those devices look
> like, the documentation I found for TPM-CRB seem to be purely for
> the software interface.
>

It has a MMIO region at 0xFED4_xxxx, and it can be on LPC or SPI bus
as far as I understand (8.2.2):

https://trustedcomputinggroup.org/wp-content/uploads/TCG_PC_Client_Platform_TPM_Profile_PTP_Specification_Family_2.0_Revision_1.3v22.pdf

> Is there a reason to make it a sysbus device instead of a
> bus-less device, then?

The calls to
    sysbus_init_mmio(sbd, &s->mmio);
    sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE);

Could perhaps be replaced by lower-level memory_region calls?

I'll give it a try

thanks
-- 
Marc-André Lureau

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

* Re: [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device
  2018-01-22 18:15                   ` Marc-André Lureau
@ 2018-01-22 19:22                     ` Eduardo Habkost
  0 siblings, 0 replies; 31+ messages in thread
From: Eduardo Habkost @ 2018-01-22 19:22 UTC (permalink / raw)
  To: Marc-André Lureau
  Cc: Michael S. Tsirkin, qemu-devel, Stefan Berger, Markus Armbruster,
	Philippe Mathieu-Daudé,
	Paolo Bonzini, Marcel Apfelbaum, Igor Mammedov,
	Richard Henderson

On Mon, Jan 22, 2018 at 07:15:01PM +0100, Marc-André Lureau wrote:
> Hi
> 
> On Mon, Jan 22, 2018 at 6:47 PM, Eduardo Habkost <ehabkost@redhat.com> wrote:
> > On Mon, Jan 22, 2018 at 06:32:37PM +0100, Marc-André Lureau wrote:
> >> Hi
> >>
> >> On Mon, Jan 22, 2018 at 6:25 PM, Eduardo Habkost <ehabkost@redhat.com> wrote:
> >> > On Mon, Jan 22, 2018 at 04:08:30PM +0100, Marc-Andre Lureau wrote:
> >> >> Hi
> >> >>
> >> >> On Sun, Jan 21, 2018 at 11:01 PM, Stefan Berger
> >> >> <stefanb@linux.vnet.ibm.com> wrote:
> >> >> > On 01/21/2018 02:24 PM, Marc-Andre Lureau wrote:
> >> >> >>
> >> >> >> Hi
> >> >> >>
> >> >> >> On Sun, Jan 21, 2018 at 6:46 AM, Stefan Berger
> >> >> >> <stefanb@linux.vnet.ibm.com> wrote:
> >> >> >>>
> >> >> >>> On 01/20/2018 07:54 AM, Philippe Mathieu-Daudé wrote:
> >> >> >>>>
> >> >> >>>> On 01/19/2018 11:11 AM, Marc-André Lureau wrote:
> >> >> >>>>>
> >> >> >>>>> tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB)
> >> >> >>>>> Interface as defined in TCG PC Client Platform TPM Profile (PTP)
> >> >> >>>>> Specification Family “2.0” Level 00 Revision 01.03 v22.
> >> >> >>>>>
> >> >> >>>>> The PTP allows device implementation to switch between TIS and CRB
> >> >> >>>>> model at run time, but given that CRB is a simpler device to
> >> >> >>>>> implement, I chose to implement it as a different device.
> >> >> >>>>>
> >> >> >>>>> The device doesn't implement other locality than 0 for now (my laptop
> >> >> >>>>> TPM doesn't either, so I assume this isn't so bad)
> >> >> >>>>>
> >> >> >>>>> The command/reply memory region is statically allocated after the CRB
> >> >> >>>>> registers address TPM_CRB_ADDR_BASE + sizeof(struct crb_regs) (I
> >> >> >>>>> wonder if the BIOS could or should allocate it instead, or what size
> >> >> >>>>> to use, again this seems to fit well expectations)
> >> >> >>>>>
> >> >> >>>>> The PTP doesn't specify a particular bus to put the device. So I added
> >> >> >>>>> it on the system bus directly, so it could hopefully be used easily on
> >> >> >>>>> a different platform than x86. Currently, it fails to init on piix,
> >> >> >>>>> because error_on_sysbus_device() check. The check may be changed in a
> >> >> >>>>> near future, see discussion on the qemu-devel ML.
> >> >> >>>>>
> >> >> >>>>> Tested with some success with Linux upstream and Windows 10, seabios &
> >> >> >>>>> modified ovmf. The device is recognized and correctly transmit
> >> >> >>>>> command/response with passthrough & emu. However, we are missing PPI
> >> >> >>>>> ACPI part atm.
> >> >> >>>>>
> >> >> >>>>> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
> >> >> >>>>> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> >> >> >>>>> ---
> >> >> >>>>>    qapi/tpm.json                      |   5 +-
> >> >> >>>>>    include/hw/acpi/tpm.h              |  72 ++++++++
> >> >> >>>>>    include/sysemu/tpm.h               |   3 +
> >> >> >>>>>    hw/i386/acpi-build.c               |  34 +++-
> >> >> >>>>>    hw/tpm/tpm_crb.c                   | 327
> >> >> >>>>> +++++++++++++++++++++++++++++++++++++
> >> >> >>>>>    default-configs/i386-softmmu.mak   |   1 +
> >> >> >>>>>    default-configs/x86_64-softmmu.mak |   1 +
> >> >> >>>>>    hw/tpm/Makefile.objs               |   1 +
> >> >> >>>>>    8 files changed, 434 insertions(+), 10 deletions(-)
> >> >> >>>>>    create mode 100644 hw/tpm/tpm_crb.c
> >> >> >>>>>
> >> >> >>>>> diff --git a/qapi/tpm.json b/qapi/tpm.json
> >> >> >>>>> index 7093f268fb..d50deef5e9 100644
> >> >> >>>>> --- a/qapi/tpm.json
> >> >> >>>>> +++ b/qapi/tpm.json
> >> >> >>>>> @@ -11,10 +11,11 @@
> >> >> >>>>>    # An enumeration of TPM models
> >> >> >>>>>    #
> >> >> >>>>>    # @tpm-tis: TPM TIS model
> >> >> >>>>> +# @tpm-crb: TPM CRB model (since 2.12)
> >> >> >>>>>    #
> >> >> >>>>>    # Since: 1.5
> >> >> >>>>>    ##
> >> >> >>>>> -{ 'enum': 'TpmModel', 'data': [ 'tpm-tis' ] }
> >> >> >>>>> +{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
> >> >> >>>>>      ##
> >> >> >>>>>    # @query-tpm-models:
> >> >> >>>>> @@ -28,7 +29,7 @@
> >> >> >>>>>    # Example:
> >> >> >>>>>    #
> >> >> >>>>>    # -> { "execute": "query-tpm-models" }
> >> >> >>>>> -# <- { "return": [ "tpm-tis" ] }
> >> >> >>>>> +# <- { "return": [ "tpm-tis", "tpm-crb" ] }
> >> >> >>>>>    #
> >> >> >>>>>    ##
> >> >> >>>>>    { 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
> >> >> >>>>> diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
> >> >> >>>>> index 6d516c6a7f..b0048515fa 100644
> >> >> >>>>> --- a/include/hw/acpi/tpm.h
> >> >> >>>>> +++ b/include/hw/acpi/tpm.h
> >> >> >>>>> @@ -16,11 +16,82 @@
> >> >> >>>>>    #ifndef HW_ACPI_TPM_H
> >> >> >>>>>    #define HW_ACPI_TPM_H
> >> >> >>>>>    +#include "qemu/osdep.h"
> >> >> >>>>> +
> >> >> >>>>>    #define TPM_TIS_ADDR_BASE           0xFED40000
> >> >> >>>>>    #define TPM_TIS_ADDR_SIZE           0x5000
> >> >> >>>>>      #define TPM_TIS_IRQ                 5
> >> >> >>>>>    +struct crb_regs {
> >> >> >>>>> +    union {
> >> >> >>>>> +        uint32_t reg;
> >> >> >>>>> +        struct {
> >> >> >>>>> +            unsigned tpm_established:1;
> >> >> >>>>> +            unsigned loc_assigned:1;
> >> >> >>>>> +            unsigned active_locality:3;
> >> >> >>>>> +            unsigned reserved:2;
> >> >> >>>>> +            unsigned tpm_reg_valid_sts:1;
> >> >> >>>>> +        } bits;
> >> >> >>>>
> >> >> >>>> I suppose this is little-endian layout, so this won't work on big-endian
> >> >> >>>> hosts.
> >> >> >>>>
> >> >> >>>> Can you add a qtest?
> >> >> >>>>
> >> >> >>>>> +    } loc_state;
> >> >> >>>>> +    uint32_t reserved1;
> >> >> >>>>> +    uint32_t loc_ctrl;
> >> >> >>>>> +    union {
> >> >> >>>>> +        uint32_t reg;
> >> >> >>>>> +        struct {
> >> >> >>>>> +            unsigned granted:1;
> >> >> >>>>> +            unsigned been_seized:1;
> >> >> >>>>> +        } bits;
> >> >> >>>>
> >> >> >>>>
> >> >> >>>> This is unclear where you expect those bits (right/left aligned).
> >> >> >>>>
> >> >> >>>> Can you add an unnamed field to be more explicit?
> >> >> >>>>
> >> >> >>>> i.e. without using struct if left alignment expected:
> >> >> >>>>
> >> >> >>>>              unsigned granted:1, been_seized:1, :30;
> >> >> >>>
> >> >> >>>
> >> >> >>>
> >> >> >>> I got rid of all the bitfields and this patch here makes it work on a
> >> >> >>> ppc64
> >> >> >>> big endian and also x86_64 host:
> >> >> >>>
> >> >> >>>
> >> >> >>> https://github.com/stefanberger/qemu-tpm/commit/28fc07f0d9314168986190effd6d72d9fd3972dd
> >> >> >>>
> >> >> >> Thank you Stefan! I am all for squashing this fix to the patch. You
> >> >> >> should then add your signed-off to the commit.
> >> >> >
> >> >> >
> >> >> > I'll do that.
> >> >> >
> >> >> > The TIS is an ISA Device and the CRB is similar. Considering the
> >> >>
> >> >> How much similarity is there between TIS and CRB is there? The two
> >> >> devices look quite different to me, CRB is way simpler it seems. Or is
> >> >> the CRB implementation just lacking many bells and whistles that TIS
> >> >> has? Should we consider merging CRB in TIS?
> >> >>
> >> >> > complications with the sysbus devices where one has to explicitly allow it
> >> >> > for a certain machine type, I would advocate to convert the CRB to an ISA
> >> >> > device. A patch that does that is this one:
> >> >>
> >> >> If it's only for that reason (an explicit enable), I would rather keep
> >> >> it on the system bus. Or should it be on an LPC bus?
> >> >>
> >> >> Eduardo, what do you think?
> >> >
> >> > Everything about sysbus is exceptional and confusing, so I would
> >> > prefer to avoid using sysbus every time we have an alternative.
> >> > If tpm-tis is already an ISA device, what are the reasons to not
> >> > use ISA for tpm-crb too?
> >>
> >> I was hoping this would make the device more portable (especially on
> >> arm) and avoid using legacy bus or resources.
> >>
> >> Putting it on ISA doesn't reflect better what a real hardware is like,
> >> or does it?
> >
> > I don't know what the hardware interface for those devices look
> > like, the documentation I found for TPM-CRB seem to be purely for
> > the software interface.
> >
> 
> It has a MMIO region at 0xFED4_xxxx, and it can be on LPC or SPI bus
> as far as I understand (8.2.2):
> 
> https://trustedcomputinggroup.org/wp-content/uploads/TCG_PC_Client_Platform_TPM_Profile_PTP_Specification_Family_2.0_Revision_1.3v22.pdf

Thanks.  It looks like the actual hardware interface doesn't
matter for QEMU and for guest software, though?


> 
> > Is there a reason to make it a sysbus device instead of a
> > bus-less device, then?
> 
> The calls to
>     sysbus_init_mmio(sbd, &s->mmio);
>     sysbus_mmio_map(sbd, 0, TPM_CRB_ADDR_BASE);
> 
> Could perhaps be replaced by lower-level memory_region calls?
> 
> I'll give it a try

If the code ends up uglier, then this sounds like a good reason
to use sysbus, at least until we make the sysbus I/O APIs
available to the rest of devices.  I would document this in a
comment above the ".parent = TYPE_SYSBUS_DEVICE" line, though.

-- 
Eduardo

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

* Re: [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool
  2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool Marc-André Lureau
@ 2018-01-23 18:39   ` Stefan Berger
  0 siblings, 0 replies; 31+ messages in thread
From: Stefan Berger @ 2018-01-23 18:39 UTC (permalink / raw)
  To: Marc-André Lureau, qemu-devel

On 01/19/2018 09:11 AM, Marc-André Lureau wrote:
> The TPM backend uses a GThreadPool to handle IO in a seperate
> thread. However, GThreadPool isn't integrated with Qemu main loops,
> making it unnecessarily complicated to deal with.
>
> Qemu has a AIO threadpool, that is better integrated with loops and
> various IO functions, provides completion BH by default etc.
>
> Remove the only user of GThreadPool from qemu, use AIO threadpool.
>
> Note that the backend:
> - no longer accepts queing multiple requests (unneeded so far)
> - increase ref to itself when handling a command, for extra safety
> - tpm_backend_thread_end() is renamed tpm_backend_finish_sync() and
> will wait for completion of BH (request_completed), which will help
> migration handling.
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

I have been using this for a while:
Tested-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>


> ---
>   include/sysemu/tpm_backend.h | 12 ++++++++--
>   backends/tpm.c               | 52 +++++++++++++++++++++++---------------------
>   2 files changed, 37 insertions(+), 27 deletions(-)
>
> diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
> index 0d6c994a62..a69593e0cd 100644
> --- a/include/sysemu/tpm_backend.h
> +++ b/include/sysemu/tpm_backend.h
> @@ -45,9 +45,8 @@ struct TPMBackend {
>       /*< protected >*/
>       TPMIf *tpmif;
>       bool opened;
> -    GThreadPool *thread_pool;
>       bool had_startup_error;
> -    QEMUBH *bh;
> +    TPMBackendCmd *cmd;
>
>       /* <public> */
>       char *id;
> @@ -196,6 +195,15 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
>    */
>   size_t tpm_backend_get_buffer_size(TPMBackend *s);
>
> +/**
> + * tpm_backend_finish_sync:
> + * @s: the backend to call into
> + *
> + * Finish the pending command synchronously (this will call aio_poll()
> + * on qemu main AIOContext until it ends)
> + */
> +void tpm_backend_finish_sync(TPMBackend *s);
> +
>   /**
>    * tpm_backend_query_tpm:
>    * @s: the backend
> diff --git a/backends/tpm.c b/backends/tpm.c
> index 91222c5164..143807aa37 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -19,30 +19,35 @@
>   #include "sysemu/tpm.h"
>   #include "qemu/thread.h"
>   #include "qemu/main-loop.h"
> +#include "block/thread-pool.h"
> +#include "qemu/error-report.h"
>
> -static void tpm_backend_request_completed_bh(void *opaque)
> +static void tpm_backend_request_completed(void *opaque, int ret)
>   {
>       TPMBackend *s = TPM_BACKEND(opaque);
>       TPMIfClass *tic = TPM_IF_GET_CLASS(s->tpmif);
>
>       tic->request_completed(s->tpmif);
> +
> +    /* no need for atomic, as long the BQL is taken */
> +    s->cmd = NULL;
> +    object_unref(OBJECT(s));
>   }
>
> -static void tpm_backend_worker_thread(gpointer data, gpointer user_data)
> +static int tpm_backend_worker_thread(gpointer data)
>   {
> -    TPMBackend *s = TPM_BACKEND(user_data);
> +    TPMBackend *s = TPM_BACKEND(data);
>       TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> -    k->handle_request(s, (TPMBackendCmd *)data);
> +    k->handle_request(s, s->cmd);
>
> -    qemu_bh_schedule(s->bh);
> +    return 0;
>   }
>
> -static void tpm_backend_thread_end(TPMBackend *s)
> +void tpm_backend_finish_sync(TPMBackend *s)
>   {
> -    if (s->thread_pool) {
> -        g_thread_pool_free(s->thread_pool, FALSE, TRUE);
> -        s->thread_pool = NULL;
> +    while (s->cmd) {
> +        aio_poll(qemu_get_aio_context(), true);
>       }
>   }
>
> @@ -74,10 +79,7 @@ int tpm_backend_startup_tpm(TPMBackend *s, size_t buffersize)
>       TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
>       /* terminate a running TPM */
> -    tpm_backend_thread_end(s);
> -
> -    s->thread_pool = g_thread_pool_new(tpm_backend_worker_thread, s, 1, TRUE,
> -                                       NULL);
> +    tpm_backend_finish_sync(s);
>
>       res = k->startup_tpm ? k->startup_tpm(s, buffersize) : 0;
>
> @@ -93,7 +95,17 @@ bool tpm_backend_had_startup_error(TPMBackend *s)
>
>   void tpm_backend_deliver_request(TPMBackend *s, TPMBackendCmd *cmd)
>   {
> -    g_thread_pool_push(s->thread_pool, cmd, NULL);
> +    ThreadPool *pool = aio_get_thread_pool(qemu_get_aio_context());
> +
> +    if (s->cmd != NULL) {
> +        error_report("There is a TPM request pending");
> +        return;
> +    }
> +
> +    s->cmd = cmd;
> +    object_ref(OBJECT(s));
> +    thread_pool_submit_aio(pool, tpm_backend_worker_thread, s,
> +                           tpm_backend_request_completed, s);
>   }
>
>   void tpm_backend_reset(TPMBackend *s)
> @@ -104,7 +116,7 @@ void tpm_backend_reset(TPMBackend *s)
>           k->reset(s);
>       }
>
> -    tpm_backend_thread_end(s);
> +    tpm_backend_finish_sync(s);
>
>       s->had_startup_error = false;
>   }
> @@ -159,28 +171,18 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s)
>       return info;
>   }
>
> -static void tpm_backend_instance_init(Object *obj)
> -{
> -    TPMBackend *s = TPM_BACKEND(obj);
> -
> -    s->bh = qemu_bh_new(tpm_backend_request_completed_bh, s);
> -}
> -
>   static void tpm_backend_instance_finalize(Object *obj)
>   {
>       TPMBackend *s = TPM_BACKEND(obj);
>
>       object_unref(OBJECT(s->tpmif));
>       g_free(s->id);
> -    tpm_backend_thread_end(s);
> -    qemu_bh_delete(s->bh);
>   }
>
>   static const TypeInfo tpm_backend_info = {
>       .name = TYPE_TPM_BACKEND,
>       .parent = TYPE_OBJECT,
>       .instance_size = sizeof(TPMBackend),
> -    .instance_init = tpm_backend_instance_init,
>       .instance_finalize = tpm_backend_instance_finalize,
>       .class_size = sizeof(TPMBackendClass),
>       .abstract = true,

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

end of thread, other threads:[~2018-01-23 18:39 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-19 14:10 [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups Marc-André Lureau
2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 1/5] tpm: lookup cancel path under tpm device class Marc-André Lureau
2018-01-19 14:32   ` Stefan Berger
2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 2/5] tpm: replace GThreadPool with AIO threadpool Marc-André Lureau
2018-01-23 18:39   ` Stefan Berger
2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 3/5] tpm: report backend request error Marc-André Lureau
2018-01-19 14:57   ` Stefan Berger
2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 4/5] tpm: add CRB device Marc-André Lureau
2018-01-19 17:10   ` Stefan Berger
2018-01-19 18:42     ` Eduardo Habkost
2018-01-19 21:56       ` Stefan Berger
2018-01-20 11:08         ` Eduardo Habkost
2018-01-20 12:54   ` Philippe Mathieu-Daudé
2018-01-21  5:46     ` Stefan Berger
2018-01-21 19:24       ` Marc-Andre Lureau
2018-01-21 22:01         ` Stefan Berger
2018-01-22 15:08           ` Marc-Andre Lureau
2018-01-22 15:47             ` Stefan Berger
2018-01-22 16:57               ` Marc-André Lureau
2018-01-22 17:25             ` Eduardo Habkost
2018-01-22 17:32               ` Marc-André Lureau
2018-01-22 17:47                 ` Eduardo Habkost
2018-01-22 18:15                   ` Marc-André Lureau
2018-01-22 19:22                     ` Eduardo Habkost
2018-01-21 22:50       ` Philippe Mathieu-Daudé
2018-01-19 14:11 ` [Qemu-devel] [PATCH v2 5/5] tpm: extend TPM CRB with state migration support Marc-André Lureau
2018-01-19 14:46   ` Stefan Berger
2018-01-19 14:49     ` Marc-André Lureau
2018-01-19 14:36 ` [Qemu-devel] [PATCH v2 0/5] tpm: CRB device and cleanups no-reply
2018-01-19 14:56   ` Marc-Andre Lureau
2018-01-19 15:06     ` Stefan Berger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.