* [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator
@ 2017-05-02 11:52 Amarnath Valluri
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
` (9 more replies)
0 siblings, 10 replies; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
Briefly, Theses set of patches introduces:
- new TPM backend driver to support software TPM emulators(swtpm(1)).
- and few supported fixes/enhancements/cleanup to existing tpm backend code.
The similar idea was initiated earliar(2) by Stefan Berger(CCed) with slightly
different approach, using CUSE. As swtpm has excellent support for unix domain
sockets, hence this implementation uses unix domain sockets to communicate
with
swtpm.
When Qemu is configured with 'emulator' tpm backend, it spawns 'swtpm' and
communicates its via Unix domain sockets.
1) https://github.com/stefanberger/swtpm
2) https://lists.nongnu.org/archive/html/qemu-devel/2016-01/msg00089.html
** Changes in V2:
- Made spawnning swtpm optional
- used QIOChannel instead of plain unix sockets
- incorporated other fixes pointed in v1 review
** Changes in v3:
- Addressed review comments made by Stefan Berger and Deniel P Berrange
Amarnath Valluri (8):
tpm-backend: Remove unneeded member variable from backend class
tpm-backend: Move thread handling inside TPMBackend
tpm-backend: Initialize and free data members in it's own methods
tpm-backend: Made few interface methods optional
tmp backend: Add new api to read backend TpmInfo
tpm-backend: Move realloc_buffer() implementation to base class
tpm-passthrough: move reusable code to utils
tpm: Added support for TPM emulator
backends/tpm.c | 121 +++--
configure | 15 +-
hmp.c | 31 +-
hw/tpm/Makefile.objs | 1 +
hw/tpm/tpm_emulator.c | 943 +++++++++++++++++++++++++++++++++++++++
hw/tpm/tpm_ioctl.h | 243 ++++++++++
hw/tpm/tpm_passthrough.c | 221 +++------
hw/tpm/tpm_util.c | 25 ++
hw/tpm/tpm_util.h | 4 +
include/sysemu/tpm_backend.h | 65 ++-
include/sysemu/tpm_backend_int.h | 41 --
qapi-schema.json | 67 ++-
qemu-options.hx | 53 ++-
tpm.c | 36 +-
14 files changed, 1545 insertions(+), 321 deletions(-)
create mode 100644 hw/tpm/tpm_emulator.c
create mode 100644 hw/tpm/tpm_ioctl.h
delete mode 100644 include/sysemu/tpm_backend_int.h
--
2.7.4
^ permalink raw reply [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 1/8] tpm-backend: Remove unneeded member variable from backend class
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 11:59 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 2/8] tpm-backend: Move thread handling inside TPMBackend Amarnath Valluri
` (8 subsequent siblings)
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
TPMDriverOps inside TPMBackend is not required, as it is supposed to be a class
member. The only possible reason for keeping in TPMBackend was, to get the
backend type in tpm.c where dedicated backend api, tpm_backend_get_type() is
present.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
hw/tpm/tpm_passthrough.c | 4 ----
include/sysemu/tpm_backend.h | 1 -
tpm.c | 2 +-
3 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index 9234eb3..a0baf5f 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -46,8 +46,6 @@
#define TPM_PASSTHROUGH(obj) \
OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
-static const TPMDriverOps tpm_passthrough_driver;
-
/* data structures */
typedef struct TPMPassthruThreadParams {
TPMState *tpm_state;
@@ -462,8 +460,6 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
/* let frontend set the fe_model to proper value */
tb->fe_model = -1;
- tb->ops = &tpm_passthrough_driver;
-
if (tpm_passthrough_handle_device_opts(opts, tb)) {
goto err_exit;
}
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index b58f52d..e7f590d 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -50,7 +50,6 @@ struct TPMBackend {
enum TpmModel fe_model;
char *path;
char *cancel_path;
- const TPMDriverOps *ops;
QLIST_ENTRY(TPMBackend) list;
};
diff --git a/tpm.c b/tpm.c
index 9a7c711..0ee021a 100644
--- a/tpm.c
+++ b/tpm.c
@@ -258,7 +258,7 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
res->model = drv->fe_model;
res->options = g_new0(TpmTypeOptions, 1);
- switch (drv->ops->type) {
+ switch (tpm_backend_get_type(drv)) {
case TPM_TYPE_PASSTHROUGH:
res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
tpo = g_new0(TPMPassthroughOptions, 1);
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 2/8] tpm-backend: Move thread handling inside TPMBackend
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 12:10 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 3/8] tpm-backend: Initialize and free data members in it's own methods Amarnath Valluri
` (7 subsequent siblings)
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
Move thread handling inside TPMBackend, this way backend implementations need
not to maintain their own thread life cycle, instead they needs to implement
'handle_request()' class method that always been called from a thread.
This change made tpm_backend_int.h kind of useless, hence removed it.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 62 +++++++++++++++++++++++++---------------
hw/tpm/tpm_passthrough.c | 58 ++++++-------------------------------
include/sysemu/tpm_backend.h | 32 +++++++++++++--------
include/sysemu/tpm_backend_int.h | 41 --------------------------
4 files changed, 67 insertions(+), 126 deletions(-)
delete mode 100644 include/sysemu/tpm_backend_int.h
diff --git a/backends/tpm.c b/backends/tpm.c
index 536f262..ce56c3b 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -18,7 +18,24 @@
#include "qapi/qmp/qerror.h"
#include "sysemu/tpm.h"
#include "qemu/thread.h"
-#include "sysemu/tpm_backend_int.h"
+
+static void tpm_backend_worker_thread(gpointer data, gpointer user_data)
+{
+ TPMBackend *s = TPM_BACKEND(user_data);
+ TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+ assert(k->handle_request != NULL);
+ k->handle_request(s, (TPMBackendCmd)data);
+}
+
+static void tpm_backend_thread_end(TPMBackend *s)
+{
+ if (s->thread_pool) {
+ g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
+ g_thread_pool_free(s->thread_pool, FALSE, TRUE);
+ s->thread_pool = NULL;
+ }
+}
enum TpmType tpm_backend_get_type(TPMBackend *s)
{
@@ -39,6 +56,8 @@ void tpm_backend_destroy(TPMBackend *s)
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
k->ops->destroy(s);
+
+ tpm_backend_thread_end(s);
}
int tpm_backend_init(TPMBackend *s, TPMState *state,
@@ -46,13 +65,23 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->init(s, state, datacb);
+ s->tpm_state = state;
+ s->recv_data_callback = datacb;
+
+ return k->ops->init(s);
}
int tpm_backend_startup_tpm(TPMBackend *s)
{
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);
+ g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
+
return k->ops->startup_tpm(s);
}
@@ -72,9 +101,8 @@ size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
void tpm_backend_deliver_request(TPMBackend *s)
{
- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
-
- k->ops->deliver_request(s);
+ g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD,
+ NULL);
}
void tpm_backend_reset(TPMBackend *s)
@@ -82,6 +110,8 @@ void tpm_backend_reset(TPMBackend *s)
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
k->ops->reset(s);
+
+ tpm_backend_thread_end(s);
}
void tpm_backend_cancel_cmd(TPMBackend *s)
@@ -156,29 +186,14 @@ static void tpm_backend_instance_init(Object *obj)
tpm_backend_prop_get_opened,
tpm_backend_prop_set_opened,
NULL);
-}
-void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
-{
- g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL);
}
-void tpm_backend_thread_create(TPMBackendThread *tbt,
- GFunc func, gpointer user_data)
+static void tpm_backend_instance_finalize(Object *obj)
{
- if (!tbt->pool) {
- tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
- g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
- }
-}
+ TPMBackend *s = TPM_BACKEND(obj);
-void tpm_backend_thread_end(TPMBackendThread *tbt)
-{
- if (tbt->pool) {
- g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
- g_thread_pool_free(tbt->pool, FALSE, TRUE);
- tbt->pool = NULL;
- }
+ tpm_backend_thread_end(s);
}
static const TypeInfo tpm_backend_info = {
@@ -186,6 +201,7 @@ static const TypeInfo tpm_backend_info = {
.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,
};
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index a0baf5f..f50d9cf 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -30,7 +30,6 @@
#include "tpm_int.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
-#include "sysemu/tpm_backend_int.h"
#include "tpm_tis.h"
#include "tpm_util.h"
@@ -47,20 +46,9 @@
OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
/* data structures */
-typedef struct TPMPassthruThreadParams {
- TPMState *tpm_state;
-
- TPMRecvDataCB *recv_data_callback;
- TPMBackend *tb;
-} TPMPassthruThreadParams;
-
struct TPMPassthruState {
TPMBackend parent;
- TPMBackendThread tbt;
-
- TPMPassthruThreadParams tpm_thread_params;
-
char *tpm_dev;
int tpm_fd;
bool tpm_executing;
@@ -214,12 +202,9 @@ static int tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt,
selftest_done);
}
-static void tpm_passthrough_worker_thread(gpointer data,
- gpointer user_data)
+static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
{
- TPMPassthruThreadParams *thr_parms = user_data;
- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
- TPMBackendCmd cmd = (TPMBackendCmd)data;
+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
bool selftest_done = false;
DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
@@ -227,12 +212,12 @@ static void tpm_passthrough_worker_thread(gpointer data,
switch (cmd) {
case TPM_BACKEND_CMD_PROCESS_CMD:
tpm_passthrough_unix_transfer(tpm_pt,
- thr_parms->tpm_state->locty_data,
+ tb->tpm_state->locty_data,
&selftest_done);
- thr_parms->recv_data_callback(thr_parms->tpm_state,
- thr_parms->tpm_state->locty_number,
- selftest_done);
+ tb->recv_data_callback(tb->tpm_state,
+ tb->tpm_state->locty_number,
+ selftest_done);
break;
case TPM_BACKEND_CMD_INIT:
case TPM_BACKEND_CMD_END:
@@ -248,15 +233,6 @@ static void tpm_passthrough_worker_thread(gpointer data,
*/
static int tpm_passthrough_startup_tpm(TPMBackend *tb)
{
- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-
- /* terminate a running TPM */
- tpm_backend_thread_end(&tpm_pt->tbt);
-
- tpm_backend_thread_create(&tpm_pt->tbt,
- tpm_passthrough_worker_thread,
- &tpm_pt->tpm_thread_params);
-
return 0;
}
@@ -268,20 +244,11 @@ static void tpm_passthrough_reset(TPMBackend *tb)
tpm_passthrough_cancel_cmd(tb);
- tpm_backend_thread_end(&tpm_pt->tbt);
-
tpm_pt->had_startup_error = false;
}
-static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
- TPMRecvDataCB *recv_data_cb)
+static int tpm_passthrough_init(TPMBackend *tb)
{
- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-
- tpm_pt->tpm_thread_params.tpm_state = s;
- tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
- tpm_pt->tpm_thread_params.tb = tb;
-
return 0;
}
@@ -315,13 +282,6 @@ static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
return sb->size;
}
-static void tpm_passthrough_deliver_request(TPMBackend *tb)
-{
- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-
- tpm_backend_thread_deliver_request(&tpm_pt->tbt);
-}
-
static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -483,8 +443,6 @@ static void tpm_passthrough_destroy(TPMBackend *tb)
tpm_passthrough_cancel_cmd(tb);
- tpm_backend_thread_end(&tpm_pt->tbt);
-
qemu_close(tpm_pt->tpm_fd);
qemu_close(tpm_pt->cancel_fd);
@@ -520,7 +478,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
.realloc_buffer = tpm_passthrough_realloc_buffer,
.reset = tpm_passthrough_reset,
.had_startup_error = tpm_passthrough_get_startup_error,
- .deliver_request = tpm_passthrough_deliver_request,
.cancel_cmd = tpm_passthrough_cancel_cmd,
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
.reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
@@ -540,6 +497,7 @@ static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
tbc->ops = &tpm_passthrough_driver;
+ tbc->handle_request = tpm_passthrough_handle_request;
}
static const TypeInfo tpm_passthrough_info = {
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index e7f590d..a538a7f 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -29,22 +29,24 @@
typedef struct TPMBackendClass TPMBackendClass;
typedef struct TPMBackend TPMBackend;
-
typedef struct TPMDriverOps TPMDriverOps;
+typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool selftest_done);
-struct TPMBackendClass {
- ObjectClass parent_class;
-
- const TPMDriverOps *ops;
-
- void (*opened)(TPMBackend *s, Error **errp);
-};
+typedef enum TPMBackendCmd {
+ TPM_BACKEND_CMD_INIT = 1,
+ TPM_BACKEND_CMD_PROCESS_CMD,
+ TPM_BACKEND_CMD_END,
+ TPM_BACKEND_CMD_TPM_RESET,
+} TPMBackendCmd;
struct TPMBackend {
Object parent;
/*< protected >*/
bool opened;
+ TPMState *tpm_state;
+ GThreadPool *thread_pool;
+ TPMRecvDataCB *recv_data_callback;
char *id;
enum TpmModel fe_model;
@@ -54,7 +56,15 @@ struct TPMBackend {
QLIST_ENTRY(TPMBackend) list;
};
-typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool selftest_done);
+struct TPMBackendClass {
+ ObjectClass parent_class;
+
+ const TPMDriverOps *ops;
+
+ void (*opened)(TPMBackend *s, Error **errp);
+
+ void (*handle_request)(TPMBackend *s, TPMBackendCmd cmd);
+};
typedef struct TPMSizedBuffer {
uint32_t size;
@@ -71,7 +81,7 @@ struct TPMDriverOps {
void (*destroy)(TPMBackend *t);
/* initialize the backend */
- int (*init)(TPMBackend *t, TPMState *s, TPMRecvDataCB *datacb);
+ int (*init)(TPMBackend *t);
/* start up the TPM on the backend */
int (*startup_tpm)(TPMBackend *t);
/* returns true if nothing will ever answer TPM requests */
@@ -79,8 +89,6 @@ struct TPMDriverOps {
size_t (*realloc_buffer)(TPMSizedBuffer *sb);
- void (*deliver_request)(TPMBackend *t);
-
void (*reset)(TPMBackend *t);
void (*cancel_cmd)(TPMBackend *t);
diff --git a/include/sysemu/tpm_backend_int.h b/include/sysemu/tpm_backend_int.h
deleted file mode 100644
index 00639dd..0000000
--- a/include/sysemu/tpm_backend_int.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * common TPM backend driver functions
- *
- * Copyright (c) 2012-2013 IBM Corporation
- * Authors:
- * Stefan Berger <stefanb@us.ibm.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>
- */
-
-#ifndef TPM_BACKEND_INT_H
-#define TPM_BACKEND_INT_H
-
-typedef struct TPMBackendThread {
- GThreadPool *pool;
-} TPMBackendThread;
-
-void tpm_backend_thread_deliver_request(TPMBackendThread *tbt);
-void tpm_backend_thread_create(TPMBackendThread *tbt,
- GFunc func, gpointer user_data);
-void tpm_backend_thread_end(TPMBackendThread *tbt);
-
-typedef enum TPMBackendCmd {
- TPM_BACKEND_CMD_INIT = 1,
- TPM_BACKEND_CMD_PROCESS_CMD,
- TPM_BACKEND_CMD_END,
- TPM_BACKEND_CMD_TPM_RESET,
-} TPMBackendCmd;
-
-#endif /* TPM_BACKEND_INT_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 3/8] tpm-backend: Initialize and free data members in it's own methods
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 2/8] tpm-backend: Move thread handling inside TPMBackend Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 12:17 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
` (6 subsequent siblings)
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
Initialize and free TPMBackend data members in it's own instance_init() and
instance_finalize methods.
Took the opportunity to remove unneeded destroy() method from TpmDriverOps
interface as TPMBackend is a Qemu Object, we can use object_unref() inplace of
tpm_backend_destroy() to free the backend object, hence removed destroy() from
TPMDriverOps interface.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 16 ++++++----------
hw/tpm/tpm_passthrough.c | 31 ++++++++++++-------------------
include/sysemu/tpm_backend.h | 7 -------
tpm.c | 2 +-
4 files changed, 19 insertions(+), 37 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index ce56c3b..cf5abf1 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -51,15 +51,6 @@ const char *tpm_backend_get_desc(TPMBackend *s)
return k->ops->desc();
}
-void tpm_backend_destroy(TPMBackend *s)
-{
- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
-
- k->ops->destroy(s);
-
- tpm_backend_thread_end(s);
-}
-
int tpm_backend_init(TPMBackend *s, TPMState *state,
TPMRecvDataCB *datacb)
{
@@ -182,17 +173,22 @@ static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp)
static void tpm_backend_instance_init(Object *obj)
{
+ TPMBackend *s = TPM_BACKEND(obj);
+
object_property_add_bool(obj, "opened",
tpm_backend_prop_get_opened,
tpm_backend_prop_set_opened,
NULL);
-
+ s->fe_model = -1;
}
static void tpm_backend_instance_finalize(Object *obj)
{
TPMBackend *s = TPM_BACKEND(obj);
+ g_free(s->id);
+ g_free(s->path);
+ g_free(s->cancel_path);
tpm_backend_thread_end(s);
}
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index f50d9cf..815a72e 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -417,8 +417,6 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
tb->id = g_strdup(id);
- /* let frontend set the fe_model to proper value */
- tb->fe_model = -1;
if (tpm_passthrough_handle_device_opts(opts, tb)) {
goto err_exit;
@@ -432,26 +430,11 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
return tb;
err_exit:
- g_free(tb->id);
+ object_unref(obj);
return NULL;
}
-static void tpm_passthrough_destroy(TPMBackend *tb)
-{
- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
-
- tpm_passthrough_cancel_cmd(tb);
-
- qemu_close(tpm_pt->tpm_fd);
- qemu_close(tpm_pt->cancel_fd);
-
- g_free(tb->id);
- g_free(tb->path);
- g_free(tb->cancel_path);
- g_free(tpm_pt->tpm_dev);
-}
-
static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
TPM_STANDARD_CMDLINE_OPTS,
{
@@ -472,7 +455,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
.opts = tpm_passthrough_cmdline_opts,
.desc = tpm_passthrough_create_desc,
.create = tpm_passthrough_create,
- .destroy = tpm_passthrough_destroy,
.init = tpm_passthrough_init,
.startup_tpm = tpm_passthrough_startup_tpm,
.realloc_buffer = tpm_passthrough_realloc_buffer,
@@ -486,10 +468,21 @@ static const TPMDriverOps tpm_passthrough_driver = {
static void tpm_passthrough_inst_init(Object *obj)
{
+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
+
+ tpm_pt->tpm_fd = -1;
+ tpm_pt->cancel_fd = -1;
}
static void tpm_passthrough_inst_finalize(Object *obj)
{
+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
+
+ tpm_passthrough_cancel_cmd(TPM_BACKEND(obj));
+
+ qemu_close(tpm_pt->tpm_fd);
+ qemu_close(tpm_pt->cancel_fd);
+ g_free(tpm_pt->tpm_dev);
}
static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index a538a7f..f61bcfe 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -78,7 +78,6 @@ struct TPMDriverOps {
const char *(*desc)(void);
TPMBackend *(*create)(QemuOpts *opts, const char *id);
- void (*destroy)(TPMBackend *t);
/* initialize the backend */
int (*init)(TPMBackend *t);
@@ -118,12 +117,6 @@ enum TpmType tpm_backend_get_type(TPMBackend *s);
const char *tpm_backend_get_desc(TPMBackend *s);
/**
- * tpm_backend_destroy:
- * @s: the backend to destroy
- */
-void tpm_backend_destroy(TPMBackend *s);
-
-/**
* tpm_backend_init:
* @s: the backend to initialized
* @state: TPMState
diff --git a/tpm.c b/tpm.c
index 0ee021a..70f74fa 100644
--- a/tpm.c
+++ b/tpm.c
@@ -197,7 +197,7 @@ void tpm_cleanup(void)
QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
QLIST_REMOVE(drv, list);
- tpm_backend_destroy(drv);
+ object_unref(OBJECT(drv));
}
}
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 4/8] tpm-backend: Made few interface methods optional
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (2 preceding siblings ...)
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 3/8] tpm-backend: Initialize and free data members in it's own methods Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 12:29 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
` (5 subsequent siblings)
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
This allows backend implementations left optional interface methods.
For mandatory methods assertion checks added.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 24 ++++++++++++++++++------
hw/tpm/tpm_passthrough.c | 16 ----------------
2 files changed, 18 insertions(+), 22 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index cf5abf1..8245426 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -48,7 +48,7 @@ const char *tpm_backend_get_desc(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->desc();
+ return k->ops->desc ? k->ops->desc() : "";
}
int tpm_backend_init(TPMBackend *s, TPMState *state,
@@ -59,7 +59,7 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
s->tpm_state = state;
s->recv_data_callback = datacb;
- return k->ops->init(s);
+ return k->ops->init ? k->ops->init(s) : 0;
}
int tpm_backend_startup_tpm(TPMBackend *s)
@@ -73,13 +73,15 @@ int tpm_backend_startup_tpm(TPMBackend *s)
NULL);
g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
- return k->ops->startup_tpm(s);
+ return k->ops->startup_tpm ? k->ops->startup_tpm(s) : 0;
}
bool tpm_backend_had_startup_error(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->had_startup_error);
+
return k->ops->had_startup_error(s);
}
@@ -87,6 +89,8 @@ size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->realloc_buffer);
+
return k->ops->realloc_buffer(sb);
}
@@ -100,7 +104,9 @@ void tpm_backend_reset(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- k->ops->reset(s);
+ if (k->ops->reset) {
+ k->ops->reset(s);
+ }
tpm_backend_thread_end(s);
}
@@ -109,6 +115,8 @@ void tpm_backend_cancel_cmd(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ g_assert(k->ops->cancel_cmd);
+
k->ops->cancel_cmd(s);
}
@@ -116,20 +124,24 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->get_tpm_established_flag(s);
+ return k->ops->get_tpm_established_flag ?
+ k->ops->get_tpm_established_flag(s) : false;
}
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->reset_tpm_established_flag(s, locty);
+ return k->ops->reset_tpm_established_flag ?
+ k->ops->reset_tpm_established_flag(s, locty) : 0;
}
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->get_tpm_version);
+
return k->ops->get_tpm_version(s);
}
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index 815a72e..bbe9e5a 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -227,15 +227,6 @@ static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
}
}
-/*
- * Start the TPM (thread). If it had been started before, then terminate
- * and start it again.
- */
-static int tpm_passthrough_startup_tpm(TPMBackend *tb)
-{
- return 0;
-}
-
static void tpm_passthrough_reset(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -247,11 +238,6 @@ static void tpm_passthrough_reset(TPMBackend *tb)
tpm_pt->had_startup_error = false;
}
-static int tpm_passthrough_init(TPMBackend *tb)
-{
- return 0;
-}
-
static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
{
return false;
@@ -455,8 +441,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
.opts = tpm_passthrough_cmdline_opts,
.desc = tpm_passthrough_create_desc,
.create = tpm_passthrough_create,
- .init = tpm_passthrough_init,
- .startup_tpm = tpm_passthrough_startup_tpm,
.realloc_buffer = tpm_passthrough_realloc_buffer,
.reset = tpm_passthrough_reset,
.had_startup_error = tpm_passthrough_get_startup_error,
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 5/8] tmp backend: Add new api to read backend TpmInfo
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (3 preceding siblings ...)
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 13:35 ` Eric Blake
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class Amarnath Valluri
` (4 subsequent siblings)
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
TPM configuration options are backend implementation details and shall not be
part of base TPMBackend object, and these shall not be accessed directly outside
of the class, hence added a new interface method, get_tpm_options() to
TPMDriverOps., which shall be implemented by the derived classes to return
configured tpm options.
A new tpm backend api - tpm_backend_query_tpm() which uses _get_tpm_options() to
prepare TpmInfo.
Made TPMPassthroughOptions type inherited from newly defined TPMOptions base type.
The TPMOptions base type is intentionally left empty and supposed to be
inherited by all backend implementations to define their tpm configuration
options.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 24 ++++++++++++++++++--
hmp.c | 10 ++++----
hw/tpm/tpm_passthrough.c | 54 +++++++++++++++++++++++++++++++++++---------
include/sysemu/tpm_backend.h | 25 ++++++++++++++++++--
qapi-schema.json | 41 +++++++++++++++++----------------
tpm.c | 32 +-------------------------
6 files changed, 115 insertions(+), 71 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index 8245426..4a6358e 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -145,6 +145,28 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
return k->ops->get_tpm_version(s);
}
+TPMOptions *tpm_backend_get_tpm_options(TPMBackend *s)
+{
+ TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+ assert(k->ops->get_tpm_options);
+
+ return k->ops->get_tpm_options(s);
+}
+
+TPMInfo *tpm_backend_query_tpm(TPMBackend *s)
+{
+ TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ TPMInfo *info = g_new0(TPMInfo, 1);
+
+ info->type = k->ops->type;
+ info->id = g_strdup(s->id);
+ info->model = s->fe_model;
+ info->options = tpm_backend_get_tpm_options(s);
+
+ return info;
+}
+
static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
{
TPMBackend *s = TPM_BACKEND(obj);
@@ -199,8 +221,6 @@ static void tpm_backend_instance_finalize(Object *obj)
TPMBackend *s = TPM_BACKEND(obj);
g_free(s->id);
- g_free(s->path);
- g_free(s->cancel_path);
tpm_backend_thread_end(s);
}
diff --git a/hmp.c b/hmp.c
index edb8970..9caf7c8 100644
--- a/hmp.c
+++ b/hmp.c
@@ -955,18 +955,18 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
c, TpmModel_lookup[ti->model]);
monitor_printf(mon, " \\ %s: type=%s",
- ti->id, TpmTypeOptionsKind_lookup[ti->options->type]);
+ ti->id, TpmType_lookup[ti->type]);
- switch (ti->options->type) {
- case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
- tpo = ti->options->u.passthrough.data;
+ switch (ti->type) {
+ case TPM_TYPE_PASSTHROUGH:
+ tpo = (TPMPassthroughOptions *)ti->options;
monitor_printf(mon, "%s%s%s%s",
tpo->has_path ? ",path=" : "",
tpo->has_path ? tpo->path : "",
tpo->has_cancel_path ? ",cancel-path=" : "",
tpo->has_cancel_path ? tpo->cancel_path : "");
break;
- case TPM_TYPE_OPTIONS_KIND__MAX:
+ default:
break;
}
monitor_printf(mon, "\n");
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index bbe9e5a..2efced1 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -49,6 +49,7 @@
struct TPMPassthruState {
TPMBackend parent;
+ TPMPassthroughOptions *ops;
char *tpm_dev;
int tpm_fd;
bool tpm_executing;
@@ -313,15 +314,14 @@ static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
* in Documentation/ABI/stable/sysfs-class-tpm.
* From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel
*/
-static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
+static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
{
- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
int fd = -1;
char *dev;
char path[PATH_MAX];
- if (tb->cancel_path) {
- fd = qemu_open(tb->cancel_path, O_WRONLY);
+ if (tpm_pt->ops->cancel_path) {
+ fd = qemu_open(tpm_pt->ops->cancel_path, O_WRONLY);
if (fd < 0) {
error_report("Could not open TPM cancel path : %s",
strerror(errno));
@@ -336,7 +336,7 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
dev) < sizeof(path)) {
fd = qemu_open(path, O_WRONLY);
if (fd >= 0) {
- tb->cancel_path = g_strdup(path);
+ tpm_pt->ops->cancel_path = g_strdup(path);
} else {
error_report("tpm_passthrough: Could not open TPM cancel "
"path %s : %s", path, strerror(errno));
@@ -356,17 +356,24 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
const char *value;
value = qemu_opt_get(opts, "cancel-path");
- tb->cancel_path = g_strdup(value);
+ if (value) {
+ tpm_pt->ops->cancel_path = g_strdup(value);
+ tpm_pt->ops->has_cancel_path = true;
+ } else {
+ tpm_pt->ops->has_cancel_path = false;
+ }
value = qemu_opt_get(opts, "path");
if (!value) {
value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
+ tpm_pt->ops->has_path = false;
+ } else {
+ tpm_pt->ops->has_path = true;
}
+ tpm_pt->ops->path = g_strdup(value);
tpm_pt->tpm_dev = g_strdup(value);
- tb->path = g_strdup(tpm_pt->tpm_dev);
-
tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
if (tpm_pt->tpm_fd < 0) {
error_report("Cannot access TPM device using '%s': %s",
@@ -387,8 +394,8 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
tpm_pt->tpm_fd = -1;
err_free_parameters:
- g_free(tb->path);
- tb->path = NULL;
+ g_free(tpm_pt->ops->path);
+ tpm_pt->ops->path = NULL;
g_free(tpm_pt->tpm_dev);
tpm_pt->tpm_dev = NULL;
@@ -408,7 +415,7 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
goto err_exit;
}
- tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
+ tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tpm_pt);
if (tpm_pt->cancel_fd < 0) {
goto err_exit;
}
@@ -421,6 +428,28 @@ err_exit:
return NULL;
}
+static TPMOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
+{
+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
+ TPMPassthroughOptions *ops = g_new0(TPMPassthroughOptions, 1);
+
+ if (!ops) {
+ return NULL;
+ }
+
+ if (tpm_pt->ops->has_path) {
+ ops->has_path = true;
+ ops->path = g_strdup(tpm_pt->ops->path);
+ }
+
+ if (tpm_pt->ops->has_cancel_path) {
+ ops->has_cancel_path = true;
+ ops->cancel_path = g_strdup(tpm_pt->ops->cancel_path);
+ }
+
+ return (TPMOptions *)ops;
+}
+
static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
TPM_STANDARD_CMDLINE_OPTS,
{
@@ -448,12 +477,14 @@ static const TPMDriverOps tpm_passthrough_driver = {
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
.reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
.get_tpm_version = tpm_passthrough_get_tpm_version,
+ .get_tpm_options = tpm_passthrough_get_tpm_options,
};
static void tpm_passthrough_inst_init(Object *obj)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
+ tpm_pt->ops = g_new0(TPMPassthroughOptions, 1);
tpm_pt->tpm_fd = -1;
tpm_pt->cancel_fd = -1;
}
@@ -467,6 +498,7 @@ static void tpm_passthrough_inst_finalize(Object *obj)
qemu_close(tpm_pt->tpm_fd);
qemu_close(tpm_pt->cancel_fd);
g_free(tpm_pt->tpm_dev);
+ qapi_free_TPMPassthroughOptions(tpm_pt->ops);
}
static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index f61bcfe..8f8f133 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -48,10 +48,9 @@ struct TPMBackend {
GThreadPool *thread_pool;
TPMRecvDataCB *recv_data_callback;
+ /* <public> */
char *id;
enum TpmModel fe_model;
- char *path;
- char *cancel_path;
QLIST_ENTRY(TPMBackend) list;
};
@@ -97,6 +96,8 @@ struct TPMDriverOps {
int (*reset_tpm_established_flag)(TPMBackend *t, uint8_t locty);
TPMVersion (*get_tpm_version)(TPMBackend *t);
+
+ TPMOptions *(*get_tpm_options)(TPMBackend *t);
};
@@ -223,6 +224,26 @@ void tpm_backend_open(TPMBackend *s, Error **errp);
*/
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
+/**
+ * tpm_backend_get_tpm_options:
+ * @s: the backend
+ *
+ * Get the backend configuration options
+ *
+ * Returns newly allocated TPMOptions
+ */
+TPMOptions *tpm_backend_get_tpm_options(TPMBackend *s);
+
+/**
+ * tpm_backend_query_tpm:
+ * @s: the backend
+ *
+ * Query backend tpm info
+ *
+ * Returns newly allocated TPMInfo
+ */
+TPMInfo *tpm_backend_query_tpm(TPMBackend *s);
+
TPMBackend *qemu_find_tpm(const char *id);
const TPMDriverOps *tpm_get_backend_driver(const char *type);
diff --git a/qapi-schema.json b/qapi-schema.json
index 250e4dc..764f731 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -5137,6 +5137,16 @@
{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }
##
+# @TPMOptions:
+#
+# Base type for TPM options
+#
+# Since: 2.10
+##
+{ 'struct': 'TPMOptions',
+ 'data': { } }
+
+##
# @TPMPassthroughOptions:
#
# Information about the TPM passthrough type
@@ -5148,20 +5158,9 @@
#
# Since: 1.5
##
-{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
- '*cancel-path' : 'str'} }
+{ 'struct': 'TPMPassthroughOptions', 'base': 'TPMOptions',
+ 'data': { '*path' : 'str', '*cancel-path' : 'str'} }
-##
-# @TpmTypeOptions:
-#
-# A union referencing different TPM backend types' configuration options
-#
-# @type: 'passthrough' The configuration options for the TPM passthrough type
-#
-# Since: 1.5
-##
-{ 'union': 'TpmTypeOptions',
- 'data': { 'passthrough' : 'TPMPassthroughOptions' } }
##
# @TPMInfo:
@@ -5170,6 +5169,8 @@
#
# @id: The Id of the TPM
#
+# @type: The TPM backend type
+#
# @model: The TPM frontend model
#
# @options: The TPM (backend) type configuration options
@@ -5178,8 +5179,9 @@
##
{ 'struct': 'TPMInfo',
'data': {'id': 'str',
+ 'type': 'TpmType',
'model': 'TpmModel',
- 'options': 'TpmTypeOptions' } }
+ 'options': 'TPMOptions' } }
##
# @query-tpm:
@@ -5196,13 +5198,12 @@
# <- { "return":
# [
# { "model": "tpm-tis",
+# "type": "passthrough",
# "options":
-# { "type": "passthrough",
-# "data":
-# { "cancel-path": "/sys/class/misc/tpm0/device/cancel",
-# "path": "/dev/tpm0"
-# }
-# },
+# {
+# "cancel-path": "/sys/class/misc/tpm0/device/cancel",
+# "path": "/dev/tpm0"
+# },
# "id": "tpm0"
# }
# ]
diff --git a/tpm.c b/tpm.c
index 70f74fa..43d980e 100644
--- a/tpm.c
+++ b/tpm.c
@@ -249,36 +249,6 @@ static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
return NULL;
}
-static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
-{
- TPMInfo *res = g_new0(TPMInfo, 1);
- TPMPassthroughOptions *tpo;
-
- res->id = g_strdup(drv->id);
- res->model = drv->fe_model;
- res->options = g_new0(TpmTypeOptions, 1);
-
- switch (tpm_backend_get_type(drv)) {
- case TPM_TYPE_PASSTHROUGH:
- res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
- tpo = g_new0(TPMPassthroughOptions, 1);
- res->options->u.passthrough.data = tpo;
- if (drv->path) {
- tpo->path = g_strdup(drv->path);
- tpo->has_path = true;
- }
- if (drv->cancel_path) {
- tpo->cancel_path = g_strdup(drv->cancel_path);
- tpo->has_cancel_path = true;
- }
- break;
- case TPM_TYPE__MAX:
- break;
- }
-
- return res;
-}
-
/*
* Walk the list of active TPM backends and collect information about them
* following the schema description in qapi-schema.json.
@@ -293,7 +263,7 @@ TPMInfoList *qmp_query_tpm(Error **errp)
continue;
}
info = g_new0(TPMInfoList, 1);
- info->value = qmp_query_tpm_inst(drv);
+ info->value = tpm_backend_query_tpm(drv);
if (!cur_item) {
head = cur_item = info;
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (4 preceding siblings ...)
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 15:54 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
` (3 subsequent siblings)
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
Provide base implementation of realloc_buffer(), so that backend implementations
can resue.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 9 ++++++++-
hw/tpm/tpm_passthrough.c | 12 ------------
2 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index 4a6358e..f048c1d 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -88,8 +88,15 @@ bool tpm_backend_had_startup_error(TPMBackend *s)
size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ if (!k->ops->realloc_buffer) {
+ size_t wanted_size = 4096; /* Linux tpm.c buffer size */
- assert(k->ops->realloc_buffer);
+ if (sb->size != wanted_size) {
+ sb->buffer = g_realloc(sb->buffer, wanted_size);
+ sb->size = wanted_size;
+ }
+ return sb->size;
+ }
return k->ops->realloc_buffer(sb);
}
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index 2efced1..a7da0f8 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -258,17 +258,6 @@ static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
return tpm_pt->had_startup_error;
}
-static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
-{
- size_t wanted_size = 4096; /* Linux tpm.c buffer size */
-
- if (sb->size != wanted_size) {
- sb->buffer = g_realloc(sb->buffer, wanted_size);
- sb->size = wanted_size;
- }
- return sb->size;
-}
-
static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -470,7 +459,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
.opts = tpm_passthrough_cmdline_opts,
.desc = tpm_passthrough_create_desc,
.create = tpm_passthrough_create,
- .realloc_buffer = tpm_passthrough_realloc_buffer,
.reset = tpm_passthrough_reset,
.had_startup_error = tpm_passthrough_get_startup_error,
.cancel_cmd = tpm_passthrough_cancel_cmd,
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 7/8] tpm-passthrough: move reusable code to utils
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (5 preceding siblings ...)
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 15:54 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator Amarnath Valluri
` (2 subsequent siblings)
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
hw/tpm/tpm_passthrough.c | 64 ++++--------------------------------------------
hw/tpm/tpm_util.c | 25 +++++++++++++++++++
hw/tpm/tpm_util.h | 4 +++
3 files changed, 34 insertions(+), 59 deletions(-)
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index a7da0f8..b00efd5 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -68,27 +68,6 @@ typedef struct TPMPassthruState TPMPassthruState;
static void tpm_passthrough_cancel_cmd(TPMBackend *tb);
-static int tpm_passthrough_unix_write(int fd, const uint8_t *buf, uint32_t len)
-{
- int ret, remain;
-
- remain = len;
- while (remain > 0) {
- ret = write(fd, buf, remain);
- if (ret < 0) {
- if (errno != EINTR && errno != EAGAIN) {
- return -1;
- }
- } else if (ret == 0) {
- break;
- } else {
- buf += ret;
- remain -= ret;
- }
- }
- return len - remain;
-}
-
static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
{
int ret;
@@ -102,45 +81,12 @@ static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
}
return ret;
}
-
-static uint32_t tpm_passthrough_get_size_from_buffer(const uint8_t *buf)
-{
- struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)buf;
-
- return be32_to_cpu(resp->len);
-}
-
-/*
- * Write an error message in the given output buffer.
- */
-static void tpm_write_fatal_error_response(uint8_t *out, uint32_t out_len)
-{
- if (out_len >= sizeof(struct tpm_resp_hdr)) {
- struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)out;
-
- resp->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
- resp->len = cpu_to_be32(sizeof(struct tpm_resp_hdr));
- resp->errcode = cpu_to_be32(TPM_FAIL);
- }
-}
-
-static bool tpm_passthrough_is_selftest(const uint8_t *in, uint32_t in_len)
-{
- struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in;
-
- if (in_len >= sizeof(*hdr)) {
- return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest);
- }
-
- return false;
-}
-
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)
{
- int ret;
+ ssize_t ret;
bool is_selftest;
const struct tpm_resp_hdr *hdr;
@@ -148,9 +94,9 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
tpm_pt->tpm_executing = true;
*selftest_done = false;
- is_selftest = tpm_passthrough_is_selftest(in, in_len);
+ is_selftest = tpm_util_is_selftest(in, in_len);
- ret = tpm_passthrough_unix_write(tpm_pt->tpm_fd, in, in_len);
+ ret = qemu_write_full(tpm_pt->tpm_fd, (const void *)in, (size_t)in_len);
if (ret != in_len) {
if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
error_report("tpm_passthrough: error while transmitting data "
@@ -170,7 +116,7 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
strerror(errno), errno);
}
} else if (ret < sizeof(struct tpm_resp_hdr) ||
- tpm_passthrough_get_size_from_buffer(out) != ret) {
+ be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
ret = -1;
error_report("tpm_passthrough: received invalid response "
"packet from TPM");
@@ -183,7 +129,7 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
err_exit:
if (ret < 0) {
- tpm_write_fatal_error_response(out, out_len);
+ tpm_util_write_fatal_error_response(out, out_len);
}
tpm_pt->tpm_executing = false;
diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c
index 7b35429..fb929f6 100644
--- a/hw/tpm/tpm_util.c
+++ b/hw/tpm/tpm_util.c
@@ -24,6 +24,31 @@
#include "tpm_int.h"
/*
+ * Write an error message in the given output buffer.
+ */
+void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len)
+{
+ if (out_len >= sizeof(struct tpm_resp_hdr)) {
+ struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)out;
+
+ resp->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
+ resp->len = cpu_to_be32(sizeof(struct tpm_resp_hdr));
+ resp->errcode = cpu_to_be32(TPM_FAIL);
+ }
+}
+
+bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len)
+{
+ struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in;
+
+ if (in_len >= sizeof(*hdr)) {
+ return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest);
+ }
+
+ return false;
+}
+
+/*
* A basic test of a TPM device. We expect a well formatted response header
* (error response is fine) within one second.
*/
diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h
index df76245..2f7c961 100644
--- a/hw/tpm/tpm_util.h
+++ b/hw/tpm/tpm_util.h
@@ -24,6 +24,10 @@
#include "sysemu/tpm_backend.h"
+void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len);
+
+bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len);
+
int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version);
#endif /* TPM_TPM_UTIL_H */
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (6 preceding siblings ...)
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
@ 2017-05-02 11:52 ` Amarnath Valluri
2017-05-02 16:05 ` Marc-André Lureau
2017-05-02 12:25 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " no-reply
2017-05-04 12:28 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " Stefan Berger
9 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-02 11:52 UTC (permalink / raw)
To: qemu-devel
Cc: stefanb, patrick.ohly, marcandre.lureau, berrange, Amarnath Valluri
This change introduces a new TPM backend driver that can communicate with
swtpm(software TPM emulator) using unix domain socket interface.
Swtpm uses two unix sockets, one for plain TPM commands and responses, and one
for out-of-band control messages.
The swtpm and associated tools can be found here:
https://github.com/stefanberger/swtpm
Usage:
# setup TPM state directory
mkdir /tmp/mytpm
chown -R tss:root /tmp/mytpm
/usr/bin/swtpm_setup --tpm-state /tmp/mytpm --createek
# Ask qemu to use TPM emulator with given tpm state directory
qemu-system-x86_64 \
[...] \
-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/mytpm,logfile=/tmp/swtpm.log \
-device tpm-tis,tpmdev=tpm0 \
[...]
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
configure | 15 +-
hmp.c | 21 ++
hw/tpm/Makefile.objs | 1 +
hw/tpm/tpm_emulator.c | 943 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/tpm/tpm_ioctl.h | 243 +++++++++++++
qapi-schema.json | 36 +-
qemu-options.hx | 53 ++-
tpm.c | 2 +-
8 files changed, 1305 insertions(+), 9 deletions(-)
create mode 100644 hw/tpm/tpm_emulator.c
create mode 100644 hw/tpm/tpm_ioctl.h
diff --git a/configure b/configure
index be4d326..a933ec7 100755
--- a/configure
+++ b/configure
@@ -3359,10 +3359,15 @@ fi
##########################################
# TPM passthrough is only on x86 Linux
-if test "$targetos" = Linux && test "$cpu" = i386 -o "$cpu" = x86_64; then
- tpm_passthrough=$tpm
+if test "$targetos" = Linux; then
+ tpm_emulator=$tpm
+ if test "$cpu" = i386 -o "$cpu" = x86_64; then
+ tpm_passthrough=$tpm
+ else
+ tpm_passthrough=no
+ fi
else
- tpm_passthrough=no
+ tpm_emulator=no
fi
##########################################
@@ -5137,6 +5142,7 @@ echo "gcov enabled $gcov"
echo "TPM support $tpm"
echo "libssh2 support $libssh2"
echo "TPM passthrough $tpm_passthrough"
+echo "TPM emulator $tpm_emulator"
echo "QOM debugging $qom_cast_debug"
echo "lzo support $lzo"
echo "snappy support $snappy"
@@ -5716,6 +5722,9 @@ if test "$tpm" = "yes"; then
if test "$tpm_passthrough" = "yes"; then
echo "CONFIG_TPM_PASSTHROUGH=y" >> $config_host_mak
fi
+ if test "$tpm_emulator" = "yes"; then
+ echo "CONFIG_TPM_EMULATOR=y" >> $config_host_mak
+ fi
fi
echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
diff --git a/hmp.c b/hmp.c
index 9caf7c8..e7fd426 100644
--- a/hmp.c
+++ b/hmp.c
@@ -937,6 +937,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
Error *err = NULL;
unsigned int c = 0;
TPMPassthroughOptions *tpo;
+ TPMEmulatorOptions *teo;
info_list = qmp_query_tpm(&err);
if (err) {
@@ -966,6 +967,26 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
tpo->has_cancel_path ? ",cancel-path=" : "",
tpo->has_cancel_path ? tpo->cancel_path : "");
break;
+ case TPM_TYPE_EMULATOR:
+ teo = (TPMEmulatorOptions *)(ti->options);
+ monitor_printf(mon, ",tmpstatedir=%s", teo->tpmstatedir);
+ monitor_printf(mon, ",spawn=%s", teo->spawn ? "on" : "off");
+ if (teo->has_path) {
+ monitor_printf(mon, ",path=%s", teo->path);
+ }
+ if (teo->has_data_path) {
+ monitor_printf(mon, ",data-path=%s", teo->data_path);
+ }
+ if (teo->has_ctrl_path) {
+ monitor_printf(mon, ",ctrl-path=%s", teo->ctrl_path);
+ }
+ if (teo->has_logfile) {
+ monitor_printf(mon, ",logfile=%s", teo->logfile);
+ }
+ if (teo->has_loglevel) {
+ monitor_printf(mon, ",loglevel=%ld", teo->loglevel);
+ }
+ break;
default:
break;
}
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index 64cecc3..41f0b7a 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -1,2 +1,3 @@
common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o tpm_util.o
+common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o tpm_util.o
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
new file mode 100644
index 0000000..b480a53
--- /dev/null
+++ b/hw/tpm/tpm_emulator.c
@@ -0,0 +1,943 @@
+/*
+ * emulator TPM driver
+ *
+ * Copyright (c) 2017 Intel Corporation
+ * Author: Amarnath Valluri <amarnath.valluri@intel.com>
+ *
+ * Copyright (c) 2010 - 2013 IBM Corporation
+ * Authors:
+ * Stefan Berger <stefanb@us.ibm.com>
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ * Author: Andreas Niederl
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/sockets.h"
+#include "io/channel-socket.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_int.h"
+#include "hw/hw.h"
+#include "hw/i386/pc.h"
+#include "tpm_util.h"
+#include "tpm_ioctl.h"
+#include "qapi/error.h"
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#define DEBUG_TPM 0
+
+#define DPRINT(fmt, ...) do { \
+ if (DEBUG_TPM) { \
+ fprintf(stderr, fmt, ## __VA_ARGS__); \
+ } \
+} while (0);
+
+#define DPRINTF(fmt, ...) DPRINT("tpm-emulator: "fmt"\n", __VA_ARGS__)
+
+#define TYPE_TPM_EMULATOR "tpm-emulator"
+#define TPM_EMULATOR(obj) \
+ OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
+
+static const TPMDriverOps tpm_emulator_driver;
+
+/* data structures */
+typedef struct TPMEmulator {
+ TPMBackend parent;
+
+ TPMEmulatorOptions *ops;
+ QIOChannel *data_ioc;
+ QIOChannel *ctrl_ioc;
+ bool op_executing;
+ bool op_canceled;
+ bool child_running;
+ TPMVersion tpm_version;
+ ptm_cap caps; /* capabilities of the TPM */
+ uint8_t cur_locty_number; /* last set locality */
+ QemuMutex state_lock;
+} TPMEmulator;
+
+#define TPM_DEFAULT_EMULATOR "swtpm"
+#define TPM_DEFAULT_LOGLEVEL 5
+#define TPM_EMULATOR_PIDFILE "/tmp/qemu-tpm.pid"
+#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
+
+static int tpm_emulator_ctrlcmd(QIOChannel *ioc, unsigned long cmd, void *msg,
+ size_t msg_len_in, size_t msg_len_out)
+{
+ ssize_t n;
+
+ uint32_t cmd_no = cpu_to_be32(cmd);
+ struct iovec iov[2] = {
+ { .iov_base = &cmd_no, .iov_len = sizeof(cmd_no), },
+ { .iov_base = msg, .iov_len = msg_len_in, },
+ };
+
+ n = qio_channel_writev(ioc, iov, 2, NULL);
+ if (n > 0) {
+ if (msg_len_out > 0) {
+ n = qio_channel_read(ioc, (char *)msg, msg_len_out, NULL);
+ /* simulate ioctl return value */
+ if (n > 0) {
+ n = 0;
+ }
+ } else {
+ n = 0;
+ }
+ }
+ return n;
+}
+
+static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_pt,
+ const uint8_t *in, uint32_t in_len,
+ uint8_t *out, uint32_t out_len,
+ bool *selftest_done)
+{
+ ssize_t ret;
+ bool is_selftest;
+ const struct tpm_resp_hdr *hdr;
+
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ tpm_pt->op_canceled = false;
+ tpm_pt->op_executing = true;
+ *selftest_done = false;
+
+ is_selftest = tpm_util_is_selftest(in, in_len);
+
+ ret = qio_channel_write(tpm_pt->data_ioc, (const char *)in, (size_t)in_len,
+ NULL);
+ if (ret != in_len) {
+ if (!tpm_pt->op_canceled || errno != ECANCELED) {
+ error_report("tpm-emulator: error while transmitting data "
+ "to TPM: %s (%i)", strerror(errno), errno);
+ }
+ goto err_exit;
+ }
+
+ tpm_pt->op_executing = false;
+
+ ret = qio_channel_read(tpm_pt->data_ioc, (char *)out, (size_t)out_len,
+ NULL);
+ if (ret < 0) {
+ if (!tpm_pt->op_canceled || errno != ECANCELED) {
+ error_report("tpm-emulator: error while reading data from "
+ "TPM: %s (%i)", strerror(errno), errno);
+ }
+ } else if (ret < sizeof(struct tpm_resp_hdr) ||
+ be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
+ ret = -1;
+ error_report("tpm-emulator: received invalid response "
+ "packet from TPM");
+ }
+
+ if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) {
+ hdr = (struct tpm_resp_hdr *)out;
+ *selftest_done = (be32_to_cpu(hdr->errcode) == 0);
+ }
+
+err_exit:
+ if (ret < 0) {
+ tpm_util_write_fatal_error_response(out, out_len);
+ }
+
+ tpm_pt->op_executing = false;
+
+ return ret;
+}
+
+static int tpm_emulator_set_locality(TPMEmulator *tpm_pt,
+ uint8_t locty_number)
+{
+ ptm_loc loc;
+
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ DPRINTF("%s : locality: 0x%x", __func__, locty_number);
+
+ if (tpm_pt->cur_locty_number != locty_number) {
+ DPRINTF("setting locality : 0x%x", locty_number);
+ loc.u.req.loc = locty_number;
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_SET_LOCALITY, &loc,
+ sizeof(loc), sizeof(loc)) < 0) {
+ error_report("tpm-emulator: could not set locality : %s",
+ strerror(errno));
+ return -1;
+ }
+ loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
+ if (loc.u.resp.tpm_result != 0) {
+ error_report("tpm-emulator: TPM result for set locality : 0x%x",
+ loc.u.resp.tpm_result);
+ return -1;
+ }
+ tpm_pt->cur_locty_number = locty_number;
+ }
+ return 0;
+}
+
+static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ TPMLocality *locty = NULL;
+ bool selftest_done = false;
+
+ DPRINTF("processing command type %d", cmd);
+
+ switch (cmd) {
+ case TPM_BACKEND_CMD_PROCESS_CMD:
+ qemu_mutex_lock(&tpm_pt->state_lock);
+ locty = tb->tpm_state->locty_data;
+ if (tpm_emulator_set_locality(tpm_pt,
+ tb->tpm_state->locty_number) < 0) {
+ tpm_util_write_fatal_error_response(locty->r_buffer.buffer,
+ locty->r_buffer.size);
+ } else {
+ tpm_emulator_unix_tx_bufs(tpm_pt, locty->w_buffer.buffer,
+ locty->w_offset, locty->r_buffer.buffer,
+ locty->r_buffer.size, &selftest_done);
+ }
+ tb->recv_data_callback(tb->tpm_state, tb->tpm_state->locty_number,
+ selftest_done);
+ qemu_mutex_unlock(&tpm_pt->state_lock);
+ break;
+ case TPM_BACKEND_CMD_INIT:
+ case TPM_BACKEND_CMD_END:
+ case TPM_BACKEND_CMD_TPM_RESET:
+ /* nothing to do */
+ break;
+ }
+}
+
+/*
+ * Gracefully shut down the external unixio TPM
+ */
+static void tpm_emulator_shutdown(TPMEmulator *tpm_pt)
+{
+ ptm_res res;
+
+ if (!tpm_pt->child_running) {
+ return;
+ }
+
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_SHUTDOWN, &res, 0,
+ sizeof(res)) < 0) {
+ error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
+ strerror(errno));
+ } else if (res != 0) {
+ error_report("tpm-emulator: TPM result for sutdown: 0x%x",
+ be32_to_cpu(res));
+ }
+}
+
+static int tpm_emulator_probe_caps(TPMEmulator *tpm_pt)
+{
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ DPRINTF("%s", __func__);
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_GET_CAPABILITY,
+ &tpm_pt->caps, 0, sizeof(tpm_pt->caps)) < 0) {
+ error_report("tpm-emulator: probing failed : %s", strerror(errno));
+ return -1;
+ }
+
+ tpm_pt->caps = be64_to_cpu(tpm_pt->caps);
+
+ DPRINTF("capbilities : 0x%lx", tpm_pt->caps);
+
+ return 0;
+}
+
+static int tpm_emulator_check_caps(TPMEmulator *tpm_pt)
+{
+ ptm_cap caps = 0;
+ const char *tpm = NULL;
+
+ /* check for min. required capabilities */
+ switch (tpm_pt->tpm_version) {
+ case TPM_VERSION_1_2:
+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
+ PTM_CAP_SET_LOCALITY;
+ tpm = "1.2";
+ break;
+ case TPM_VERSION_2_0:
+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
+ PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED;
+ tpm = "2";
+ break;
+ case TPM_VERSION_UNSPEC:
+ error_report("tpm-emulator: TPM version has not been set");
+ return -1;
+ }
+
+ if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_pt, caps)) {
+ error_report("tpm-emulator: TPM does not implement minimum set of "
+ "required capabilities for TPM %s (0x%x)", tpm, (int)caps);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tpm_emulator_init_tpm(TPMEmulator *tpm_pt)
+{
+ ptm_init init;
+ ptm_res res;
+
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ DPRINTF("%s", __func__);
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_INIT, &init, sizeof(init),
+ sizeof(init)) < 0) {
+ error_report("tpm-emulator: could not send INIT: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ res = be32_to_cpu(init.u.resp.tpm_result);
+ if (res) {
+ error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x", res);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tpm_emulator_startup_tpm(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+
+ DPRINTF("%s", __func__);
+
+ tpm_emulator_init_tpm(tpm_pt) ;
+
+ return 0;
+}
+
+static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ ptm_est est;
+
+ DPRINTF("%s", __func__);
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_GET_TPMESTABLISHED, &est, 0,
+ sizeof(est)) < 0) {
+ error_report("tpm-emulator: Could not get the TPM established flag: %s",
+ strerror(errno));
+ return false;
+ }
+ DPRINTF("established flag: %0x", est.u.resp.bit);
+
+ return (est.u.resp.bit != 0);
+}
+
+static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
+ uint8_t locty)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ ptm_reset_est reset_est;
+ ptm_res res;
+
+ /* only a TPM 2.0 will support this */
+ if (tpm_pt->tpm_version == TPM_VERSION_2_0) {
+ reset_est.u.req.loc = tpm_pt->cur_locty_number;
+
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_RESET_TPMESTABLISHED,
+ &reset_est, sizeof(reset_est),
+ sizeof(reset_est)) < 0) {
+ error_report("tpm-emulator: Could not reset the establishment bit: "
+ "%s", strerror(errno));
+ return -1;
+ }
+
+ res = be32_to_cpu(reset_est.u.resp.tpm_result);
+ if (res) {
+ error_report("tpm-emulator: TPM result for rest establixhed flag: "
+ "0x%x", res);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static bool tpm_emulator_had_startup_error(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+
+ return !tpm_pt->child_running;
+}
+
+static void tpm_emulator_cancel_cmd(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ ptm_res res;
+
+ /*
+ * As of Linux 3.7 the tpm_tis driver does not properly cancel
+ * commands on all TPM manufacturers' TPMs.
+ * Only cancel if we're busy so we don't cancel someone else's
+ * command, e.g., a command executed on the host.
+ */
+ if (tpm_pt->op_executing) {
+ if (TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_pt, PTM_CAP_CANCEL_TPM_CMD)) {
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_CANCEL_TPM_CMD, &res,
+ 0, sizeof(res)) < 0) {
+ error_report("tpm-emulator: Could not cancel command: %s",
+ strerror(errno));
+ } else if (res != 0) {
+ error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
+ be32_to_cpu(res));
+ } else {
+ tpm_pt->op_canceled = true;
+ }
+ }
+ }
+}
+
+static void tpm_emulator_reset(TPMBackend *tb)
+{
+ DPRINTF("%s", __func__);
+
+ tpm_emulator_cancel_cmd(tb);
+}
+
+static const char *tpm_emulator_desc(void)
+{
+ return "TPM emulator backend driver";
+}
+
+static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+
+ return tpm_pt->tpm_version;
+}
+
+static gboolean tpm_emulator_fd_handler(QIOChannel *ioc, GIOCondition cnd,
+ void *opaque)
+{
+ TPMEmulator *tpm_pt = opaque;
+
+ if (cnd & G_IO_ERR || cnd & G_IO_HUP) {
+ error_report("TPM backend disappeared");
+ tpm_pt->child_running = false;
+ return false;
+ }
+
+ return true;
+}
+
+static QIOChannel *_iochannel_new(const char *path, int fd, Error **err)
+{
+ int socket = path ? unix_connect(path, err) : fd;
+ if (socket < 0) {
+ return NULL;
+ }
+
+ return QIO_CHANNEL(qio_channel_socket_new_fd(socket, err));
+}
+
+static int tpm_emulator_spawn_emulator(TPMEmulator *tpm_pt)
+{
+ int fds[2] = { -1, -1 };
+ int ctrl_fds[2] = { -1, -1 };
+ pid_t cpid;
+
+ if (!tpm_pt->ops->has_data_path) {
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) < 0) {
+ return -1;
+ }
+ }
+
+ if (!tpm_pt->ops->has_ctrl_path) {
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ctrl_fds) < 0) {
+ if (!tpm_pt->ops->has_data_path) {
+ closesocket(fds[0]);
+ closesocket(fds[1]);
+ }
+ return -1;
+ }
+ }
+
+ cpid = qemu_fork(NULL);
+ if (cpid < 0) {
+ error_report("tpm-emulator: Fork failure: %s", strerror(errno));
+ if (!tpm_pt->ops->has_data_path) {
+ closesocket(fds[0]);
+ closesocket(fds[1]);
+ }
+ if (!tpm_pt->ops->has_ctrl_path) {
+ closesocket(ctrl_fds[0]);
+ closesocket(ctrl_fds[1]);
+ }
+ return -1;
+ }
+
+ unlink(TPM_EMULATOR_PIDFILE);
+
+ if (cpid == 0) { /* CHILD */
+ enum {
+ PARAM_PATH,
+ PARAM_IFACE,
+ PARAM_SERVER, PARAM_SERVER_ARGS,
+ PARAM_CTRL, PARAM_CTRL_ARGS,
+ PARAM_STATE, PARAM_STATE_ARGS,
+ PARAM_PIDFILE, PARAM_PIDFILE_ARGS,
+ PARAM_LOG, PARAM_LOG_ARGS,
+ PARAM_MAX
+ };
+
+ int i;
+ int data_fd = -1, ctrl_fd = -1;
+ char *argv[PARAM_MAX + 1];
+
+ /* close all unused inherited sockets */
+ if (fds[0] >= 0) {
+ closesocket(fds[0]);
+ }
+ if (ctrl_fds[0] >= 0) {
+ closesocket(ctrl_fds[0]);
+ }
+
+ i = STDERR_FILENO + 1;
+ if (fds[1] >= 0) {
+ data_fd = dup2(fds[1], i++);
+ if (data_fd < 0) {
+ error_report("tpm-emulator: dup2() failure - %s",
+ strerror(errno));
+ goto exit_child;
+ }
+ }
+ if (ctrl_fds[1] >= 0) {
+ ctrl_fd = dup2(ctrl_fds[1], i++);
+ if (ctrl_fd < 0) {
+ error_report("tpm-emulator: dup2() failure - %s",
+ strerror(errno));
+ goto exit_child;
+ }
+ }
+ for ( ; i < sysconf(_SC_OPEN_MAX); i++) {
+ close(i);
+ }
+
+ argv[PARAM_MAX] = NULL;
+ argv[PARAM_PATH] = g_strdup(tpm_pt->ops->path);
+ argv[PARAM_IFACE] = g_strdup("socket");
+ if (tpm_pt->ops->has_data_path) {
+ argv[PARAM_SERVER] = g_strdup("--server");
+ argv[PARAM_SERVER_ARGS] = g_strdup_printf("type=unixio,path=%s",
+ tpm_pt->ops->data_path);
+ } else {
+ argv[PARAM_SERVER] = g_strdup("--fd");
+ argv[PARAM_SERVER_ARGS] = g_strdup_printf("%d", data_fd);
+ }
+
+ argv[PARAM_CTRL] = g_strdup("--ctrl");
+ if (tpm_pt->ops->has_ctrl_path) {
+ argv[PARAM_CTRL_ARGS] = g_strdup_printf("type=unixio,path=%s",
+ tpm_pt->ops->ctrl_path);
+ } else {
+ argv[PARAM_CTRL_ARGS] = g_strdup_printf("type=unixio,clientfd=%d",
+ ctrl_fd);
+ }
+
+ argv[PARAM_STATE] = g_strdup("--tpmstate");
+ argv[PARAM_STATE_ARGS] = g_strdup_printf("dir=%s",
+ tpm_pt->ops->tpmstatedir);
+ argv[PARAM_PIDFILE] = g_strdup("--pid");
+ argv[PARAM_PIDFILE_ARGS] = g_strdup_printf("file=%s",
+ TPM_EMULATOR_PIDFILE);
+ if (tpm_pt->ops->has_logfile) {
+ argv[PARAM_LOG] = g_strdup("--log");
+ argv[PARAM_LOG_ARGS] = g_strdup_printf("file=%s,level=%d",
+ tpm_pt->ops->logfile, (int)tpm_pt->ops->loglevel);
+ } else {
+ /* truncate logs */
+ argv[PARAM_LOG] = NULL;
+ }
+ DPRINTF("%s", "Running cmd: ")
+ for (i = 0; argv[i]; i++) {
+ DPRINT(" %s", argv[i])
+ }
+ DPRINT("\n")
+ if (execv(tpm_pt->ops->path, (char * const *)argv) < 0) {
+ error_report("execv() failure : %s", strerror(errno));
+ }
+
+exit_child:
+ g_strfreev(argv);
+ if (data_fd >= 0) {
+ closesocket(data_fd);
+ }
+ if (ctrl_fd >= 0) {
+ closesocket(ctrl_fd);
+ }
+
+ _exit(1);
+ } else { /* self */
+ struct stat st;
+ DPRINTF("child pid: %d", cpid);
+ int rc;
+ useconds_t usec = 100 * 1000L; /* wait for 100 milliseconds */
+ useconds_t timeout = 10; /* max 1 second */
+
+ /* close unused sockets */
+ if (fds[1] >= 0) {
+ closesocket(fds[1]);
+ }
+ if (ctrl_fds[1] >= 0) {
+ closesocket(ctrl_fds[1]);
+ }
+
+ tpm_pt->data_ioc = _iochannel_new(tpm_pt->ops->data_path, fds[0], NULL);
+ if (!tpm_pt->data_ioc) {
+ error_report("tpm-emulator: Unable to connect socket : %s",
+ tpm_pt->ops->data_path);
+ goto err_kill_child;
+ }
+
+ tpm_pt->ctrl_ioc = _iochannel_new(tpm_pt->ops->ctrl_path, ctrl_fds[0],
+ NULL);
+ if (!tpm_pt->ctrl_ioc) {
+ error_report("tpm-emulator: Unable to connect socket : %s",
+ tpm_pt->ops->ctrl_path);
+ goto err_kill_child;
+ }
+
+ qemu_add_child_watch(cpid);
+
+ qio_channel_add_watch(tpm_pt->data_ioc, G_IO_HUP | G_IO_ERR,
+ tpm_emulator_fd_handler, tpm_pt, NULL);
+
+ while ((rc = stat(TPM_EMULATOR_PIDFILE, &st)) < 0 && timeout--) {
+ usleep(usec);
+ }
+
+ if (timeout == -1) {
+ error_report("tpm-emulator: pid file not ready: %s",
+ strerror(errno));
+ goto err_kill_child;
+ }
+
+ /* check if child really running */
+ if (kill(cpid, 0) < 0 && errno == ESRCH) {
+ goto err_no_child;
+ }
+
+ tpm_pt->child_running = true;
+ }
+
+ return 0;
+
+err_kill_child:
+ kill(cpid, SIGTERM);
+ /* wait for 10 mill-seconds */
+ usleep(10 * 1000);
+ /* force kill if still reachable */
+ if (kill(cpid, 0) == 0) {
+ kill(cpid, SIGKILL);
+ }
+
+err_no_child:
+ tpm_pt->child_running = false;
+
+ return -1;
+}
+
+static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_pt, QemuOpts *opts)
+{
+ const char *value;
+
+ value = qemu_opt_get(opts, "tpmstatedir");
+ if (!value) {
+ error_report("tpm-emulator: Missing tpm state directory");
+ return -1;
+ }
+ tpm_pt->ops->tpmstatedir = g_strdup(value);
+
+ tpm_pt->ops->spawn = qemu_opt_get_bool(opts, "spawn", false);
+
+ value = qemu_opt_get(opts, "path");
+ if (!value) {
+ value = TPM_DEFAULT_EMULATOR;
+ tpm_pt->ops->has_path = false;
+ } else {
+ tpm_pt->ops->has_path = true;
+ if (value[0] == '/') {
+ struct stat st;
+ if (stat(value, &st) < 0 || !(S_ISREG(st.st_mode)
+ || S_ISLNK(st.st_mode))) {
+ error_report("tpm-emulator: Invalid emulator path: %s", value);
+ return -1;
+ }
+ }
+ }
+ tpm_pt->ops->path = g_strdup(value);
+
+ value = qemu_opt_get(opts, "data-path");
+ if (value) {
+ tpm_pt->ops->has_data_path = true;
+ tpm_pt->ops->data_path = g_strdup(value);
+ } else {
+ tpm_pt->ops->has_data_path = false;
+ if (!tpm_pt->ops->spawn) {
+ error_report("tpm-emulator: missing mandatory data-path");
+ return -1;
+ }
+ }
+
+ value = qemu_opt_get(opts, "ctrl-path");
+ if (value) {
+ tpm_pt->ops->has_ctrl_path = true;
+ tpm_pt->ops->ctrl_path = g_strdup(value);
+ } else {
+ tpm_pt->ops->has_ctrl_path = false;
+ if (!tpm_pt->ops->spawn) {
+ error_report("tpm-emulator: missing mandatory ctrl-path");
+ return -1;
+ }
+ }
+
+ value = qemu_opt_get(opts, "logfile");
+ if (value) {
+ tpm_pt->ops->has_logfile = true;
+ tpm_pt->ops->logfile = g_strdup(value);
+ tpm_pt->ops->loglevel = qemu_opt_get_number(opts, "loglevel",
+ TPM_DEFAULT_LOGLEVEL);
+ tpm_pt->ops->has_loglevel = tpm_pt->ops->loglevel !=
+ TPM_DEFAULT_LOGLEVEL;
+ }
+
+ if (tpm_pt->ops->spawn) {
+ if (tpm_emulator_spawn_emulator(tpm_pt) < 0) {
+ goto err_close_dev;
+ }
+ } else {
+ tpm_pt->data_ioc = _iochannel_new(tpm_pt->ops->data_path, -1, NULL);
+ if (tpm_pt->data_ioc == NULL) {
+ error_report("tpm-emulator: Failed to connect data socket: %s",
+ tpm_pt->ops->data_path);
+ goto err_close_dev;
+ }
+ tpm_pt->ctrl_ioc = _iochannel_new(tpm_pt->ops->ctrl_path, -1, NULL);
+ if (tpm_pt->ctrl_ioc == NULL) {
+ DPRINTF("Failed to connect control socket: %s",
+ strerror(errno));
+ goto err_close_dev;
+ }
+ tpm_pt->child_running = true;
+ }
+
+ /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used
+ * by passthrough driver, which not yet using GIOChannel.
+ */
+ if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_pt->data_ioc)->fd,
+ &tpm_pt->tpm_version)) {
+ error_report("'%s' is not emulating TPM device.", tpm_pt->ops->path);
+ goto err_close_dev;
+ }
+
+ DPRINTF("TPM Version %s", tpm_pt->tpm_version == TPM_VERSION_1_2 ? "1.2" :
+ (tpm_pt->tpm_version == TPM_VERSION_2_0 ? "2.0" : "Unspecified"));
+
+ if (tpm_emulator_probe_caps(tpm_pt) ||
+ tpm_emulator_check_caps(tpm_pt)) {
+ goto err_close_dev;
+ }
+
+ return 0;
+
+err_close_dev:
+ DPRINT("Startup error\n");
+ return -1;
+}
+
+static TPMBackend *tpm_emulator_create(QemuOpts *opts, const char *id)
+{
+ TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
+
+ tb->id = g_strdup(id);
+
+ if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
+ goto err_exit;
+ }
+
+ return tb;
+
+err_exit:
+ object_unref(OBJECT(tb));
+
+ return NULL;
+}
+
+static TPMOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ TPMEmulatorOptions *ops = g_new0(TPMEmulatorOptions, 1);
+
+ if (!ops) {
+ return NULL;
+ }
+ DPRINTF("%s", __func__);
+
+ ops->tpmstatedir = g_strdup(tpm_pt->ops->tpmstatedir);
+ ops->spawn = tpm_pt->ops->spawn;
+ if (tpm_pt->ops->has_path) {
+ ops->has_path = true;
+ ops->path = g_strdup(tpm_pt->ops->path);
+ }
+ if (tpm_pt->ops->has_data_path) {
+ ops->has_data_path = true;
+ ops->data_path = g_strdup(tpm_pt->ops->data_path);
+ }
+ if (tpm_pt->ops->has_ctrl_path) {
+ ops->has_ctrl_path = true;
+ ops->ctrl_path = g_strdup(tpm_pt->ops->ctrl_path);
+ }
+ if (tpm_pt->ops->has_logfile) {
+ ops->has_logfile = true;
+ ops->logfile = g_strdup(tpm_pt->ops->logfile);
+ }
+ if (tpm_pt->ops->has_loglevel) {
+ ops->has_loglevel = true;
+ ops->loglevel = tpm_pt->ops->loglevel;
+ }
+
+ return (TPMOptions *)ops;
+}
+
+static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
+ TPM_STANDARD_CMDLINE_OPTS,
+ {
+ .name = "tpmstatedir",
+ .type = QEMU_OPT_STRING,
+ .help = "TPM state directroy",
+ },
+ {
+ .name = "spawn",
+ .type = QEMU_OPT_BOOL,
+ .help = "Wether to spwan given emlatory binary",
+ },
+ {
+ .name = "path",
+ .type = QEMU_OPT_STRING,
+ .help = "Path to TPM emulator binary",
+ },
+ {
+ .name = "data-path",
+ .type = QEMU_OPT_STRING,
+ .help = "Socket path to use for data exhange",
+ },
+ {
+ .name = "ctrl-path",
+ .type = QEMU_OPT_STRING,
+ .help = "Socket path to use for out-of-band control messages",
+ },
+ {
+ .name = "logfile",
+ .type = QEMU_OPT_STRING,
+ .help = "Path to log file",
+ },
+ {
+ .name = "level",
+ .type = QEMU_OPT_STRING,
+ .help = "Log level number",
+ },
+ { /* end of list */ },
+};
+
+static const TPMDriverOps tpm_emulator_driver = {
+ .type = TPM_TYPE_EMULATOR,
+ .opts = tpm_emulator_cmdline_opts,
+ .desc = tpm_emulator_desc,
+ .create = tpm_emulator_create,
+ .startup_tpm = tpm_emulator_startup_tpm,
+ .reset = tpm_emulator_reset,
+ .had_startup_error = tpm_emulator_had_startup_error,
+ .cancel_cmd = tpm_emulator_cancel_cmd,
+ .get_tpm_established_flag = tpm_emulator_get_tpm_established_flag,
+ .reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag,
+ .get_tpm_version = tpm_emulator_get_tpm_version,
+ .get_tpm_options = tpm_emulator_get_tpm_options,
+};
+
+static void tpm_emulator_inst_init(Object *obj)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(obj);
+
+ DPRINTF("%s", __func__);
+ tpm_pt->ops = g_new0(TPMEmulatorOptions, 1);
+ tpm_pt->data_ioc = tpm_pt->ctrl_ioc = NULL;
+ tpm_pt->op_executing = tpm_pt->op_canceled = false;
+ tpm_pt->child_running = false;
+ tpm_pt->cur_locty_number = ~0;
+ qemu_mutex_init(&tpm_pt->state_lock);
+}
+
+static void tpm_emulator_inst_finalize(Object *obj)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(obj);
+
+ tpm_emulator_cancel_cmd(TPM_BACKEND(obj));
+ tpm_emulator_shutdown(tpm_pt);
+
+ if (tpm_pt->data_ioc) {
+ qio_channel_close(tpm_pt->data_ioc, NULL);
+ }
+ if (tpm_pt->ctrl_ioc) {
+ qio_channel_close(tpm_pt->ctrl_ioc, NULL);
+ }
+ if (tpm_pt->ops) {
+ qapi_free_TPMEmulatorOptions(tpm_pt->ops);
+ }
+}
+
+static void tpm_emulator_class_init(ObjectClass *klass, void *data)
+{
+ TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
+ tbc->ops = &tpm_emulator_driver;
+ tbc->handle_request = tpm_emulator_handle_request;
+}
+
+static const TypeInfo tpm_emulator_info = {
+ .name = TYPE_TPM_EMULATOR,
+ .parent = TYPE_TPM_BACKEND,
+ .instance_size = sizeof(TPMEmulator),
+ .class_init = tpm_emulator_class_init,
+ .instance_init = tpm_emulator_inst_init,
+ .instance_finalize = tpm_emulator_inst_finalize,
+};
+
+static void tpm_emulator_register(void)
+{
+ type_register_static(&tpm_emulator_info);
+ tpm_register_driver(&tpm_emulator_driver);
+}
+
+type_init(tpm_emulator_register)
diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h
new file mode 100644
index 0000000..af49708
--- /dev/null
+++ b/hw/tpm/tpm_ioctl.h
@@ -0,0 +1,243 @@
+/*
+ * tpm_ioctl.h
+ *
+ * (c) Copyright IBM Corporation 2014, 2015.
+ *
+ * This file is licensed under the terms of the 3-clause BSD license
+ */
+#ifndef _TPM_IOCTL_H_
+#define _TPM_IOCTL_H_
+
+#include <stdint.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+/*
+ * Every response from a command involving a TPM command execution must hold
+ * the ptm_res as the first element.
+ * ptm_res corresponds to the error code of a command executed by the TPM.
+ */
+
+typedef uint32_t ptm_res;
+
+/* PTM_GET_TPMESTABLISHED: get the establishment bit */
+struct ptm_est {
+ union {
+ struct {
+ ptm_res tpm_result;
+ unsigned char bit; /* TPM established bit */
+ } resp; /* response */
+ } u;
+};
+
+/* PTM_RESET_TPMESTABLISHED: reset establishment bit */
+struct ptm_reset_est {
+ union {
+ struct {
+ uint8_t loc; /* locality to use */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/* PTM_INIT */
+struct ptm_init {
+ union {
+ struct {
+ uint32_t init_flags; /* see definitions below */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/* above init_flags */
+#define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0)
+ /* delete volatile state file after reading it */
+
+/* PTM_SET_LOCALITY */
+struct ptm_loc {
+ union {
+ struct {
+ uint8_t loc; /* locality to set */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/* PTM_HASH_DATA: hash given data */
+struct ptm_hdata {
+ union {
+ struct {
+ uint32_t length;
+ uint8_t data[4096];
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/*
+ * size of the TPM state blob to transfer; x86_64 can handle 8k,
+ * ppc64le only ~7k; keep the response below a 4k page size
+ */
+#define PTM_STATE_BLOB_SIZE (3 * 1024)
+
+/*
+ * The following is the data structure to get state blobs from the TPM.
+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple reads
+ * with this ioctl and with adjusted offset are necessary. All bytes
+ * must be transferred and the transfer is done once the last byte has been
+ * returned.
+ * It is possible to use the read() interface for reading the data; however, the
+ * first bytes of the state blob will be part of the response to the ioctl(); a
+ * subsequent read() is only necessary if the total length (totlength) exceeds
+ * the number of received bytes. seek() is not supported.
+ */
+struct ptm_getstate {
+ union {
+ struct {
+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */
+ uint32_t type; /* which blob to pull */
+ uint32_t offset; /* offset from where to read */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */
+ uint32_t totlength; /* total length that will be transferred */
+ uint32_t length; /* number of bytes in following buffer */
+ uint8_t data[PTM_STATE_BLOB_SIZE];
+ } resp; /* response */
+ } u;
+};
+
+/* TPM state blob types */
+#define PTM_BLOB_TYPE_PERMANENT 1
+#define PTM_BLOB_TYPE_VOLATILE 2
+#define PTM_BLOB_TYPE_SAVESTATE 3
+
+/* state_flags above : */
+#define PTM_STATE_FLAG_DECRYPTED 1 /* on input: get decrypted state */
+#define PTM_STATE_FLAG_ENCRYPTED 2 /* on output: state is encrypted */
+
+/*
+ * The following is the data structure to set state blobs in the TPM.
+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple
+ * 'writes' using this ioctl are necessary. The last packet is indicated
+ * by the length being smaller than the PTM_STATE_BLOB_SIZE.
+ * The very first packet may have a length indicator of '0' enabling
+ * a write() with all the bytes from a buffer. If the write() interface
+ * is used, a final ioctl with a non-full buffer must be made to indicate
+ * that all data were transferred (a write with 0 bytes would not work).
+ */
+struct ptm_setstate {
+ union {
+ struct {
+ uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */
+ uint32_t type; /* which blob to set */
+ uint32_t length; /* length of the data;
+ use 0 on the first packet to
+ transfer using write() */
+ uint8_t data[PTM_STATE_BLOB_SIZE];
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/*
+ * PTM_GET_CONFIG: Data structure to get runtime configuration information
+ * such as which keys are applied.
+ */
+struct ptm_getconfig {
+ union {
+ struct {
+ ptm_res tpm_result;
+ uint32_t flags;
+ } resp; /* response */
+ } u;
+};
+
+#define PTM_CONFIG_FLAG_FILE_KEY 0x1
+#define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2
+
+
+typedef uint64_t ptm_cap;
+typedef struct ptm_est ptm_est;
+typedef struct ptm_reset_est ptm_reset_est;
+typedef struct ptm_loc ptm_loc;
+typedef struct ptm_hdata ptm_hdata;
+typedef struct ptm_init ptm_init;
+typedef struct ptm_getstate ptm_getstate;
+typedef struct ptm_setstate ptm_setstate;
+typedef struct ptm_getconfig ptm_getconfig;
+
+/* capability flags returned by PTM_GET_CAPABILITY */
+#define PTM_CAP_INIT (1)
+#define PTM_CAP_SHUTDOWN (1 << 1)
+#define PTM_CAP_GET_TPMESTABLISHED (1 << 2)
+#define PTM_CAP_SET_LOCALITY (1 << 3)
+#define PTM_CAP_HASHING (1 << 4)
+#define PTM_CAP_CANCEL_TPM_CMD (1 << 5)
+#define PTM_CAP_STORE_VOLATILE (1 << 6)
+#define PTM_CAP_RESET_TPMESTABLISHED (1 << 7)
+#define PTM_CAP_GET_STATEBLOB (1 << 8)
+#define PTM_CAP_SET_STATEBLOB (1 << 9)
+#define PTM_CAP_STOP (1 << 10)
+#define PTM_CAP_GET_CONFIG (1 << 11)
+
+enum {
+ PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap),
+ PTM_INIT = _IOWR('P', 1, ptm_init),
+ PTM_SHUTDOWN = _IOR('P', 2, ptm_res),
+ PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est),
+ PTM_SET_LOCALITY = _IOWR('P', 4, ptm_loc),
+ PTM_HASH_START = _IOR('P', 5, ptm_res),
+ PTM_HASH_DATA = _IOWR('P', 6, ptm_hdata),
+ PTM_HASH_END = _IOR('P', 7, ptm_res),
+ PTM_CANCEL_TPM_CMD = _IOR('P', 8, ptm_res),
+ PTM_STORE_VOLATILE = _IOR('P', 9, ptm_res),
+ PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est),
+ PTM_GET_STATEBLOB = _IOWR('P', 11, ptm_getstate),
+ PTM_SET_STATEBLOB = _IOWR('P', 12, ptm_setstate),
+ PTM_STOP = _IOR('P', 13, ptm_res),
+ PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig),
+};
+
+/*
+ * Commands used by the non-CUSE TPMs
+ *
+ * All messages container big-endian data.
+ *
+ * The return messages only contain the 'resp' part of the unions
+ * in the data structures above. Besides that the limits in the
+ * buffers above (ptm_hdata:u.req.data and ptm_get_state:u.resp.data
+ * and ptm_set_state:u.req.data) are 0xffffffff.
+ */
+enum {
+ CMD_GET_CAPABILITY = 1,
+ CMD_INIT,
+ CMD_SHUTDOWN,
+ CMD_GET_TPMESTABLISHED,
+ CMD_SET_LOCALITY,
+ CMD_HASH_START,
+ CMD_HASH_DATA,
+ CMD_HASH_END,
+ CMD_CANCEL_TPM_CMD,
+ CMD_STORE_VOLATILE,
+ CMD_RESET_TPMESTABLISHED,
+ CMD_GET_STATEBLOB,
+ CMD_SET_STATEBLOB,
+ CMD_STOP,
+ CMD_GET_CONFIG,
+};
+
+#endif /* _TPM_IOCTL_H */
diff --git a/qapi-schema.json b/qapi-schema.json
index 764f731..17c2ae9 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -5114,10 +5114,12 @@
# An enumeration of TPM types
#
# @passthrough: TPM passthrough type
+# @emulator: Software Emulator TPM type
+# Since: 2.10
#
# Since: 1.5
##
-{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }
+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ] }
##
# @query-tpm-types:
@@ -5131,7 +5133,7 @@
# Example:
#
# -> { "execute": "query-tpm-types" }
-# <- { "return": [ "passthrough" ] }
+# <- { "return": [ "passthrough", "emulator" ] }
#
##
{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }
@@ -5161,6 +5163,36 @@
{ 'struct': 'TPMPassthroughOptions', 'base': 'TPMOptions',
'data': { '*path' : 'str', '*cancel-path' : 'str'} }
+##
+# @TPMEmulatorOptions:
+#
+# Information about the TPM emulator
+#
+# @tpmstatedir: TPM emulator state directory
+# @spawn: true if, qemu has to spawn a new emulator process with given @path,
+# otherwise it connects to already rinning emulator with given @data-path
+# and @ctrl-path sockets. (default: 'false')
+# @path: TPM emulator binary path to spawn.(default: 'swtpm')
+# @data-path: path of the unix socket to use for exchanging data messages, if
+# not provided socket pairs are used when @sapwn is true.
+# @ctrl-path: path of the unix socket file to use for exchagning out-of-band
+# control messages, if not provided socket pairs are used when
+# @spawn is true.
+# @logfile: file to use to place TPM emulator logs, if not provided logging is
+# disabled.
+# @loglevel: optional log level number, loglevel is ignored if no logfile
+# provided. (default: 5)
+#
+# Since: 2.10
+##
+{ 'struct': 'TPMEmulatorOptions', 'base': 'TPMOptions',
+ 'data': { 'tpmstatedir' : 'str',
+ 'spawn': 'bool',
+ '*path': 'str',
+ '*data-path': 'str',
+ '*ctrl-path': 'str',
+ '*logfile': 'str',
+ '*loglevel': 'int' } }
##
# @TPMInfo:
diff --git a/qemu-options.hx b/qemu-options.hx
index 99af8ed..aae0de0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2846,7 +2846,15 @@ DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
"-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n"
" use path to provide path to a character device; default is /dev/tpm0\n"
" use cancel-path to provide path to TPM's cancel sysfs entry; if\n"
- " not provided it will be searched for in /sys/class/misc/tpm?/device\n",
+ " not provided it will be searched for in /sys/class/misc/tpm?/device\n"
+ "-tpmdev emulator,id=id,spawn=on|off,tpmstatedir=dir[,path=emulator-path,data-path=path,ctrl-path=path,logfile=path,loglevel=level]\n"
+ " spawn=on|off controls spawning support\n"
+ " use tpmstatedir to provide path to the tpm state dirctory\n"
+ " use path to provide the emulator binary to launch; default is 'swtpm'\n"
+ " use data-path to provide the socket path for exchanging data messages\n"
+ " use ctrl-path to provide the socket path for sending control messages to software emulator\n"
+ " use logfile to provide where to place the swtpm logs\n"
+ " use loglevel to controls the swtpm log level\n",
QEMU_ARCH_ALL)
STEXI
@@ -2855,8 +2863,8 @@ The general form of a TPM device option is:
@item -tpmdev @var{backend} ,id=@var{id} [,@var{options}]
@findex -tpmdev
-Backend type must be:
-@option{passthrough}.
+Backend type must be either one of the following:
+@option{passthrough}, @option{emulator}.
The specific backend type will determine the applicable options.
The @code{-tpmdev} option creates the TPM backend and requires a
@@ -2906,6 +2914,45 @@ To create a passthrough TPM use the following two options:
Note that the @code{-tpmdev} id is @code{tpm0} and is referenced by
@code{tpmdev=tpm0} in the device option.
+@item -tpmdev emulator, id=@var{id}, tpmstatedir=@var{path}, spawn=@var{on|off}, path=@var{emulator-binary-path}, data-path=@var{path}, ctrl-path=@var{path}, logfile=@var{path}, loglevel=@var{level}
+
+(Linux-host only) Enable access to a TPM emulator using unix domain sockets.
+
+@option{tpmstatedir} specifies the tpm state directory
+
+@option{spawn} specifies if qemu should spawn new emulator process with given @option{path}
+
+@option{path} specifies the emulator binary path to use for spawning
+
+@option{data-path} optional socket path to use for exchanging TPM data with emulator
+
+@option{ctrl-path} optional socket path to use for sending control data to emulator
+
+@option{logfile} optional log file to use to place log messages
+
+@option{loglevel} specifies the log level to use
+
+To create TPM emulator backend device that spawns new swtpm binary and communicate with socket pairs:
+@example
+
+-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=on,path=/usr/local/bin/swtpm,logfile=/tmp/qemu-tpm.log,loglevel=5 -device tpm-tis,tpmdev=tpm0
+
+@end example
+
+To create TPM emulator backend device that spawns new swtpm binary and communicate using unix file system sockets:
+@example
+
+-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=on,path=/usr/local/bin/swtpm,data-path=/tmp/swtpm-data.socket,ctrl-path=/tmp/swtpm-ctrl.socket,logfile=/tmp/qemu-tpm.log,loglevel=5 -device tpm-tis,tpmdev=tpm0
+
+@end example
+
+To create a TOM emulator backend device that connects to already running swtpm binary using file system sockets:
+@example
+
+-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=off,data-path=/tmp/swtpm-data.socket,ctrl-path=/tmp/swtpm-ctrl.socket,logfile=/tmp/qemu-tpm.log,loglevel=5 -device tpm-tis,tpmdev=tpm0
+
+@end example
+
@end table
ETEXI
diff --git a/tpm.c b/tpm.c
index 43d980e..ce07c40 100644
--- a/tpm.c
+++ b/tpm.c
@@ -25,7 +25,7 @@ static QLIST_HEAD(, TPMBackend) tpm_backends =
#define TPM_MAX_MODELS 1
-#define TPM_MAX_DRIVERS 1
+#define TPM_MAX_DRIVERS 2
static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
NULL,
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 1/8] tpm-backend: Remove unneeded member variable from backend class
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
@ 2017-05-02 11:59 ` Marc-André Lureau
0 siblings, 0 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 11:59 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
On Tue, May 2, 2017 at 3:52 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> TPMDriverOps inside TPMBackend is not required, as it is supposed to be a
> class
> member. The only possible reason for keeping in TPMBackend was, to get the
> backend type in tpm.c where dedicated backend api, tpm_backend_get_type()
> is
> present.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
>
> ---
> hw/tpm/tpm_passthrough.c | 4 ----
> include/sysemu/tpm_backend.h | 1 -
> tpm.c | 2 +-
> 3 files changed, 1 insertion(+), 6 deletions(-)
>
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index 9234eb3..a0baf5f 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -46,8 +46,6 @@
> #define TPM_PASSTHROUGH(obj) \
> OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
>
> -static const TPMDriverOps tpm_passthrough_driver;
> -
> /* data structures */
> typedef struct TPMPassthruThreadParams {
> TPMState *tpm_state;
> @@ -462,8 +460,6 @@ static TPMBackend *tpm_passthrough_create(QemuOpts
> *opts, const char *id)
> /* let frontend set the fe_model to proper value */
> tb->fe_model = -1;
>
> - tb->ops = &tpm_passthrough_driver;
> -
> if (tpm_passthrough_handle_device_opts(opts, tb)) {
> goto err_exit;
> }
> diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
> index b58f52d..e7f590d 100644
> --- a/include/sysemu/tpm_backend.h
> +++ b/include/sysemu/tpm_backend.h
> @@ -50,7 +50,6 @@ struct TPMBackend {
> enum TpmModel fe_model;
> char *path;
> char *cancel_path;
> - const TPMDriverOps *ops;
>
> QLIST_ENTRY(TPMBackend) list;
> };
> diff --git a/tpm.c b/tpm.c
> index 9a7c711..0ee021a 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -258,7 +258,7 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
> res->model = drv->fe_model;
> res->options = g_new0(TpmTypeOptions, 1);
>
> - switch (drv->ops->type) {
> + switch (tpm_backend_get_type(drv)) {
> case TPM_TYPE_PASSTHROUGH:
> res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
> tpo = g_new0(TPMPassthroughOptions, 1);
> --
> 2.7.4
>
> --
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 2/8] tpm-backend: Move thread handling inside TPMBackend
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 2/8] tpm-backend: Move thread handling inside TPMBackend Amarnath Valluri
@ 2017-05-02 12:10 ` Marc-André Lureau
0 siblings, 0 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 12:10 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
Hi
On Tue, May 2, 2017 at 3:52 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> Move thread handling inside TPMBackend, this way backend implementations
> need
> not to maintain their own thread life cycle, instead they needs to
> implement
> 'handle_request()' class method that always been called from a thread.
>
> This change made tpm_backend_int.h kind of useless, hence removed it.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> ---
> backends/tpm.c | 62
> +++++++++++++++++++++++++---------------
> hw/tpm/tpm_passthrough.c | 58
> ++++++-------------------------------
> include/sysemu/tpm_backend.h | 32 +++++++++++++--------
> include/sysemu/tpm_backend_int.h | 41 --------------------------
> 4 files changed, 67 insertions(+), 126 deletions(-)
> delete mode 100644 include/sysemu/tpm_backend_int.h
>
> diff --git a/backends/tpm.c b/backends/tpm.c
> index 536f262..ce56c3b 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -18,7 +18,24 @@
> #include "qapi/qmp/qerror.h"
> #include "sysemu/tpm.h"
> #include "qemu/thread.h"
> -#include "sysemu/tpm_backend_int.h"
> +
> +static void tpm_backend_worker_thread(gpointer data, gpointer user_data)
> +{
> + TPMBackend *s = TPM_BACKEND(user_data);
> + TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
> +
> + assert(k->handle_request != NULL);
> + k->handle_request(s, (TPMBackendCmd)data);
> +}
> +
> +static void tpm_backend_thread_end(TPMBackend *s)
> +{
> + if (s->thread_pool) {
> + g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_END,
> NULL);
> + g_thread_pool_free(s->thread_pool, FALSE, TRUE);
> + s->thread_pool = NULL;
> + }
> +}
>
> enum TpmType tpm_backend_get_type(TPMBackend *s)
> {
> @@ -39,6 +56,8 @@ void tpm_backend_destroy(TPMBackend *s)
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> k->ops->destroy(s);
> +
> + tpm_backend_thread_end(s);
> }
>
> int tpm_backend_init(TPMBackend *s, TPMState *state,
> @@ -46,13 +65,23 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> - return k->ops->init(s, state, datacb);
> + s->tpm_state = state;
> + s->recv_data_callback = datacb;
> +
> + return k->ops->init(s);
> }
>
> int tpm_backend_startup_tpm(TPMBackend *s)
> {
> 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);
> + g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT,
> NULL);
> +
> return k->ops->startup_tpm(s);
> }
>
> @@ -72,9 +101,8 @@ size_t tpm_backend_realloc_buffer(TPMBackend *s,
> TPMSizedBuffer *sb)
>
> void tpm_backend_deliver_request(TPMBackend *s)
> {
> - TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
> -
> - k->ops->deliver_request(s);
> + g_thread_pool_push(s->thread_pool,
> (gpointer)TPM_BACKEND_CMD_PROCESS_CMD,
> + NULL);
> }
>
> void tpm_backend_reset(TPMBackend *s)
> @@ -82,6 +110,8 @@ void tpm_backend_reset(TPMBackend *s)
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> k->ops->reset(s);
> +
> + tpm_backend_thread_end(s);
> }
>
> void tpm_backend_cancel_cmd(TPMBackend *s)
> @@ -156,29 +186,14 @@ static void tpm_backend_instance_init(Object *obj)
> tpm_backend_prop_get_opened,
> tpm_backend_prop_set_opened,
> NULL);
> -}
>
> -void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
> -{
> - g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD,
> NULL);
> }
>
> -void tpm_backend_thread_create(TPMBackendThread *tbt,
> - GFunc func, gpointer user_data)
> +static void tpm_backend_instance_finalize(Object *obj)
> {
> - if (!tbt->pool) {
> - tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
> - g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT,
> NULL);
> - }
> -}
> + TPMBackend *s = TPM_BACKEND(obj);
>
> -void tpm_backend_thread_end(TPMBackendThread *tbt)
> -{
> - if (tbt->pool) {
> - g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END,
> NULL);
> - g_thread_pool_free(tbt->pool, FALSE, TRUE);
> - tbt->pool = NULL;
> - }
> + tpm_backend_thread_end(s);
> }
>
> static const TypeInfo tpm_backend_info = {
> @@ -186,6 +201,7 @@ static const TypeInfo tpm_backend_info = {
> .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,
> };
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index a0baf5f..f50d9cf 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -30,7 +30,6 @@
> #include "tpm_int.h"
> #include "hw/hw.h"
> #include "hw/i386/pc.h"
> -#include "sysemu/tpm_backend_int.h"
> #include "tpm_tis.h"
> #include "tpm_util.h"
>
> @@ -47,20 +46,9 @@
> OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
>
> /* data structures */
> -typedef struct TPMPassthruThreadParams {
> - TPMState *tpm_state;
> -
> - TPMRecvDataCB *recv_data_callback;
> - TPMBackend *tb;
> -} TPMPassthruThreadParams;
> -
> struct TPMPassthruState {
> TPMBackend parent;
>
> - TPMBackendThread tbt;
> -
> - TPMPassthruThreadParams tpm_thread_params;
> -
> char *tpm_dev;
> int tpm_fd;
> bool tpm_executing;
> @@ -214,12 +202,9 @@ static int
> tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt,
> selftest_done);
> }
>
> -static void tpm_passthrough_worker_thread(gpointer data,
> - gpointer user_data)
> +static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd
> cmd)
> {
> - TPMPassthruThreadParams *thr_parms = user_data;
> - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
> - TPMBackendCmd cmd = (TPMBackendCmd)data;
> + TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> bool selftest_done = false;
>
> DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
> @@ -227,12 +212,12 @@ static void tpm_passthrough_worker_thread(gpointer
> data,
> switch (cmd) {
> case TPM_BACKEND_CMD_PROCESS_CMD:
> tpm_passthrough_unix_transfer(tpm_pt,
> - thr_parms->tpm_state->locty_data,
> + tb->tpm_state->locty_data,
> &selftest_done);
>
> - thr_parms->recv_data_callback(thr_parms->tpm_state,
> - thr_parms->tpm_state->locty_number,
> - selftest_done);
> + tb->recv_data_callback(tb->tpm_state,
> + tb->tpm_state->locty_number,
> + selftest_done);
> break;
> case TPM_BACKEND_CMD_INIT:
> case TPM_BACKEND_CMD_END:
> @@ -248,15 +233,6 @@ static void tpm_passthrough_worker_thread(gpointer
> data,
> */
> static int tpm_passthrough_startup_tpm(TPMBackend *tb)
> {
> - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> -
> - /* terminate a running TPM */
> - tpm_backend_thread_end(&tpm_pt->tbt);
> -
> - tpm_backend_thread_create(&tpm_pt->tbt,
> - tpm_passthrough_worker_thread,
> - &tpm_pt->tpm_thread_params);
> -
> return 0;
> }
>
> @@ -268,20 +244,11 @@ static void tpm_passthrough_reset(TPMBackend *tb)
>
> tpm_passthrough_cancel_cmd(tb);
>
> - tpm_backend_thread_end(&tpm_pt->tbt);
> -
> tpm_pt->had_startup_error = false;
> }
>
> -static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
> - TPMRecvDataCB *recv_data_cb)
> +static int tpm_passthrough_init(TPMBackend *tb)
> {
> - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> -
> - tpm_pt->tpm_thread_params.tpm_state = s;
> - tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
> - tpm_pt->tpm_thread_params.tb = tb;
> -
> return 0;
> }
>
I think you could get rid of the function & callback in this patch (no need
to wait for later patch)
>
> @@ -315,13 +282,6 @@ static size_t
> tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
> return sb->size;
> }
>
> -static void tpm_passthrough_deliver_request(TPMBackend *tb)
> -{
> - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> -
> - tpm_backend_thread_deliver_request(&tpm_pt->tbt);
> -}
> -
> static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
> {
> TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> @@ -483,8 +443,6 @@ static void tpm_passthrough_destroy(TPMBackend *tb)
>
> tpm_passthrough_cancel_cmd(tb);
>
> - tpm_backend_thread_end(&tpm_pt->tbt);
> -
> qemu_close(tpm_pt->tpm_fd);
> qemu_close(tpm_pt->cancel_fd);
>
> @@ -520,7 +478,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
> .realloc_buffer = tpm_passthrough_realloc_buffer,
> .reset = tpm_passthrough_reset,
> .had_startup_error = tpm_passthrough_get_startup_error,
> - .deliver_request = tpm_passthrough_deliver_request,
> .cancel_cmd = tpm_passthrough_cancel_cmd,
> .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
> .reset_tpm_established_flag =
> tpm_passthrough_reset_tpm_established_flag,
> @@ -540,6 +497,7 @@ static void tpm_passthrough_class_init(ObjectClass
> *klass, void *data)
> TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
>
> tbc->ops = &tpm_passthrough_driver;
> + tbc->handle_request = tpm_passthrough_handle_request;
> }
>
> static const TypeInfo tpm_passthrough_info = {
> diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
> index e7f590d..a538a7f 100644
> --- a/include/sysemu/tpm_backend.h
> +++ b/include/sysemu/tpm_backend.h
> @@ -29,22 +29,24 @@
>
> typedef struct TPMBackendClass TPMBackendClass;
> typedef struct TPMBackend TPMBackend;
> -
> typedef struct TPMDriverOps TPMDriverOps;
> +typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool
> selftest_done);
>
> -struct TPMBackendClass {
> - ObjectClass parent_class;
> -
> - const TPMDriverOps *ops;
> -
> - void (*opened)(TPMBackend *s, Error **errp);
> -};
> +typedef enum TPMBackendCmd {
> + TPM_BACKEND_CMD_INIT = 1,
> + TPM_BACKEND_CMD_PROCESS_CMD,
> + TPM_BACKEND_CMD_END,
> + TPM_BACKEND_CMD_TPM_RESET,
> +} TPMBackendCmd;
>
> struct TPMBackend {
> Object parent;
>
> /*< protected >*/
> bool opened;
> + TPMState *tpm_state;
> + GThreadPool *thread_pool;
> + TPMRecvDataCB *recv_data_callback;
>
> char *id;
> enum TpmModel fe_model;
> @@ -54,7 +56,15 @@ struct TPMBackend {
> QLIST_ENTRY(TPMBackend) list;
> };
>
> -typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool
> selftest_done);
> +struct TPMBackendClass {
> + ObjectClass parent_class;
> +
> + const TPMDriverOps *ops;
> +
> + void (*opened)(TPMBackend *s, Error **errp);
> +
> + void (*handle_request)(TPMBackend *s, TPMBackendCmd cmd);
> +};
>
> typedef struct TPMSizedBuffer {
> uint32_t size;
> @@ -71,7 +81,7 @@ struct TPMDriverOps {
> void (*destroy)(TPMBackend *t);
>
> /* initialize the backend */
> - int (*init)(TPMBackend *t, TPMState *s, TPMRecvDataCB *datacb);
> + int (*init)(TPMBackend *t);
> /* start up the TPM on the backend */
> int (*startup_tpm)(TPMBackend *t);
> /* returns true if nothing will ever answer TPM requests */
> @@ -79,8 +89,6 @@ struct TPMDriverOps {
>
> size_t (*realloc_buffer)(TPMSizedBuffer *sb);
>
> - void (*deliver_request)(TPMBackend *t);
> -
> void (*reset)(TPMBackend *t);
>
> void (*cancel_cmd)(TPMBackend *t);
> diff --git a/include/sysemu/tpm_backend_int.h
> b/include/sysemu/tpm_backend_int.h
> deleted file mode 100644
> index 00639dd..0000000
> --- a/include/sysemu/tpm_backend_int.h
> +++ /dev/null
> @@ -1,41 +0,0 @@
> -/*
> - * common TPM backend driver functions
> - *
> - * Copyright (c) 2012-2013 IBM Corporation
> - * Authors:
> - * Stefan Berger <stefanb@us.ibm.com>
> - *
> - * This library is free software; you can redistribute it and/or
> - * modify it under the terms of the GNU Lesser General Public
> - * License as published by the Free Software Foundation; either
> - * version 2 of the License, or (at your option) any later version.
> - *
> - * This library is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> - * Lesser General Public License for more details.
> - *
> - * You should have received a copy of the GNU Lesser General Public
> - * License along with this library; if not, see <
> http://www.gnu.org/licenses/>
> - */
> -
> -#ifndef TPM_BACKEND_INT_H
> -#define TPM_BACKEND_INT_H
> -
> -typedef struct TPMBackendThread {
> - GThreadPool *pool;
> -} TPMBackendThread;
> -
> -void tpm_backend_thread_deliver_request(TPMBackendThread *tbt);
> -void tpm_backend_thread_create(TPMBackendThread *tbt,
> - GFunc func, gpointer user_data);
> -void tpm_backend_thread_end(TPMBackendThread *tbt);
> -
> -typedef enum TPMBackendCmd {
> - TPM_BACKEND_CMD_INIT = 1,
> - TPM_BACKEND_CMD_PROCESS_CMD,
> - TPM_BACKEND_CMD_END,
> - TPM_BACKEND_CMD_TPM_RESET,
> -} TPMBackendCmd;
> -
> -#endif /* TPM_BACKEND_INT_H */
> --
> 2.7.4
>
anyway,
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 3/8] tpm-backend: Initialize and free data members in it's own methods
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 3/8] tpm-backend: Initialize and free data members in it's own methods Amarnath Valluri
@ 2017-05-02 12:17 ` Marc-André Lureau
0 siblings, 0 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 12:17 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
Hi
On Tue, May 2, 2017 at 3:52 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> Initialize and free TPMBackend data members in it's own instance_init() and
> instance_finalize methods.
>
> Took the opportunity to remove unneeded destroy() method from TpmDriverOps
> interface as TPMBackend is a Qemu Object, we can use object_unref()
> inplace of
> tpm_backend_destroy() to free the backend object, hence removed destroy()
> from
> TPMDriverOps interface.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> ---
> backends/tpm.c | 16 ++++++----------
> hw/tpm/tpm_passthrough.c | 31 ++++++++++++-------------------
> include/sysemu/tpm_backend.h | 7 -------
> tpm.c | 2 +-
> 4 files changed, 19 insertions(+), 37 deletions(-)
>
> diff --git a/backends/tpm.c b/backends/tpm.c
> index ce56c3b..cf5abf1 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -51,15 +51,6 @@ const char *tpm_backend_get_desc(TPMBackend *s)
> return k->ops->desc();
> }
>
> -void tpm_backend_destroy(TPMBackend *s)
> -{
> - TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
> -
> - k->ops->destroy(s);
> -
> - tpm_backend_thread_end(s);
> -}
> -
> int tpm_backend_init(TPMBackend *s, TPMState *state,
> TPMRecvDataCB *datacb)
> {
> @@ -182,17 +173,22 @@ static void tpm_backend_prop_set_opened(Object *obj,
> bool value, Error **errp)
>
> static void tpm_backend_instance_init(Object *obj)
> {
> + TPMBackend *s = TPM_BACKEND(obj);
> +
> object_property_add_bool(obj, "opened",
> tpm_backend_prop_get_opened,
> tpm_backend_prop_set_opened,
> NULL);
> -
> + s->fe_model = -1;
> }
>
> static void tpm_backend_instance_finalize(Object *obj)
> {
> TPMBackend *s = TPM_BACKEND(obj);
>
> + g_free(s->id);
> + g_free(s->path);
> + g_free(s->cancel_path);
> tpm_backend_thread_end(s);
> }
>
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index f50d9cf..815a72e 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -417,8 +417,6 @@ static TPMBackend *tpm_passthrough_create(QemuOpts
> *opts, const char *id)
> TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
>
> tb->id = g_strdup(id);
> - /* let frontend set the fe_model to proper value */
> - tb->fe_model = -1;
>
> if (tpm_passthrough_handle_device_opts(opts, tb)) {
> goto err_exit;
> @@ -432,26 +430,11 @@ static TPMBackend *tpm_passthrough_create(QemuOpts
> *opts, const char *id)
> return tb;
>
> err_exit:
> - g_free(tb->id);
> + object_unref(obj);
>
> return NULL;
> }
>
> -static void tpm_passthrough_destroy(TPMBackend *tb)
> -{
> - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> -
> - tpm_passthrough_cancel_cmd(tb);
> -
> - qemu_close(tpm_pt->tpm_fd);
> - qemu_close(tpm_pt->cancel_fd);
> -
> - g_free(tb->id);
> - g_free(tb->path);
> - g_free(tb->cancel_path);
> - g_free(tpm_pt->tpm_dev);
> -}
> -
> static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
> TPM_STANDARD_CMDLINE_OPTS,
> {
> @@ -472,7 +455,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
> .opts = tpm_passthrough_cmdline_opts,
> .desc = tpm_passthrough_create_desc,
> .create = tpm_passthrough_create,
> - .destroy = tpm_passthrough_destroy,
> .init = tpm_passthrough_init,
> .startup_tpm = tpm_passthrough_startup_tpm,
> .realloc_buffer = tpm_passthrough_realloc_buffer,
> @@ -486,10 +468,21 @@ static const TPMDriverOps tpm_passthrough_driver = {
>
> static void tpm_passthrough_inst_init(Object *obj)
> {
> + TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
> +
> + tpm_pt->tpm_fd = -1;
> + tpm_pt->cancel_fd = -1;
> }
>
> static void tpm_passthrough_inst_finalize(Object *obj)
> {
> + TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
> +
> + tpm_passthrough_cancel_cmd(TPM_BACKEND(obj));
> +
> + qemu_close(tpm_pt->tpm_fd);
> + qemu_close(tpm_pt->cancel_fd);
>
Better if you should check if fd >= 0 while touching it. Alternatively, I
wonder if we could add that check to qemu_close().
> + g_free(tpm_pt->tpm_dev);
> }
>
> static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
> diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
> index a538a7f..f61bcfe 100644
> --- a/include/sysemu/tpm_backend.h
> +++ b/include/sysemu/tpm_backend.h
> @@ -78,7 +78,6 @@ struct TPMDriverOps {
> const char *(*desc)(void);
>
> TPMBackend *(*create)(QemuOpts *opts, const char *id);
> - void (*destroy)(TPMBackend *t);
>
> /* initialize the backend */
> int (*init)(TPMBackend *t);
> @@ -118,12 +117,6 @@ enum TpmType tpm_backend_get_type(TPMBackend *s);
> const char *tpm_backend_get_desc(TPMBackend *s);
>
> /**
> - * tpm_backend_destroy:
> - * @s: the backend to destroy
> - */
> -void tpm_backend_destroy(TPMBackend *s);
> -
> -/**
> * tpm_backend_init:
> * @s: the backend to initialized
> * @state: TPMState
> diff --git a/tpm.c b/tpm.c
> index 0ee021a..70f74fa 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -197,7 +197,7 @@ void tpm_cleanup(void)
>
> QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
> QLIST_REMOVE(drv, list);
> - tpm_backend_destroy(drv);
> + object_unref(OBJECT(drv));
> }
> }
>
>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (7 preceding siblings ...)
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator Amarnath Valluri
@ 2017-05-02 12:25 ` no-reply
2017-05-04 11:35 ` [Qemu-devel] [PATCH v4 8/8] tpm: Added support for " Amarnath Valluri
2017-05-04 12:28 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " Stefan Berger
9 siblings, 1 reply; 46+ messages in thread
From: no-reply @ 2017-05-02 12:25 UTC (permalink / raw)
To: amarnath.valluri
Cc: famz, qemu-devel, patrick.ohly, marcandre.lureau, stefanb
Hi,
This series failed automatic build test. Please find the testing commands and
their output below. If you have docker installed, you can probably reproduce it
locally.
Type: series
Subject: [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator
Message-id: 1493725969-19518-1-git-send-email-amarnath.valluri@intel.com
=== 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
make docker-test-quick@centos6
make docker-test-mingw@fedora
make docker-test-build@min-glib
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
* [new tag] patchew/1493725969-19518-1-git-send-email-amarnath.valluri@intel.com -> patchew/1493725969-19518-1-git-send-email-amarnath.valluri@intel.com
Auto packing the repository in background for optimum performance.
See "git help gc" for manual housekeeping.
Switched to a new branch 'test'
75f8838 tpm: Added support for TPM emulator
fb4ba72 tpm-passthrough: move reusable code to utils
4bcc454 tpm-backend: Move realloc_buffer() implementation to base class
1f15c35 tmp backend: Add new api to read backend TpmInfo
594e3a0 tpm-backend: Made few interface methods optional
8bbb6a8 tpm-backend: Initialize and free data members in it's own methods
8fca69c tpm-backend: Move thread handling inside TPMBackend
e1ba1d2 tpm-backend: Remove unneeded member variable from backend class
=== OUTPUT BEGIN ===
Submodule 'dtc' (git://git.qemu-project.org/dtc.git) registered for path 'dtc'
Cloning into '/var/tmp/patchew-tester-tmp-tytg9d57/src/dtc'...
Submodule path 'dtc': checked out '558cd81bdd432769b59bff01240c44f82cfb1a9d'
BUILD centos6
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-tytg9d57/src'
ARCHIVE qemu.tgz
ARCHIVE dtc.tgz
COPY RUNNER
RUN test-quick in qemu:centos6
Packages installed:
SDL-devel-1.2.14-7.el6_7.1.x86_64
ccache-3.1.6-2.el6.x86_64
epel-release-6-8.noarch
gcc-4.4.7-17.el6.x86_64
git-1.7.1-4.el6_7.1.x86_64
glib2-devel-2.28.8-5.el6.x86_64
libfdt-devel-1.4.0-1.el6.x86_64
make-3.81-23.el6.x86_64
package g++ is not installed
pixman-devel-0.32.8-1.el6.x86_64
tar-1.23-15.el6_8.x86_64
zlib-devel-1.2.3-29.el6.x86_64
Environment variables:
PACKAGES=libfdt-devel ccache tar git make gcc g++ zlib-devel glib2-devel SDL-devel pixman-devel epel-release
HOSTNAME=69967e021c82
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
LANG=en_US.UTF-8
TARGET_LIST=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES= dtc
DEBUG=
G_BROKEN_FILENAMES=1
CCACHE_HASHDIR=
_=/usr/bin/env
Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install
No C++ compiler available; disabling C++ specific optional code
Install prefix /var/tmp/qemu-build/install
BIOS directory /var/tmp/qemu-build/install/share/qemu
binary directory /var/tmp/qemu-build/install/bin
library directory /var/tmp/qemu-build/install/lib
module directory /var/tmp/qemu-build/install/lib/qemu
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory /var/tmp/qemu-build/install/etc
local state directory /var/tmp/qemu-build/install/var
Manual directory /var/tmp/qemu-build/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path /tmp/qemu-test/src
C compiler cc
Host C compiler cc
C++ compiler
Objective-C compiler cc
ARFLAGS rv
CFLAGS -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g
QEMU_CFLAGS -I/usr/include/pixman-1 -I$(SRC_PATH)/dtc/libfdt -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -fPIE -DPIE -m64 -mcx16 -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-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-all
LDFLAGS -Wl,--warn-common -Wl,-z,relro -Wl,-z,now -pie -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
tcg debug enabled no
gprof enabled no
sparse enabled no
strip binaries yes
profiler no
static build no
pixman system
SDL support yes (1.2.14)
GTK support no
GTK GL support no
VTE support no
TLS priority NORMAL
GNUTLS support no
GNUTLS rnd no
libgcrypt no
libgcrypt kdf no
nettle no
nettle kdf no
libtasn1 no
curses support no
virgl support no
curl support no
mingw32 support no
Audio drivers oss
Block whitelist (rw)
Block whitelist (ro)
VirtFS support no
VNC support yes
VNC SASL support no
VNC JPEG support no
VNC PNG support no
xen support no
brlapi support no
bluez support no
Documentation no
PIE yes
vde support no
netmap support no
Linux AIO support no
ATTR/XATTR support yes
Install blobs yes
KVM support yes
HAX support no
RDMA support no
TCG interpreter no
fdt support yes
preadv support yes
fdatasync yes
madvise yes
posix_madvise yes
libcap-ng support no
vhost-net support yes
vhost-scsi support yes
vhost-vsock support yes
Trace backends log
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 no
QGA MSI support no
seccomp support no
coroutine backend ucontext
coroutine pool yes
debug stack usage no
GlusterFS support no
gcov gcov
gcov enabled no
TPM support yes
libssh2 support no
TPM passthrough yes
TPM emulator yes
QOM debugging yes
lzo support no
snappy support no
bzip2 support no
NUMA host support no
tcmalloc support no
jemalloc support no
avx2 optimization no
replication support yes
VxHS block device no
GEN x86_64-softmmu/config-devices.mak.tmp
GEN aarch64-softmmu/config-devices.mak.tmp
mkdir -p dtc/libfdt
mkdir -p dtc/tests
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 trace/generated-helpers.c
GEN module_block.h
GEN tests/test-qapi-types.h
GEN tests/test-qapi-visit.h
GEN tests/test-qmp-commands.h
GEN tests/test-qapi-event.h
GEN tests/test-qmp-introspect.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 backends/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/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 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 trace-root.c
GEN util/trace.c
GEN crypto/trace.c
GEN io/trace.c
GEN migration/trace.c
GEN block/trace.c
GEN backends/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/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 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 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/dtbs_equal_unordered.c
DEP /tmp/qemu-test/src/dtc/tests/dtb_reverse.c
DEP /tmp/qemu-test/src/dtc/tests/add_subnode_with_nops.c
DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.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/move_and_save.c
DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
DEP /tmp/qemu-test/src/dtc/tests/stringlist.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/get_alias.c
DEP /tmp/qemu-test/src/dtc/tests/node_check_compatible.c
DEP /tmp/qemu-test/src/dtc/tests/node_offset_by_phandle.c
DEP /tmp/qemu-test/src/dtc/tests/supernode_atdepth_offset.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/get_path.c
DEP /tmp/qemu-test/src/dtc/tests/get_phandle.c
DEP /tmp/qemu-test/src/dtc/tests/getprop.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/find_property.c
DEP /tmp/qemu-test/src/dtc/tests/root_node.c
DEP /tmp/qemu-test/src/dtc/tests/subnode_offset.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_strerror.c
DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.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_ro.c
DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
DEP /tmp/qemu-test/src/dtc/util.c
DEP /tmp/qemu-test/src/dtc/fdtput.c
DEP /tmp/qemu-test/src/dtc/fdtget.c
DEP /tmp/qemu-test/src/dtc/fdtdump.c
LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
BISON dtc-parser.tab.c
DEP /tmp/qemu-test/src/dtc/srcpos.c
make[1]: bison: Command not found
LEX dtc-lexer.lex.c
make[1]: flex: Command not found
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/treesource.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
CHK version_gen.h
LEX convert-dtsv0-lexer.lex.c
make[1]: flex: Command not found
BISON dtc-parser.tab.c
make[1]: bison: Command not found
UPD version_gen.h
LEX dtc-lexer.lex.c
make[1]: flex: Command not found
DEP /tmp/qemu-test/src/dtc/util.c
LEX convert-dtsv0-lexer.lex.c
BISON dtc-parser.tab.c
make[1]: flex: Command not found
LEX dtc-lexer.lex.c
make[1]: bison: Command not found
make[1]: flex: Command not found
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_addresses.o
CC libfdt/fdt_empty_tree.o
CC libfdt/fdt_overlay.o
AR libfdt/libfdt.a
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
LEX convert-dtsv0-lexer.lex.c
BISON dtc-parser.tab.c
make[1]: flex: Command not found
LEX dtc-lexer.lex.c
make[1]: bison: Command not found
make[1]: flex: Command not found
CC tests/qemu-iotests/socket_scm_helper.o
GEN qga/qapi-generated/qga-qapi-types.c
GEN qga/qapi-generated/qga-qapi-visit.h
GEN qga/qapi-generated/qga-qapi-types.h
GEN qga/qapi-generated/qga-qapi-visit.c
GEN qga/qapi-generated/qga-qmp-commands.h
CC qmp-introspect.o
GEN qga/qapi-generated/qga-qmp-marshal.c
CC qapi-visit.o
CC qapi-types.o
CC qapi-event.o
CC qapi/qapi-visit-core.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/qint.o
CC qobject/qstring.o
CC qobject/qdict.o
CC qobject/qlist.o
CC qobject/qfloat.o
CC qobject/qbool.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/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-posix.o
CC util/compatfd.o
CC util/event_notifier-posix.o
CC util/mmap-alloc.o
CC util/oslib-posix.o
CC util/qemu-openpty.o
CC util/qemu-thread-posix.o
CC util/memfd.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/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-ucontext.o
CC util/timed-average.o
CC util/buffer.o
CC util/log.o
CC util/base64.o
CC util/qdist.o
CC util/qht.o
CC util/range.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 backends/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/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 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 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/notify-event.o
CC stubs/replay.o
CC stubs/qtest.o
CC stubs/monitor.o
CC stubs/runstate-check.o
CC stubs/set-fd-handler.o
CC stubs/slirp.o
CC stubs/sysbus.o
CC stubs/trace-control.o
CC stubs/uuid.o
CC stubs/vm-stop.o
CC stubs/vmstate.o
CC stubs/qmp_pc_dimm_device_list.o
CC stubs/target-get-monitor-def.o
CC stubs/target-monitor-defs.o
CC stubs/pc_madt_cpu_entry.o
CC stubs/vmgenid.o
CC stubs/xen-common.o
CC stubs/xen-hvm.o
CC contrib/ivshmem-client/ivshmem-client.o
CC contrib/ivshmem-client/main.o
CC contrib/ivshmem-server/ivshmem-server.o
CC contrib/ivshmem-server/main.o
CC qemu-nbd.o
CC block.o
CC blockjob.o
CC qemu-io-cmds.o
CC replication.o
CC block/raw-format.o
CC block/vdi.o
CC block/qcow.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/qed.o
CC block/qed-gencb.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/vhdx-log.o
CC block/quorum.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-posix.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/crypto.o
CC nbd/server.o
CC nbd/client.o
CC nbd/common.o
CC crypto/init.o
CC crypto/hash.o
CC crypto/hash-glib.o
CC crypto/hmac.o
CC crypto/hmac-glib.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-platform.o
CC crypto/pbkdf.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/task.o
CC qom/object.o
CC qom/container.o
CC qom/qom-qobject.o
CC qom/object_interfaces.o
GEN qemu-img-cmds.h
CC qemu-io.o
CC qemu-bridge-helper.o
CC blockdev.o
CC blockdev-nbd.o
CC iothread.o
CC qdev-monitor.o
CC device-hotplug.o
CC os-posix.o
CC page_cache.o
CC accel.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/ossaudio.o
CC audio/wavcapture.o
CC backends/rng.o
CC backends/rng-egd.o
CC backends/rng-random.o
CC backends/msmouse.o
CC backends/wctablet.o
CC backends/testdev.o
CC backends/tpm.o
CC backends/hostmem.o
CC backends/hostmem-ram.o
CC backends/cryptodev.o
CC backends/hostmem-file.o
CC backends/cryptodev-builtin.o
CC block/stream.o
CC disas/arm.o
CC disas/i386.o
CC fsdev/qemu-fsdev-dummy.o
CC fsdev/qemu-fsdev-opts.o
CC fsdev/qemu-fsdev-throttle.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/block/block.o
CC hw/block/cdrom.o
CC hw/block/hd-geometry.o
CC hw/block/fdc.o
CC hw/block/nand.o
CC hw/block/m25p80.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/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/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/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/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/ahci.o
CC hw/ide/ich.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/vmmouse.o
CC hw/input/virtio-input.o
CC hw/input/virtio-input-hid.o
CC hw/input/virtio-input-host.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/debugexit.o
CC hw/misc/sga.o
CC hw/misc/pc-testdev.o
CC hw/misc/pci-testdev.o
CC hw/misc/unimp.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/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/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/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/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/tpm/tpm_tis.o
CC hw/tpm/tpm_passthrough.o
CC hw/tpm/tpm_util.o
CC hw/tpm/tpm_emulator.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
CC hw/usb/hcd-uhci.o
CC hw/usb/hcd-ohci.o
CC hw/usb/hcd-ehci.o
CC hw/usb/hcd-ehci-pci.o
CC hw/usb/hcd-ehci-sysbus.o
CC hw/usb/hcd-xhci.o
CC hw/usb/hcd-musb.o
CC hw/usb/dev-hub.o
CC hw/usb/dev-hid.o
CC hw/usb/dev-wacom.o
CC hw/usb/dev-storage.o
CC hw/usb/dev-uas.o
CC hw/usb/dev-audio.o
CC hw/usb/dev-serial.o
CC hw/usb/dev-network.o
CC hw/usb/dev-bluetooth.o
CC hw/usb/dev-smartcard-reader.o
CC hw/usb/dev-mtp.o
CC hw/usb/host-stub.o
CC hw/virtio/virtio-rng.o
CC hw/virtio/virtio-pci.o
CC hw/virtio/virtio-bus.o
CC hw/virtio/virtio-mmio.o
CC hw/virtio/vhost-stub.o
CC hw/watchdog/watchdog.o
CC hw/watchdog/wdt_i6300esb.o
CC hw/watchdog/wdt_ib700.o
CC hw/watchdog/wdt_aspeed.o
CC migration/migration.o
CC migration/socket.o
CC migration/fd.o
CC migration/exec.o
CC migration/tls.o
CC migration/colo-comm.o
CC migration/colo.o
CC migration/colo-failover.o
CC migration/vmstate.o
CC migration/qemu-file.o
CC migration/qemu-file-channel.o
CC migration/xbzrle.o
CC migration/postcopy-ram.o
CC migration/qjson.o
CC migration/block.o
CC net/net.o
CC net/queue.o
CC net/checksum.o
CC net/util.o
CC net/hub.o
CC net/socket.o
CC net/dump.o
CC net/eth.o
CC net/l2tpv3.o
CC net/tap.o
CC net/vhost-user.o
CC net/tap-linux.o
CC net/slirp.o
CC net/filter.o
CC net/filter-buffer.o
CC net/filter-mirror.o
CC net/colo-compare.o
CC net/colo.o
CC net/filter-rewriter.o
CC net/filter-replay.o
CC qom/cpu.o
CC replay/replay-internal.o
CC replay/replay.o
CC replay/replay-events.o
CC replay/replay-time.o
CC replay/replay-input.o
CC replay/replay-char.o
CC replay/replay-snapshot.o
CC replay/replay-net.o
/tmp/qemu-test/src/replay/replay-internal.c: In function ‘replay_put_array’:
/tmp/qemu-test/src/replay/replay-internal.c:65: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
CC replay/replay-audio.o
CC slirp/cksum.o
CC slirp/if.o
CC slirp/ip_icmp.o
CC slirp/ip6_icmp.o
CC slirp/ip6_input.o
CC slirp/ip6_output.o
CC slirp/ip_input.o
CC slirp/ip_output.o
CC slirp/dnssearch.o
CC slirp/dhcpv6.o
CC slirp/slirp.o
CC slirp/mbuf.o
CC slirp/misc.o
CC slirp/sbuf.o
CC slirp/socket.o
CC slirp/tcp_input.o
CC slirp/tcp_output.o
CC slirp/tcp_subr.o
CC slirp/tcp_timer.o
CC slirp/udp.o
CC slirp/udp6.o
CC slirp/bootp.o
CC slirp/tftp.o
CC slirp/arp_table.o
/tmp/qemu-test/src/slirp/tcp_input.c: In function ‘tcp_input’:
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_p’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_len’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_tos’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_id’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_off’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_ttl’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_sum’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_src.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:219: warning: ‘save_ip.ip_dst.s_addr’ may be used uninitialized in this function
/tmp/qemu-test/src/slirp/tcp_input.c:220: warning: ‘save_ip6.ip_nh’ may be used uninitialized in this function
CC slirp/ndp_table.o
CC slirp/ncsi.o
CC ui/keymaps.o
CC ui/console.o
CC ui/cursor.o
CC ui/qemu-pixman.o
CC ui/input.o
CC ui/input-keymap.o
CC ui/input-legacy.o
CC ui/input-linux.o
CC ui/sdl.o
CC ui/sdl_zoom.o
CC ui/x_keymap.o
CC ui/vnc.o
CC ui/vnc-enc-zlib.o
CC ui/vnc-enc-hextile.o
CC ui/vnc-enc-tight.o
CC ui/vnc-palette.o
CC ui/vnc-enc-zrle.o
CC ui/vnc-auth-vencrypt.o
CC ui/vnc-ws.o
CC ui/vnc-jobs.o
CC chardev/char.o
CC chardev/char-fd.o
CC chardev/char-file.o
CC chardev/char-io.o
CC chardev/char-mux.o
CC chardev/char-null.o
CC chardev/char-parallel.o
CC chardev/char-pipe.o
CC chardev/char-pty.o
CC chardev/char-serial.o
CC chardev/char-ringbuf.o
CC chardev/char-socket.o
CC chardev/char-stdio.o
CC chardev/char-udp.o
LINK tests/qemu-iotests/socket_scm_helper
CC qga/commands.o
AS optionrom/multiboot.o
AS optionrom/linuxboot.o
CC optionrom/linuxboot_dma.o
cc: unrecognized option '-no-integrated-as'
cc: unrecognized option '-no-integrated-as'
AS optionrom/kvmvapic.o
BUILD optionrom/multiboot.img
BUILD optionrom/linuxboot.img
BUILD optionrom/linuxboot_dma.img
BUILD optionrom/kvmvapic.img
CC qga/guest-agent-command-state.o
BUILD optionrom/multiboot.raw
BUILD optionrom/linuxboot.raw
CC qga/main.o
CC qga/commands-posix.o
CC qga/channel-posix.o
CC qga/qapi-generated/qga-qapi-types.o
CC qga/qapi-generated/qga-qapi-visit.o
CC qga/qapi-generated/qga-qmp-marshal.o
AR libqemuutil.a
AR libqemustub.a
CC qemu-img.o
BUILD optionrom/kvmvapic.raw
BUILD optionrom/linuxboot_dma.raw
SIGN optionrom/multiboot.bin
SIGN optionrom/linuxboot.bin
SIGN optionrom/linuxboot_dma.bin
SIGN optionrom/kvmvapic.bin
LINK qemu-io
LINK qemu-bridge-helper
LINK ivshmem-client
LINK ivshmem-server
LINK qemu-nbd
LINK qemu-img
GEN aarch64-softmmu/hmp-commands.h
GEN aarch64-softmmu/hmp-commands-info.h
GEN aarch64-softmmu/config-target.h
CC aarch64-softmmu/exec.o
CC aarch64-softmmu/translate-all.o
CC aarch64-softmmu/translate-common.o
CC aarch64-softmmu/cpu-exec-common.o
CC aarch64-softmmu/cpu-exec.o
GEN x86_64-softmmu/hmp-commands.h
GEN x86_64-softmmu/hmp-commands-info.h
CC aarch64-softmmu/tcg/tcg.o
GEN x86_64-softmmu/config-target.h
CC aarch64-softmmu/tcg/tcg-op.o
CC x86_64-softmmu/exec.o
CC x86_64-softmmu/translate-all.o
CC x86_64-softmmu/cpu-exec.o
CC x86_64-softmmu/translate-common.o
CC x86_64-softmmu/cpu-exec-common.o
CC x86_64-softmmu/tcg/tcg.o
CC x86_64-softmmu/tcg/tcg-op.o
CC x86_64-softmmu/tcg/optimize.o
CC aarch64-softmmu/tcg/optimize.o
CC aarch64-softmmu/tcg/tcg-common.o
CC x86_64-softmmu/tcg/tcg-common.o
CC x86_64-softmmu/fpu/softfloat.o
CC x86_64-softmmu/disas.o
CC aarch64-softmmu/fpu/softfloat.o
CC aarch64-softmmu/disas.o
CC aarch64-softmmu/tcg-runtime.o
CC x86_64-softmmu/tcg-runtime.o
GEN aarch64-softmmu/gdbstub-xml.c
CC x86_64-softmmu/hax-stub.o
CC aarch64-softmmu/hax-stub.o
CC aarch64-softmmu/kvm-stub.o
CC x86_64-softmmu/arch_init.o
CC aarch64-softmmu/arch_init.o
CC x86_64-softmmu/cpus.o
CC aarch64-softmmu/cpus.o
CC x86_64-softmmu/monitor.o
CC aarch64-softmmu/monitor.o
CC x86_64-softmmu/gdbstub.o
CC x86_64-softmmu/balloon.o
CC x86_64-softmmu/ioport.o
CC x86_64-softmmu/numa.o
LINK qemu-ga
CC aarch64-softmmu/gdbstub.o
CC x86_64-softmmu/qtest.o
CC x86_64-softmmu/bootdevice.o
CC aarch64-softmmu/balloon.o
CC aarch64-softmmu/ioport.o
CC x86_64-softmmu/kvm-all.o
CC x86_64-softmmu/memory.o
CC x86_64-softmmu/cputlb.o
CC x86_64-softmmu/memory_mapping.o
CC x86_64-softmmu/dump.o
CC aarch64-softmmu/numa.o
CC aarch64-softmmu/qtest.o
CC x86_64-softmmu/migration/ram.o
CC aarch64-softmmu/bootdevice.o
CC aarch64-softmmu/memory.o
CC aarch64-softmmu/cputlb.o
CC x86_64-softmmu/migration/savevm.o
CC x86_64-softmmu/hw/block/virtio-blk.o
CC x86_64-softmmu/hw/block/dataplane/virtio-blk.o
CC x86_64-softmmu/hw/char/virtio-serial-bus.o
CC aarch64-softmmu/memory_mapping.o
CC x86_64-softmmu/hw/core/nmi.o
CC aarch64-softmmu/dump.o
CC x86_64-softmmu/hw/core/generic-loader.o
CC x86_64-softmmu/hw/core/null-machine.o
CC aarch64-softmmu/migration/ram.o
CC aarch64-softmmu/migration/savevm.o
CC x86_64-softmmu/hw/cpu/core.o
CC x86_64-softmmu/hw/display/vga.o
CC x86_64-softmmu/hw/display/virtio-gpu.o
CC aarch64-softmmu/hw/adc/stm32f2xx_adc.o
CC aarch64-softmmu/hw/block/virtio-blk.o
CC x86_64-softmmu/hw/display/virtio-gpu-3d.o
CC x86_64-softmmu/hw/display/virtio-gpu-pci.o
CC aarch64-softmmu/hw/block/dataplane/virtio-blk.o
CC aarch64-softmmu/hw/char/exynos4210_uart.o
CC x86_64-softmmu/hw/display/virtio-vga.o
CC aarch64-softmmu/hw/char/omap_uart.o
CC x86_64-softmmu/hw/intc/apic.o
CC aarch64-softmmu/hw/char/digic-uart.o
CC x86_64-softmmu/hw/intc/apic_common.o
CC x86_64-softmmu/hw/intc/ioapic.o
CC aarch64-softmmu/hw/char/stm32f2xx_usart.o
CC aarch64-softmmu/hw/char/bcm2835_aux.o
CC aarch64-softmmu/hw/char/virtio-serial-bus.o
CC aarch64-softmmu/hw/core/nmi.o
CC x86_64-softmmu/hw/isa/lpc_ich9.o
CC x86_64-softmmu/hw/misc/vmport.o
CC x86_64-softmmu/hw/misc/ivshmem.o
CC aarch64-softmmu/hw/core/generic-loader.o
CC aarch64-softmmu/hw/core/null-machine.o
CC aarch64-softmmu/hw/cpu/arm11mpcore.o
CC x86_64-softmmu/hw/misc/pvpanic.o
CC aarch64-softmmu/hw/cpu/realview_mpcore.o
CC aarch64-softmmu/hw/cpu/a9mpcore.o
CC x86_64-softmmu/hw/misc/edu.o
CC x86_64-softmmu/hw/misc/hyperv_testdev.o
CC aarch64-softmmu/hw/cpu/a15mpcore.o
CC aarch64-softmmu/hw/cpu/core.o
CC x86_64-softmmu/hw/net/virtio-net.o
CC aarch64-softmmu/hw/display/omap_dss.o
CC x86_64-softmmu/hw/net/vhost_net.o
CC aarch64-softmmu/hw/display/omap_lcdc.o
CC aarch64-softmmu/hw/display/pxa2xx_lcd.o
CC x86_64-softmmu/hw/scsi/virtio-scsi.o
CC aarch64-softmmu/hw/display/bcm2835_fb.o
CC x86_64-softmmu/hw/scsi/virtio-scsi-dataplane.o
CC aarch64-softmmu/hw/display/vga.o
CC x86_64-softmmu/hw/scsi/vhost-scsi.o
CC aarch64-softmmu/hw/display/virtio-gpu.o
CC x86_64-softmmu/hw/timer/mc146818rtc.o
CC x86_64-softmmu/hw/vfio/common.o
CC x86_64-softmmu/hw/vfio/pci.o
CC x86_64-softmmu/hw/vfio/pci-quirks.o
CC x86_64-softmmu/hw/vfio/platform.o
CC aarch64-softmmu/hw/display/virtio-gpu-3d.o
CC x86_64-softmmu/hw/vfio/spapr.o
CC x86_64-softmmu/hw/virtio/virtio.o
CC aarch64-softmmu/hw/display/virtio-gpu-pci.o
CC x86_64-softmmu/hw/virtio/virtio-balloon.o
CC aarch64-softmmu/hw/display/dpcd.o
CC aarch64-softmmu/hw/display/xlnx_dp.o
CC x86_64-softmmu/hw/virtio/vhost.o
CC x86_64-softmmu/hw/virtio/vhost-backend.o
CC x86_64-softmmu/hw/virtio/vhost-user.o
CC aarch64-softmmu/hw/dma/xlnx_dpdma.o
CC aarch64-softmmu/hw/dma/omap_dma.o
CC x86_64-softmmu/hw/virtio/vhost-vsock.o
CC x86_64-softmmu/hw/virtio/virtio-crypto.o
CC x86_64-softmmu/hw/virtio/virtio-crypto-pci.o
CC x86_64-softmmu/hw/i386/multiboot.o
CC x86_64-softmmu/hw/i386/pc.o
CC aarch64-softmmu/hw/dma/soc_dma.o
CC x86_64-softmmu/hw/i386/pc_piix.o
CC x86_64-softmmu/hw/i386/pc_q35.o
CC x86_64-softmmu/hw/i386/pc_sysfw.o
CC x86_64-softmmu/hw/i386/x86-iommu.o
CC x86_64-softmmu/hw/i386/intel_iommu.o
CC aarch64-softmmu/hw/dma/pxa2xx_dma.o
CC aarch64-softmmu/hw/dma/bcm2835_dma.o
CC aarch64-softmmu/hw/gpio/omap_gpio.o
CC aarch64-softmmu/hw/gpio/imx_gpio.o
/tmp/qemu-test/src/hw/i386/pc_piix.c: In function ‘igd_passthrough_isa_bridge_create’:
/tmp/qemu-test/src/hw/i386/pc_piix.c:1055: warning: ‘pch_rev_id’ may be used uninitialized in this function
CC x86_64-softmmu/hw/i386/amd_iommu.o
CC x86_64-softmmu/hw/i386/kvmvapic.o
CC aarch64-softmmu/hw/gpio/bcm2835_gpio.o
CC x86_64-softmmu/hw/i386/acpi-build.o
CC aarch64-softmmu/hw/i2c/omap_i2c.o
CC x86_64-softmmu/hw/i386/pci-assign-load-rom.o
CC x86_64-softmmu/hw/i386/kvm/clock.o
CC x86_64-softmmu/hw/i386/kvm/apic.o
CC aarch64-softmmu/hw/input/pxa2xx_keypad.o
CC aarch64-softmmu/hw/input/tsc210x.o
CC aarch64-softmmu/hw/intc/armv7m_nvic.o
CC x86_64-softmmu/hw/i386/kvm/i8259.o
CC x86_64-softmmu/hw/i386/kvm/ioapic.o
CC aarch64-softmmu/hw/intc/exynos4210_gic.o
CC aarch64-softmmu/hw/intc/exynos4210_combiner.o
CC x86_64-softmmu/hw/i386/kvm/i8254.o
CC x86_64-softmmu/hw/i386/kvm/pci-assign.o
/tmp/qemu-test/src/hw/i386/acpi-build.c: In function ‘build_append_pci_bus_devices’:
/tmp/qemu-test/src/hw/i386/acpi-build.c:496: warning: ‘notify_method’ may be used uninitialized in this function
CC aarch64-softmmu/hw/intc/omap_intc.o
CC x86_64-softmmu/target/i386/translate.o
CC x86_64-softmmu/target/i386/helper.o
CC x86_64-softmmu/target/i386/cpu.o
CC aarch64-softmmu/hw/intc/bcm2835_ic.o
CC aarch64-softmmu/hw/intc/bcm2836_control.o
CC x86_64-softmmu/target/i386/bpt_helper.o
CC aarch64-softmmu/hw/intc/allwinner-a10-pic.o
CC aarch64-softmmu/hw/intc/aspeed_vic.o
CC x86_64-softmmu/target/i386/excp_helper.o
CC x86_64-softmmu/target/i386/fpu_helper.o
CC aarch64-softmmu/hw/intc/arm_gicv3_cpuif.o
CC aarch64-softmmu/hw/misc/ivshmem.o
CC x86_64-softmmu/target/i386/cc_helper.o
CC aarch64-softmmu/hw/misc/arm_sysctl.o
CC aarch64-softmmu/hw/misc/cbus.o
CC x86_64-softmmu/target/i386/int_helper.o
CC x86_64-softmmu/target/i386/svm_helper.o
CC aarch64-softmmu/hw/misc/exynos4210_pmu.o
CC aarch64-softmmu/hw/misc/exynos4210_clk.o
CC aarch64-softmmu/hw/misc/imx_ccm.o
CC x86_64-softmmu/target/i386/smm_helper.o
CC aarch64-softmmu/hw/misc/imx31_ccm.o
CC x86_64-softmmu/target/i386/misc_helper.o
CC x86_64-softmmu/target/i386/mem_helper.o
CC aarch64-softmmu/hw/misc/imx25_ccm.o
CC aarch64-softmmu/hw/misc/imx6_ccm.o
CC aarch64-softmmu/hw/misc/imx6_src.o
CC x86_64-softmmu/target/i386/seg_helper.o
CC aarch64-softmmu/hw/misc/mst_fpga.o
CC x86_64-softmmu/target/i386/mpx_helper.o
CC x86_64-softmmu/target/i386/gdbstub.o
CC aarch64-softmmu/hw/misc/omap_clk.o
CC aarch64-softmmu/hw/misc/omap_gpmc.o
CC aarch64-softmmu/hw/misc/omap_l4.o
CC aarch64-softmmu/hw/misc/omap_sdrc.o
CC x86_64-softmmu/target/i386/machine.o
CC aarch64-softmmu/hw/misc/omap_tap.o
CC x86_64-softmmu/target/i386/arch_memory_mapping.o
CC x86_64-softmmu/target/i386/arch_dump.o
CC aarch64-softmmu/hw/misc/bcm2835_mbox.o
CC aarch64-softmmu/hw/misc/bcm2835_property.o
CC x86_64-softmmu/target/i386/monitor.o
CC aarch64-softmmu/hw/misc/bcm2835_rng.o
CC x86_64-softmmu/target/i386/hyperv.o
CC x86_64-softmmu/target/i386/kvm.o
GEN trace/generated-helpers.c
CC x86_64-softmmu/trace/control-target.o
CC aarch64-softmmu/hw/misc/zynq_slcr.o
CC aarch64-softmmu/hw/misc/zynq-xadc.o
CC aarch64-softmmu/hw/misc/stm32f2xx_syscfg.o
CC aarch64-softmmu/hw/misc/edu.o
CC aarch64-softmmu/hw/misc/auxbus.o
CC aarch64-softmmu/hw/misc/aspeed_scu.o
CC aarch64-softmmu/hw/misc/aspeed_sdmc.o
CC aarch64-softmmu/hw/net/virtio-net.o
CC aarch64-softmmu/hw/net/vhost_net.o
CC aarch64-softmmu/hw/pcmcia/pxa2xx.o
CC aarch64-softmmu/hw/scsi/virtio-scsi.o
CC aarch64-softmmu/hw/scsi/virtio-scsi-dataplane.o
CC aarch64-softmmu/hw/scsi/vhost-scsi.o
CC aarch64-softmmu/hw/sd/omap_mmc.o
CC aarch64-softmmu/hw/sd/pxa2xx_mmci.o
CC aarch64-softmmu/hw/sd/bcm2835_sdhost.o
CC aarch64-softmmu/hw/ssi/omap_spi.o
CC aarch64-softmmu/hw/ssi/imx_spi.o
CC aarch64-softmmu/hw/timer/exynos4210_mct.o
CC aarch64-softmmu/hw/timer/exynos4210_pwm.o
CC aarch64-softmmu/hw/timer/exynos4210_rtc.o
CC aarch64-softmmu/hw/timer/omap_gptimer.o
CC aarch64-softmmu/hw/timer/omap_synctimer.o
CC aarch64-softmmu/hw/timer/pxa2xx_timer.o
CC aarch64-softmmu/hw/timer/digic-timer.o
CC aarch64-softmmu/hw/timer/allwinner-a10-pit.o
CC aarch64-softmmu/hw/usb/tusb6010.o
CC aarch64-softmmu/hw/vfio/common.o
CC aarch64-softmmu/hw/vfio/pci.o
CC aarch64-softmmu/hw/vfio/pci-quirks.o
CC aarch64-softmmu/hw/vfio/platform.o
CC x86_64-softmmu/trace/generated-helpers.o
CC aarch64-softmmu/hw/vfio/calxeda-xgmac.o
CC aarch64-softmmu/hw/vfio/amd-xgbe.o
CC aarch64-softmmu/hw/vfio/spapr.o
CC aarch64-softmmu/hw/virtio/virtio.o
CC aarch64-softmmu/hw/virtio/virtio-balloon.o
CC aarch64-softmmu/hw/virtio/vhost.o
CC aarch64-softmmu/hw/virtio/vhost-backend.o
LINK x86_64-softmmu/qemu-system-x86_64
CC aarch64-softmmu/hw/virtio/vhost-user.o
CC aarch64-softmmu/hw/virtio/vhost-vsock.o
CC aarch64-softmmu/hw/virtio/virtio-crypto.o
CC aarch64-softmmu/hw/virtio/virtio-crypto-pci.o
CC aarch64-softmmu/hw/arm/boot.o
CC aarch64-softmmu/hw/arm/collie.o
CC aarch64-softmmu/hw/arm/exynos4_boards.o
CC aarch64-softmmu/hw/arm/gumstix.o
CC aarch64-softmmu/hw/arm/highbank.o
CC aarch64-softmmu/hw/arm/digic_boards.o
CC aarch64-softmmu/hw/arm/integratorcp.o
CC aarch64-softmmu/hw/arm/mainstone.o
CC aarch64-softmmu/hw/arm/musicpal.o
CC aarch64-softmmu/hw/arm/nseries.o
CC aarch64-softmmu/hw/arm/omap_sx1.o
CC aarch64-softmmu/hw/arm/palm.o
CC aarch64-softmmu/hw/arm/realview.o
CC aarch64-softmmu/hw/arm/spitz.o
CC aarch64-softmmu/hw/arm/stellaris.o
CC aarch64-softmmu/hw/arm/tosa.o
CC aarch64-softmmu/hw/arm/versatilepb.o
CC aarch64-softmmu/hw/arm/vexpress.o
CC aarch64-softmmu/hw/arm/virt.o
CC aarch64-softmmu/hw/arm/xilinx_zynq.o
CC aarch64-softmmu/hw/arm/z2.o
CC aarch64-softmmu/hw/arm/virt-acpi-build.o
CC aarch64-softmmu/hw/arm/netduino2.o
CC aarch64-softmmu/hw/arm/sysbus-fdt.o
CC aarch64-softmmu/hw/arm/armv7m.o
CC aarch64-softmmu/hw/arm/exynos4210.o
CC aarch64-softmmu/hw/arm/pxa2xx.o
CC aarch64-softmmu/hw/arm/pxa2xx_gpio.o
CC aarch64-softmmu/hw/arm/pxa2xx_pic.o
CC aarch64-softmmu/hw/arm/digic.o
CC aarch64-softmmu/hw/arm/omap1.o
CC aarch64-softmmu/hw/arm/omap2.o
CC aarch64-softmmu/hw/arm/strongarm.o
CC aarch64-softmmu/hw/arm/allwinner-a10.o
CC aarch64-softmmu/hw/arm/cubieboard.o
CC aarch64-softmmu/hw/arm/bcm2835_peripherals.o
CC aarch64-softmmu/hw/arm/bcm2836.o
CC aarch64-softmmu/hw/arm/raspi.o
CC aarch64-softmmu/hw/arm/stm32f205_soc.o
CC aarch64-softmmu/hw/arm/xlnx-zynqmp.o
CC aarch64-softmmu/hw/arm/xlnx-ep108.o
CC aarch64-softmmu/hw/arm/fsl-imx25.o
CC aarch64-softmmu/hw/arm/imx25_pdk.o
CC aarch64-softmmu/hw/arm/fsl-imx31.o
CC aarch64-softmmu/hw/arm/kzm.o
CC aarch64-softmmu/hw/arm/fsl-imx6.o
CC aarch64-softmmu/hw/arm/sabrelite.o
CC aarch64-softmmu/hw/arm/aspeed_soc.o
CC aarch64-softmmu/hw/arm/aspeed.o
CC aarch64-softmmu/target/arm/arm-semi.o
CC aarch64-softmmu/target/arm/machine.o
CC aarch64-softmmu/target/arm/psci.o
CC aarch64-softmmu/target/arm/arch_dump.o
CC aarch64-softmmu/target/arm/monitor.o
CC aarch64-softmmu/target/arm/kvm-stub.o
CC aarch64-softmmu/target/arm/translate.o
CC aarch64-softmmu/target/arm/op_helper.o
CC aarch64-softmmu/target/arm/helper.o
CC aarch64-softmmu/target/arm/cpu.o
CC aarch64-softmmu/target/arm/neon_helper.o
CC aarch64-softmmu/target/arm/iwmmxt_helper.o
CC aarch64-softmmu/target/arm/gdbstub.o
CC aarch64-softmmu/target/arm/cpu64.o
CC aarch64-softmmu/target/arm/translate-a64.o
CC aarch64-softmmu/target/arm/helper-a64.o
CC aarch64-softmmu/target/arm/gdbstub64.o
CC aarch64-softmmu/target/arm/crypto_helper.o
CC aarch64-softmmu/target/arm/arm-powerctl.o
GEN trace/generated-helpers.c
CC aarch64-softmmu/trace/control-target.o
CC aarch64-softmmu/gdbstub-xml.o
CC aarch64-softmmu/trace/generated-helpers.o
/tmp/qemu-test/src/target/arm/translate-a64.c: In function ‘handle_shri_with_rndacc’:
/tmp/qemu-test/src/target/arm/translate-a64.c:6359: warning: ‘tcg_src_hi’ may be used uninitialized in this function
/tmp/qemu-test/src/target/arm/translate-a64.c: In function ‘disas_simd_scalar_two_reg_misc’:
/tmp/qemu-test/src/target/arm/translate-a64.c:8086: warning: ‘rmode’ may be used uninitialized in this function
LINK aarch64-softmmu/qemu-system-aarch64
BISON dtc-parser.tab.c
LEX convert-dtsv0-lexer.lex.c
make[1]: bison: Command not found
LEX dtc-lexer.lex.c
make[1]: flex: Command not found
make[1]: flex: Command not found
TEST tests/qapi-schema/alternate-any.out
TEST tests/qapi-schema/alternate-clash.out
TEST tests/qapi-schema/alternate-array.out
TEST tests/qapi-schema/alternate-conflict-dict.out
TEST tests/qapi-schema/alternate-conflict-string.out
TEST tests/qapi-schema/alternate-base.out
TEST tests/qapi-schema/alternate-empty.out
TEST tests/qapi-schema/alternate-nested.out
TEST tests/qapi-schema/args-alternate.out
TEST tests/qapi-schema/alternate-unknown.out
TEST tests/qapi-schema/args-any.out
TEST tests/qapi-schema/args-array-empty.out
TEST tests/qapi-schema/args-bad-boxed.out
TEST tests/qapi-schema/args-array-unknown.out
TEST tests/qapi-schema/args-boxed-anon.out
TEST tests/qapi-schema/args-boxed-empty.out
TEST tests/qapi-schema/args-boxed-string.out
TEST tests/qapi-schema/args-int.out
TEST tests/qapi-schema/args-invalid.out
TEST tests/qapi-schema/args-member-array-bad.out
TEST tests/qapi-schema/args-member-case.out
TEST tests/qapi-schema/args-member-unknown.out
TEST tests/qapi-schema/args-name-clash.out
TEST tests/qapi-schema/args-union.out
TEST tests/qapi-schema/args-unknown.out
TEST tests/qapi-schema/bad-base.out
TEST tests/qapi-schema/bad-data.out
TEST tests/qapi-schema/bad-type-bool.out
TEST tests/qapi-schema/bad-ident.out
TEST tests/qapi-schema/bad-type-dict.out
TEST tests/qapi-schema/bad-type-int.out
TEST tests/qapi-schema/base-cycle-direct.out
TEST tests/qapi-schema/base-cycle-indirect.out
TEST tests/qapi-schema/comments.out
TEST tests/qapi-schema/command-int.out
TEST tests/qapi-schema/doc-bad-alternate-member.out
TEST tests/qapi-schema/doc-bad-command-arg.out
TEST tests/qapi-schema/doc-bad-symbol.out
TEST tests/qapi-schema/doc-bad-union-member.out
TEST tests/qapi-schema/doc-before-include.out
TEST tests/qapi-schema/doc-before-pragma.out
TEST tests/qapi-schema/doc-duplicated-arg.out
TEST tests/qapi-schema/doc-duplicated-return.out
TEST tests/qapi-schema/doc-duplicated-since.out
TEST tests/qapi-schema/doc-empty-arg.out
TEST tests/qapi-schema/doc-empty-section.out
TEST tests/qapi-schema/doc-empty-symbol.out
TEST tests/qapi-schema/doc-good.out
TEST tests/qapi-schema/doc-interleaved-section.out
TEST tests/qapi-schema/doc-invalid-end.out
TEST tests/qapi-schema/doc-invalid-end2.out
TEST tests/qapi-schema/doc-invalid-return.out
TEST tests/qapi-schema/doc-invalid-section.out
TEST tests/qapi-schema/doc-invalid-start.out
TEST tests/qapi-schema/doc-missing.out
TEST tests/qapi-schema/doc-missing-colon.out
TEST tests/qapi-schema/doc-missing-expr.out
TEST tests/qapi-schema/doc-missing-space.out
TEST tests/qapi-schema/doc-no-symbol.out
TEST tests/qapi-schema/double-data.out
TEST tests/qapi-schema/double-type.out
TEST tests/qapi-schema/duplicate-key.out
TEST tests/qapi-schema/empty.out
TEST tests/qapi-schema/enum-bad-name.out
TEST tests/qapi-schema/enum-bad-prefix.out
TEST tests/qapi-schema/enum-clash-member.out
TEST tests/qapi-schema/enum-dict-member.out
TEST tests/qapi-schema/enum-int-member.out
TEST tests/qapi-schema/enum-member-case.out
TEST tests/qapi-schema/enum-missing-data.out
TEST tests/qapi-schema/enum-wrong-data.out
TEST tests/qapi-schema/escape-outside-string.out
TEST tests/qapi-schema/escape-too-big.out
TEST tests/qapi-schema/escape-too-short.out
TEST tests/qapi-schema/event-boxed-empty.out
TEST tests/qapi-schema/event-case.out
TEST tests/qapi-schema/event-nest-struct.out
TEST tests/qapi-schema/flat-union-array-branch.out
TEST tests/qapi-schema/flat-union-bad-base.out
TEST tests/qapi-schema/flat-union-bad-discriminator.out
TEST tests/qapi-schema/flat-union-base-any.out
TEST tests/qapi-schema/flat-union-base-union.out
TEST tests/qapi-schema/flat-union-clash-member.out
TEST tests/qapi-schema/flat-union-empty.out
TEST tests/qapi-schema/flat-union-incomplete-branch.out
TEST tests/qapi-schema/flat-union-inline.out
TEST tests/qapi-schema/flat-union-int-branch.out
TEST tests/qapi-schema/flat-union-invalid-branch-key.out
TEST tests/qapi-schema/flat-union-invalid-discriminator.out
TEST tests/qapi-schema/flat-union-no-base.out
TEST tests/qapi-schema/flat-union-optional-discriminator.out
TEST tests/qapi-schema/flat-union-string-discriminator.out
TEST tests/qapi-schema/funny-char.out
TEST tests/qapi-schema/ident-with-escape.out
TEST tests/qapi-schema/include-before-err.out
TEST tests/qapi-schema/include-cycle.out
TEST tests/qapi-schema/include-extra-junk.out
TEST tests/qapi-schema/include-format-err.out
TEST tests/qapi-schema/include-nested-err.out
TEST tests/qapi-schema/include-no-file.out
TEST tests/qapi-schema/include-non-file.out
TEST tests/qapi-schema/include-repetition.out
TEST tests/qapi-schema/include-relpath.out
TEST tests/qapi-schema/include-self-cycle.out
TEST tests/qapi-schema/include-simple.out
TEST tests/qapi-schema/indented-expr.out
TEST tests/qapi-schema/leading-comma-list.out
TEST tests/qapi-schema/leading-comma-object.out
TEST tests/qapi-schema/missing-colon.out
TEST tests/qapi-schema/missing-comma-list.out
TEST tests/qapi-schema/missing-comma-object.out
TEST tests/qapi-schema/missing-type.out
TEST tests/qapi-schema/nested-struct-data.out
TEST tests/qapi-schema/non-objects.out
TEST tests/qapi-schema/pragma-doc-required-crap.out
TEST tests/qapi-schema/pragma-extra-junk.out
TEST tests/qapi-schema/pragma-name-case-whitelist-crap.out
TEST tests/qapi-schema/pragma-non-dict.out
TEST tests/qapi-schema/pragma-returns-whitelist-crap.out
TEST tests/qapi-schema/qapi-schema-test.out
TEST tests/qapi-schema/quoted-structural-chars.out
TEST tests/qapi-schema/redefined-builtin.out
TEST tests/qapi-schema/redefined-command.out
TEST tests/qapi-schema/redefined-event.out
TEST tests/qapi-schema/redefined-type.out
TEST tests/qapi-schema/reserved-command-q.out
TEST tests/qapi-schema/reserved-enum-q.out
TEST tests/qapi-schema/reserved-member-has.out
TEST tests/qapi-schema/reserved-member-q.out
TEST tests/qapi-schema/reserved-member-u.out
TEST tests/qapi-schema/reserved-member-underscore.out
TEST tests/qapi-schema/reserved-type-kind.out
TEST tests/qapi-schema/reserved-type-list.out
TEST tests/qapi-schema/returns-alternate.out
TEST tests/qapi-schema/returns-array-bad.out
TEST tests/qapi-schema/returns-dict.out
TEST tests/qapi-schema/returns-unknown.out
TEST tests/qapi-schema/returns-whitelist.out
TEST tests/qapi-schema/struct-base-clash-deep.out
TEST tests/qapi-schema/struct-base-clash.out
TEST tests/qapi-schema/struct-data-invalid.out
TEST tests/qapi-schema/struct-member-invalid.out
TEST tests/qapi-schema/trailing-comma-list.out
TEST tests/qapi-schema/trailing-comma-object.out
TEST tests/qapi-schema/type-bypass-bad-gen.out
TEST tests/qapi-schema/unclosed-list.out
TEST tests/qapi-schema/unclosed-object.out
TEST tests/qapi-schema/unclosed-string.out
TEST tests/qapi-schema/unicode-str.out
TEST tests/qapi-schema/union-base-empty.out
TEST tests/qapi-schema/union-base-no-discriminator.out
TEST tests/qapi-schema/union-branch-case.out
TEST tests/qapi-schema/union-clash-branches.out
TEST tests/qapi-schema/union-empty.out
TEST tests/qapi-schema/union-optional-branch.out
TEST tests/qapi-schema/union-invalid-base.out
TEST tests/qapi-schema/union-unknown.out
TEST tests/qapi-schema/unknown-escape.out
TEST tests/qapi-schema/unknown-expr-key.out
GEN tests/qapi-schema/doc-good.test.texi
CC tests/check-qdict.o
CC tests/test-char.o
CC tests/check-qfloat.o
CC tests/check-qint.o
CC tests/check-qstring.o
CC tests/check-qnull.o
CC tests/check-qlist.o
CC tests/check-qjson.o
CC tests/test-qobject-output-visitor.o
GEN tests/test-qapi-visit.c
GEN tests/test-qapi-types.c
GEN tests/test-qapi-event.c
GEN tests/test-qmp-introspect.c
CC tests/test-clone-visitor.o
CC tests/test-qobject-input-visitor.o
CC tests/test-qmp-commands.o
GEN tests/test-qmp-marshal.c
CC tests/test-string-input-visitor.o
CC tests/test-string-output-visitor.o
CC tests/test-qmp-event.o
CC tests/test-opts-visitor.o
CC tests/test-coroutine.o
CC tests/iothread.o
CC tests/test-visitor-serialization.o
CC tests/test-iov.o
CC tests/test-aio.o
CC tests/test-aio-multithread.o
CC tests/test-throttle.o
CC tests/test-thread-pool.o
CC tests/test-hbitmap.o
CC tests/test-blockjob.o
CC tests/test-blockjob-txn.o
CC tests/test-x86-cpuid.o
CC tests/test-xbzrle.o
CC tests/test-vmstate.o
CC tests/test-cutils.o
CC tests/test-shift128.o
CC tests/test-mul64.o
CC tests/test-int128.o
CC tests/rcutorture.o
CC tests/test-rcu-list.o
CC tests/test-qdist.o
CC tests/test-qht.o
CC tests/test-qht-par.o
CC tests/qht-bench.o
/tmp/qemu-test/src/tests/test-int128.c:180: warning: ‘__noclone__’ attribute directive ignored
CC tests/test-bitops.o
CC tests/test-bitcnt.o
CC tests/check-qom-interface.o
CC tests/check-qom-proplist.o
CC tests/test-qemu-opts.o
CC tests/test-keyval.o
CC tests/test-write-threshold.o
CC tests/test-crypto-hash.o
CC tests/test-crypto-hmac.o
CC tests/test-crypto-cipher.o
CC tests/test-crypto-secret.o
CC tests/test-qga.o
CC tests/libqtest.o
CC tests/test-timed-average.o
CC tests/test-io-task.o
CC tests/test-io-channel-socket.o
CC tests/io-channel-helpers.o
CC tests/test-io-channel-file.o
CC tests/test-io-channel-command.o
CC tests/test-io-channel-buffer.o
CC tests/test-base64.o
CC tests/test-crypto-ivgen.o
CC tests/test-crypto-afsplit.o
CC tests/test-crypto-xts.o
CC tests/test-crypto-block.o
CC tests/test-logging.o
CC tests/test-replication.o
CC tests/test-bufferiszero.o
CC tests/test-uuid.o
CC tests/ptimer-test.o
CC tests/ptimer-test-stubs.o
CC tests/test-qapi-util.o
CC tests/vhost-user-test.o
CC tests/libqos/pci.o
CC tests/libqos/fw_cfg.o
CC tests/libqos/malloc.o
CC tests/libqos/i2c.o
CC tests/libqos/libqos.o
CC tests/libqos/malloc-spapr.o
CC tests/libqos/libqos-spapr.o
CC tests/libqos/rtas.o
CC tests/libqos/pci-spapr.o
CC tests/libqos/pci-pc.o
CC tests/libqos/malloc-pc.o
CC tests/libqos/libqos-pc.o
CC tests/libqos/ahci.o
CC tests/libqos/virtio.o
CC tests/libqos/virtio-pci.o
CC tests/libqos/virtio-mmio.o
CC tests/libqos/malloc-generic.o
CC tests/endianness-test.o
CC tests/fdc-test.o
CC tests/ide-test.o
CC tests/ahci-test.o
CC tests/hd-geo-test.o
CC tests/boot-order-test.o
CC tests/bios-tables-test.o
CC tests/boot-sector.o
CC tests/acpi-utils.o
CC tests/boot-serial-test.o
/tmp/qemu-test/src/tests/ide-test.c: In function ‘cdrom_pio_impl’:
/tmp/qemu-test/src/tests/ide-test.c:803: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
/tmp/qemu-test/src/tests/ide-test.c: In function ‘test_cdrom_dma’:
/tmp/qemu-test/src/tests/ide-test.c:899: warning: ignoring return value of ‘fwrite’, declared with attribute warn_unused_result
CC tests/pxe-test.o
CC tests/rtc-test.o
CC tests/ipmi-kcs-test.o
CC tests/ipmi-bt-test.o
CC tests/i440fx-test.o
CC tests/fw_cfg-test.o
CC tests/drive_del-test.o
CC tests/wdt_ib700-test.o
CC tests/tco-test.o
CC tests/e1000-test.o
CC tests/e1000e-test.o
CC tests/rtl8139-test.o
CC tests/pcnet-test.o
CC tests/eepro100-test.o
CC tests/ne2000-test.o
CC tests/nvme-test.o
CC tests/ac97-test.o
CC tests/es1370-test.o
CC tests/virtio-balloon-test.o
CC tests/virtio-net-test.o
CC tests/virtio-blk-test.o
CC tests/virtio-rng-test.o
CC tests/virtio-scsi-test.o
CC tests/virtio-serial-test.o
CC tests/virtio-console-test.o
CC tests/tpci200-test.o
CC tests/ipoctal232-test.o
CC tests/display-vga-test.o
CC tests/intel-hda-test.o
CC tests/ivshmem-test.o
CC tests/vmxnet3-test.o
CC tests/pvpanic-test.o
CC tests/i82801b11-test.o
CC tests/ioh3420-test.o
CC tests/usb-hcd-ohci-test.o
CC tests/libqos/usb.o
CC tests/usb-hcd-uhci-test.o
CC tests/usb-hcd-ehci-test.o
CC tests/usb-hcd-xhci-test.o
CC tests/pc-cpu-test.o
CC tests/q35-test.o
CC tests/test-netfilter.o
CC tests/test-filter-mirror.o
CC tests/test-filter-redirector.o
CC tests/postcopy-test.o
CC tests/test-x86-cpuid-compat.o
CC tests/qmp-test.o
CC tests/device-introspect-test.o
CC tests/qom-test.o
CC tests/test-hmp.o
LINK tests/check-qdict
LINK tests/test-char
LINK tests/check-qfloat
LINK tests/check-qint
LINK tests/check-qstring
LINK tests/check-qlist
LINK tests/check-qnull
LINK tests/check-qjson
CC tests/test-qapi-visit.o
CC tests/test-qapi-types.o
CC tests/test-qapi-event.o
CC tests/test-qmp-introspect.o
CC tests/test-qmp-marshal.o
LINK tests/test-coroutine
LINK tests/test-iov
LINK tests/test-aio
LINK tests/test-aio-multithread
LINK tests/test-throttle
LINK tests/test-thread-pool
LINK tests/test-hbitmap
LINK tests/test-blockjob
LINK tests/test-blockjob-txn
LINK tests/test-x86-cpuid
LINK tests/test-xbzrle
LINK tests/test-vmstate
LINK tests/test-cutils
LINK tests/test-shift128
LINK tests/test-mul64
LINK tests/test-int128
LINK tests/rcutorture
LINK tests/test-rcu-list
LINK tests/test-qdist
LINK tests/test-qht
LINK tests/qht-bench
LINK tests/test-bitops
LINK tests/test-bitcnt
LINK tests/check-qom-interface
LINK tests/check-qom-proplist
LINK tests/test-qemu-opts
LINK tests/test-keyval
LINK tests/test-write-threshold
LINK tests/test-crypto-hash
LINK tests/test-crypto-hmac
LINK tests/test-crypto-cipher
LINK tests/test-crypto-secret
LINK tests/test-qga
LINK tests/test-timed-average
LINK tests/test-io-task
LINK tests/test-io-channel-socket
LINK tests/test-io-channel-file
LINK tests/test-io-channel-command
LINK tests/test-io-channel-buffer
LINK tests/test-base64
LINK tests/test-crypto-ivgen
LINK tests/test-crypto-afsplit
LINK tests/test-crypto-xts
LINK tests/test-crypto-block
LINK tests/test-logging
LINK tests/test-replication
LINK tests/test-bufferiszero
LINK tests/test-uuid
LINK tests/ptimer-test
LINK tests/test-qapi-util
LINK tests/vhost-user-test
LINK tests/endianness-test
LINK tests/fdc-test
LINK tests/ide-test
LINK tests/ahci-test
LINK tests/hd-geo-test
LINK tests/boot-order-test
LINK tests/bios-tables-test
LINK tests/boot-serial-test
LINK tests/pxe-test
LINK tests/rtc-test
LINK tests/ipmi-kcs-test
LINK tests/ipmi-bt-test
LINK tests/i440fx-test
LINK tests/fw_cfg-test
LINK tests/drive_del-test
LINK tests/wdt_ib700-test
LINK tests/tco-test
LINK tests/e1000-test
LINK tests/e1000e-test
LINK tests/rtl8139-test
LINK tests/pcnet-test
LINK tests/eepro100-test
LINK tests/ne2000-test
LINK tests/nvme-test
LINK tests/ac97-test
LINK tests/es1370-test
LINK tests/virtio-net-test
LINK tests/virtio-balloon-test
LINK tests/virtio-blk-test
LINK tests/virtio-rng-test
LINK tests/virtio-scsi-test
LINK tests/virtio-serial-test
LINK tests/virtio-console-test
LINK tests/tpci200-test
LINK tests/ipoctal232-test
LINK tests/display-vga-test
LINK tests/intel-hda-test
LINK tests/ivshmem-test
LINK tests/vmxnet3-test
LINK tests/pvpanic-test
LINK tests/i82801b11-test
LINK tests/ioh3420-test
LINK tests/usb-hcd-ohci-test
LINK tests/usb-hcd-uhci-test
LINK tests/usb-hcd-ehci-test
LINK tests/usb-hcd-xhci-test
LINK tests/pc-cpu-test
LINK tests/q35-test
LINK tests/test-netfilter
LINK tests/test-filter-mirror
LINK tests/test-filter-redirector
LINK tests/postcopy-test
LINK tests/test-x86-cpuid-compat
LINK tests/qmp-test
LINK tests/device-introspect-test
LINK tests/qom-test
LINK tests/test-hmp
GTESTER tests/check-qdict
GTESTER tests/check-qfloat
GTESTER tests/test-char
GTESTER tests/check-qstring
GTESTER tests/check-qint
GTESTER tests/check-qlist
GTESTER tests/check-qnull
GTESTER tests/check-qjson
LINK tests/test-qobject-output-visitor
LINK tests/test-clone-visitor
LINK tests/test-qobject-input-visitor
LINK tests/test-qmp-commands
LINK tests/test-string-input-visitor
LINK tests/test-string-output-visitor
LINK tests/test-qmp-event
LINK tests/test-opts-visitor
GTESTER tests/test-coroutine
LINK tests/test-visitor-serialization
GTESTER tests/test-aio-multithread
GTESTER tests/test-aio
GTESTER tests/test-iov
GTESTER tests/test-throttle
GTESTER tests/test-thread-pool
GTESTER tests/test-hbitmap
GTESTER tests/test-blockjob
GTESTER tests/test-blockjob-txn
GTESTER tests/test-x86-cpuid
GTESTER tests/test-vmstate
GTESTER tests/test-xbzrle
Failed to load simple/primitive:b_1
Failed to load simple/primitive:i64_2
Failed to load simple/primitive:i32_1
Failed to load simple/primitive:i32_1
Failed to load test/with_tmp:a
Failed to load test/tmp_child_parent:f
Failed to load test/tmp_child:parent
Failed to load test/with_tmp:tmp
Failed to load test/tmp_child:diff
Failed to load test/with_tmp:tmp
Failed to load test/tmp_child:diff
Failed to load test/with_tmp:tmp
GTESTER tests/test-cutils
GTESTER tests/test-shift128
GTESTER tests/test-mul64
GTESTER tests/test-int128
GTESTER tests/rcutorture
GTESTER tests/test-rcu-list
GTESTER tests/test-qdist
GTESTER tests/test-qht
LINK tests/test-qht-par
GTESTER tests/test-bitops
GTESTER tests/test-bitcnt
GTESTER tests/check-qom-interface
GTESTER tests/check-qom-proplist
GTESTER tests/test-qemu-opts
GTESTER tests/test-keyval
GTESTER tests/test-write-threshold
GTESTER tests/test-crypto-hash
GTESTER tests/test-crypto-hmac
GTESTER tests/test-crypto-cipher
GTESTER tests/test-crypto-secret
GTESTER tests/test-qga
GTESTER tests/test-timed-average
GTESTER tests/test-io-task
GTESTER tests/test-io-channel-socket
GTESTER tests/test-io-channel-file
GTESTER tests/test-io-channel-command
GTESTER tests/test-io-channel-buffer
GTESTER tests/test-base64
GTESTER tests/test-crypto-ivgen
GTESTER tests/test-crypto-afsplit
GTESTER tests/test-crypto-xts
GTESTER tests/test-crypto-block
GTESTER tests/test-logging
GTESTER tests/test-replication
GTESTER tests/test-bufferiszero
GTESTER tests/test-uuid
GTESTER tests/ptimer-test
GTESTER tests/test-qapi-util
GTESTER check-qtest-x86_64
GTESTER check-qtest-aarch64
GTESTER tests/test-qobject-output-visitor
GTESTER tests/test-clone-visitor
GTESTER tests/test-qobject-input-visitor
GTESTER tests/test-qmp-commands
GTESTER tests/test-string-input-visitor
GTESTER tests/test-string-output-visitor
GTESTER tests/test-qmp-event
GTESTER tests/test-opts-visitor
GTESTER tests/test-visitor-serialization
GTESTER tests/test-qht-par
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
Could not access KVM kernel module: No such file or directory
failed to initialize KVM: No such file or directory
Back to tcg accelerator.
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-tytg9d57/src'
BUILD fedora
make[1]: Entering directory '/var/tmp/patchew-tester-tmp-tytg9d57/src'
ARCHIVE qemu.tgz
ARCHIVE dtc.tgz
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
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.3.1-1.fc25.x86_64
gcc-c++-6.3.1-1.fc25.x86_64
git-2.9.3-2.fc25.x86_64
glib2-devel-2.50.3-1.fc25.x86_64
libfdt-devel-1.4.2-1.fc25.x86_64
make-4.1-5.fc24.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.1-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.2-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.1-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.2-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
package python2 is not installed
perl-5.24.1-385.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:
FBR=f25
PACKAGES=ccache git tar PyYAML sparse flex bison python2 glib2-devel pixman-devel zlib-devel SDL-devel libfdt-devel gcc gcc-c++ clang make perl which bc findutils 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=
TERM=xterm
MAKEFLAGS= -j8
HISTSIZE=1000
J=8
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.m4a=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.oga=01;36:*.opus=01;36:*.spx=01;36:*.xspf=01;36:
CCACHE_DIR=/var/tmp/ccache
EXTRA_CONFIGURE_OPTS=
V=
SHOW_ENV=1
MAIL=/var/spool/mail/root
PATH=/usr/lib/ccache:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
TARGET_LIST=
HISTCONTROL=ignoredups
FGC=f25
SHLVL=1
HOME=/root
TEST_DIR=/tmp/qemu-test
DISTTAG=f25docker
LOGNAME=root
LESSOPEN=||/usr/bin/lesspipe.sh %s
FEATURES=mingw clang pyyaml dtc
DEBUG=
_=/usr/bin/env
Configure options:
--enable-werror --target-list=x86_64-softmmu,aarch64-softmmu --prefix=/var/tmp/qemu-build/install --cross-prefix=x86_64-w64-mingw32- --enable-trace-backends=simple --enable-debug --enable-gnutls --enable-nettle --enable-curl --enable-vnc --enable-bzip2 --enable-guest-agent --with-sdlabi=1.2 --with-gtkabi=2.0
Install prefix /var/tmp/qemu-build/install
BIOS directory /var/tmp/qemu-build/install
binary directory /var/tmp/qemu-build/install
library directory /var/tmp/qemu-build/install/lib
module directory /var/tmp/qemu-build/install/lib
libexec directory /var/tmp/qemu-build/install/libexec
include directory /var/tmp/qemu-build/install/include
config directory /var/tmp/qemu-build/install
local state directory queried at runtime
Windows SDK no
Source path /tmp/qemu-test/src
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 -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
tcg debug enabled yes
gprof enabled no
sparse enabled no
strip binaries no
profiler no
static build no
pixman system
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
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
RDMA support no
TCG interpreter 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
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
GlusterFS support no
gcov gcov
gcov enabled no
TPM support yes
libssh2 support yes
TPM passthrough
TPM emulator no
QOM debugging 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
mkdir -p dtc/libfdt
mkdir -p dtc/tests
GEN x86_64-softmmu/config-devices.mak.tmp
GEN aarch64-softmmu/config-devices.mak.tmp
GEN config-host.h
GEN qapi-visit.h
GEN qapi-types.h
GEN qmp-commands.h
GEN qemu-options.def
GEN qapi-event.h
GEN x86_64-softmmu/config-devices.mak
GEN aarch64-softmmu/config-devices.mak
GEN qapi-types.c
GEN qmp-marshal.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 trace/generated-helpers.c
GEN module_block.h
GEN tests/test-qapi-types.h
GEN tests/test-qapi-visit.h
GEN tests/test-qmp-commands.h
GEN tests/test-qapi-event.h
GEN tests/test-qmp-introspect.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 backends/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/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 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 trace-root.c
GEN util/trace.c
GEN crypto/trace.c
GEN io/trace.c
GEN migration/trace.c
GEN block/trace.c
GEN backends/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/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 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 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/dtb_reverse.c
DEP /tmp/qemu-test/src/dtc/tests/dtbs_equal_ordered.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/move_and_save.c
DEP /tmp/qemu-test/src/dtc/tests/sw_tree1.c
DEP /tmp/qemu-test/src/dtc/tests/nop_node.c
DEP /tmp/qemu-test/src/dtc/tests/nop_property.c
DEP /tmp/qemu-test/src/dtc/tests/setprop_inplace.c
DEP /tmp/qemu-test/src/dtc/tests/stringlist.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/get_alias.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/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/get_phandle.c
DEP /tmp/qemu-test/src/dtc/tests/getprop.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_strerror.c
DEP /tmp/qemu-test/src/dtc/libfdt/fdt_rw.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_ro.c
DEP /tmp/qemu-test/src/dtc/libfdt/fdt.c
DEP /tmp/qemu-test/src/dtc/util.c
DEP /tmp/qemu-test/src/dtc/fdtput.c
DEP /tmp/qemu-test/src/dtc/fdtget.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-lexer.lex.c
DEP dtc-parser.tab.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_sw.o
CC libfdt/fdt_rw.o
CC libfdt/fdt_wip.o
CC libfdt/fdt_empty_tree.o
CC libfdt/fdt_strerror.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-qmp-commands.h
GEN qga/qapi-generated/qga-qapi-types.c
CC qmp-introspect.o
GEN qga/qapi-generated/qga-qapi-visit.c
CC qapi-types.o
GEN qga/qapi-generated/qga-qmp-marshal.c
CC qapi-visit.o
CC qapi-event.o
CC qapi/qapi-visit-core.o
CC qapi/qobject-input-visitor.o
CC qapi/qapi-dealloc-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/qint.o
CC qobject/qstring.o
CC qobject/qdict.o
CC qobject/qlist.o
CC qobject/qfloat.o
CC qobject/qbool.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/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/qdist.o
CC util/qht.o
CC util/range.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 backends/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/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 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 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/monitor.o
CC stubs/notify-event.o
CC stubs/qtest.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/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_device_list.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
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/qed.o
CC block/qed-gencb.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/vhdx-log.o
CC block/quorum.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/crypto.o
CC nbd/server.o
CC nbd/client.o
CC nbd/common.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/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 iothread.o
CC qdev-monitor.o
CC device-hotplug.o
CC os-win32.o
CC page_cache.o
CC accel.o
CC bt-host.o
CC bt-vhci.o
CC dma-helpers.o
CC tpm.o
CC vl.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
/tmp/qemu-test/src/hmp.c: In function 'hmp_info_tpm':
/tmp/qemu-test/src/hmp.c:986:50: error: format '%ld' expects argument of type 'long int', but argument 3 has type 'int64_t {aka long long int}' [-Werror=format=]
monitor_printf(mon, ",loglevel=%ld", teo->loglevel);
^
cc1: all warnings being treated as errors
/tmp/qemu-test/src/rules.mak:69: recipe for target 'hmp.o' failed
make: *** [hmp.o] Error 1
make: *** Waiting for unfinished jobs....
tests/docker/Makefile.include:118: recipe for target 'docker-run' failed
make[1]: *** [docker-run] Error 2
make[1]: Leaving directory '/var/tmp/patchew-tester-tmp-tytg9d57/src'
tests/docker/Makefile.include:149: recipe for target 'docker-run-test-mingw@fedora' failed
make: *** [docker-run-test-mingw@fedora] Error 2
=== 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] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/8] tpm-backend: Made few interface methods optional
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
@ 2017-05-02 12:29 ` Marc-André Lureau
2017-05-04 8:39 ` Amarnath Valluri
2017-05-04 11:06 ` [Qemu-devel] [PATCH v4 " Amarnath Valluri
0 siblings, 2 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 12:29 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
On Tue, May 2, 2017 at 3:52 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> This allows backend implementations left optional interface methods.
> For mandatory methods assertion checks added.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
> backends/tpm.c | 24 ++++++++++++++++++------
> hw/tpm/tpm_passthrough.c | 16 ----------------
> 2 files changed, 18 insertions(+), 22 deletions(-)
>
> diff --git a/backends/tpm.c b/backends/tpm.c
> index cf5abf1..8245426 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -48,7 +48,7 @@ const char *tpm_backend_get_desc(TPMBackend *s)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> - return k->ops->desc();
> + return k->ops->desc ? k->ops->desc() : "";
> }
>
If it only need to returns const, we may consider using a class field,
defaulting to null.
Who is using it? tpm_backend_get_desc() not being called anywhere. Let's
remove it?
> int tpm_backend_init(TPMBackend *s, TPMState *state,
> @@ -59,7 +59,7 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
> s->tpm_state = state;
> s->recv_data_callback = datacb;
>
> - return k->ops->init(s);
> + return k->ops->init ? k->ops->init(s) : 0;
> }
>
> int tpm_backend_startup_tpm(TPMBackend *s)
> @@ -73,13 +73,15 @@ int tpm_backend_startup_tpm(TPMBackend *s)
> NULL);
> g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT,
> NULL);
>
> - return k->ops->startup_tpm(s);
> + return k->ops->startup_tpm ? k->ops->startup_tpm(s) : 0;
> }
>
> bool tpm_backend_had_startup_error(TPMBackend *s)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> + assert(k->ops->had_startup_error);
> +
> return k->ops->had_startup_error(s);
> }
>
> @@ -87,6 +89,8 @@ size_t tpm_backend_realloc_buffer(TPMBackend *s,
> TPMSizedBuffer *sb)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> + assert(k->ops->realloc_buffer);
> +
> return k->ops->realloc_buffer(sb);
> }
>
> @@ -100,7 +104,9 @@ void tpm_backend_reset(TPMBackend *s)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> - k->ops->reset(s);
> + if (k->ops->reset) {
> + k->ops->reset(s);
> + }
>
> tpm_backend_thread_end(s);
> }
> @@ -109,6 +115,8 @@ void tpm_backend_cancel_cmd(TPMBackend *s)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> + g_assert(k->ops->cancel_cmd);
>
Let's use assert() for consistency in the file
> +
> k->ops->cancel_cmd(s);
> }
>
> @@ -116,20 +124,24 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend
> *s)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> - return k->ops->get_tpm_established_flag(s);
> + return k->ops->get_tpm_established_flag ?
> + k->ops->get_tpm_established_flag(s) : false;
> }
>
> int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> - return k->ops->reset_tpm_established_flag(s, locty);
> + return k->ops->reset_tpm_established_flag ?
> + k->ops->reset_tpm_established_flag(s, locty) : 0;
> }
>
> TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> + assert(k->ops->get_tpm_version);
> +
> return k->ops->get_tpm_version(s);
> }
>
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index 815a72e..bbe9e5a 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -227,15 +227,6 @@ static void tpm_passthrough_handle_request(TPMBackend
> *tb, TPMBackendCmd cmd)
> }
> }
>
> -/*
> - * Start the TPM (thread). If it had been started before, then terminate
> - * and start it again.
> - */
> -static int tpm_passthrough_startup_tpm(TPMBackend *tb)
> -{
> - return 0;
> -}
> -
> static void tpm_passthrough_reset(TPMBackend *tb)
> {
> TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> @@ -247,11 +238,6 @@ static void tpm_passthrough_reset(TPMBackend *tb)
> tpm_pt->had_startup_error = false;
> }
>
> -static int tpm_passthrough_init(TPMBackend *tb)
> -{
> - return 0;
> -}
> -
> static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
> {
> return false;
> @@ -455,8 +441,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
> .opts = tpm_passthrough_cmdline_opts,
> .desc = tpm_passthrough_create_desc,
> .create = tpm_passthrough_create,
> - .init = tpm_passthrough_init,
> - .startup_tpm = tpm_passthrough_startup_tpm,
> .realloc_buffer = tpm_passthrough_realloc_buffer,
> .reset = tpm_passthrough_reset,
> .had_startup_error = tpm_passthrough_get_startup_error,
> --
> 2.7.4
>
>
othewise,
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 5/8] tmp backend: Add new api to read backend TpmInfo
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
@ 2017-05-02 13:35 ` Eric Blake
2017-05-04 9:05 ` Amarnath Valluri
2017-05-04 11:17 ` [Qemu-devel] [PATCH v4 " Amarnath Valluri
0 siblings, 2 replies; 46+ messages in thread
From: Eric Blake @ 2017-05-02 13:35 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel
Cc: patrick.ohly, marcandre.lureau, stefanb, Markus Armbruster
[-- Attachment #1: Type: text/plain, Size: 3406 bytes --]
On 05/02/2017 06:52 AM, Amarnath Valluri wrote:
> TPM configuration options are backend implementation details and shall not be
> part of base TPMBackend object, and these shall not be accessed directly outside
> of the class, hence added a new interface method, get_tpm_options() to
> TPMDriverOps., which shall be implemented by the derived classes to return
> configured tpm options.
>
> A new tpm backend api - tpm_backend_query_tpm() which uses _get_tpm_options() to
> prepare TpmInfo.
>
> Made TPMPassthroughOptions type inherited from newly defined TPMOptions base type.
> The TPMOptions base type is intentionally left empty and supposed to be
> inherited by all backend implementations to define their tpm configuration
> options.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> ---
> +++ b/qapi-schema.json
> @@ -5137,6 +5137,16 @@
> { 'command': 'query-tpm-types', 'returns': ['TpmType'] }
>
> ##
> +# @TPMOptions:
> +#
> +# Base type for TPM options
> +#
> +# Since: 2.10
> +##
> +{ 'struct': 'TPMOptions',
> + 'data': { } }
> +
> +##
> # @TPMPassthroughOptions:
> #
> # Information about the TPM passthrough type
> @@ -5148,20 +5158,9 @@
> #
> # Since: 1.5
> ##
> -{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
> - '*cancel-path' : 'str'} }
> +{ 'struct': 'TPMPassthroughOptions', 'base': 'TPMOptions',
> + 'data': { '*path' : 'str', '*cancel-path' : 'str'} }
>
> -##
> -# @TpmTypeOptions:
> -#
> -# A union referencing different TPM backend types' configuration options
> -#
> -# @type: 'passthrough' The configuration options for the TPM passthrough type
> -#
> -# Since: 1.5
> -##
> -{ 'union': 'TpmTypeOptions',
> - 'data': { 'passthrough' : 'TPMPassthroughOptions' } }
Getting rid of a simple union is nice. However,
>
> ##
> # @TPMInfo:
> @@ -5170,6 +5169,8 @@
> #
> # @id: The Id of the TPM
> #
> +# @type: The TPM backend type
> +#
> # @model: The TPM frontend model
> #
> # @options: The TPM (backend) type configuration options
> @@ -5178,8 +5179,9 @@
> ##
> { 'struct': 'TPMInfo',
> 'data': {'id': 'str',
> + 'type': 'TpmType',
> 'model': 'TpmModel',
> - 'options': 'TpmTypeOptions' } }
> + 'options': 'TPMOptions' } }
>
> ##
> # @query-tpm:
> @@ -5196,13 +5198,12 @@
> # <- { "return":
> # [
> # { "model": "tpm-tis",
> +# "type": "passthrough",
> # "options":
> -# { "type": "passthrough",
> -# "data":
> -# { "cancel-path": "/sys/class/misc/tpm0/device/cancel",
> -# "path": "/dev/tpm0"
> -# }
> -# },
> +# {
> +# "cancel-path": "/sys/class/misc/tpm0/device/cancel",
> +# "path": "/dev/tpm0"
> +# },
> # "id": "tpm0"
Doing it in a manner that is NOT backwards-compatible (as evidenced by
your change to the output text) is NOT good. It will break any existing
client that was expecting to parse information in the old layout.
I'm afraid you're going to have to fix this to not break QMP wire
compatibility.
--
Eric Blake, Principal Software Engineer
Red Hat, Inc. +1-919-301-3266
Virtualization: qemu.org | libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 7/8] tpm-passthrough: move reusable code to utils
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
@ 2017-05-02 15:54 ` Marc-André Lureau
0 siblings, 0 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 15:54 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
Hi
On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> ---
> hw/tpm/tpm_passthrough.c | 64
> ++++--------------------------------------------
> hw/tpm/tpm_util.c | 25 +++++++++++++++++++
> hw/tpm/tpm_util.h | 4 +++
> 3 files changed, 34 insertions(+), 59 deletions(-)
>
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index a7da0f8..b00efd5 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -68,27 +68,6 @@ typedef struct TPMPassthruState TPMPassthruState;
>
> static void tpm_passthrough_cancel_cmd(TPMBackend *tb);
>
> -static int tpm_passthrough_unix_write(int fd, const uint8_t *buf,
> uint32_t len)
> -{
> - int ret, remain;
> -
> - remain = len;
> - while (remain > 0) {
> - ret = write(fd, buf, remain);
> - if (ret < 0) {
> - if (errno != EINTR && errno != EAGAIN) {
> - return -1;
> - }
> - } else if (ret == 0) {
> - break;
> - } else {
> - buf += ret;
> - remain -= ret;
> - }
> - }
> - return len - remain;
> -}
> -
> static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
> {
> int ret;
> @@ -102,45 +81,12 @@ static int tpm_passthrough_unix_read(int fd, uint8_t
> *buf, uint32_t len)
> }
> return ret;
> }
> -
> -static uint32_t tpm_passthrough_get_size_from_buffer(const uint8_t *buf)
> -{
> - struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)buf;
> -
> - return be32_to_cpu(resp->len);
> -}
> -
>
Why not keep that function? Possibly in header as inline?
> -/*
> - * Write an error message in the given output buffer.
> - */
> -static void tpm_write_fatal_error_response(uint8_t *out, uint32_t out_len)
> -{
> - if (out_len >= sizeof(struct tpm_resp_hdr)) {
> - struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)out;
> -
> - resp->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
> - resp->len = cpu_to_be32(sizeof(struct tpm_resp_hdr));
> - resp->errcode = cpu_to_be32(TPM_FAIL);
> - }
> -}
> -
> -static bool tpm_passthrough_is_selftest(const uint8_t *in, uint32_t
> in_len)
> -{
> - struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in;
> -
> - if (in_len >= sizeof(*hdr)) {
> - return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest);
> - }
> -
> - return false;
> -}
> -
> 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)
> {
> - int ret;
> + ssize_t ret;
> bool is_selftest;
> const struct tpm_resp_hdr *hdr;
>
> @@ -148,9 +94,9 @@ static int
> tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
> tpm_pt->tpm_executing = true;
> *selftest_done = false;
>
> - is_selftest = tpm_passthrough_is_selftest(in, in_len);
> + is_selftest = tpm_util_is_selftest(in, in_len);
>
> - ret = tpm_passthrough_unix_write(tpm_pt->tpm_fd, in, in_len);
> + ret = qemu_write_full(tpm_pt->tpm_fd, (const void *)in,
> (size_t)in_len);
> if (ret != in_len) {
> if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
> error_report("tpm_passthrough: error while transmitting data "
> @@ -170,7 +116,7 @@ static int
> tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
> strerror(errno), errno);
> }
> } else if (ret < sizeof(struct tpm_resp_hdr) ||
> - tpm_passthrough_get_size_from_buffer(out) != ret) {
> + be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
> ret = -1;
> error_report("tpm_passthrough: received invalid response "
> "packet from TPM");
> @@ -183,7 +129,7 @@ static int
> tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
>
> err_exit:
> if (ret < 0) {
> - tpm_write_fatal_error_response(out, out_len);
> + tpm_util_write_fatal_error_response(out, out_len);
> }
>
> tpm_pt->tpm_executing = false;
> diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c
> index 7b35429..fb929f6 100644
> --- a/hw/tpm/tpm_util.c
> +++ b/hw/tpm/tpm_util.c
> @@ -24,6 +24,31 @@
> #include "tpm_int.h"
>
> /*
> + * Write an error message in the given output buffer.
> + */
> +void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len)
> +{
> + if (out_len >= sizeof(struct tpm_resp_hdr)) {
> + struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)out;
> +
> + resp->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
> + resp->len = cpu_to_be32(sizeof(struct tpm_resp_hdr));
> + resp->errcode = cpu_to_be32(TPM_FAIL);
> + }
> +}
> +
> +bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len)
> +{
> + struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in;
> +
> + if (in_len >= sizeof(*hdr)) {
> + return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest);
> + }
> +
> + return false;
> +}
> +
> +/*
> * A basic test of a TPM device. We expect a well formatted response
> header
> * (error response is fine) within one second.
> */
> diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h
> index df76245..2f7c961 100644
> --- a/hw/tpm/tpm_util.h
> +++ b/hw/tpm/tpm_util.h
> @@ -24,6 +24,10 @@
>
> #include "sysemu/tpm_backend.h"
>
> +void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len);
> +
> +bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len);
> +
> int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version);
>
> #endif /* TPM_TPM_UTIL_H */
>
looks good otherwise
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class Amarnath Valluri
@ 2017-05-02 15:54 ` Marc-André Lureau
2017-05-04 9:25 ` Amarnath Valluri
0 siblings, 1 reply; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 15:54 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
Hi
On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> Provide base implementation of realloc_buffer(), so that backend
> implementations
> can resue.
>
>
I doubt that base class facility helps at this point, and would suggest
moving it to tpm-tis only.
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> ---
> backends/tpm.c | 9 ++++++++-
> hw/tpm/tpm_passthrough.c | 12 ------------
> 2 files changed, 8 insertions(+), 13 deletions(-)
>
> diff --git a/backends/tpm.c b/backends/tpm.c
> index 4a6358e..f048c1d 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -88,8 +88,15 @@ bool tpm_backend_had_startup_error(TPMBackend *s)
> size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
> + if (!k->ops->realloc_buffer) {
> + size_t wanted_size = 4096; /* Linux tpm.c buffer size */
>
> - assert(k->ops->realloc_buffer);
> + if (sb->size != wanted_size) {
> + sb->buffer = g_realloc(sb->buffer, wanted_size);
> + sb->size = wanted_size;
> + }
> + return sb->size;
> + }
>
> return k->ops->realloc_buffer(sb);
> }
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index 2efced1..a7da0f8 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -258,17 +258,6 @@ static bool
> tpm_passthrough_get_startup_error(TPMBackend *tb)
> return tpm_pt->had_startup_error;
> }
>
> -static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
> -{
> - size_t wanted_size = 4096; /* Linux tpm.c buffer size */
> -
> - if (sb->size != wanted_size) {
> - sb->buffer = g_realloc(sb->buffer, wanted_size);
> - sb->size = wanted_size;
> - }
> - return sb->size;
> -}
> -
> static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
> {
> TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> @@ -470,7 +459,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
> .opts = tpm_passthrough_cmdline_opts,
> .desc = tpm_passthrough_create_desc,
> .create = tpm_passthrough_create,
> - .realloc_buffer = tpm_passthrough_realloc_buffer,
> .reset = tpm_passthrough_reset,
> .had_startup_error = tpm_passthrough_get_startup_error,
> .cancel_cmd = tpm_passthrough_cancel_cmd,
> --
> 2.7.4
>
> --
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator Amarnath Valluri
@ 2017-05-02 16:05 ` Marc-André Lureau
2017-05-02 16:32 ` Stefan Berger
2017-05-02 16:58 ` Stefan Berger
0 siblings, 2 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 16:05 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
Hi
On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> This change introduces a new TPM backend driver that can communicate with
> swtpm(software TPM emulator) using unix domain socket interface.
>
> Swtpm uses two unix sockets, one for plain TPM commands and responses, and
> one
> for out-of-band control messages.
>
>
Let's not forget to mention the external protocol this backend rely on:
https://github.com/stefanberger/swtpm/wiki/Control-Channel-Specification
The protocol documentation is quite limited.
(I still question the need to rely on a public protocol, and a seperate
helper process project. If we had a qemu-swtpm, we could more easily evolve
the protocol in the future)
The swtpm and associated tools can be found here:
> https://github.com/stefanberger/swtpm
>
> Usage:
> # setup TPM state directory
> mkdir /tmp/mytpm
> chown -R tss:root /tmp/mytpm
> /usr/bin/swtpm_setup --tpm-state /tmp/mytpm --createek
>
> # Ask qemu to use TPM emulator with given tpm state directory
> qemu-system-x86_64 \
> [...] \
> -tpmdev
> emulator,id=tpm0,tpmstatedir=/tmp/mytpm,logfile=/tmp/swtpm.log \
> -device tpm-tis,tpmdev=tpm0 \
> [...]
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> ---
> configure | 15 +-
> hmp.c | 21 ++
> hw/tpm/Makefile.objs | 1 +
> hw/tpm/tpm_emulator.c | 943
> ++++++++++++++++++++++++++++++++++++++++++++++++++
> hw/tpm/tpm_ioctl.h | 243 +++++++++++++
> qapi-schema.json | 36 +-
> qemu-options.hx | 53 ++-
> tpm.c | 2 +-
> 8 files changed, 1305 insertions(+), 9 deletions(-)
> create mode 100644 hw/tpm/tpm_emulator.c
> create mode 100644 hw/tpm/tpm_ioctl.h
>
> diff --git a/configure b/configure
> index be4d326..a933ec7 100755
> --- a/configure
> +++ b/configure
> @@ -3359,10 +3359,15 @@ fi
> ##########################################
> # TPM passthrough is only on x86 Linux
>
> -if test "$targetos" = Linux && test "$cpu" = i386 -o "$cpu" = x86_64; then
> - tpm_passthrough=$tpm
> +if test "$targetos" = Linux; then
> + tpm_emulator=$tpm
> + if test "$cpu" = i386 -o "$cpu" = x86_64; then
> + tpm_passthrough=$tpm
> + else
> + tpm_passthrough=no
> + fi
> else
> - tpm_passthrough=no
> + tpm_emulator=no
> fi
>
> ##########################################
> @@ -5137,6 +5142,7 @@ echo "gcov enabled $gcov"
> echo "TPM support $tpm"
> echo "libssh2 support $libssh2"
> echo "TPM passthrough $tpm_passthrough"
> +echo "TPM emulator $tpm_emulator"
> echo "QOM debugging $qom_cast_debug"
> echo "lzo support $lzo"
> echo "snappy support $snappy"
> @@ -5716,6 +5722,9 @@ if test "$tpm" = "yes"; then
> if test "$tpm_passthrough" = "yes"; then
> echo "CONFIG_TPM_PASSTHROUGH=y" >> $config_host_mak
> fi
> + if test "$tpm_emulator" = "yes"; then
> + echo "CONFIG_TPM_EMULATOR=y" >> $config_host_mak
> + fi
> fi
>
> echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
> diff --git a/hmp.c b/hmp.c
> index 9caf7c8..e7fd426 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -937,6 +937,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
> Error *err = NULL;
> unsigned int c = 0;
> TPMPassthroughOptions *tpo;
> + TPMEmulatorOptions *teo;
>
> info_list = qmp_query_tpm(&err);
> if (err) {
> @@ -966,6 +967,26 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
> tpo->has_cancel_path ? ",cancel-path=" : "",
> tpo->has_cancel_path ? tpo->cancel_path : "");
> break;
> + case TPM_TYPE_EMULATOR:
> + teo = (TPMEmulatorOptions *)(ti->options);
> + monitor_printf(mon, ",tmpstatedir=%s", teo->tpmstatedir);
> + monitor_printf(mon, ",spawn=%s", teo->spawn ? "on" : "off");
> + if (teo->has_path) {
> + monitor_printf(mon, ",path=%s", teo->path);
> + }
> + if (teo->has_data_path) {
> + monitor_printf(mon, ",data-path=%s", teo->data_path);
> + }
> + if (teo->has_ctrl_path) {
> + monitor_printf(mon, ",ctrl-path=%s", teo->ctrl_path);
> + }
> + if (teo->has_logfile) {
> + monitor_printf(mon, ",logfile=%s", teo->logfile);
> + }
> + if (teo->has_loglevel) {
> + monitor_printf(mon, ",loglevel=%ld", teo->loglevel);
> + }
> + break;
> default:
> break;
> }
> diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
> index 64cecc3..41f0b7a 100644
> --- a/hw/tpm/Makefile.objs
> +++ b/hw/tpm/Makefile.objs
> @@ -1,2 +1,3 @@
> common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
> common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o tpm_util.o
> +common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o tpm_util.o
> diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
> new file mode 100644
> index 0000000..b480a53
> --- /dev/null
> +++ b/hw/tpm/tpm_emulator.c
> @@ -0,0 +1,943 @@
> +/*
> + * emulator TPM driver
> + *
> + * Copyright (c) 2017 Intel Corporation
> + * Author: Amarnath Valluri <amarnath.valluri@intel.com>
> + *
> + * Copyright (c) 2010 - 2013 IBM Corporation
> + * Authors:
> + * Stefan Berger <stefanb@us.ibm.com>
> + *
> + * Copyright (C) 2011 IAIK, Graz University of Technology
> + * Author: Andreas Niederl
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <
> http://www.gnu.org/licenses/>
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/error-report.h"
> +#include "qemu/sockets.h"
> +#include "io/channel-socket.h"
> +#include "sysemu/tpm_backend.h"
> +#include "tpm_int.h"
> +#include "hw/hw.h"
> +#include "hw/i386/pc.h"
> +#include "tpm_util.h"
> +#include "tpm_ioctl.h"
> +#include "qapi/error.h"
> +
> +#include <fcntl.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <stdio.h>
> +
> +#define DEBUG_TPM 0
> +
> +#define DPRINT(fmt, ...) do { \
> + if (DEBUG_TPM) { \
> + fprintf(stderr, fmt, ## __VA_ARGS__); \
> + } \
> +} while (0);
> +
> +#define DPRINTF(fmt, ...) DPRINT("tpm-emulator: "fmt"\n", __VA_ARGS__)
> +
> +#define TYPE_TPM_EMULATOR "tpm-emulator"
> +#define TPM_EMULATOR(obj) \
> + OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
> +
> +static const TPMDriverOps tpm_emulator_driver;
> +
> +/* data structures */
> +typedef struct TPMEmulator {
> + TPMBackend parent;
> +
> + TPMEmulatorOptions *ops;
> + QIOChannel *data_ioc;
> + QIOChannel *ctrl_ioc;
> + bool op_executing;
> + bool op_canceled;
> + bool child_running;
> + TPMVersion tpm_version;
> + ptm_cap caps; /* capabilities of the TPM */
> + uint8_t cur_locty_number; /* last set locality */
> + QemuMutex state_lock;
> +} TPMEmulator;
> +
> +#define TPM_DEFAULT_EMULATOR "swtpm"
> +#define TPM_DEFAULT_LOGLEVEL 5
> +#define TPM_EMULATOR_PIDFILE "/tmp/qemu-tpm.pid"
> +#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) ==
> (cap))
> +
> +static int tpm_emulator_ctrlcmd(QIOChannel *ioc, unsigned long cmd, void
> *msg,
> + size_t msg_len_in, size_t msg_len_out)
> +{
> + ssize_t n;
> +
> + uint32_t cmd_no = cpu_to_be32(cmd);
> + struct iovec iov[2] = {
> + { .iov_base = &cmd_no, .iov_len = sizeof(cmd_no), },
> + { .iov_base = msg, .iov_len = msg_len_in, },
> + };
> +
> + n = qio_channel_writev(ioc, iov, 2, NULL);
> + if (n > 0) {
> + if (msg_len_out > 0) {
> + n = qio_channel_read(ioc, (char *)msg, msg_len_out, NULL);
> + /* simulate ioctl return value */
> + if (n > 0) {
> + n = 0;
> + }
> + } else {
> + n = 0;
> + }
> + }
> + return n;
> +}
> +
> +static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_pt,
> + const uint8_t *in, uint32_t in_len,
> + uint8_t *out, uint32_t out_len,
> + bool *selftest_done)
> +{
> + ssize_t ret;
> + bool is_selftest;
> + const struct tpm_resp_hdr *hdr;
> +
> + if (!tpm_pt->child_running) {
> + return -1;
> + }
> +
> + tpm_pt->op_canceled = false;
> + tpm_pt->op_executing = true;
> + *selftest_done = false;
> +
> + is_selftest = tpm_util_is_selftest(in, in_len);
> +
> + ret = qio_channel_write(tpm_pt->data_ioc, (const char *)in,
> (size_t)in_len,
> + NULL);
> + if (ret != in_len) {
> + if (!tpm_pt->op_canceled || errno != ECANCELED) {
> + error_report("tpm-emulator: error while transmitting data "
> + "to TPM: %s (%i)", strerror(errno), errno);
> + }
> + goto err_exit;
> + }
> +
> + tpm_pt->op_executing = false;
> +
> + ret = qio_channel_read(tpm_pt->data_ioc, (char *)out, (size_t)out_len,
> + NULL);
> + if (ret < 0) {
> + if (!tpm_pt->op_canceled || errno != ECANCELED) {
> + error_report("tpm-emulator: error while reading data from "
> + "TPM: %s (%i)", strerror(errno), errno);
> + }
> + } else if (ret < sizeof(struct tpm_resp_hdr) ||
> + be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
> + ret = -1;
> + error_report("tpm-emulator: received invalid response "
> + "packet from TPM");
> + }
> +
> + if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) {
> + hdr = (struct tpm_resp_hdr *)out;
> + *selftest_done = (be32_to_cpu(hdr->errcode) == 0);
> + }
> +
> +err_exit:
> + if (ret < 0) {
> + tpm_util_write_fatal_error_response(out, out_len);
> + }
> +
> + tpm_pt->op_executing = false;
> +
> + return ret;
> +}
> +
> +static int tpm_emulator_set_locality(TPMEmulator *tpm_pt,
> + uint8_t locty_number)
> +{
> + ptm_loc loc;
> +
> + if (!tpm_pt->child_running) {
> + return -1;
> + }
> +
> + DPRINTF("%s : locality: 0x%x", __func__, locty_number);
> +
> + if (tpm_pt->cur_locty_number != locty_number) {
> + DPRINTF("setting locality : 0x%x", locty_number);
> + loc.u.req.loc = locty_number;
> + if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_SET_LOCALITY, &loc,
> + sizeof(loc), sizeof(loc)) < 0) {
> + error_report("tpm-emulator: could not set locality : %s",
> + strerror(errno));
> + return -1;
> + }
> + loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
> + if (loc.u.resp.tpm_result != 0) {
> + error_report("tpm-emulator: TPM result for set locality :
> 0x%x",
> + loc.u.resp.tpm_result);
> + return -1;
> + }
> + tpm_pt->cur_locty_number = locty_number;
> + }
> + return 0;
> +}
> +
> +static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> + TPMLocality *locty = NULL;
> + bool selftest_done = false;
> +
> + DPRINTF("processing command type %d", cmd);
> +
> + switch (cmd) {
> + case TPM_BACKEND_CMD_PROCESS_CMD:
> + qemu_mutex_lock(&tpm_pt->state_lock);
> + locty = tb->tpm_state->locty_data;
> + if (tpm_emulator_set_locality(tpm_pt,
> + tb->tpm_state->locty_number) < 0) {
> + tpm_util_write_fatal_error_response(locty->r_buffer.buffer,
> + locty->r_buffer.size);
> + } else {
> + tpm_emulator_unix_tx_bufs(tpm_pt, locty->w_buffer.buffer,
> + locty->w_offset, locty->r_buffer.buffer,
> + locty->r_buffer.size, &selftest_done);
> + }
> + tb->recv_data_callback(tb->tpm_state, tb->tpm_state->locty_number,
> + selftest_done);
> + qemu_mutex_unlock(&tpm_pt->state_lock);
> + break;
> + case TPM_BACKEND_CMD_INIT:
> + case TPM_BACKEND_CMD_END:
> + case TPM_BACKEND_CMD_TPM_RESET:
> + /* nothing to do */
> + break;
> + }
> +}
> +
> +/*
> + * Gracefully shut down the external unixio TPM
> + */
> +static void tpm_emulator_shutdown(TPMEmulator *tpm_pt)
> +{
> + ptm_res res;
> +
> + if (!tpm_pt->child_running) {
> + return;
> + }
> +
> + if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_SHUTDOWN, &res, 0,
> + sizeof(res)) < 0) {
> + error_report("tpm-emulator: Could not cleanly shutdown the TPM:
> %s",
> + strerror(errno));
> + } else if (res != 0) {
> + error_report("tpm-emulator: TPM result for sutdown: 0x%x",
> + be32_to_cpu(res));
> + }
> +}
> +
> +static int tpm_emulator_probe_caps(TPMEmulator *tpm_pt)
> +{
> + if (!tpm_pt->child_running) {
> + return -1;
> + }
> +
> + DPRINTF("%s", __func__);
> + if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_GET_CAPABILITY,
> + &tpm_pt->caps, 0, sizeof(tpm_pt->caps)) < 0) {
> + error_report("tpm-emulator: probing failed : %s",
> strerror(errno));
> + return -1;
> + }
> +
> + tpm_pt->caps = be64_to_cpu(tpm_pt->caps);
> +
> + DPRINTF("capbilities : 0x%lx", tpm_pt->caps);
> +
> + return 0;
> +}
> +
> +static int tpm_emulator_check_caps(TPMEmulator *tpm_pt)
> +{
> + ptm_cap caps = 0;
> + const char *tpm = NULL;
> +
> + /* check for min. required capabilities */
> + switch (tpm_pt->tpm_version) {
> + case TPM_VERSION_1_2:
> + caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN |
> PTM_CAP_GET_TPMESTABLISHED |
> + PTM_CAP_SET_LOCALITY;
> + tpm = "1.2";
> + break;
> + case TPM_VERSION_2_0:
> + caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN |
> PTM_CAP_GET_TPMESTABLISHED |
> + PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED;
> + tpm = "2";
> + break;
> + case TPM_VERSION_UNSPEC:
> + error_report("tpm-emulator: TPM version has not been set");
> + return -1;
> + }
> +
> + if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_pt, caps)) {
> + error_report("tpm-emulator: TPM does not implement minimum set of
> "
> + "required capabilities for TPM %s (0x%x)", tpm,
> (int)caps);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int tpm_emulator_init_tpm(TPMEmulator *tpm_pt)
> +{
> + ptm_init init;
> + ptm_res res;
> +
> + if (!tpm_pt->child_running) {
> + return -1;
> + }
> +
> + DPRINTF("%s", __func__);
> + if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_INIT, &init,
> sizeof(init),
> + sizeof(init)) < 0) {
> + error_report("tpm-emulator: could not send INIT: %s",
> + strerror(errno));
> + return -1;
> + }
> +
> + res = be32_to_cpu(init.u.resp.tpm_result);
> + if (res) {
> + error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x", res);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int tpm_emulator_startup_tpm(TPMBackend *tb)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> +
> + DPRINTF("%s", __func__);
> +
> + tpm_emulator_init_tpm(tpm_pt) ;
> +
> + return 0;
> +}
> +
> +static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> + ptm_est est;
> +
> + DPRINTF("%s", __func__);
> + if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_GET_TPMESTABLISHED,
> &est, 0,
> + sizeof(est)) < 0) {
> + error_report("tpm-emulator: Could not get the TPM established
> flag: %s",
> + strerror(errno));
> + return false;
> + }
> + DPRINTF("established flag: %0x", est.u.resp.bit);
> +
> + return (est.u.resp.bit != 0);
> +}
> +
> +static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
> + uint8_t locty)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> + ptm_reset_est reset_est;
> + ptm_res res;
> +
> + /* only a TPM 2.0 will support this */
> + if (tpm_pt->tpm_version == TPM_VERSION_2_0) {
> + reset_est.u.req.loc = tpm_pt->cur_locty_number;
> +
> + if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc,
> CMD_RESET_TPMESTABLISHED,
> + &reset_est, sizeof(reset_est),
> + sizeof(reset_est)) < 0) {
> + error_report("tpm-emulator: Could not reset the establishment
> bit: "
> + "%s", strerror(errno));
> + return -1;
> + }
> +
> + res = be32_to_cpu(reset_est.u.resp.tpm_result);
> + if (res) {
> + error_report("tpm-emulator: TPM result for rest establixhed
> flag: "
> + "0x%x", res);
> + return -1;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static bool tpm_emulator_had_startup_error(TPMBackend *tb)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> +
> + return !tpm_pt->child_running;
> +}
> +
> +static void tpm_emulator_cancel_cmd(TPMBackend *tb)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> + ptm_res res;
> +
> + /*
> + * As of Linux 3.7 the tpm_tis driver does not properly cancel
> + * commands on all TPM manufacturers' TPMs.
> + * Only cancel if we're busy so we don't cancel someone else's
> + * command, e.g., a command executed on the host.
> + */
> + if (tpm_pt->op_executing) {
> + if (TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_pt,
> PTM_CAP_CANCEL_TPM_CMD)) {
> + if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc,
> CMD_CANCEL_TPM_CMD, &res,
> + 0, sizeof(res)) < 0) {
> + error_report("tpm-emulator: Could not cancel command: %s",
> + strerror(errno));
> + } else if (res != 0) {
> + error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
> + be32_to_cpu(res));
> + } else {
> + tpm_pt->op_canceled = true;
> + }
> + }
> + }
> +}
> +
> +static void tpm_emulator_reset(TPMBackend *tb)
> +{
> + DPRINTF("%s", __func__);
> +
> + tpm_emulator_cancel_cmd(tb);
> +}
> +
> +static const char *tpm_emulator_desc(void)
> +{
> + return "TPM emulator backend driver";
> +}
> +
> +static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> +
> + return tpm_pt->tpm_version;
> +}
> +
> +static gboolean tpm_emulator_fd_handler(QIOChannel *ioc, GIOCondition cnd,
> + void *opaque)
> +{
> + TPMEmulator *tpm_pt = opaque;
> +
> + if (cnd & G_IO_ERR || cnd & G_IO_HUP) {
> + error_report("TPM backend disappeared");
> + tpm_pt->child_running = false;
> + return false;
> + }
> +
> + return true;
> +}
> +
> +static QIOChannel *_iochannel_new(const char *path, int fd, Error **err)
> +{
> + int socket = path ? unix_connect(path, err) : fd;
> + if (socket < 0) {
> + return NULL;
> + }
> +
> + return QIO_CHANNEL(qio_channel_socket_new_fd(socket, err));
> +}
> +
> +static int tpm_emulator_spawn_emulator(TPMEmulator *tpm_pt)
> +{
> + int fds[2] = { -1, -1 };
> + int ctrl_fds[2] = { -1, -1 };
> + pid_t cpid;
> +
> + if (!tpm_pt->ops->has_data_path) {
> + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) < 0) {
> + return -1;
> + }
> + }
> +
> + if (!tpm_pt->ops->has_ctrl_path) {
> + if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ctrl_fds) < 0) {
> + if (!tpm_pt->ops->has_data_path) {
> + closesocket(fds[0]);
> + closesocket(fds[1]);
> + }
> + return -1;
> + }
> + }
> +
> + cpid = qemu_fork(NULL);
> + if (cpid < 0) {
> + error_report("tpm-emulator: Fork failure: %s", strerror(errno));
> + if (!tpm_pt->ops->has_data_path) {
> + closesocket(fds[0]);
> + closesocket(fds[1]);
> + }
> + if (!tpm_pt->ops->has_ctrl_path) {
> + closesocket(ctrl_fds[0]);
> + closesocket(ctrl_fds[1]);
> + }
> + return -1;
> + }
> +
> + unlink(TPM_EMULATOR_PIDFILE);
> +
> + if (cpid == 0) { /* CHILD */
> + enum {
> + PARAM_PATH,
> + PARAM_IFACE,
> + PARAM_SERVER, PARAM_SERVER_ARGS,
> + PARAM_CTRL, PARAM_CTRL_ARGS,
> + PARAM_STATE, PARAM_STATE_ARGS,
> + PARAM_PIDFILE, PARAM_PIDFILE_ARGS,
> + PARAM_LOG, PARAM_LOG_ARGS,
> + PARAM_MAX
> + };
> +
> + int i;
> + int data_fd = -1, ctrl_fd = -1;
> + char *argv[PARAM_MAX + 1];
> +
> + /* close all unused inherited sockets */
> + if (fds[0] >= 0) {
> + closesocket(fds[0]);
> + }
> + if (ctrl_fds[0] >= 0) {
> + closesocket(ctrl_fds[0]);
> + }
> +
> + i = STDERR_FILENO + 1;
> + if (fds[1] >= 0) {
> + data_fd = dup2(fds[1], i++);
> + if (data_fd < 0) {
> + error_report("tpm-emulator: dup2() failure - %s",
> + strerror(errno));
> + goto exit_child;
> + }
> + }
> + if (ctrl_fds[1] >= 0) {
> + ctrl_fd = dup2(ctrl_fds[1], i++);
> + if (ctrl_fd < 0) {
> + error_report("tpm-emulator: dup2() failure - %s",
> + strerror(errno));
> + goto exit_child;
> + }
> + }
> + for ( ; i < sysconf(_SC_OPEN_MAX); i++) {
> + close(i);
> + }
> +
> + argv[PARAM_MAX] = NULL;
> + argv[PARAM_PATH] = g_strdup(tpm_pt->ops->path);
> + argv[PARAM_IFACE] = g_strdup("socket");
> + if (tpm_pt->ops->has_data_path) {
> + argv[PARAM_SERVER] = g_strdup("--server");
> + argv[PARAM_SERVER_ARGS] =
> g_strdup_printf("type=unixio,path=%s",
> + tpm_pt->ops->data_path);
> + } else {
> + argv[PARAM_SERVER] = g_strdup("--fd");
> + argv[PARAM_SERVER_ARGS] = g_strdup_printf("%d", data_fd);
> + }
> +
> + argv[PARAM_CTRL] = g_strdup("--ctrl");
> + if (tpm_pt->ops->has_ctrl_path) {
> + argv[PARAM_CTRL_ARGS] = g_strdup_printf("type=unixio,path=%s",
> +
> tpm_pt->ops->ctrl_path);
> + } else {
> + argv[PARAM_CTRL_ARGS] =
> g_strdup_printf("type=unixio,clientfd=%d",
> + ctrl_fd);
> + }
> +
> + argv[PARAM_STATE] = g_strdup("--tpmstate");
> + argv[PARAM_STATE_ARGS] = g_strdup_printf("dir=%s",
> + tpm_pt->ops->tpmstatedir);
> + argv[PARAM_PIDFILE] = g_strdup("--pid");
> + argv[PARAM_PIDFILE_ARGS] = g_strdup_printf("file=%s",
> + TPM_EMULATOR_PIDFILE);
> + if (tpm_pt->ops->has_logfile) {
> + argv[PARAM_LOG] = g_strdup("--log");
> + argv[PARAM_LOG_ARGS] = g_strdup_printf("file=%s,level=%d",
> + tpm_pt->ops->logfile, (int)tpm_pt->ops->loglevel);
> + } else {
> + /* truncate logs */
> + argv[PARAM_LOG] = NULL;
> + }
> + DPRINTF("%s", "Running cmd: ")
> + for (i = 0; argv[i]; i++) {
> + DPRINT(" %s", argv[i])
> + }
> + DPRINT("\n")
> + if (execv(tpm_pt->ops->path, (char * const *)argv) < 0) {
> + error_report("execv() failure : %s", strerror(errno));
> + }
> +
> +exit_child:
> + g_strfreev(argv);
> + if (data_fd >= 0) {
> + closesocket(data_fd);
> + }
> + if (ctrl_fd >= 0) {
> + closesocket(ctrl_fd);
> + }
> +
> + _exit(1);
> + } else { /* self */
> + struct stat st;
> + DPRINTF("child pid: %d", cpid);
> + int rc;
> + useconds_t usec = 100 * 1000L; /* wait for 100 milliseconds */
> + useconds_t timeout = 10; /* max 1 second */
> +
> + /* close unused sockets */
> + if (fds[1] >= 0) {
> + closesocket(fds[1]);
> + }
> + if (ctrl_fds[1] >= 0) {
> + closesocket(ctrl_fds[1]);
> + }
> +
> + tpm_pt->data_ioc = _iochannel_new(tpm_pt->ops->data_path, fds[0],
> NULL);
> + if (!tpm_pt->data_ioc) {
> + error_report("tpm-emulator: Unable to connect socket : %s",
> + tpm_pt->ops->data_path);
> + goto err_kill_child;
> + }
> +
> + tpm_pt->ctrl_ioc = _iochannel_new(tpm_pt->ops->ctrl_path,
> ctrl_fds[0],
> + NULL);
> + if (!tpm_pt->ctrl_ioc) {
> + error_report("tpm-emulator: Unable to connect socket : %s",
> + tpm_pt->ops->ctrl_path);
> + goto err_kill_child;
> + }
> +
> + qemu_add_child_watch(cpid);
> +
> + qio_channel_add_watch(tpm_pt->data_ioc, G_IO_HUP | G_IO_ERR,
> + tpm_emulator_fd_handler, tpm_pt, NULL);
> +
> + while ((rc = stat(TPM_EMULATOR_PIDFILE, &st)) < 0 && timeout--) {
> + usleep(usec);
> + }
> +
> + if (timeout == -1) {
> + error_report("tpm-emulator: pid file not ready: %s",
> + strerror(errno));
> + goto err_kill_child;
> + }
> +
> + /* check if child really running */
> + if (kill(cpid, 0) < 0 && errno == ESRCH) {
> + goto err_no_child;
> + }
> +
> + tpm_pt->child_running = true;
> + }
> +
> + return 0;
> +
> +err_kill_child:
> + kill(cpid, SIGTERM);
> + /* wait for 10 mill-seconds */
> + usleep(10 * 1000);
> + /* force kill if still reachable */
> + if (kill(cpid, 0) == 0) {
> + kill(cpid, SIGKILL);
> + }
> +
> +err_no_child:
> + tpm_pt->child_running = false;
> +
> + return -1;
> +}
> +
> +static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_pt, QemuOpts
> *opts)
> +{
> + const char *value;
> +
> + value = qemu_opt_get(opts, "tpmstatedir");
> + if (!value) {
> + error_report("tpm-emulator: Missing tpm state directory");
> + return -1;
> + }
> + tpm_pt->ops->tpmstatedir = g_strdup(value);
> +
> + tpm_pt->ops->spawn = qemu_opt_get_bool(opts, "spawn", false);
> +
> + value = qemu_opt_get(opts, "path");
> + if (!value) {
> + value = TPM_DEFAULT_EMULATOR;
> + tpm_pt->ops->has_path = false;
> + } else {
> + tpm_pt->ops->has_path = true;
> + if (value[0] == '/') {
> + struct stat st;
> + if (stat(value, &st) < 0 || !(S_ISREG(st.st_mode)
> + || S_ISLNK(st.st_mode))) {
> + error_report("tpm-emulator: Invalid emulator path: %s",
> value);
> + return -1;
> + }
> + }
> + }
> + tpm_pt->ops->path = g_strdup(value);
> +
> + value = qemu_opt_get(opts, "data-path");
> + if (value) {
> + tpm_pt->ops->has_data_path = true;
> + tpm_pt->ops->data_path = g_strdup(value);
> + } else {
> + tpm_pt->ops->has_data_path = false;
> + if (!tpm_pt->ops->spawn) {
> + error_report("tpm-emulator: missing mandatory data-path");
> + return -1;
> + }
> + }
> +
> + value = qemu_opt_get(opts, "ctrl-path");
> + if (value) {
> + tpm_pt->ops->has_ctrl_path = true;
> + tpm_pt->ops->ctrl_path = g_strdup(value);
> + } else {
> + tpm_pt->ops->has_ctrl_path = false;
> + if (!tpm_pt->ops->spawn) {
> + error_report("tpm-emulator: missing mandatory ctrl-path");
> + return -1;
> + }
> + }
> +
> + value = qemu_opt_get(opts, "logfile");
> + if (value) {
> + tpm_pt->ops->has_logfile = true;
> + tpm_pt->ops->logfile = g_strdup(value);
> + tpm_pt->ops->loglevel = qemu_opt_get_number(opts, "loglevel",
> + TPM_DEFAULT_LOGLEVEL);
> + tpm_pt->ops->has_loglevel = tpm_pt->ops->loglevel !=
> + TPM_DEFAULT_LOGLEVEL;
> + }
> +
> + if (tpm_pt->ops->spawn) {
> + if (tpm_emulator_spawn_emulator(tpm_pt) < 0) {
> + goto err_close_dev;
> + }
> + } else {
> + tpm_pt->data_ioc = _iochannel_new(tpm_pt->ops->data_path, -1,
> NULL);
> + if (tpm_pt->data_ioc == NULL) {
> + error_report("tpm-emulator: Failed to connect data socket:
> %s",
> + tpm_pt->ops->data_path);
> + goto err_close_dev;
> + }
> + tpm_pt->ctrl_ioc = _iochannel_new(tpm_pt->ops->ctrl_path, -1,
> NULL);
> + if (tpm_pt->ctrl_ioc == NULL) {
> + DPRINTF("Failed to connect control socket: %s",
> + strerror(errno));
> + goto err_close_dev;
> + }
> + tpm_pt->child_running = true;
> + }
> +
> + /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it
> also used
> + * by passthrough driver, which not yet using GIOChannel.
> + */
> + if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_pt->data_ioc)->fd,
> + &tpm_pt->tpm_version)) {
> + error_report("'%s' is not emulating TPM device.",
> tpm_pt->ops->path);
> + goto err_close_dev;
> + }
> +
> + DPRINTF("TPM Version %s", tpm_pt->tpm_version == TPM_VERSION_1_2 ?
> "1.2" :
> + (tpm_pt->tpm_version == TPM_VERSION_2_0 ? "2.0" :
> "Unspecified"));
> +
> + if (tpm_emulator_probe_caps(tpm_pt) ||
> + tpm_emulator_check_caps(tpm_pt)) {
> + goto err_close_dev;
> + }
> +
> + return 0;
> +
> +err_close_dev:
> + DPRINT("Startup error\n");
> + return -1;
> +}
> +
> +static TPMBackend *tpm_emulator_create(QemuOpts *opts, const char *id)
> +{
> + TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
> +
> + tb->id = g_strdup(id);
> +
> + if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
> + goto err_exit;
> + }
> +
> + return tb;
> +
> +err_exit:
> + object_unref(OBJECT(tb));
> +
> + return NULL;
> +}
> +
> +static TPMOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
> + TPMEmulatorOptions *ops = g_new0(TPMEmulatorOptions, 1);
> +
> + if (!ops) {
> + return NULL;
> + }
> + DPRINTF("%s", __func__);
> +
> + ops->tpmstatedir = g_strdup(tpm_pt->ops->tpmstatedir);
> + ops->spawn = tpm_pt->ops->spawn;
> + if (tpm_pt->ops->has_path) {
> + ops->has_path = true;
> + ops->path = g_strdup(tpm_pt->ops->path);
> + }
> + if (tpm_pt->ops->has_data_path) {
> + ops->has_data_path = true;
> + ops->data_path = g_strdup(tpm_pt->ops->data_path);
> + }
> + if (tpm_pt->ops->has_ctrl_path) {
> + ops->has_ctrl_path = true;
> + ops->ctrl_path = g_strdup(tpm_pt->ops->ctrl_path);
> + }
> + if (tpm_pt->ops->has_logfile) {
> + ops->has_logfile = true;
> + ops->logfile = g_strdup(tpm_pt->ops->logfile);
> + }
> + if (tpm_pt->ops->has_loglevel) {
> + ops->has_loglevel = true;
> + ops->loglevel = tpm_pt->ops->loglevel;
> + }
> +
> + return (TPMOptions *)ops;
> +}
> +
> +static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
> + TPM_STANDARD_CMDLINE_OPTS,
> + {
> + .name = "tpmstatedir",
> + .type = QEMU_OPT_STRING,
> + .help = "TPM state directroy",
> + },
> + {
> + .name = "spawn",
> + .type = QEMU_OPT_BOOL,
> + .help = "Wether to spwan given emlatory binary",
> + },
> + {
> + .name = "path",
> + .type = QEMU_OPT_STRING,
> + .help = "Path to TPM emulator binary",
> + },
> + {
> + .name = "data-path",
> + .type = QEMU_OPT_STRING,
> + .help = "Socket path to use for data exhange",
> + },
> + {
> + .name = "ctrl-path",
> + .type = QEMU_OPT_STRING,
> + .help = "Socket path to use for out-of-band control messages",
> + },
> + {
> + .name = "logfile",
> + .type = QEMU_OPT_STRING,
> + .help = "Path to log file",
> + },
> + {
> + .name = "level",
> + .type = QEMU_OPT_STRING,
> + .help = "Log level number",
> + },
> + { /* end of list */ },
> +};
> +
> +static const TPMDriverOps tpm_emulator_driver = {
> + .type = TPM_TYPE_EMULATOR,
> + .opts = tpm_emulator_cmdline_opts,
> + .desc = tpm_emulator_desc,
> + .create = tpm_emulator_create,
> + .startup_tpm = tpm_emulator_startup_tpm,
> + .reset = tpm_emulator_reset,
> + .had_startup_error = tpm_emulator_had_startup_error,
> + .cancel_cmd = tpm_emulator_cancel_cmd,
> + .get_tpm_established_flag = tpm_emulator_get_tpm_established_flag,
> + .reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag,
> + .get_tpm_version = tpm_emulator_get_tpm_version,
> + .get_tpm_options = tpm_emulator_get_tpm_options,
> +};
> +
> +static void tpm_emulator_inst_init(Object *obj)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(obj);
> +
> + DPRINTF("%s", __func__);
> + tpm_pt->ops = g_new0(TPMEmulatorOptions, 1);
> + tpm_pt->data_ioc = tpm_pt->ctrl_ioc = NULL;
> + tpm_pt->op_executing = tpm_pt->op_canceled = false;
> + tpm_pt->child_running = false;
> + tpm_pt->cur_locty_number = ~0;
> + qemu_mutex_init(&tpm_pt->state_lock);
> +}
> +
> +static void tpm_emulator_inst_finalize(Object *obj)
> +{
> + TPMEmulator *tpm_pt = TPM_EMULATOR(obj);
> +
> + tpm_emulator_cancel_cmd(TPM_BACKEND(obj));
> + tpm_emulator_shutdown(tpm_pt);
> +
> + if (tpm_pt->data_ioc) {
> + qio_channel_close(tpm_pt->data_ioc, NULL);
> + }
> + if (tpm_pt->ctrl_ioc) {
> + qio_channel_close(tpm_pt->ctrl_ioc, NULL);
> + }
> + if (tpm_pt->ops) {
> + qapi_free_TPMEmulatorOptions(tpm_pt->ops);
> + }
> +}
> +
> +static void tpm_emulator_class_init(ObjectClass *klass, void *data)
> +{
> + TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
> + tbc->ops = &tpm_emulator_driver;
> + tbc->handle_request = tpm_emulator_handle_request;
> +}
> +
> +static const TypeInfo tpm_emulator_info = {
> + .name = TYPE_TPM_EMULATOR,
> + .parent = TYPE_TPM_BACKEND,
> + .instance_size = sizeof(TPMEmulator),
> + .class_init = tpm_emulator_class_init,
> + .instance_init = tpm_emulator_inst_init,
> + .instance_finalize = tpm_emulator_inst_finalize,
> +};
> +
> +static void tpm_emulator_register(void)
> +{
> + type_register_static(&tpm_emulator_info);
> + tpm_register_driver(&tpm_emulator_driver);
> +}
> +
> +type_init(tpm_emulator_register)
> diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h
> new file mode 100644
> index 0000000..af49708
> --- /dev/null
> +++ b/hw/tpm/tpm_ioctl.h
> @@ -0,0 +1,243 @@
> +/*
> + * tpm_ioctl.h
> + *
> + * (c) Copyright IBM Corporation 2014, 2015.
> + *
> + * This file is licensed under the terms of the 3-clause BSD license
> + */
> +#ifndef _TPM_IOCTL_H_
> +#define _TPM_IOCTL_H_
> +
> +#include <stdint.h>
> +#include <sys/uio.h>
> +#include <sys/types.h>
> +#include <sys/ioctl.h>
> +
> +/*
> + * Every response from a command involving a TPM command execution must
> hold
> + * the ptm_res as the first element.
> + * ptm_res corresponds to the error code of a command executed by the TPM.
> + */
> +
> +typedef uint32_t ptm_res;
> +
> +/* PTM_GET_TPMESTABLISHED: get the establishment bit */
> +struct ptm_est {
> + union {
> + struct {
> + ptm_res tpm_result;
> + unsigned char bit; /* TPM established bit */
> + } resp; /* response */
> + } u;
> +};
> +
> +/* PTM_RESET_TPMESTABLISHED: reset establishment bit */
> +struct ptm_reset_est {
> + union {
> + struct {
> + uint8_t loc; /* locality to use */
> + } req; /* request */
> + struct {
> + ptm_res tpm_result;
> + } resp; /* response */
> + } u;
> +};
> +
> +/* PTM_INIT */
> +struct ptm_init {
> + union {
> + struct {
> + uint32_t init_flags; /* see definitions below */
> + } req; /* request */
> + struct {
> + ptm_res tpm_result;
> + } resp; /* response */
> + } u;
> +};
> +
> +/* above init_flags */
> +#define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0)
> + /* delete volatile state file after reading it */
> +
> +/* PTM_SET_LOCALITY */
> +struct ptm_loc {
> + union {
> + struct {
> + uint8_t loc; /* locality to set */
> + } req; /* request */
> + struct {
> + ptm_res tpm_result;
> + } resp; /* response */
> + } u;
> +};
> +
> +/* PTM_HASH_DATA: hash given data */
> +struct ptm_hdata {
> + union {
> + struct {
> + uint32_t length;
> + uint8_t data[4096];
> + } req; /* request */
> + struct {
> + ptm_res tpm_result;
> + } resp; /* response */
> + } u;
> +};
> +
> +/*
> + * size of the TPM state blob to transfer; x86_64 can handle 8k,
> + * ppc64le only ~7k; keep the response below a 4k page size
> + */
> +#define PTM_STATE_BLOB_SIZE (3 * 1024)
> +
> +/*
> + * The following is the data structure to get state blobs from the TPM.
> + * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE,
> multiple reads
> + * with this ioctl and with adjusted offset are necessary. All bytes
> + * must be transferred and the transfer is done once the last byte has
> been
> + * returned.
> + * It is possible to use the read() interface for reading the data;
> however, the
> + * first bytes of the state blob will be part of the response to the
> ioctl(); a
> + * subsequent read() is only necessary if the total length (totlength)
> exceeds
> + * the number of received bytes. seek() is not supported.
> + */
> +struct ptm_getstate {
> + union {
> + struct {
> + uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */
> + uint32_t type; /* which blob to pull */
> + uint32_t offset; /* offset from where to read */
> + } req; /* request */
> + struct {
> + ptm_res tpm_result;
> + uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */
> + uint32_t totlength; /* total length that will be
> transferred */
> + uint32_t length; /* number of bytes in following buffer
> */
> + uint8_t data[PTM_STATE_BLOB_SIZE];
> + } resp; /* response */
> + } u;
> +};
> +
> +/* TPM state blob types */
> +#define PTM_BLOB_TYPE_PERMANENT 1
> +#define PTM_BLOB_TYPE_VOLATILE 2
> +#define PTM_BLOB_TYPE_SAVESTATE 3
> +
> +/* state_flags above : */
> +#define PTM_STATE_FLAG_DECRYPTED 1 /* on input: get decrypted state
> */
> +#define PTM_STATE_FLAG_ENCRYPTED 2 /* on output: state is encrypted */
> +
> +/*
> + * The following is the data structure to set state blobs in the TPM.
> + * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple
> + * 'writes' using this ioctl are necessary. The last packet is indicated
> + * by the length being smaller than the PTM_STATE_BLOB_SIZE.
> + * The very first packet may have a length indicator of '0' enabling
> + * a write() with all the bytes from a buffer. If the write() interface
> + * is used, a final ioctl with a non-full buffer must be made to indicate
> + * that all data were transferred (a write with 0 bytes would not work).
> + */
> +struct ptm_setstate {
> + union {
> + struct {
> + uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */
> + uint32_t type; /* which blob to set */
> + uint32_t length; /* length of the data;
> + use 0 on the first packet to
> + transfer using write() */
> + uint8_t data[PTM_STATE_BLOB_SIZE];
> + } req; /* request */
> + struct {
> + ptm_res tpm_result;
> + } resp; /* response */
> + } u;
> +};
> +
> +/*
> + * PTM_GET_CONFIG: Data structure to get runtime configuration information
> + * such as which keys are applied.
> + */
> +struct ptm_getconfig {
> + union {
> + struct {
> + ptm_res tpm_result;
> + uint32_t flags;
> + } resp; /* response */
> + } u;
> +};
> +
> +#define PTM_CONFIG_FLAG_FILE_KEY 0x1
> +#define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2
> +
> +
> +typedef uint64_t ptm_cap;
> +typedef struct ptm_est ptm_est;
> +typedef struct ptm_reset_est ptm_reset_est;
> +typedef struct ptm_loc ptm_loc;
> +typedef struct ptm_hdata ptm_hdata;
> +typedef struct ptm_init ptm_init;
> +typedef struct ptm_getstate ptm_getstate;
> +typedef struct ptm_setstate ptm_setstate;
> +typedef struct ptm_getconfig ptm_getconfig;
> +
> +/* capability flags returned by PTM_GET_CAPABILITY */
> +#define PTM_CAP_INIT (1)
> +#define PTM_CAP_SHUTDOWN (1 << 1)
> +#define PTM_CAP_GET_TPMESTABLISHED (1 << 2)
> +#define PTM_CAP_SET_LOCALITY (1 << 3)
> +#define PTM_CAP_HASHING (1 << 4)
> +#define PTM_CAP_CANCEL_TPM_CMD (1 << 5)
> +#define PTM_CAP_STORE_VOLATILE (1 << 6)
> +#define PTM_CAP_RESET_TPMESTABLISHED (1 << 7)
> +#define PTM_CAP_GET_STATEBLOB (1 << 8)
> +#define PTM_CAP_SET_STATEBLOB (1 << 9)
> +#define PTM_CAP_STOP (1 << 10)
> +#define PTM_CAP_GET_CONFIG (1 << 11)
> +
> +enum {
> + PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap),
> + PTM_INIT = _IOWR('P', 1, ptm_init),
> + PTM_SHUTDOWN = _IOR('P', 2, ptm_res),
> + PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est),
> + PTM_SET_LOCALITY = _IOWR('P', 4, ptm_loc),
> + PTM_HASH_START = _IOR('P', 5, ptm_res),
> + PTM_HASH_DATA = _IOWR('P', 6, ptm_hdata),
> + PTM_HASH_END = _IOR('P', 7, ptm_res),
> + PTM_CANCEL_TPM_CMD = _IOR('P', 8, ptm_res),
> + PTM_STORE_VOLATILE = _IOR('P', 9, ptm_res),
> + PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est),
> + PTM_GET_STATEBLOB = _IOWR('P', 11, ptm_getstate),
> + PTM_SET_STATEBLOB = _IOWR('P', 12, ptm_setstate),
> + PTM_STOP = _IOR('P', 13, ptm_res),
> + PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig),
> +};
> +
> +/*
> + * Commands used by the non-CUSE TPMs
> + *
> + * All messages container big-endian data.
> + *
> + * The return messages only contain the 'resp' part of the unions
> + * in the data structures above. Besides that the limits in the
> + * buffers above (ptm_hdata:u.req.data and ptm_get_state:u.resp.data
> + * and ptm_set_state:u.req.data) are 0xffffffff.
> + */
> +enum {
> + CMD_GET_CAPABILITY = 1,
> + CMD_INIT,
> + CMD_SHUTDOWN,
> + CMD_GET_TPMESTABLISHED,
> + CMD_SET_LOCALITY,
> + CMD_HASH_START,
> + CMD_HASH_DATA,
> + CMD_HASH_END,
> + CMD_CANCEL_TPM_CMD,
> + CMD_STORE_VOLATILE,
> + CMD_RESET_TPMESTABLISHED,
> + CMD_GET_STATEBLOB,
> + CMD_SET_STATEBLOB,
> + CMD_STOP,
> + CMD_GET_CONFIG,
> +};
> +
> +#endif /* _TPM_IOCTL_H */
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 764f731..17c2ae9 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -5114,10 +5114,12 @@
> # An enumeration of TPM types
> #
> # @passthrough: TPM passthrough type
> +# @emulator: Software Emulator TPM type
> +# Since: 2.10
> #
> # Since: 1.5
> ##
> -{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }
> +{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ] }
>
> ##
> # @query-tpm-types:
> @@ -5131,7 +5133,7 @@
> # Example:
> #
> # -> { "execute": "query-tpm-types" }
> -# <- { "return": [ "passthrough" ] }
> +# <- { "return": [ "passthrough", "emulator" ] }
> #
> ##
> { 'command': 'query-tpm-types', 'returns': ['TpmType'] }
> @@ -5161,6 +5163,36 @@
> { 'struct': 'TPMPassthroughOptions', 'base': 'TPMOptions',
> 'data': { '*path' : 'str', '*cancel-path' : 'str'} }
>
> +##
> +# @TPMEmulatorOptions:
> +#
> +# Information about the TPM emulator
> +#
> +# @tpmstatedir: TPM emulator state directory
> +# @spawn: true if, qemu has to spawn a new emulator process with given
> @path,
> +# otherwise it connects to already rinning emulator with given
> @data-path
> +# and @ctrl-path sockets. (default: 'false')
> +# @path: TPM emulator binary path to spawn.(default: 'swtpm')
> +# @data-path: path of the unix socket to use for exchanging data
> messages, if
> +# not provided socket pairs are used when @sapwn is true.
> +# @ctrl-path: path of the unix socket file to use for exchagning
> out-of-band
> +# control messages, if not provided socket pairs are used when
> +# @spawn is true.
> +# @logfile: file to use to place TPM emulator logs, if not provided
> logging is
> +# disabled.
> +# @loglevel: optional log level number, loglevel is ignored if no logfile
> +# provided. (default: 5)
> +#
> +# Since: 2.10
> +##
> +{ 'struct': 'TPMEmulatorOptions', 'base': 'TPMOptions',
> + 'data': { 'tpmstatedir' : 'str',
> + 'spawn': 'bool',
> + '*path': 'str',
> + '*data-path': 'str',
> + '*ctrl-path': 'str',
> + '*logfile': 'str',
> + '*loglevel': 'int' } }
>
> ##
> # @TPMInfo:
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 99af8ed..aae0de0 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -2846,7 +2846,15 @@ DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
> "-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n"
> " use path to provide path to a character device;
> default is /dev/tpm0\n"
> " use cancel-path to provide path to TPM's cancel
> sysfs entry; if\n"
> - " not provided it will be searched for in
> /sys/class/misc/tpm?/device\n",
> + " not provided it will be searched for in
> /sys/class/misc/tpm?/device\n"
> + "-tpmdev
> emulator,id=id,spawn=on|off,tpmstatedir=dir[,path=emulator-path,data-path=path,ctrl-path=path,logfile=path,loglevel=level]\n"
> + " spawn=on|off controls spawning support\n"
> + " use tpmstatedir to provide path to the tpm state
> dirctory\n"
> + " use path to provide the emulator binary to launch;
> default is 'swtpm'\n"
> + " use data-path to provide the socket path for
> exchanging data messages\n"
> + " use ctrl-path to provide the socket path for sending
> control messages to software emulator\n"
> + " use logfile to provide where to place the swtpm
> logs\n"
> + " use loglevel to controls the swtpm log level\n",
> QEMU_ARCH_ALL)
> STEXI
>
> @@ -2855,8 +2863,8 @@ The general form of a TPM device option is:
>
> @item -tpmdev @var{backend} ,id=@var{id} [,@var{options}]
> @findex -tpmdev
> -Backend type must be:
> -@option{passthrough}.
> +Backend type must be either one of the following:
> +@option{passthrough}, @option{emulator}.
>
> The specific backend type will determine the applicable options.
> The @code{-tpmdev} option creates the TPM backend and requires a
> @@ -2906,6 +2914,45 @@ To create a passthrough TPM use the following two
> options:
> Note that the @code{-tpmdev} id is @code{tpm0} and is referenced by
> @code{tpmdev=tpm0} in the device option.
>
> +@item -tpmdev emulator, id=@var{id}, tpmstatedir=@var{path},
> spawn=@var{on|off}, path=@var{emulator-binary-path}, data-path=@var{path},
> ctrl-path=@var{path}, logfile=@var{path}, loglevel=@var{level}
> +
> +(Linux-host only) Enable access to a TPM emulator using unix domain
> sockets.
> +
> +@option{tpmstatedir} specifies the tpm state directory
> +
> +@option{spawn} specifies if qemu should spawn new emulator process with
> given @option{path}
> +
> +@option{path} specifies the emulator binary path to use for spawning
> +
> +@option{data-path} optional socket path to use for exchanging TPM data
> with emulator
> +
> +@option{ctrl-path} optional socket path to use for sending control data
> to emulator
> +
> +@option{logfile} optional log file to use to place log messages
> +
> +@option{loglevel} specifies the log level to use
> +
> +To create TPM emulator backend device that spawns new swtpm binary and
> communicate with socket pairs:
> +@example
> +
> +-tpmdev
> emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=on,path=/usr/local/bin/swtpm,logfile=/tmp/qemu-tpm.log,loglevel=5
> -device tpm-tis,tpmdev=tpm0
> +
> +@end example
> +
> +To create TPM emulator backend device that spawns new swtpm binary and
> communicate using unix file system sockets:
> +@example
> +
> +-tpmdev
> emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=on,path=/usr/local/bin/swtpm,data-path=/tmp/swtpm-data.socket,ctrl-path=/tmp/swtpm-ctrl.socket,logfile=/tmp/qemu-tpm.log,loglevel=5
> -device tpm-tis,tpmdev=tpm0
> +
> +@end example
> +
> +To create a TOM emulator backend device that connects to already running
> swtpm binary using file system sockets:
> +@example
> +
> +-tpmdev
> emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=off,data-path=/tmp/swtpm-data.socket,ctrl-path=/tmp/swtpm-ctrl.socket,logfile=/tmp/qemu-tpm.log,loglevel=5
> -device tpm-tis,tpmdev=tpm0
> +
> +@end example
> +
> @end table
>
> ETEXI
> diff --git a/tpm.c b/tpm.c
> index 43d980e..ce07c40 100644
> --- a/tpm.c
> +++ b/tpm.c
> @@ -25,7 +25,7 @@ static QLIST_HEAD(, TPMBackend) tpm_backends =
>
>
> #define TPM_MAX_MODELS 1
> -#define TPM_MAX_DRIVERS 1
> +#define TPM_MAX_DRIVERS 2
>
> static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
> NULL,
> --
> 2.7.4
>
> --
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 16:05 ` Marc-André Lureau
@ 2017-05-02 16:32 ` Stefan Berger
2017-05-02 16:58 ` Stefan Berger
1 sibling, 0 replies; 46+ messages in thread
From: Stefan Berger @ 2017-05-02 16:32 UTC (permalink / raw)
To: Marc-André Lureau, Amarnath Valluri, qemu-devel; +Cc: patrick.ohly
On 05/02/2017 12:05 PM, Marc-André Lureau wrote:
> Hi
>
> On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri <amarnath.valluri@intel.com>
> wrote:
>
>> This change introduces a new TPM backend driver that can communicate with
>> swtpm(software TPM emulator) using unix domain socket interface.
>>
>> Swtpm uses two unix sockets, one for plain TPM commands and responses, and
>> one
>> for out-of-band control messages.
>>
>>
> Let's not forget to mention the external protocol this backend rely on:
> https://github.com/stefanberger/swtpm/wiki/Control-Channel-Specification
>
> The protocol documentation is quite limited.
better documentation is here:
https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 16:05 ` Marc-André Lureau
2017-05-02 16:32 ` Stefan Berger
@ 2017-05-02 16:58 ` Stefan Berger
2017-05-02 17:09 ` Marc-André Lureau
1 sibling, 1 reply; 46+ messages in thread
From: Stefan Berger @ 2017-05-02 16:58 UTC (permalink / raw)
To: Marc-André Lureau, Amarnath Valluri, qemu-devel
Cc: patrick.ohly, berrange
On 05/02/2017 12:05 PM, Marc-André Lureau wrote:
> Hi
>
> On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri
> <amarnath.valluri@intel.com <mailto:amarnath.valluri@intel.com>> wrote:
>
> This change introduces a new TPM backend driver that can
> communicate with
> swtpm(software TPM emulator) using unix domain socket interface.
>
> Swtpm uses two unix sockets, one for plain TPM commands and
> responses, and one
> for out-of-band control messages.
>
>
> Let's not forget to mention the external protocol this backend rely on:
> https://github.com/stefanberger/swtpm/wiki/Control-Channel-Specification
>
> The protocol documentation is quite limited.
>
> (I still question the need to rely on a public protocol, and a
> seperate helper process project. If we had a qemu-swtpm, we could more
> easily evolve the protocol in the future)
And who is going to implement that qemu-swtpm? Obviously this discussion
doesn't contribute to progress if nobody is doing that in the end.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 16:58 ` Stefan Berger
@ 2017-05-02 17:09 ` Marc-André Lureau
2017-05-02 17:19 ` Stefan Berger
0 siblings, 1 reply; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 17:09 UTC (permalink / raw)
To: Stefan Berger, Amarnath Valluri, qemu-devel; +Cc: patrick.ohly, berrange
Hi
On Tue, May 2, 2017 at 8:59 PM Stefan Berger <stefanb@linux.vnet.ibm.com>
wrote:
> On 05/02/2017 12:05 PM, Marc-André Lureau wrote:
>
> Hi
>
> On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri <
> amarnath.valluri@intel.com> wrote:
>
>> This change introduces a new TPM backend driver that can communicate with
>> swtpm(software TPM emulator) using unix domain socket interface.
>>
>> Swtpm uses two unix sockets, one for plain TPM commands and responses,
>> and one
>> for out-of-band control messages.
>>
>>
> Let's not forget to mention the external protocol this backend rely on:
> https://github.com/stefanberger/swtpm/wiki/Control-Channel-Specification
>
> The protocol documentation is quite limited.
>
> (I still question the need to rely on a public protocol, and a seperate
> helper process project. If we had a qemu-swtpm, we could more easily evolve
> the protocol in the future)
>
>
> And who is going to implement that qemu-swtpm? Obviously this discussion
> doesn't contribute to progress if nobody is doing that in the end.
>
The same persons who try to push for that emulated TPM code. The easiest
approach would be to copy/adapt the swtpm code in qemu, if the licence is
compatible. I can help with that if there is a consensus it's a better
approach.
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 17:09 ` Marc-André Lureau
@ 2017-05-02 17:19 ` Stefan Berger
2017-05-02 18:25 ` Patrick Ohly
0 siblings, 1 reply; 46+ messages in thread
From: Stefan Berger @ 2017-05-02 17:19 UTC (permalink / raw)
To: Marc-André Lureau, Amarnath Valluri, qemu-devel; +Cc: patrick.ohly
On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> Hi
>
> On Tue, May 2, 2017 at 8:59 PM Stefan Berger <stefanb@linux.vnet.ibm.com>
> wrote:
>
>> On 05/02/2017 12:05 PM, Marc-André Lureau wrote:
>>
>> Hi
>>
>> On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri <
>> amarnath.valluri@intel.com> wrote:
>>
>>> This change introduces a new TPM backend driver that can communicate with
>>> swtpm(software TPM emulator) using unix domain socket interface.
>>>
>>> Swtpm uses two unix sockets, one for plain TPM commands and responses,
>>> and one
>>> for out-of-band control messages.
>>>
>>>
>> Let's not forget to mention the external protocol this backend rely on:
>> https://github.com/stefanberger/swtpm/wiki/Control-Channel-Specification
>>
>> The protocol documentation is quite limited.
>>
>> (I still question the need to rely on a public protocol, and a seperate
>> helper process project. If we had a qemu-swtpm, we could more easily evolve
>> the protocol in the future)
>>
>>
>> And who is going to implement that qemu-swtpm? Obviously this discussion
>> doesn't contribute to progress if nobody is doing that in the end.
>>
> The same persons who try to push for that emulated TPM code. The easiest
> approach would be to copy/adapt the swtpm code in qemu, if the licence is
> compatible. I can help with that if there is a consensus it's a better
> approach.
It's a matter of time and at least I don't have time for that.
Nevertheless, I would suggest to reach that consensus so that we know
what will happen to at least 8/8 of this series.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 17:19 ` Stefan Berger
@ 2017-05-02 18:25 ` Patrick Ohly
2017-05-02 18:50 ` Marc-André Lureau
0 siblings, 1 reply; 46+ messages in thread
From: Patrick Ohly @ 2017-05-02 18:25 UTC (permalink / raw)
To: Stefan Berger; +Cc: Marc-André Lureau, Amarnath Valluri, qemu-devel
On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > On Tue, May 2, 2017 at 8:59 PM Stefan Berger <stefanb@linux.vnet.ibm.com>
> > wrote:
> >
> >> And who is going to implement that qemu-swtpm? Obviously this discussion
> >> doesn't contribute to progress if nobody is doing that in the end.
> >>
> > The same persons who try to push for that emulated TPM code. The easiest
> > approach would be to copy/adapt the swtpm code in qemu, if the licence is
> > compatible. I can help with that if there is a consensus it's a better
> > approach.
>
>
> It's a matter of time and at least I don't have time for that.
Neither do I, and nor (I believe) does Amarnath. The approach with using
the existing swtpm project seemed attractive to us exactly because it
avoids having to write and maintain more than just the glue code between
the two projects.
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 18:25 ` Patrick Ohly
@ 2017-05-02 18:50 ` Marc-André Lureau
2017-05-02 19:35 ` Stefan Berger
0 siblings, 1 reply; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-02 18:50 UTC (permalink / raw)
To: Patrick Ohly, Stefan Berger; +Cc: Amarnath Valluri, qemu-devel
Hi
On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <patrick.ohly@intel.com> wrote:
> On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger <
> stefanb@linux.vnet.ibm.com>
> > > wrote:
> > >
> > >> And who is going to implement that qemu-swtpm? Obviously this
> discussion
> > >> doesn't contribute to progress if nobody is doing that in the end.
> > >>
> > > The same persons who try to push for that emulated TPM code. The
> easiest
> > > approach would be to copy/adapt the swtpm code in qemu, if the licence
> is
> > > compatible. I can help with that if there is a consensus it's a better
> > > approach.
> >
> >
> > It's a matter of time and at least I don't have time for that.
>
> Neither do I, and nor (I believe) does Amarnath. The approach with using
> the existing swtpm project seemed attractive to us exactly because it
> avoids having to write and maintain more than just the glue code between
> the two projects.
>
The main argument is not about having more or less code in qemu to
maintain, but yes this is a concern (although giving up that maintenance to
a seperate project with mostly Stefan-alone isn't a much better
alternative). btw, is the project actually used by something else than
qemu? (I am not talking about developpers/testing). If not, then it makes
sense to make it part of qemu.
But it's mostly a technical reason, to avoid having to rely on a foreign
protocol and project with all the compatibility constrains.
In the end, we may decide to start with a separate project, and change it
in the future if it's problematic (that would break some cases, such as
being able to freely switch the helper). Tbh, I am not so happy with the
code quality of swtpm, and I haven't looked closely at libtpms. Having a
qemu-swtpm as part of qemu would probably help improve it too, and bring a
few more developers for maintainance...
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 18:50 ` Marc-André Lureau
@ 2017-05-02 19:35 ` Stefan Berger
2017-05-03 8:41 ` Daniel P. Berrange
0 siblings, 1 reply; 46+ messages in thread
From: Stefan Berger @ 2017-05-02 19:35 UTC (permalink / raw)
To: Marc-André Lureau, Patrick Ohly; +Cc: Amarnath Valluri, qemu-devel
On 05/02/2017 02:50 PM, Marc-André Lureau wrote:
> Hi
>
> On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <patrick.ohly@intel.com
> <mailto:patrick.ohly@intel.com>> wrote:
>
> On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger
> <stefanb@linux.vnet.ibm.com <mailto:stefanb@linux.vnet.ibm.com>>
> > > wrote:
> > >
> > >> And who is going to implement that qemu-swtpm? Obviously this
> discussion
> > >> doesn't contribute to progress if nobody is doing that in the
> end.
> > >>
> > > The same persons who try to push for that emulated TPM code.
> The easiest
> > > approach would be to copy/adapt the swtpm code in qemu, if the
> licence is
> > > compatible. I can help with that if there is a consensus it's
> a better
> > > approach.
> >
> >
> > It's a matter of time and at least I don't have time for that.
>
> Neither do I, and nor (I believe) does Amarnath. The approach with
> using
> the existing swtpm project seemed attractive to us exactly because it
> avoids having to write and maintain more than just the glue code
> between
> the two projects.
>
>
> The main argument is not about having more or less code in qemu to
> maintain, but yes this is a concern (although giving up that
> maintenance to a seperate project with mostly Stefan-alone isn't a
> much better alternative). btw, is the project actually used by
> something else than qemu? (I am not talking about
> developpers/testing). If not, then it makes sense to make it part of qemu.
The intention would be to use it for RunC as well (plus higher layers
afterwards): https://github.com/opencontainers/runc/pull/1082
>
> But it's mostly a technical reason, to avoid having to rely on a
> foreign protocol and project with all the compatibility constrains.
I understand. Ideally swtpm-0.1 would be equivalent to 1.0 with all
features available and no further protocol extensions necessary. In
practice that may look different.
>
> In the end, we may decide to start with a separate project, and change
> it in the future if it's problematic (that would break some cases,
> such as being able to freely switch the helper). Tbh, I am not so
> happy with the code quality of swtpm, and I haven't looked closely at
> libtpms. Having a qemu-swtpm as part of qemu would probably help
> improve it too, and bring a few more developers for maintainance...
libtpms combines a few source codes with some glue around it. The coding
style is different for TPM 1.2 and TPM 2 code for example and the code
bases are in the 10s of thousands of line. In the case of TPM 2 it
'lives from' TCG code drops and thus there is no reformatting of source
code etc.
If someone wants to get started on qemu-swtpm that's certainly cool but
over the years it's just been quite difficult to find developers for it
to share the burden. All that said, someone should state whether this
series is a go or no-go because of the external project it requires.
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-02 19:35 ` Stefan Berger
@ 2017-05-03 8:41 ` Daniel P. Berrange
2017-05-03 11:17 ` Dr. David Alan Gilbert
0 siblings, 1 reply; 46+ messages in thread
From: Daniel P. Berrange @ 2017-05-03 8:41 UTC (permalink / raw)
To: Stefan Berger
Cc: Marc-André Lureau, Patrick Ohly, Amarnath Valluri, qemu-devel
On Tue, May 02, 2017 at 03:35:48PM -0400, Stefan Berger wrote:
> On 05/02/2017 02:50 PM, Marc-André Lureau wrote:
> > Hi
> >
> > On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <patrick.ohly@intel.com
> > <mailto:patrick.ohly@intel.com>> wrote:
> >
> > On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> > > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger
> > <stefanb@linux.vnet.ibm.com <mailto:stefanb@linux.vnet.ibm.com>>
> > > > wrote:
> > > >
> > > >> And who is going to implement that qemu-swtpm? Obviously this
> > discussion
> > > >> doesn't contribute to progress if nobody is doing that in the
> > end.
> > > >>
> > > > The same persons who try to push for that emulated TPM code.
> > The easiest
> > > > approach would be to copy/adapt the swtpm code in qemu, if the
> > licence is
> > > > compatible. I can help with that if there is a consensus it's
> > a better
> > > > approach.
> > >
> > >
> > > It's a matter of time and at least I don't have time for that.
> >
> > Neither do I, and nor (I believe) does Amarnath. The approach with
> > using
> > the existing swtpm project seemed attractive to us exactly because it
> > avoids having to write and maintain more than just the glue code
> > between
> > the two projects.
> >
> >
> > The main argument is not about having more or less code in qemu to
> > maintain, but yes this is a concern (although giving up that maintenance
> > to a seperate project with mostly Stefan-alone isn't a much better
> > alternative). btw, is the project actually used by something else than
> > qemu? (I am not talking about developpers/testing). If not, then it
> > makes sense to make it part of qemu.
>
> The intention would be to use it for RunC as well (plus higher layers
> afterwards): https://github.com/opencontainers/runc/pull/1082
>
> >
> > But it's mostly a technical reason, to avoid having to rely on a foreign
> > protocol and project with all the compatibility constrains.
>
> I understand. Ideally swtpm-0.1 would be equivalent to 1.0 with all features
> available and no further protocol extensions necessary. In practice that may
> look different.
>
> >
> > In the end, we may decide to start with a separate project, and change
> > it in the future if it's problematic (that would break some cases, such
> > as being able to freely switch the helper). Tbh, I am not so happy with
> > the code quality of swtpm, and I haven't looked closely at libtpms.
> > Having a qemu-swtpm as part of qemu would probably help improve it too,
> > and bring a few more developers for maintainance...
>
> libtpms combines a few source codes with some glue around it. The coding
> style is different for TPM 1.2 and TPM 2 code for example and the code bases
> are in the 10s of thousands of line. In the case of TPM 2 it 'lives from'
> TCG code drops and thus there is no reformatting of source code etc.
>
> If someone wants to get started on qemu-swtpm that's certainly cool but over
> the years it's just been quite difficult to find developers for it to share
> the burden. All that said, someone should state whether this series is a go
> or no-go because of the external project it requires.
I think it is *good* that it uses the external swtpm project and do not
want to see it reimplemented inside QEMU, particularly with the interest
for swtpm to be used in container contexts via RunC. Such common infrastructure
for both containers & QEMU will be important given the increasing convergance
of technology across containers & VMs.
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-03 8:41 ` Daniel P. Berrange
@ 2017-05-03 11:17 ` Dr. David Alan Gilbert
2017-05-03 11:24 ` Marc-André Lureau
0 siblings, 1 reply; 46+ messages in thread
From: Dr. David Alan Gilbert @ 2017-05-03 11:17 UTC (permalink / raw)
To: Daniel P. Berrange
Cc: Stefan Berger, Amarnath Valluri, Patrick Ohly,
Marc-André Lureau, qemu-devel
* Daniel P. Berrange (berrange@redhat.com) wrote:
> On Tue, May 02, 2017 at 03:35:48PM -0400, Stefan Berger wrote:
> > On 05/02/2017 02:50 PM, Marc-André Lureau wrote:
> > > Hi
> > >
> > > On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <patrick.ohly@intel.com
> > > <mailto:patrick.ohly@intel.com>> wrote:
> > >
> > > On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> > > > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > > > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger
> > > <stefanb@linux.vnet.ibm.com <mailto:stefanb@linux.vnet.ibm.com>>
> > > > > wrote:
> > > > >
> > > > >> And who is going to implement that qemu-swtpm? Obviously this
> > > discussion
> > > > >> doesn't contribute to progress if nobody is doing that in the
> > > end.
> > > > >>
> > > > > The same persons who try to push for that emulated TPM code.
> > > The easiest
> > > > > approach would be to copy/adapt the swtpm code in qemu, if the
> > > licence is
> > > > > compatible. I can help with that if there is a consensus it's
> > > a better
> > > > > approach.
> > > >
> > > >
> > > > It's a matter of time and at least I don't have time for that.
> > >
> > > Neither do I, and nor (I believe) does Amarnath. The approach with
> > > using
> > > the existing swtpm project seemed attractive to us exactly because it
> > > avoids having to write and maintain more than just the glue code
> > > between
> > > the two projects.
> > >
> > >
> > > The main argument is not about having more or less code in qemu to
> > > maintain, but yes this is a concern (although giving up that maintenance
> > > to a seperate project with mostly Stefan-alone isn't a much better
> > > alternative). btw, is the project actually used by something else than
> > > qemu? (I am not talking about developpers/testing). If not, then it
> > > makes sense to make it part of qemu.
> >
> > The intention would be to use it for RunC as well (plus higher layers
> > afterwards): https://github.com/opencontainers/runc/pull/1082
> >
> > >
> > > But it's mostly a technical reason, to avoid having to rely on a foreign
> > > protocol and project with all the compatibility constrains.
> >
> > I understand. Ideally swtpm-0.1 would be equivalent to 1.0 with all features
> > available and no further protocol extensions necessary. In practice that may
> > look different.
> >
> > >
> > > In the end, we may decide to start with a separate project, and change
> > > it in the future if it's problematic (that would break some cases, such
> > > as being able to freely switch the helper). Tbh, I am not so happy with
> > > the code quality of swtpm, and I haven't looked closely at libtpms.
> > > Having a qemu-swtpm as part of qemu would probably help improve it too,
> > > and bring a few more developers for maintainance...
> >
> > libtpms combines a few source codes with some glue around it. The coding
> > style is different for TPM 1.2 and TPM 2 code for example and the code bases
> > are in the 10s of thousands of line. In the case of TPM 2 it 'lives from'
> > TCG code drops and thus there is no reformatting of source code etc.
> >
> > If someone wants to get started on qemu-swtpm that's certainly cool but over
> > the years it's just been quite difficult to find developers for it to share
> > the burden. All that said, someone should state whether this series is a go
> > or no-go because of the external project it requires.
>
> I think it is *good* that it uses the external swtpm project and do not
> want to see it reimplemented inside QEMU, particularly with the interest
> for swtpm to be used in container contexts via RunC. Such common infrastructure
> for both containers & QEMU will be important given the increasing convergance
> of technology across containers & VMs.
I agree; there aren't that many people who understand the details of TPMs,
reimplementing one in QEMU isn't something you'd want to do.
Dave
> Regards,
> Daniel
> --
> |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
> |: https://libvirt.org -o- https://fstop138.berrange.com :|
> |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-03 11:17 ` Dr. David Alan Gilbert
@ 2017-05-03 11:24 ` Marc-André Lureau
2017-05-03 11:29 ` Daniel P. Berrange
0 siblings, 1 reply; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-03 11:24 UTC (permalink / raw)
To: Dr. David Alan Gilbert, Daniel P. Berrange
Cc: Stefan Berger, Amarnath Valluri, Patrick Ohly, qemu-devel
Hi
On Wed, May 3, 2017 at 3:17 PM Dr. David Alan Gilbert <dgilbert@redhat.com>
wrote:
> * Daniel P. Berrange (berrange@redhat.com) wrote:
> > On Tue, May 02, 2017 at 03:35:48PM -0400, Stefan Berger wrote:
> > > On 05/02/2017 02:50 PM, Marc-André Lureau wrote:
> > > > Hi
> > > >
> > > > On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <patrick.ohly@intel.com
> > > > <mailto:patrick.ohly@intel.com>> wrote:
> > > >
> > > > On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> > > > > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > > > > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger
> > > > <stefanb@linux.vnet.ibm.com <mailto:stefanb@linux.vnet.ibm.com>>
> > > > > > wrote:
> > > > > >
> > > > > >> And who is going to implement that qemu-swtpm? Obviously
> this
> > > > discussion
> > > > > >> doesn't contribute to progress if nobody is doing that in
> the
> > > > end.
> > > > > >>
> > > > > > The same persons who try to push for that emulated TPM code.
> > > > The easiest
> > > > > > approach would be to copy/adapt the swtpm code in qemu, if
> the
> > > > licence is
> > > > > > compatible. I can help with that if there is a consensus it's
> > > > a better
> > > > > > approach.
> > > > >
> > > > >
> > > > > It's a matter of time and at least I don't have time for that.
> > > >
> > > > Neither do I, and nor (I believe) does Amarnath. The approach
> with
> > > > using
> > > > the existing swtpm project seemed attractive to us exactly
> because it
> > > > avoids having to write and maintain more than just the glue code
> > > > between
> > > > the two projects.
> > > >
> > > >
> > > > The main argument is not about having more or less code in qemu to
> > > > maintain, but yes this is a concern (although giving up that
> maintenance
> > > > to a seperate project with mostly Stefan-alone isn't a much better
> > > > alternative). btw, is the project actually used by something else
> than
> > > > qemu? (I am not talking about developpers/testing). If not, then it
> > > > makes sense to make it part of qemu.
> > >
> > > The intention would be to use it for RunC as well (plus higher layers
> > > afterwards): https://github.com/opencontainers/runc/pull/1082
> > >
> > > >
> > > > But it's mostly a technical reason, to avoid having to rely on a
> foreign
> > > > protocol and project with all the compatibility constrains.
> > >
> > > I understand. Ideally swtpm-0.1 would be equivalent to 1.0 with all
> features
> > > available and no further protocol extensions necessary. In practice
> that may
> > > look different.
> > >
> > > >
> > > > In the end, we may decide to start with a separate project, and
> change
> > > > it in the future if it's problematic (that would break some cases,
> such
> > > > as being able to freely switch the helper). Tbh, I am not so happy
> with
> > > > the code quality of swtpm, and I haven't looked closely at libtpms.
> > > > Having a qemu-swtpm as part of qemu would probably help improve it
> too,
> > > > and bring a few more developers for maintainance...
> > >
> > > libtpms combines a few source codes with some glue around it. The
> coding
> > > style is different for TPM 1.2 and TPM 2 code for example and the code
> bases
> > > are in the 10s of thousands of line. In the case of TPM 2 it 'lives
> from'
> > > TCG code drops and thus there is no reformatting of source code etc.
> > >
> > > If someone wants to get started on qemu-swtpm that's certainly cool
> but over
> > > the years it's just been quite difficult to find developers for it to
> share
> > > the burden. All that said, someone should state whether this series is
> a go
> > > or no-go because of the external project it requires.
> >
> > I think it is *good* that it uses the external swtpm project and do not
> > want to see it reimplemented inside QEMU, particularly with the interest
> > for swtpm to be used in container contexts via RunC. Such common
> infrastructure
> > for both containers & QEMU will be important given the increasing
> convergance
> > of technology across containers & VMs.
>
> I agree; there aren't that many people who understand the details of TPMs,
> reimplementing one in QEMU isn't something you'd want to do.
>
It's not about reimplementing TPM emulation. swtpm is a small utility
talking to libtpms doing the heavy work. swtpm could quite easily be
copied/adapted to fit in qemu if it's only meant to be used by qemu.
However, it seems the helper is going to be used by other projects, so it
make sense to make it a seperate project. Nevertheless, I think we should
carefully review the protocol and the compatibility situation before
committing this work, it's a major burden ahead..
>
> > Regards,
> > Daniel
> > --
> > |: https://berrange.com -o-
> https://www.flickr.com/photos/dberrange :|
> > |: https://libvirt.org -o-
> https://fstop138.berrange.com :|
> > |: https://entangle-photo.org -o-
> https://www.instagram.com/dberrange :|
> >
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-03 11:24 ` Marc-André Lureau
@ 2017-05-03 11:29 ` Daniel P. Berrange
2017-05-03 11:37 ` Marc-André Lureau
2017-05-03 14:42 ` Stefan Berger
0 siblings, 2 replies; 46+ messages in thread
From: Daniel P. Berrange @ 2017-05-03 11:29 UTC (permalink / raw)
To: Marc-André Lureau
Cc: Dr. David Alan Gilbert, Stefan Berger, Amarnath Valluri,
Patrick Ohly, qemu-devel
On Wed, May 03, 2017 at 11:24:42AM +0000, Marc-André Lureau wrote:
> Hi
>
> On Wed, May 3, 2017 at 3:17 PM Dr. David Alan Gilbert <dgilbert@redhat.com>
> wrote:
>
> > * Daniel P. Berrange (berrange@redhat.com) wrote:
> > > On Tue, May 02, 2017 at 03:35:48PM -0400, Stefan Berger wrote:
> > > > On 05/02/2017 02:50 PM, Marc-André Lureau wrote:
> > > > > Hi
> > > > >
> > > > > On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <patrick.ohly@intel.com
> > > > > <mailto:patrick.ohly@intel.com>> wrote:
> > > > >
> > > > > On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> > > > > > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > > > > > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger
> > > > > <stefanb@linux.vnet.ibm.com <mailto:stefanb@linux.vnet.ibm.com>>
> > > > > > > wrote:
> > > > > > >
> > > > > > >> And who is going to implement that qemu-swtpm? Obviously
> > this
> > > > > discussion
> > > > > > >> doesn't contribute to progress if nobody is doing that in
> > the
> > > > > end.
> > > > > > >>
> > > > > > > The same persons who try to push for that emulated TPM code.
> > > > > The easiest
> > > > > > > approach would be to copy/adapt the swtpm code in qemu, if
> > the
> > > > > licence is
> > > > > > > compatible. I can help with that if there is a consensus it's
> > > > > a better
> > > > > > > approach.
> > > > > >
> > > > > >
> > > > > > It's a matter of time and at least I don't have time for that.
> > > > >
> > > > > Neither do I, and nor (I believe) does Amarnath. The approach
> > with
> > > > > using
> > > > > the existing swtpm project seemed attractive to us exactly
> > because it
> > > > > avoids having to write and maintain more than just the glue code
> > > > > between
> > > > > the two projects.
> > > > >
> > > > >
> > > > > The main argument is not about having more or less code in qemu to
> > > > > maintain, but yes this is a concern (although giving up that
> > maintenance
> > > > > to a seperate project with mostly Stefan-alone isn't a much better
> > > > > alternative). btw, is the project actually used by something else
> > than
> > > > > qemu? (I am not talking about developpers/testing). If not, then it
> > > > > makes sense to make it part of qemu.
> > > >
> > > > The intention would be to use it for RunC as well (plus higher layers
> > > > afterwards): https://github.com/opencontainers/runc/pull/1082
> > > >
> > > > >
> > > > > But it's mostly a technical reason, to avoid having to rely on a
> > foreign
> > > > > protocol and project with all the compatibility constrains.
> > > >
> > > > I understand. Ideally swtpm-0.1 would be equivalent to 1.0 with all
> > features
> > > > available and no further protocol extensions necessary. In practice
> > that may
> > > > look different.
> > > >
> > > > >
> > > > > In the end, we may decide to start with a separate project, and
> > change
> > > > > it in the future if it's problematic (that would break some cases,
> > such
> > > > > as being able to freely switch the helper). Tbh, I am not so happy
> > with
> > > > > the code quality of swtpm, and I haven't looked closely at libtpms.
> > > > > Having a qemu-swtpm as part of qemu would probably help improve it
> > too,
> > > > > and bring a few more developers for maintainance...
> > > >
> > > > libtpms combines a few source codes with some glue around it. The
> > coding
> > > > style is different for TPM 1.2 and TPM 2 code for example and the code
> > bases
> > > > are in the 10s of thousands of line. In the case of TPM 2 it 'lives
> > from'
> > > > TCG code drops and thus there is no reformatting of source code etc.
> > > >
> > > > If someone wants to get started on qemu-swtpm that's certainly cool
> > but over
> > > > the years it's just been quite difficult to find developers for it to
> > share
> > > > the burden. All that said, someone should state whether this series is
> > a go
> > > > or no-go because of the external project it requires.
> > >
> > > I think it is *good* that it uses the external swtpm project and do not
> > > want to see it reimplemented inside QEMU, particularly with the interest
> > > for swtpm to be used in container contexts via RunC. Such common
> > infrastructure
> > > for both containers & QEMU will be important given the increasing
> > convergance
> > > of technology across containers & VMs.
> >
> > I agree; there aren't that many people who understand the details of TPMs,
> > reimplementing one in QEMU isn't something you'd want to do.
> >
>
> It's not about reimplementing TPM emulation. swtpm is a small utility
> talking to libtpms doing the heavy work. swtpm could quite easily be
> copied/adapted to fit in qemu if it's only meant to be used by qemu.
> However, it seems the helper is going to be used by other projects, so it
> make sense to make it a seperate project. Nevertheless, I think we should
> carefully review the protocol and the compatibility situation before
> committing this work, it's a major burden ahead..
Yes, I agree that reviewing the protocol is a very neccessary step, to
ensure it is going to be forwards compatible in a manner suitable for
QEMU.
In particular we need to understand what, if any, relationship there
needs to be wrt machine types & live migration stability. eg if a
VM is booted and the protocol negotiates version X, and we then live
migrate to a host with a newer swtpm, we need to ensure that the
protocol doesn't negotiate something that leads to guest OS incompatiblity
problems in accessing the TPM.
basically similar scenario to that which we have had with vhost-user
and version compatibility with external vhost-user server implementations
across live migration.
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-03 11:29 ` Daniel P. Berrange
@ 2017-05-03 11:37 ` Marc-André Lureau
2017-05-03 14:42 ` Stefan Berger
1 sibling, 0 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-03 11:37 UTC (permalink / raw)
To: Daniel P. Berrange
Cc: Dr. David Alan Gilbert, Stefan Berger, Amarnath Valluri,
Patrick Ohly, qemu-devel
Hi
On Wed, May 3, 2017 at 3:29 PM Daniel P. Berrange <berrange@redhat.com>
wrote:
> On Wed, May 03, 2017 at 11:24:42AM +0000, Marc-André Lureau wrote:
> > Hi
> >
> > On Wed, May 3, 2017 at 3:17 PM Dr. David Alan Gilbert <
> dgilbert@redhat.com>
> > wrote:
> >
> > > * Daniel P. Berrange (berrange@redhat.com) wrote:
> > > > On Tue, May 02, 2017 at 03:35:48PM -0400, Stefan Berger wrote:
> > > > > On 05/02/2017 02:50 PM, Marc-André Lureau wrote:
> > > > > > Hi
> > > > > >
> > > > > > On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <
> patrick.ohly@intel.com
> > > > > > <mailto:patrick.ohly@intel.com>> wrote:
> > > > > >
> > > > > > On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
> > > > > > > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
> > > > > > > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger
> > > > > > <stefanb@linux.vnet.ibm.com <mailto:
> stefanb@linux.vnet.ibm.com>>
> > > > > > > > wrote:
> > > > > > > >
> > > > > > > >> And who is going to implement that qemu-swtpm? Obviously
> > > this
> > > > > > discussion
> > > > > > > >> doesn't contribute to progress if nobody is doing that
> in
> > > the
> > > > > > end.
> > > > > > > >>
> > > > > > > > The same persons who try to push for that emulated TPM
> code.
> > > > > > The easiest
> > > > > > > > approach would be to copy/adapt the swtpm code in qemu,
> if
> > > the
> > > > > > licence is
> > > > > > > > compatible. I can help with that if there is a consensus
> it's
> > > > > > a better
> > > > > > > > approach.
> > > > > > >
> > > > > > >
> > > > > > > It's a matter of time and at least I don't have time for
> that.
> > > > > >
> > > > > > Neither do I, and nor (I believe) does Amarnath. The approach
> > > with
> > > > > > using
> > > > > > the existing swtpm project seemed attractive to us exactly
> > > because it
> > > > > > avoids having to write and maintain more than just the glue
> code
> > > > > > between
> > > > > > the two projects.
> > > > > >
> > > > > >
> > > > > > The main argument is not about having more or less code in qemu
> to
> > > > > > maintain, but yes this is a concern (although giving up that
> > > maintenance
> > > > > > to a seperate project with mostly Stefan-alone isn't a much
> better
> > > > > > alternative). btw, is the project actually used by something else
> > > than
> > > > > > qemu? (I am not talking about developpers/testing). If not, then
> it
> > > > > > makes sense to make it part of qemu.
> > > > >
> > > > > The intention would be to use it for RunC as well (plus higher
> layers
> > > > > afterwards): https://github.com/opencontainers/runc/pull/1082
> > > > >
> > > > > >
> > > > > > But it's mostly a technical reason, to avoid having to rely on a
> > > foreign
> > > > > > protocol and project with all the compatibility constrains.
> > > > >
> > > > > I understand. Ideally swtpm-0.1 would be equivalent to 1.0 with all
> > > features
> > > > > available and no further protocol extensions necessary. In practice
> > > that may
> > > > > look different.
> > > > >
> > > > > >
> > > > > > In the end, we may decide to start with a separate project, and
> > > change
> > > > > > it in the future if it's problematic (that would break some
> cases,
> > > such
> > > > > > as being able to freely switch the helper). Tbh, I am not so
> happy
> > > with
> > > > > > the code quality of swtpm, and I haven't looked closely at
> libtpms.
> > > > > > Having a qemu-swtpm as part of qemu would probably help improve
> it
> > > too,
> > > > > > and bring a few more developers for maintainance...
> > > > >
> > > > > libtpms combines a few source codes with some glue around it. The
> > > coding
> > > > > style is different for TPM 1.2 and TPM 2 code for example and the
> code
> > > bases
> > > > > are in the 10s of thousands of line. In the case of TPM 2 it 'lives
> > > from'
> > > > > TCG code drops and thus there is no reformatting of source code
> etc.
> > > > >
> > > > > If someone wants to get started on qemu-swtpm that's certainly cool
> > > but over
> > > > > the years it's just been quite difficult to find developers for it
> to
> > > share
> > > > > the burden. All that said, someone should state whether this
> series is
> > > a go
> > > > > or no-go because of the external project it requires.
> > > >
> > > > I think it is *good* that it uses the external swtpm project and do
> not
> > > > want to see it reimplemented inside QEMU, particularly with the
> interest
> > > > for swtpm to be used in container contexts via RunC. Such common
> > > infrastructure
> > > > for both containers & QEMU will be important given the increasing
> > > convergance
> > > > of technology across containers & VMs.
> > >
> > > I agree; there aren't that many people who understand the details of
> TPMs,
> > > reimplementing one in QEMU isn't something you'd want to do.
> > >
> >
> > It's not about reimplementing TPM emulation. swtpm is a small utility
> > talking to libtpms doing the heavy work. swtpm could quite easily be
> > copied/adapted to fit in qemu if it's only meant to be used by qemu.
> > However, it seems the helper is going to be used by other projects, so it
> > make sense to make it a seperate project. Nevertheless, I think we should
> > carefully review the protocol and the compatibility situation before
> > committing this work, it's a major burden ahead..
>
> Yes, I agree that reviewing the protocol is a very neccessary step, to
> ensure it is going to be forwards compatible in a manner suitable for
> QEMU.
>
> In particular we need to understand what, if any, relationship there
> needs to be wrt machine types & live migration stability. eg if a
> VM is booted and the protocol negotiates version X, and we then live
> migrate to a host with a newer swtpm, we need to ensure that the
> protocol doesn't negotiate something that leads to guest OS incompatiblity
> problems in accessing the TPM.
>
>
Not only the protocol, but the management aspect of this helper too. See
the commit message for instance for the preparatory swtpm steps and
arguments.
If it would be part of qemu, there are more chances we could make it speak
qmp for instance, which would likely help in the future.
> basically similar scenario to that which we have had with vhost-user
> and version compatibility with external vhost-user server implementations
> across live migration.
>
>
Yes, this is already quite painful and not very well tested, I would rather
avoid this situation even at the cost of small code duplication...
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-03 11:29 ` Daniel P. Berrange
2017-05-03 11:37 ` Marc-André Lureau
@ 2017-05-03 14:42 ` Stefan Berger
2017-05-04 9:44 ` Patrick Ohly
1 sibling, 1 reply; 46+ messages in thread
From: Stefan Berger @ 2017-05-03 14:42 UTC (permalink / raw)
To: Daniel P. Berrange, Marc-André Lureau
Cc: Dr. David Alan Gilbert, Amarnath Valluri, Patrick Ohly, qemu-devel
On 05/03/2017 07:29 AM, Daniel P. Berrange wrote:
> On Wed, May 03, 2017 at 11:24:42AM +0000, Marc-André Lureau wrote:
>> Hi
>>
>> On Wed, May 3, 2017 at 3:17 PM Dr. David Alan Gilbert <dgilbert@redhat.com>
>> wrote:
>>
>>> * Daniel P. Berrange (berrange@redhat.com) wrote:
>>>> On Tue, May 02, 2017 at 03:35:48PM -0400, Stefan Berger wrote:
>>>>> On 05/02/2017 02:50 PM, Marc-André Lureau wrote:
>>>>>> Hi
>>>>>>
>>>>>> On Tue, May 2, 2017 at 10:25 PM Patrick Ohly <patrick.ohly@intel.com
>>>>>> <mailto:patrick.ohly@intel.com>> wrote:
>>>>>>
>>>>>> On Tue, 2017-05-02 at 13:19 -0400, Stefan Berger wrote:
>>>>>> > On 05/02/2017 01:09 PM, Marc-André Lureau wrote:
>>>>>> > > On Tue, May 2, 2017 at 8:59 PM Stefan Berger
>>>>>> <stefanb@linux.vnet.ibm.com <mailto:stefanb@linux.vnet.ibm.com>>
>>>>>> > > wrote:
>>>>>> > >
>>>>>> > >> And who is going to implement that qemu-swtpm? Obviously
>>> this
>>>>>> discussion
>>>>>> > >> doesn't contribute to progress if nobody is doing that in
>>> the
>>>>>> end.
>>>>>> > >>
>>>>>> > > The same persons who try to push for that emulated TPM code.
>>>>>> The easiest
>>>>>> > > approach would be to copy/adapt the swtpm code in qemu, if
>>> the
>>>>>> licence is
>>>>>> > > compatible. I can help with that if there is a consensus it's
>>>>>> a better
>>>>>> > > approach.
>>>>>> >
>>>>>> >
>>>>>> > It's a matter of time and at least I don't have time for that.
>>>>>>
>>>>>> Neither do I, and nor (I believe) does Amarnath. The approach
>>> with
>>>>>> using
>>>>>> the existing swtpm project seemed attractive to us exactly
>>> because it
>>>>>> avoids having to write and maintain more than just the glue code
>>>>>> between
>>>>>> the two projects.
>>>>>>
>>>>>>
>>>>>> The main argument is not about having more or less code in qemu to
>>>>>> maintain, but yes this is a concern (although giving up that
>>> maintenance
>>>>>> to a seperate project with mostly Stefan-alone isn't a much better
>>>>>> alternative). btw, is the project actually used by something else
>>> than
>>>>>> qemu? (I am not talking about developpers/testing). If not, then it
>>>>>> makes sense to make it part of qemu.
>>>>> The intention would be to use it for RunC as well (plus higher layers
>>>>> afterwards): https://github.com/opencontainers/runc/pull/1082
>>>>>
>>>>>> But it's mostly a technical reason, to avoid having to rely on a
>>> foreign
>>>>>> protocol and project with all the compatibility constrains.
>>>>> I understand. Ideally swtpm-0.1 would be equivalent to 1.0 with all
>>> features
>>>>> available and no further protocol extensions necessary. In practice
>>> that may
>>>>> look different.
>>>>>
>>>>>> In the end, we may decide to start with a separate project, and
>>> change
>>>>>> it in the future if it's problematic (that would break some cases,
>>> such
>>>>>> as being able to freely switch the helper). Tbh, I am not so happy
>>> with
>>>>>> the code quality of swtpm, and I haven't looked closely at libtpms.
>>>>>> Having a qemu-swtpm as part of qemu would probably help improve it
>>> too,
>>>>>> and bring a few more developers for maintainance...
>>>>> libtpms combines a few source codes with some glue around it. The
>>> coding
>>>>> style is different for TPM 1.2 and TPM 2 code for example and the code
>>> bases
>>>>> are in the 10s of thousands of line. In the case of TPM 2 it 'lives
>>> from'
>>>>> TCG code drops and thus there is no reformatting of source code etc.
>>>>>
>>>>> If someone wants to get started on qemu-swtpm that's certainly cool
>>> but over
>>>>> the years it's just been quite difficult to find developers for it to
>>> share
>>>>> the burden. All that said, someone should state whether this series is
>>> a go
>>>>> or no-go because of the external project it requires.
>>>> I think it is *good* that it uses the external swtpm project and do not
>>>> want to see it reimplemented inside QEMU, particularly with the interest
>>>> for swtpm to be used in container contexts via RunC. Such common
>>> infrastructure
>>>> for both containers & QEMU will be important given the increasing
>>> convergance
>>>> of technology across containers & VMs.
>>> I agree; there aren't that many people who understand the details of TPMs,
>>> reimplementing one in QEMU isn't something you'd want to do.
>>>
>> It's not about reimplementing TPM emulation. swtpm is a small utility
>> talking to libtpms doing the heavy work. swtpm could quite easily be
>> copied/adapted to fit in qemu if it's only meant to be used by qemu.
>> However, it seems the helper is going to be used by other projects, so it
>> make sense to make it a seperate project. Nevertheless, I think we should
>> carefully review the protocol and the compatibility situation before
>> committing this work, it's a major burden ahead..
> Yes, I agree that reviewing the protocol is a very neccessary step, to
> ensure it is going to be forwards compatible in a manner suitable for
> QEMU.
>
> In particular we need to understand what, if any, relationship there
> needs to be wrt machine types & live migration stability. eg if a
> VM is booted and the protocol negotiates version X, and we then live
> migrate to a host with a newer swtpm, we need to ensure that the
> protocol doesn't negotiate something that leads to guest OS incompatiblity
> problems in accessing the TPM.
>
> basically similar scenario to that which we have had with vhost-user
> and version compatibility with external vhost-user server implementations
> across live migration.
Ok, please have a look at the protocol.
As for the state of the TPM implementations:
- the TPM 1.2 part is stable and besides openssl changes in the future
I would not expect any more changes to the core code. That means that
the state blobs the code is writing out and we are migrating are
'stable'. They are written in big endian format just like any other QEMU
device and thus are migratable between endianess.
- the TPM 2 part , as stated before, is still somewhat in flux. I am
not sure when there will be a final TPM 2 from TCG. There the
possibility exists that the state blobs the TPM 2 is writing out still
change. I have added a version tag in front of the blobs so in case
something else gets added that that can be accommodated. Besides that
it's also adapted to write the state blobs in big endian format for the
same reason as above. Maybe at some point I'll just freeze the code and
don't follow the ongoing TPM 2 development anymore besides bug fixes to
exsting code, which then freezes the state blobs as well.
The issue on the swtpm and QEMU side then is the protocols to transfer 3
opaque (possibly encrypted) swtpm state blobs when suspending/resuming
or migrating the swtpm. I currently have 1 command to pull them out by
their 3 identifies (so run that command 3 times) and 1 commands to put
them back in by their identifier. When is comes to migration, this is
probably one of the most critical parts to look at.
Stefan
>
> Regards,
> Daniel
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 4/8] tpm-backend: Made few interface methods optional
2017-05-02 12:29 ` Marc-André Lureau
@ 2017-05-04 8:39 ` Amarnath Valluri
2017-05-04 11:06 ` [Qemu-devel] [PATCH v4 " Amarnath Valluri
1 sibling, 0 replies; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-04 8:39 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
On 05/02/2017 03:29 PM, Marc-André Lureau wrote:
>
>
> On Tue, May 2, 2017 at 3:52 PM Amarnath Valluri
> <amarnath.valluri@intel.com <mailto:amarnath.valluri@intel.com>> wrote:
>
> This allows backend implementations left optional interface methods.
> For mandatory methods assertion checks added.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com
> <mailto:amarnath.valluri@intel.com>>
>
> ---
> backends/tpm.c | 24 ++++++++++++++++++------
> hw/tpm/tpm_passthrough.c | 16 ----------------
> 2 files changed, 18 insertions(+), 22 deletions(-)
>
> diff --git a/backends/tpm.c b/backends/tpm.c
> index cf5abf1..8245426 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -48,7 +48,7 @@ const char *tpm_backend_get_desc(TPMBackend *s)
> {
> TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
>
> - return k->ops->desc();
> + return k->ops->desc ? k->ops->desc() : "";
> }
>
>
> If it only need to returns const, we may consider using a class field,
> defaulting to null.
Yes, it makes more sense being a const member than a function pointer.
>
> Who is using it? tpm_backend_get_desc() not being called anywhere.
> Let's remove it?
Frankly no one using this API, rather it's been accessed
directly(be_drivers[i]->desc()) in tpm.c. It can be removed.
- Amarnath
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 5/8] tmp backend: Add new api to read backend TpmInfo
2017-05-02 13:35 ` Eric Blake
@ 2017-05-04 9:05 ` Amarnath Valluri
2017-05-04 11:17 ` [Qemu-devel] [PATCH v4 " Amarnath Valluri
1 sibling, 0 replies; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-04 9:05 UTC (permalink / raw)
To: Eric Blake, qemu-devel
Cc: patrick.ohly, marcandre.lureau, stefanb, Markus Armbruster
On 05/02/2017 04:35 PM, Eric Blake wrote:
> On 05/02/2017 06:52 AM, Amarnath Valluri wrote:
>> TPM configuration options are backend implementation details and shall not be
>> part of base TPMBackend object, and these shall not be accessed directly outside
>> of the class, hence added a new interface method, get_tpm_options() to
>> TPMDriverOps., which shall be implemented by the derived classes to return
>> configured tpm options.
>>
>> A new tpm backend api - tpm_backend_query_tpm() which uses _get_tpm_options() to
>> prepare TpmInfo.
>>
>> Made TPMPassthroughOptions type inherited from newly defined TPMOptions base type.
>> The TPMOptions base type is intentionally left empty and supposed to be
>> inherited by all backend implementations to define their tpm configuration
>> options.
>>
>> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
>> ---
>> +++ b/qapi-schema.json
>> @@ -5137,6 +5137,16 @@
>> { 'command': 'query-tpm-types', 'returns': ['TpmType'] }
>>
>> ##
>> +# @TPMOptions:
>> +#
>> +# Base type for TPM options
>> +#
>> +# Since: 2.10
>> +##
>> +{ 'struct': 'TPMOptions',
>> + 'data': { } }
>> +
>> +##
>> # @TPMPassthroughOptions:
>> #
>> # Information about the TPM passthrough type
>> @@ -5148,20 +5158,9 @@
>> #
>> # Since: 1.5
>> ##
>> -{ 'struct': 'TPMPassthroughOptions', 'data': { '*path' : 'str',
>> - '*cancel-path' : 'str'} }
>> +{ 'struct': 'TPMPassthroughOptions', 'base': 'TPMOptions',
>> + 'data': { '*path' : 'str', '*cancel-path' : 'str'} }
>>
>> -##
>> -# @TpmTypeOptions:
>> -#
>> -# A union referencing different TPM backend types' configuration options
>> -#
>> -# @type: 'passthrough' The configuration options for the TPM passthrough type
>> -#
>> -# Since: 1.5
>> -##
>> -{ 'union': 'TpmTypeOptions',
>> - 'data': { 'passthrough' : 'TPMPassthroughOptions' } }
> Getting rid of a simple union is nice. However,
>
>>
>> ##
>> # @TPMInfo:
>> @@ -5170,6 +5169,8 @@
>> #
>> # @id: The Id of the TPM
>> #
>> +# @type: The TPM backend type
>> +#
>> # @model: The TPM frontend model
>> #
>> # @options: The TPM (backend) type configuration options
>> @@ -5178,8 +5179,9 @@
>> ##
>> { 'struct': 'TPMInfo',
>> 'data': {'id': 'str',
>> + 'type': 'TpmType',
>> 'model': 'TpmModel',
>> - 'options': 'TpmTypeOptions' } }
>> + 'options': 'TPMOptions' } }
>>
>> ##
>> # @query-tpm:
>> @@ -5196,13 +5198,12 @@
>> # <- { "return":
>> # [
>> # { "model": "tpm-tis",
>> +# "type": "passthrough",
>> # "options":
>> -# { "type": "passthrough",
>> -# "data":
>> -# { "cancel-path": "/sys/class/misc/tpm0/device/cancel",
>> -# "path": "/dev/tpm0"
>> -# }
>> -# },
>> +# {
>> +# "cancel-path": "/sys/class/misc/tpm0/device/cancel",
>> +# "path": "/dev/tpm0"
>> +# },
>> # "id": "tpm0"
> Doing it in a manner that is NOT backwards-compatible (as evidenced by
> your change to the output text) is NOT good. It will break any existing
> client that was expecting to parse information in the old layout.
>
> I'm afraid you're going to have to fix this to not break QMP wire
> compatibility.
>
Ok, I will revert the changes touching TpmTypeOptions which breaks the
existing clients, :(
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class
2017-05-02 15:54 ` Marc-André Lureau
@ 2017-05-04 9:25 ` Amarnath Valluri
2017-05-04 9:32 ` Marc-André Lureau
0 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-04 9:25 UTC (permalink / raw)
To: Marc-André Lureau, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
On 05/02/2017 06:54 PM, Marc-André Lureau wrote:
> Hi
>
> On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri
> <amarnath.valluri@intel.com <mailto:amarnath.valluri@intel.com>> wrote:
>
> Provide base implementation of realloc_buffer(), so that backend
> implementations
> can resue.
>
>
> I doubt that base class facility helps at this point, and would
> suggest moving it to tpm-tis only.
The intention here is to provided the default implementation in base
class, still backends can overwrite with their suitable reallocation size.
- Amarnath
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class
2017-05-04 9:25 ` Amarnath Valluri
@ 2017-05-04 9:32 ` Marc-André Lureau
2017-05-04 11:31 ` [Qemu-devel] [PATCH v4 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model Amarnath Valluri
0 siblings, 1 reply; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-04 9:32 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb, patrick.ohly, berrange
On Thu, May 4, 2017 at 1:23 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
>
>
> On 05/02/2017 06:54 PM, Marc-André Lureau wrote:
>
> Hi
>
> On Tue, May 2, 2017 at 3:53 PM Amarnath Valluri <
> amarnath.valluri@intel.com> wrote:
>
>> Provide base implementation of realloc_buffer(), so that backend
>> implementations
>> can resue.
>>
>>
> I doubt that base class facility helps at this point, and would suggest
> moving it to tpm-tis only.
>
> The intention here is to provided the default implementation in base
> class, still backends can overwrite with their suitable reallocation size.
>
>
But no other backend uses it.
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-03 14:42 ` Stefan Berger
@ 2017-05-04 9:44 ` Patrick Ohly
2017-05-04 11:08 ` Stefan Berger
0 siblings, 1 reply; 46+ messages in thread
From: Patrick Ohly @ 2017-05-04 9:44 UTC (permalink / raw)
To: Stefan Berger
Cc: Daniel P. Berrange, Marc-André Lureau,
Dr. David Alan Gilbert, Amarnath Valluri, qemu-devel
On Wed, 2017-05-03 at 10:42 -0400, Stefan Berger wrote:
> - the TPM 2 part , as stated before, is still somewhat in flux. I am
> not sure when there will be a final TPM 2 from TCG. There the
> possibility exists that the state blobs the TPM 2 is writing out still
> change. I have added a version tag in front of the blobs so in case
> something else gets added that that can be accommodated. Besides that
> it's also adapted to write the state blobs in big endian format for the
> same reason as above. Maybe at some point I'll just freeze the code and
> don't follow the ongoing TPM 2 development anymore besides bug fixes to
> exsting code, which then freezes the state blobs as well.
Ignoring the "work in progress" status of TPM 2 and your
https://github.com/stefanberger/swtpm/tree/tpm2-preview branch, should
your current code already also work with the qemu device backend that is
getting discussed here?
In other words, are protocol changes needed? I know that TPM 2 has
changed the commands, but I don't know whether that affects also the
lower layers.
--
Best Regards, Patrick Ohly
The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v4 4/8] tpm-backend: Made few interface methods optional
2017-05-02 12:29 ` Marc-André Lureau
2017-05-04 8:39 ` Amarnath Valluri
@ 2017-05-04 11:06 ` Amarnath Valluri
1 sibling, 0 replies; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-04 11:06 UTC (permalink / raw)
To: qemu-devel; +Cc: Amarnath Valluri
This allows backend implementations left optional interface methods.
For mandatory methods assertion checks added.
Took the opportunity to remove unused methods:
tpm_backend_get_type()
tpm_backend_get_desc()
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 36 +++++++++++++++++-------------------
hw/tpm/tpm_passthrough.c | 23 +----------------------
include/sysemu/tpm_backend.h | 19 +------------------
tpm.c | 2 +-
4 files changed, 20 insertions(+), 60 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index cf5abf1..05002e6 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -37,20 +37,6 @@ static void tpm_backend_thread_end(TPMBackend *s)
}
}
-enum TpmType tpm_backend_get_type(TPMBackend *s)
-{
- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
-
- return k->ops->type;
-}
-
-const char *tpm_backend_get_desc(TPMBackend *s)
-{
- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
-
- return k->ops->desc();
-}
-
int tpm_backend_init(TPMBackend *s, TPMState *state,
TPMRecvDataCB *datacb)
{
@@ -59,7 +45,7 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
s->tpm_state = state;
s->recv_data_callback = datacb;
- return k->ops->init(s);
+ return k->ops->init ? k->ops->init(s) : 0;
}
int tpm_backend_startup_tpm(TPMBackend *s)
@@ -73,13 +59,15 @@ int tpm_backend_startup_tpm(TPMBackend *s)
NULL);
g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
- return k->ops->startup_tpm(s);
+ return k->ops->startup_tpm ? k->ops->startup_tpm(s) : 0;
}
bool tpm_backend_had_startup_error(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->had_startup_error);
+
return k->ops->had_startup_error(s);
}
@@ -87,6 +75,8 @@ size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->realloc_buffer);
+
return k->ops->realloc_buffer(sb);
}
@@ -100,7 +90,9 @@ void tpm_backend_reset(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- k->ops->reset(s);
+ if (k->ops->reset) {
+ k->ops->reset(s);
+ }
tpm_backend_thread_end(s);
}
@@ -109,6 +101,8 @@ void tpm_backend_cancel_cmd(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->cancel_cmd);
+
k->ops->cancel_cmd(s);
}
@@ -116,20 +110,24 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->get_tpm_established_flag(s);
+ return k->ops->get_tpm_established_flag ?
+ k->ops->get_tpm_established_flag(s) : false;
}
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->reset_tpm_established_flag(s, locty);
+ return k->ops->reset_tpm_established_flag ?
+ k->ops->reset_tpm_established_flag(s, locty) : 0;
}
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->get_tpm_version);
+
return k->ops->get_tpm_version(s);
}
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index 815a72e..a0459a6 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -227,15 +227,6 @@ static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
}
}
-/*
- * Start the TPM (thread). If it had been started before, then terminate
- * and start it again.
- */
-static int tpm_passthrough_startup_tpm(TPMBackend *tb)
-{
- return 0;
-}
-
static void tpm_passthrough_reset(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -247,11 +238,6 @@ static void tpm_passthrough_reset(TPMBackend *tb)
tpm_pt->had_startup_error = false;
}
-static int tpm_passthrough_init(TPMBackend *tb)
-{
- return 0;
-}
-
static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
{
return false;
@@ -309,11 +295,6 @@ static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
}
}
-static const char *tpm_passthrough_create_desc(void)
-{
- return "Passthrough TPM backend driver";
-}
-
static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -453,10 +434,8 @@ static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
static const TPMDriverOps tpm_passthrough_driver = {
.type = TPM_TYPE_PASSTHROUGH,
.opts = tpm_passthrough_cmdline_opts,
- .desc = tpm_passthrough_create_desc,
+ .desc = "Passthrough TPM backend driver",
.create = tpm_passthrough_create,
- .init = tpm_passthrough_init,
- .startup_tpm = tpm_passthrough_startup_tpm,
.realloc_buffer = tpm_passthrough_realloc_buffer,
.reset = tpm_passthrough_reset,
.had_startup_error = tpm_passthrough_get_startup_error,
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index f61bcfe..d6ae463 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -75,7 +75,7 @@ struct TPMDriverOps {
enum TpmType type;
const QemuOptDesc *opts;
/* get a descriptive text of the backend to display to the user */
- const char *(*desc)(void);
+ const char *desc;
TPMBackend *(*create)(QemuOpts *opts, const char *id);
@@ -99,23 +99,6 @@ struct TPMDriverOps {
TPMVersion (*get_tpm_version)(TPMBackend *t);
};
-
-/**
- * tpm_backend_get_type:
- * @s: the backend
- *
- * Returns the TpmType of the backend.
- */
-enum TpmType tpm_backend_get_type(TPMBackend *s);
-
-/**
- * tpm_backend_get_desc:
- * @s: the backend
- *
- * Returns a human readable description of the backend.
- */
-const char *tpm_backend_get_desc(TPMBackend *s);
-
/**
* tpm_backend_init:
* @s: the backend to initialized
diff --git a/tpm.c b/tpm.c
index 70f74fa..2979508 100644
--- a/tpm.c
+++ b/tpm.c
@@ -102,7 +102,7 @@ static void tpm_display_backend_drivers(void)
for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
fprintf(stderr, "%12s %s\n",
- TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc());
+ TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc);
}
fprintf(stderr, "\n");
}
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator
2017-05-04 9:44 ` Patrick Ohly
@ 2017-05-04 11:08 ` Stefan Berger
0 siblings, 0 replies; 46+ messages in thread
From: Stefan Berger @ 2017-05-04 11:08 UTC (permalink / raw)
To: Patrick Ohly
Cc: Daniel P. Berrange, Marc-André Lureau,
Dr. David Alan Gilbert, Amarnath Valluri, qemu-devel
On 05/04/2017 05:44 AM, Patrick Ohly wrote:
> On Wed, 2017-05-03 at 10:42 -0400, Stefan Berger wrote:
>> - the TPM 2 part , as stated before, is still somewhat in flux. I am
>> not sure when there will be a final TPM 2 from TCG. There the
>> possibility exists that the state blobs the TPM 2 is writing out still
>> change. I have added a version tag in front of the blobs so in case
>> something else gets added that that can be accommodated. Besides that
>> it's also adapted to write the state blobs in big endian format for the
>> same reason as above. Maybe at some point I'll just freeze the code and
>> don't follow the ongoing TPM 2 development anymore besides bug fixes to
>> exsting code, which then freezes the state blobs as well.
> Ignoring the "work in progress" status of TPM 2 and your
> https://github.com/stefanberger/swtpm/tree/tpm2-preview branch, should
> your current code already also work with the qemu device backend that is
> getting discussed here?
Yes.
>
> In other words, are protocol changes needed? I know that TPM 2 has
> changed the commands, but I don't know whether that affects also the
> lower layers.
>
No, should work as-is.
^ permalink raw reply [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v4 5/8] tmp backend: Add new api to read backend TpmInfo
2017-05-02 13:35 ` Eric Blake
2017-05-04 9:05 ` Amarnath Valluri
@ 2017-05-04 11:17 ` Amarnath Valluri
1 sibling, 0 replies; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-04 11:17 UTC (permalink / raw)
To: qemu-devel; +Cc: Amarnath Valluri
TPM configuration options are backend implementation details and shall not be
part of base TPMBackend object, and these shall not be accessed directly outside
of the class, hence added a new interface method, get_tpm_options() to
TPMDriverOps., which shall be implemented by the derived classes to return
configured tpm options.
A new tpm backend api - tpm_backend_query_tpm() which uses _get_tpm_options() to
prepare TpmInfo.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 22 +++++++++++++--
hmp.c | 6 ++---
hw/tpm/tpm_passthrough.c | 64 ++++++++++++++++++++++++++++++++++++--------
include/sysemu/tpm_backend.h | 25 +++++++++++++++--
tpm.c | 32 +---------------------
5 files changed, 100 insertions(+), 49 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index 05002e6..4ae6129 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -131,6 +131,26 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
return k->ops->get_tpm_version(s);
}
+TpmTypeOptions *tpm_backend_get_tpm_options(TPMBackend *s)
+{
+ TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+ assert(k->ops->get_tpm_options);
+
+ return k->ops->get_tpm_options(s);
+}
+
+TPMInfo *tpm_backend_query_tpm(TPMBackend *s)
+{
+ TPMInfo *info = g_new0(TPMInfo, 1);
+
+ info->id = g_strdup(s->id);
+ info->model = s->fe_model;
+ info->options = tpm_backend_get_tpm_options(s);
+
+ return info;
+}
+
static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
{
TPMBackend *s = TPM_BACKEND(obj);
@@ -185,8 +205,6 @@ static void tpm_backend_instance_finalize(Object *obj)
TPMBackend *s = TPM_BACKEND(obj);
g_free(s->id);
- g_free(s->path);
- g_free(s->cancel_path);
tpm_backend_thread_end(s);
}
diff --git a/hmp.c b/hmp.c
index ab407d6..728422c 100644
--- a/hmp.c
+++ b/hmp.c
@@ -954,10 +954,10 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
c, TpmModel_lookup[ti->model]);
monitor_printf(mon, " \\ %s: type=%s",
- ti->id, TpmTypeOptionsKind_lookup[ti->options->type]);
+ ti->id, TpmType_lookup[ti->options->type]);
switch (ti->options->type) {
- case TPM_TYPE_OPTIONS_KIND_PASSTHROUGH:
+ case TPM_TYPE_PASSTHROUGH:
tpo = ti->options->u.passthrough.data;
monitor_printf(mon, "%s%s%s%s",
tpo->has_path ? ",path=" : "",
@@ -965,7 +965,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
tpo->has_cancel_path ? ",cancel-path=" : "",
tpo->has_cancel_path ? tpo->cancel_path : "");
break;
- case TPM_TYPE_OPTIONS_KIND__MAX:
+ default:
break;
}
monitor_printf(mon, "\n");
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index a0459a6..c7706e4 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -49,6 +49,7 @@
struct TPMPassthruState {
TPMBackend parent;
+ TPMPassthroughOptions *ops;
char *tpm_dev;
int tpm_fd;
bool tpm_executing;
@@ -308,15 +309,14 @@ static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
* in Documentation/ABI/stable/sysfs-class-tpm.
* From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel
*/
-static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
+static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
{
- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
int fd = -1;
char *dev;
char path[PATH_MAX];
- if (tb->cancel_path) {
- fd = qemu_open(tb->cancel_path, O_WRONLY);
+ if (tpm_pt->ops->cancel_path) {
+ fd = qemu_open(tpm_pt->ops->cancel_path, O_WRONLY);
if (fd < 0) {
error_report("Could not open TPM cancel path : %s",
strerror(errno));
@@ -331,7 +331,7 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
dev) < sizeof(path)) {
fd = qemu_open(path, O_WRONLY);
if (fd >= 0) {
- tb->cancel_path = g_strdup(path);
+ tpm_pt->ops->cancel_path = g_strdup(path);
} else {
error_report("tpm_passthrough: Could not open TPM cancel "
"path %s : %s", path, strerror(errno));
@@ -351,17 +351,24 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
const char *value;
value = qemu_opt_get(opts, "cancel-path");
- tb->cancel_path = g_strdup(value);
+ if (value) {
+ tpm_pt->ops->cancel_path = g_strdup(value);
+ tpm_pt->ops->has_cancel_path = true;
+ } else {
+ tpm_pt->ops->has_cancel_path = false;
+ }
value = qemu_opt_get(opts, "path");
if (!value) {
value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
+ tpm_pt->ops->has_path = false;
+ } else {
+ tpm_pt->ops->has_path = true;
}
+ tpm_pt->ops->path = g_strdup(value);
tpm_pt->tpm_dev = g_strdup(value);
- tb->path = g_strdup(tpm_pt->tpm_dev);
-
tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
if (tpm_pt->tpm_fd < 0) {
error_report("Cannot access TPM device using '%s': %s",
@@ -382,8 +389,8 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
tpm_pt->tpm_fd = -1;
err_free_parameters:
- g_free(tb->path);
- tb->path = NULL;
+ g_free(tpm_pt->ops->path);
+ tpm_pt->ops->path = NULL;
g_free(tpm_pt->tpm_dev);
tpm_pt->tpm_dev = NULL;
@@ -403,7 +410,7 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
goto err_exit;
}
- tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
+ tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tpm_pt);
if (tpm_pt->cancel_fd < 0) {
goto err_exit;
}
@@ -416,6 +423,38 @@ err_exit:
return NULL;
}
+static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
+{
+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
+ TpmTypeOptions *ops = NULL;
+ TPMPassthroughOptions *pops = NULL;
+
+ pops = g_new0(TPMPassthroughOptions, 1);
+ if (!pops) {
+ return NULL;
+ }
+
+ if (tpm_pt->ops->has_path) {
+ pops->has_path = true;
+ pops->path = g_strdup(tpm_pt->ops->path);
+ }
+
+ if (tpm_pt->ops->has_cancel_path) {
+ pops->has_cancel_path = true;
+ pops->cancel_path = g_strdup(tpm_pt->ops->cancel_path);
+ }
+
+ ops = g_new0(TpmTypeOptions, 1);
+ if (!ops) {
+ qapi_free_TPMPassthroughOptions(pops);
+ return NULL;
+ }
+ ops->type = TPM_TYPE_PASSTHROUGH;
+ ops->u.passthrough.data = pops;
+
+ return ops;
+}
+
static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
TPM_STANDARD_CMDLINE_OPTS,
{
@@ -443,12 +482,14 @@ static const TPMDriverOps tpm_passthrough_driver = {
.get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
.reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
.get_tpm_version = tpm_passthrough_get_tpm_version,
+ .get_tpm_options = tpm_passthrough_get_tpm_options,
};
static void tpm_passthrough_inst_init(Object *obj)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
+ tpm_pt->ops = g_new0(TPMPassthroughOptions, 1);
tpm_pt->tpm_fd = -1;
tpm_pt->cancel_fd = -1;
}
@@ -462,6 +503,7 @@ static void tpm_passthrough_inst_finalize(Object *obj)
qemu_close(tpm_pt->tpm_fd);
qemu_close(tpm_pt->cancel_fd);
g_free(tpm_pt->tpm_dev);
+ qapi_free_TPMPassthroughOptions(tpm_pt->ops);
}
static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index d6ae463..6e5bb8d 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -48,10 +48,9 @@ struct TPMBackend {
GThreadPool *thread_pool;
TPMRecvDataCB *recv_data_callback;
+ /* <public> */
char *id;
enum TpmModel fe_model;
- char *path;
- char *cancel_path;
QLIST_ENTRY(TPMBackend) list;
};
@@ -97,6 +96,8 @@ struct TPMDriverOps {
int (*reset_tpm_established_flag)(TPMBackend *t, uint8_t locty);
TPMVersion (*get_tpm_version)(TPMBackend *t);
+
+ TpmTypeOptions *(*get_tpm_options)(TPMBackend *t);
};
/**
@@ -206,6 +207,26 @@ void tpm_backend_open(TPMBackend *s, Error **errp);
*/
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
+/**
+ * tpm_backend_get_tpm_options:
+ * @s: the backend
+ *
+ * Get the backend configuration options
+ *
+ * Returns newly allocated TpmTypeOptions
+ */
+TpmTypeOptions *tpm_backend_get_tpm_options(TPMBackend *s);
+
+/**
+ * tpm_backend_query_tpm:
+ * @s: the backend
+ *
+ * Query backend tpm info
+ *
+ * Returns newly allocated TPMInfo
+ */
+TPMInfo *tpm_backend_query_tpm(TPMBackend *s);
+
TPMBackend *qemu_find_tpm(const char *id);
const TPMDriverOps *tpm_get_backend_driver(const char *type);
diff --git a/tpm.c b/tpm.c
index 2979508..84e9667 100644
--- a/tpm.c
+++ b/tpm.c
@@ -249,36 +249,6 @@ static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
return NULL;
}
-static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
-{
- TPMInfo *res = g_new0(TPMInfo, 1);
- TPMPassthroughOptions *tpo;
-
- res->id = g_strdup(drv->id);
- res->model = drv->fe_model;
- res->options = g_new0(TpmTypeOptions, 1);
-
- switch (tpm_backend_get_type(drv)) {
- case TPM_TYPE_PASSTHROUGH:
- res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
- tpo = g_new0(TPMPassthroughOptions, 1);
- res->options->u.passthrough.data = tpo;
- if (drv->path) {
- tpo->path = g_strdup(drv->path);
- tpo->has_path = true;
- }
- if (drv->cancel_path) {
- tpo->cancel_path = g_strdup(drv->cancel_path);
- tpo->has_cancel_path = true;
- }
- break;
- case TPM_TYPE__MAX:
- break;
- }
-
- return res;
-}
-
/*
* Walk the list of active TPM backends and collect information about them
* following the schema description in qapi-schema.json.
@@ -293,7 +263,7 @@ TPMInfoList *qmp_query_tpm(Error **errp)
continue;
}
info = g_new0(TPMInfoList, 1);
- info->value = qmp_query_tpm_inst(drv);
+ info->value = tpm_backend_query_tpm(drv);
if (!cur_item) {
head = cur_item = info;
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v4 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model
2017-05-04 9:32 ` Marc-André Lureau
@ 2017-05-04 11:31 ` Amarnath Valluri
2017-05-06 12:27 ` Marc-André Lureau
0 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-04 11:31 UTC (permalink / raw)
To: qemu-devel; +Cc: Amarnath Valluri
buffer reallocation is very unlikely to be backend specific. Hence move inside
the tis.
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 9 ---------
hw/tpm/tpm_passthrough.c | 12 ------------
hw/tpm/tpm_tis.c | 14 ++++++++++++--
include/sysemu/tpm_backend.h | 12 ------------
4 files changed, 12 insertions(+), 35 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index 4ae6129..3519570 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -71,15 +71,6 @@ bool tpm_backend_had_startup_error(TPMBackend *s)
return k->ops->had_startup_error(s);
}
-size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
-{
- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
-
- assert(k->ops->realloc_buffer);
-
- return k->ops->realloc_buffer(sb);
-}
-
void tpm_backend_deliver_request(TPMBackend *s)
{
g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD,
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index c7706e4..4ac47ed 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -258,17 +258,6 @@ static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
return tpm_pt->had_startup_error;
}
-static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
-{
- size_t wanted_size = 4096; /* Linux tpm.c buffer size */
-
- if (sb->size != wanted_size) {
- sb->buffer = g_realloc(sb->buffer, wanted_size);
- sb->size = wanted_size;
- }
- return sb->size;
-}
-
static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -475,7 +464,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
.opts = tpm_passthrough_cmdline_opts,
.desc = "Passthrough TPM backend driver",
.create = tpm_passthrough_create,
- .realloc_buffer = tpm_passthrough_realloc_buffer,
.reset = tpm_passthrough_reset,
.had_startup_error = tpm_passthrough_get_startup_error,
.cancel_cmd = tpm_passthrough_cancel_cmd,
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index a6440fe..d5118e7 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -963,6 +963,16 @@ static int tpm_tis_do_startup_tpm(TPMState *s)
return tpm_backend_startup_tpm(s->be_driver);
}
+static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb)
+{
+ size_t wanted_size = 4096; /* Linux tpm.c buffer size */
+
+ if (sb->size != wanted_size) {
+ sb->buffer = g_realloc(sb->buffer, wanted_size);
+ sb->size = wanted_size;
+ }
+}
+
/*
* Get the TPMVersion of the backend device being used
*/
@@ -1010,9 +1020,9 @@ static void tpm_tis_reset(DeviceState *dev)
tis->loc[c].state = TPM_TIS_STATE_IDLE;
tis->loc[c].w_offset = 0;
- tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer);
+ tpm_tis_realloc_buffer(&tis->loc[c].w_buffer);
tis->loc[c].r_offset = 0;
- tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer);
+ tpm_tis_realloc_buffer(&tis->loc[c].r_buffer);
}
tpm_tis_do_startup_tpm(s);
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index 6e5bb8d..bebfba3 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -85,8 +85,6 @@ struct TPMDriverOps {
/* returns true if nothing will ever answer TPM requests */
bool (*had_startup_error)(TPMBackend *t);
- size_t (*realloc_buffer)(TPMSizedBuffer *sb);
-
void (*reset)(TPMBackend *t);
void (*cancel_cmd)(TPMBackend *t);
@@ -132,16 +130,6 @@ int tpm_backend_startup_tpm(TPMBackend *s);
bool tpm_backend_had_startup_error(TPMBackend *s);
/**
- * tpm_backend_realloc_buffer:
- * @s: the backend
- * @sb: the TPMSizedBuffer to re-allocated to the size suitable for the
- * backend.
- *
- * This function returns the size of the allocated buffer
- */
-size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb);
-
-/**
* tpm_backend_deliver_request:
* @s: the backend to send the request to
*
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v4 8/8] tpm: Added support for TPM emulator
2017-05-02 12:25 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " no-reply
@ 2017-05-04 11:35 ` Amarnath Valluri
0 siblings, 0 replies; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-04 11:35 UTC (permalink / raw)
To: qemu-devel; +Cc: Amarnath Valluri
This change introduces a new TPM backend driver that can communicate with
swtpm(software TPM emulator) using unix domain socket interface.
Swtpm uses two unix sockets, one for plain TPM commands and responses, and one
for out-of-band control messages.
The swtpm and associated tools can be found here:
https://github.com/stefanberger/swtpm
The swtpm's control channel protocol specification can be found here:
https://github.com/stefanberger/swtpm/wiki/Control-Channel-Specification
Usage:
# setup TPM state directory
mkdir /tmp/mytpm
chown -R tss:root /tmp/mytpm
/usr/bin/swtpm_setup --tpm-state /tmp/mytpm --createek
# Ask qemu to use TPM emulator with given tpm state directory
qemu-system-x86_64 \
[...] \
-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/mytpm,logfile=/tmp/swtpm.log \
-device tpm-tis,tpmdev=tpm0 \
[...]
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
configure | 15 +-
hmp.c | 21 ++
hw/tpm/Makefile.objs | 1 +
hw/tpm/tpm_emulator.c | 950 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/tpm/tpm_ioctl.h | 243 +++++++++++++
qapi-schema.json | 41 ++-
qemu-options.hx | 53 ++-
tpm.c | 2 +-
8 files changed, 1316 insertions(+), 10 deletions(-)
create mode 100644 hw/tpm/tpm_emulator.c
create mode 100644 hw/tpm/tpm_ioctl.h
diff --git a/configure b/configure
index 48a9370..37a94d9 100755
--- a/configure
+++ b/configure
@@ -3404,10 +3404,15 @@ fi
##########################################
# TPM passthrough is only on x86 Linux
-if test "$targetos" = Linux && test "$cpu" = i386 -o "$cpu" = x86_64; then
- tpm_passthrough=$tpm
+if test "$targetos" = Linux; then
+ tpm_emulator=$tpm
+ if test "$cpu" = i386 -o "$cpu" = x86_64; then
+ tpm_passthrough=$tpm
+ else
+ tpm_passthrough=no
+ fi
else
- tpm_passthrough=no
+ tpm_emulator=no
fi
##########################################
@@ -5209,6 +5214,7 @@ echo "gcov enabled $gcov"
echo "TPM support $tpm"
echo "libssh2 support $libssh2"
echo "TPM passthrough $tpm_passthrough"
+echo "TPM emulator $tpm_emulator"
echo "QOM debugging $qom_cast_debug"
echo "lzo support $lzo"
echo "snappy support $snappy"
@@ -5789,6 +5795,9 @@ if test "$tpm" = "yes"; then
if test "$tpm_passthrough" = "yes"; then
echo "CONFIG_TPM_PASSTHROUGH=y" >> $config_host_mak
fi
+ if test "$tpm_emulator" = "yes"; then
+ echo "CONFIG_TPM_EMULATOR=y" >> $config_host_mak
+ fi
fi
echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
diff --git a/hmp.c b/hmp.c
index 728422c..be97d3d 100644
--- a/hmp.c
+++ b/hmp.c
@@ -936,6 +936,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
Error *err = NULL;
unsigned int c = 0;
TPMPassthroughOptions *tpo;
+ TPMEmulatorOptions *teo;
info_list = qmp_query_tpm(&err);
if (err) {
@@ -965,6 +966,26 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
tpo->has_cancel_path ? ",cancel-path=" : "",
tpo->has_cancel_path ? tpo->cancel_path : "");
break;
+ case TPM_TYPE_EMULATOR:
+ teo = ti->options->u.emulator.data;
+ monitor_printf(mon, ",tmpstatedir=%s", teo->tpmstatedir);
+ monitor_printf(mon, ",spawn=%s", teo->spawn ? "on" : "off");
+ if (teo->has_path) {
+ monitor_printf(mon, ",path=%s", teo->path);
+ }
+ if (teo->has_data_path) {
+ monitor_printf(mon, ",data-path=%s", teo->data_path);
+ }
+ if (teo->has_ctrl_path) {
+ monitor_printf(mon, ",ctrl-path=%s", teo->ctrl_path);
+ }
+ if (teo->has_logfile) {
+ monitor_printf(mon, ",logfile=%s", teo->logfile);
+ }
+ if (teo->has_loglevel) {
+ monitor_printf(mon, ",loglevel=%u", teo->loglevel);
+ }
+ break;
default:
break;
}
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index 64cecc3..41f0b7a 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -1,2 +1,3 @@
common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o tpm_util.o
+common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o tpm_util.o
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
new file mode 100644
index 0000000..2ad63be
--- /dev/null
+++ b/hw/tpm/tpm_emulator.c
@@ -0,0 +1,950 @@
+/*
+ * emulator TPM driver
+ *
+ * Copyright (c) 2017 Intel Corporation
+ * Author: Amarnath Valluri <amarnath.valluri@intel.com>
+ *
+ * Copyright (c) 2010 - 2013 IBM Corporation
+ * Authors:
+ * Stefan Berger <stefanb@us.ibm.com>
+ *
+ * Copyright (C) 2011 IAIK, Graz University of Technology
+ * Author: Andreas Niederl
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qemu/sockets.h"
+#include "io/channel-socket.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_int.h"
+#include "hw/hw.h"
+#include "hw/i386/pc.h"
+#include "tpm_util.h"
+#include "tpm_ioctl.h"
+#include "qapi/error.h"
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+
+#define DEBUG_TPM 0
+
+#define DPRINT(fmt, ...) do { \
+ if (DEBUG_TPM) { \
+ fprintf(stderr, fmt, ## __VA_ARGS__); \
+ } \
+} while (0);
+
+#define DPRINTF(fmt, ...) DPRINT("tpm-emulator: "fmt"\n", __VA_ARGS__)
+
+#define TYPE_TPM_EMULATOR "tpm-emulator"
+#define TPM_EMULATOR(obj) \
+ OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
+
+static const TPMDriverOps tpm_emulator_driver;
+
+/* data structures */
+typedef struct TPMEmulator {
+ TPMBackend parent;
+
+ TPMEmulatorOptions *ops;
+ QIOChannel *data_ioc;
+ QIOChannel *ctrl_ioc;
+ bool op_executing;
+ bool op_canceled;
+ bool child_running;
+ TPMVersion tpm_version;
+ ptm_cap caps; /* capabilities of the TPM */
+ uint8_t cur_locty_number; /* last set locality */
+ QemuMutex state_lock;
+} TPMEmulator;
+
+#define TPM_DEFAULT_EMULATOR "swtpm"
+#define TPM_DEFAULT_LOGLEVEL 5
+#define TPM_EMULATOR_PIDFILE "/tmp/qemu-tpm.pid"
+#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
+
+static int tpm_emulator_ctrlcmd(QIOChannel *ioc, unsigned long cmd, void *msg,
+ size_t msg_len_in, size_t msg_len_out)
+{
+ ssize_t n;
+
+ uint32_t cmd_no = cpu_to_be32(cmd);
+ struct iovec iov[2] = {
+ { .iov_base = &cmd_no, .iov_len = sizeof(cmd_no), },
+ { .iov_base = msg, .iov_len = msg_len_in, },
+ };
+
+ n = qio_channel_writev(ioc, iov, 2, NULL);
+ if (n > 0) {
+ if (msg_len_out > 0) {
+ n = qio_channel_read(ioc, (char *)msg, msg_len_out, NULL);
+ /* simulate ioctl return value */
+ if (n > 0) {
+ n = 0;
+ }
+ } else {
+ n = 0;
+ }
+ }
+ return n;
+}
+
+static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_pt,
+ const uint8_t *in, uint32_t in_len,
+ uint8_t *out, uint32_t out_len,
+ bool *selftest_done)
+{
+ ssize_t ret;
+ bool is_selftest;
+ const struct tpm_resp_hdr *hdr;
+
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ tpm_pt->op_canceled = false;
+ tpm_pt->op_executing = true;
+ *selftest_done = false;
+
+ is_selftest = tpm_util_is_selftest(in, in_len);
+
+ ret = qio_channel_write(tpm_pt->data_ioc, (const char *)in, (size_t)in_len,
+ NULL);
+ if (ret != in_len) {
+ if (!tpm_pt->op_canceled || errno != ECANCELED) {
+ error_report("tpm-emulator: error while transmitting data "
+ "to TPM: %s (%i)", strerror(errno), errno);
+ }
+ goto err_exit;
+ }
+
+ tpm_pt->op_executing = false;
+
+ ret = qio_channel_read(tpm_pt->data_ioc, (char *)out, (size_t)out_len,
+ NULL);
+ if (ret < 0) {
+ if (!tpm_pt->op_canceled || errno != ECANCELED) {
+ error_report("tpm-emulator: error while reading data from "
+ "TPM: %s (%i)", strerror(errno), errno);
+ }
+ } else if (ret < sizeof(struct tpm_resp_hdr) ||
+ be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
+ ret = -1;
+ error_report("tpm-emulator: received invalid response "
+ "packet from TPM");
+ }
+
+ if (is_selftest && (ret >= sizeof(struct tpm_resp_hdr))) {
+ hdr = (struct tpm_resp_hdr *)out;
+ *selftest_done = (be32_to_cpu(hdr->errcode) == 0);
+ }
+
+err_exit:
+ if (ret < 0) {
+ tpm_util_write_fatal_error_response(out, out_len);
+ }
+
+ tpm_pt->op_executing = false;
+
+ return ret;
+}
+
+static int tpm_emulator_set_locality(TPMEmulator *tpm_pt,
+ uint8_t locty_number)
+{
+ ptm_loc loc;
+
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ DPRINTF("%s : locality: 0x%x", __func__, locty_number);
+
+ if (tpm_pt->cur_locty_number != locty_number) {
+ DPRINTF("setting locality : 0x%x", locty_number);
+ loc.u.req.loc = locty_number;
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_SET_LOCALITY, &loc,
+ sizeof(loc), sizeof(loc)) < 0) {
+ error_report("tpm-emulator: could not set locality : %s",
+ strerror(errno));
+ return -1;
+ }
+ loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
+ if (loc.u.resp.tpm_result != 0) {
+ error_report("tpm-emulator: TPM result for set locality : 0x%x",
+ loc.u.resp.tpm_result);
+ return -1;
+ }
+ tpm_pt->cur_locty_number = locty_number;
+ }
+ return 0;
+}
+
+static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ TPMLocality *locty = NULL;
+ bool selftest_done = false;
+
+ DPRINTF("processing command type %d", cmd);
+
+ switch (cmd) {
+ case TPM_BACKEND_CMD_PROCESS_CMD:
+ qemu_mutex_lock(&tpm_pt->state_lock);
+ locty = tb->tpm_state->locty_data;
+ if (tpm_emulator_set_locality(tpm_pt,
+ tb->tpm_state->locty_number) < 0) {
+ tpm_util_write_fatal_error_response(locty->r_buffer.buffer,
+ locty->r_buffer.size);
+ } else {
+ tpm_emulator_unix_tx_bufs(tpm_pt, locty->w_buffer.buffer,
+ locty->w_offset, locty->r_buffer.buffer,
+ locty->r_buffer.size, &selftest_done);
+ }
+ tb->recv_data_callback(tb->tpm_state, tb->tpm_state->locty_number,
+ selftest_done);
+ qemu_mutex_unlock(&tpm_pt->state_lock);
+ break;
+ case TPM_BACKEND_CMD_INIT:
+ case TPM_BACKEND_CMD_END:
+ case TPM_BACKEND_CMD_TPM_RESET:
+ /* nothing to do */
+ break;
+ }
+}
+
+/*
+ * Gracefully shut down the external unixio TPM
+ */
+static void tpm_emulator_shutdown(TPMEmulator *tpm_pt)
+{
+ ptm_res res;
+
+ if (!tpm_pt->child_running) {
+ return;
+ }
+
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_SHUTDOWN, &res, 0,
+ sizeof(res)) < 0) {
+ error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
+ strerror(errno));
+ } else if (res != 0) {
+ error_report("tpm-emulator: TPM result for sutdown: 0x%x",
+ be32_to_cpu(res));
+ }
+}
+
+static int tpm_emulator_probe_caps(TPMEmulator *tpm_pt)
+{
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ DPRINTF("%s", __func__);
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_GET_CAPABILITY,
+ &tpm_pt->caps, 0, sizeof(tpm_pt->caps)) < 0) {
+ error_report("tpm-emulator: probing failed : %s", strerror(errno));
+ return -1;
+ }
+
+ tpm_pt->caps = be64_to_cpu(tpm_pt->caps);
+
+ DPRINTF("capbilities : 0x%lx", tpm_pt->caps);
+
+ return 0;
+}
+
+static int tpm_emulator_check_caps(TPMEmulator *tpm_pt)
+{
+ ptm_cap caps = 0;
+ const char *tpm = NULL;
+
+ /* check for min. required capabilities */
+ switch (tpm_pt->tpm_version) {
+ case TPM_VERSION_1_2:
+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
+ PTM_CAP_SET_LOCALITY;
+ tpm = "1.2";
+ break;
+ case TPM_VERSION_2_0:
+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
+ PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED;
+ tpm = "2";
+ break;
+ case TPM_VERSION_UNSPEC:
+ error_report("tpm-emulator: TPM version has not been set");
+ return -1;
+ }
+
+ if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_pt, caps)) {
+ error_report("tpm-emulator: TPM does not implement minimum set of "
+ "required capabilities for TPM %s (0x%x)", tpm, (int)caps);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tpm_emulator_init_tpm(TPMEmulator *tpm_pt)
+{
+ ptm_init init;
+ ptm_res res;
+
+ if (!tpm_pt->child_running) {
+ return -1;
+ }
+
+ DPRINTF("%s", __func__);
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_INIT, &init, sizeof(init),
+ sizeof(init)) < 0) {
+ error_report("tpm-emulator: could not send INIT: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ res = be32_to_cpu(init.u.resp.tpm_result);
+ if (res) {
+ error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x", res);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tpm_emulator_startup_tpm(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+
+ DPRINTF("%s", __func__);
+
+ tpm_emulator_init_tpm(tpm_pt) ;
+
+ return 0;
+}
+
+static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ ptm_est est;
+
+ DPRINTF("%s", __func__);
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_GET_TPMESTABLISHED, &est, 0,
+ sizeof(est)) < 0) {
+ error_report("tpm-emulator: Could not get the TPM established flag: %s",
+ strerror(errno));
+ return false;
+ }
+ DPRINTF("established flag: %0x", est.u.resp.bit);
+
+ return (est.u.resp.bit != 0);
+}
+
+static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
+ uint8_t locty)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ ptm_reset_est reset_est;
+ ptm_res res;
+
+ /* only a TPM 2.0 will support this */
+ if (tpm_pt->tpm_version == TPM_VERSION_2_0) {
+ reset_est.u.req.loc = tpm_pt->cur_locty_number;
+
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_RESET_TPMESTABLISHED,
+ &reset_est, sizeof(reset_est),
+ sizeof(reset_est)) < 0) {
+ error_report("tpm-emulator: Could not reset the establishment bit: "
+ "%s", strerror(errno));
+ return -1;
+ }
+
+ res = be32_to_cpu(reset_est.u.resp.tpm_result);
+ if (res) {
+ error_report("tpm-emulator: TPM result for rest establixhed flag: "
+ "0x%x", res);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static bool tpm_emulator_had_startup_error(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+
+ return !tpm_pt->child_running;
+}
+
+static void tpm_emulator_cancel_cmd(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ ptm_res res;
+
+ /*
+ * As of Linux 3.7 the tpm_tis driver does not properly cancel
+ * commands on all TPM manufacturers' TPMs.
+ * Only cancel if we're busy so we don't cancel someone else's
+ * command, e.g., a command executed on the host.
+ */
+ if (tpm_pt->op_executing) {
+ if (TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_pt, PTM_CAP_CANCEL_TPM_CMD)) {
+ if (tpm_emulator_ctrlcmd(tpm_pt->ctrl_ioc, CMD_CANCEL_TPM_CMD, &res,
+ 0, sizeof(res)) < 0) {
+ error_report("tpm-emulator: Could not cancel command: %s",
+ strerror(errno));
+ } else if (res != 0) {
+ error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
+ be32_to_cpu(res));
+ } else {
+ tpm_pt->op_canceled = true;
+ }
+ }
+ }
+}
+
+static void tpm_emulator_reset(TPMBackend *tb)
+{
+ DPRINTF("%s", __func__);
+
+ tpm_emulator_cancel_cmd(tb);
+}
+
+static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+
+ return tpm_pt->tpm_version;
+}
+
+static gboolean tpm_emulator_fd_handler(QIOChannel *ioc, GIOCondition cnd,
+ void *opaque)
+{
+ TPMEmulator *tpm_pt = opaque;
+
+ if (cnd & G_IO_ERR || cnd & G_IO_HUP) {
+ error_report("TPM backend disappeared");
+ tpm_pt->child_running = false;
+ return false;
+ }
+
+ return true;
+}
+
+static QIOChannel *_iochannel_new(const char *path, int fd, Error **err)
+{
+ int socket = path ? unix_connect(path, err) : fd;
+ if (socket < 0) {
+ return NULL;
+ }
+
+ return QIO_CHANNEL(qio_channel_socket_new_fd(socket, err));
+}
+
+static int tpm_emulator_spawn_emulator(TPMEmulator *tpm_pt)
+{
+ int fds[2] = { -1, -1 };
+ int ctrl_fds[2] = { -1, -1 };
+ pid_t cpid;
+
+ if (!tpm_pt->ops->has_data_path) {
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) < 0) {
+ return -1;
+ }
+ }
+
+ if (!tpm_pt->ops->has_ctrl_path) {
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ctrl_fds) < 0) {
+ if (!tpm_pt->ops->has_data_path) {
+ closesocket(fds[0]);
+ closesocket(fds[1]);
+ }
+ return -1;
+ }
+ }
+
+ cpid = qemu_fork(NULL);
+ if (cpid < 0) {
+ error_report("tpm-emulator: Fork failure: %s", strerror(errno));
+ if (!tpm_pt->ops->has_data_path) {
+ closesocket(fds[0]);
+ closesocket(fds[1]);
+ }
+ if (!tpm_pt->ops->has_ctrl_path) {
+ closesocket(ctrl_fds[0]);
+ closesocket(ctrl_fds[1]);
+ }
+ return -1;
+ }
+
+ unlink(TPM_EMULATOR_PIDFILE);
+
+ if (cpid == 0) { /* CHILD */
+ enum {
+ PARAM_PATH,
+ PARAM_IFACE,
+ PARAM_SERVER, PARAM_SERVER_ARGS,
+ PARAM_CTRL, PARAM_CTRL_ARGS,
+ PARAM_STATE, PARAM_STATE_ARGS,
+ PARAM_PIDFILE, PARAM_PIDFILE_ARGS,
+ PARAM_LOG, PARAM_LOG_ARGS,
+ PARAM_MAX
+ };
+
+ int i;
+ int data_fd = -1, ctrl_fd = -1;
+ char *argv[PARAM_MAX + 1];
+
+ /* close all unused inherited sockets */
+ if (fds[0] >= 0) {
+ closesocket(fds[0]);
+ }
+ if (ctrl_fds[0] >= 0) {
+ closesocket(ctrl_fds[0]);
+ }
+
+ i = STDERR_FILENO + 1;
+ if (fds[1] >= 0) {
+ data_fd = dup2(fds[1], i++);
+ if (data_fd < 0) {
+ error_report("tpm-emulator: dup2() failure - %s",
+ strerror(errno));
+ goto exit_child;
+ }
+ }
+ if (ctrl_fds[1] >= 0) {
+ ctrl_fd = dup2(ctrl_fds[1], i++);
+ if (ctrl_fd < 0) {
+ error_report("tpm-emulator: dup2() failure - %s",
+ strerror(errno));
+ goto exit_child;
+ }
+ }
+ for ( ; i < sysconf(_SC_OPEN_MAX); i++) {
+ close(i);
+ }
+
+ argv[PARAM_MAX] = NULL;
+ argv[PARAM_PATH] = g_strdup(tpm_pt->ops->path);
+ argv[PARAM_IFACE] = g_strdup("socket");
+ if (tpm_pt->ops->has_data_path) {
+ argv[PARAM_SERVER] = g_strdup("--server");
+ argv[PARAM_SERVER_ARGS] = g_strdup_printf("type=unixio,path=%s",
+ tpm_pt->ops->data_path);
+ } else {
+ argv[PARAM_SERVER] = g_strdup("--fd");
+ argv[PARAM_SERVER_ARGS] = g_strdup_printf("%d", data_fd);
+ }
+
+ argv[PARAM_CTRL] = g_strdup("--ctrl");
+ if (tpm_pt->ops->has_ctrl_path) {
+ argv[PARAM_CTRL_ARGS] = g_strdup_printf("type=unixio,path=%s",
+ tpm_pt->ops->ctrl_path);
+ } else {
+ argv[PARAM_CTRL_ARGS] = g_strdup_printf("type=unixio,clientfd=%d",
+ ctrl_fd);
+ }
+
+ argv[PARAM_STATE] = g_strdup("--tpmstate");
+ argv[PARAM_STATE_ARGS] = g_strdup_printf("dir=%s",
+ tpm_pt->ops->tpmstatedir);
+ argv[PARAM_PIDFILE] = g_strdup("--pid");
+ argv[PARAM_PIDFILE_ARGS] = g_strdup_printf("file=%s",
+ TPM_EMULATOR_PIDFILE);
+ if (tpm_pt->ops->has_logfile) {
+ argv[PARAM_LOG] = g_strdup("--log");
+ argv[PARAM_LOG_ARGS] = g_strdup_printf("file=%s,level=%d",
+ tpm_pt->ops->logfile, (int)tpm_pt->ops->loglevel);
+ } else {
+ /* truncate logs */
+ argv[PARAM_LOG] = NULL;
+ }
+ DPRINTF("%s", "Running cmd: ")
+ for (i = 0; argv[i]; i++) {
+ DPRINT(" %s", argv[i])
+ }
+ DPRINT("\n")
+ if (execv(tpm_pt->ops->path, (char * const *)argv) < 0) {
+ error_report("execv() failure : %s", strerror(errno));
+ }
+
+exit_child:
+ g_strfreev(argv);
+ if (data_fd >= 0) {
+ closesocket(data_fd);
+ }
+ if (ctrl_fd >= 0) {
+ closesocket(ctrl_fd);
+ }
+
+ _exit(1);
+ } else { /* self */
+ struct stat st;
+ DPRINTF("child pid: %d", cpid);
+ int rc;
+ useconds_t usec = 100 * 1000L; /* wait for 100 milliseconds */
+ useconds_t timeout = 10; /* max 1 second */
+
+ /* close unused sockets */
+ if (fds[1] >= 0) {
+ closesocket(fds[1]);
+ }
+ if (ctrl_fds[1] >= 0) {
+ closesocket(ctrl_fds[1]);
+ }
+
+ tpm_pt->data_ioc = _iochannel_new(tpm_pt->ops->data_path, fds[0], NULL);
+ if (!tpm_pt->data_ioc) {
+ error_report("tpm-emulator: Unable to connect socket : %s",
+ tpm_pt->ops->data_path);
+ goto err_kill_child;
+ }
+
+ tpm_pt->ctrl_ioc = _iochannel_new(tpm_pt->ops->ctrl_path, ctrl_fds[0],
+ NULL);
+ if (!tpm_pt->ctrl_ioc) {
+ error_report("tpm-emulator: Unable to connect socket : %s",
+ tpm_pt->ops->ctrl_path);
+ goto err_kill_child;
+ }
+
+ qemu_add_child_watch(cpid);
+
+ qio_channel_add_watch(tpm_pt->data_ioc, G_IO_HUP | G_IO_ERR,
+ tpm_emulator_fd_handler, tpm_pt, NULL);
+
+ while ((rc = stat(TPM_EMULATOR_PIDFILE, &st)) < 0 && timeout--) {
+ usleep(usec);
+ }
+
+ if (timeout == -1) {
+ error_report("tpm-emulator: pid file not ready: %s",
+ strerror(errno));
+ goto err_kill_child;
+ }
+
+ /* check if child really running */
+ if (kill(cpid, 0) < 0 && errno == ESRCH) {
+ goto err_no_child;
+ }
+
+ tpm_pt->child_running = true;
+ }
+
+ return 0;
+
+err_kill_child:
+ kill(cpid, SIGTERM);
+ /* wait for 10 mill-seconds */
+ usleep(10 * 1000);
+ /* force kill if still reachable */
+ if (kill(cpid, 0) == 0) {
+ kill(cpid, SIGKILL);
+ }
+
+err_no_child:
+ tpm_pt->child_running = false;
+
+ return -1;
+}
+
+static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_pt, QemuOpts *opts)
+{
+ const char *value;
+
+ value = qemu_opt_get(opts, "tpmstatedir");
+ if (!value) {
+ error_report("tpm-emulator: Missing tpm state directory");
+ return -1;
+ }
+ tpm_pt->ops->tpmstatedir = g_strdup(value);
+
+ tpm_pt->ops->spawn = qemu_opt_get_bool(opts, "spawn", false);
+
+ value = qemu_opt_get(opts, "path");
+ if (!value) {
+ value = TPM_DEFAULT_EMULATOR;
+ tpm_pt->ops->has_path = false;
+ } else {
+ tpm_pt->ops->has_path = true;
+ if (value[0] == '/') {
+ struct stat st;
+ if (stat(value, &st) < 0 || !(S_ISREG(st.st_mode)
+ || S_ISLNK(st.st_mode))) {
+ error_report("tpm-emulator: Invalid emulator path: %s", value);
+ return -1;
+ }
+ }
+ }
+ tpm_pt->ops->path = g_strdup(value);
+
+ value = qemu_opt_get(opts, "data-path");
+ if (value) {
+ tpm_pt->ops->has_data_path = true;
+ tpm_pt->ops->data_path = g_strdup(value);
+ } else {
+ tpm_pt->ops->has_data_path = false;
+ if (!tpm_pt->ops->spawn) {
+ error_report("tpm-emulator: missing mandatory data-path");
+ return -1;
+ }
+ }
+
+ value = qemu_opt_get(opts, "ctrl-path");
+ if (value) {
+ tpm_pt->ops->has_ctrl_path = true;
+ tpm_pt->ops->ctrl_path = g_strdup(value);
+ } else {
+ tpm_pt->ops->has_ctrl_path = false;
+ if (!tpm_pt->ops->spawn) {
+ error_report("tpm-emulator: missing mandatory ctrl-path");
+ return -1;
+ }
+ }
+
+ value = qemu_opt_get(opts, "logfile");
+ if (value) {
+ tpm_pt->ops->has_logfile = true;
+ tpm_pt->ops->logfile = g_strdup(value);
+ tpm_pt->ops->loglevel = qemu_opt_get_number(opts, "loglevel",
+ TPM_DEFAULT_LOGLEVEL);
+ tpm_pt->ops->has_loglevel = tpm_pt->ops->loglevel !=
+ TPM_DEFAULT_LOGLEVEL;
+ }
+
+ if (tpm_pt->ops->spawn) {
+ if (tpm_emulator_spawn_emulator(tpm_pt) < 0) {
+ goto err_close_dev;
+ }
+ } else {
+ tpm_pt->data_ioc = _iochannel_new(tpm_pt->ops->data_path, -1, NULL);
+ if (tpm_pt->data_ioc == NULL) {
+ error_report("tpm-emulator: Failed to connect data socket: %s",
+ tpm_pt->ops->data_path);
+ goto err_close_dev;
+ }
+ tpm_pt->ctrl_ioc = _iochannel_new(tpm_pt->ops->ctrl_path, -1, NULL);
+ if (tpm_pt->ctrl_ioc == NULL) {
+ DPRINTF("Failed to connect control socket: %s",
+ strerror(errno));
+ goto err_close_dev;
+ }
+ tpm_pt->child_running = true;
+ }
+
+ /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used
+ * by passthrough driver, which not yet using GIOChannel.
+ */
+ if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_pt->data_ioc)->fd,
+ &tpm_pt->tpm_version)) {
+ error_report("'%s' is not emulating TPM device.", tpm_pt->ops->path);
+ goto err_close_dev;
+ }
+
+ DPRINTF("TPM Version %s", tpm_pt->tpm_version == TPM_VERSION_1_2 ? "1.2" :
+ (tpm_pt->tpm_version == TPM_VERSION_2_0 ? "2.0" : "Unspecified"));
+
+ if (tpm_emulator_probe_caps(tpm_pt) ||
+ tpm_emulator_check_caps(tpm_pt)) {
+ goto err_close_dev;
+ }
+
+ return 0;
+
+err_close_dev:
+ DPRINT("Startup error\n");
+ return -1;
+}
+
+static TPMBackend *tpm_emulator_create(QemuOpts *opts, const char *id)
+{
+ TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
+
+ tb->id = g_strdup(id);
+
+ if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
+ goto err_exit;
+ }
+
+ return tb;
+
+err_exit:
+ object_unref(OBJECT(tb));
+
+ return NULL;
+}
+
+static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(tb);
+ TpmTypeOptions *ops = NULL;
+ TPMEmulatorOptions *eops = NULL;
+
+ eops = g_new0(TPMEmulatorOptions, 1);
+ if (!eops) {
+ return NULL;
+ }
+ DPRINTF("%s", __func__);
+
+ eops->tpmstatedir = g_strdup(tpm_pt->ops->tpmstatedir);
+ eops->spawn = tpm_pt->ops->spawn;
+ if (tpm_pt->ops->has_path) {
+ eops->has_path = true;
+ eops->path = g_strdup(tpm_pt->ops->path);
+ }
+ if (tpm_pt->ops->has_data_path) {
+ eops->has_data_path = true;
+ eops->data_path = g_strdup(tpm_pt->ops->data_path);
+ }
+ if (tpm_pt->ops->has_ctrl_path) {
+ eops->has_ctrl_path = true;
+ eops->ctrl_path = g_strdup(tpm_pt->ops->ctrl_path);
+ }
+ if (tpm_pt->ops->has_logfile) {
+ eops->has_logfile = true;
+ eops->logfile = g_strdup(tpm_pt->ops->logfile);
+ }
+ if (tpm_pt->ops->has_loglevel) {
+ eops->has_loglevel = true;
+ eops->loglevel = tpm_pt->ops->loglevel;
+ }
+
+ ops = g_new0(TpmTypeOptions, 1);
+ if (!ops) {
+ qapi_free_TPMEmulatorOptions(eops);
+ return NULL;
+ }
+
+ ops->type = TPM_TYPE_EMULATOR;
+ ops->u.emulator.data = eops;
+
+ return ops;
+}
+
+static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
+ TPM_STANDARD_CMDLINE_OPTS,
+ {
+ .name = "tpmstatedir",
+ .type = QEMU_OPT_STRING,
+ .help = "TPM state directroy",
+ },
+ {
+ .name = "spawn",
+ .type = QEMU_OPT_BOOL,
+ .help = "Wether to spwan given emlatory binary",
+ },
+ {
+ .name = "path",
+ .type = QEMU_OPT_STRING,
+ .help = "Path to TPM emulator binary",
+ },
+ {
+ .name = "data-path",
+ .type = QEMU_OPT_STRING,
+ .help = "Socket path to use for data exhange",
+ },
+ {
+ .name = "ctrl-path",
+ .type = QEMU_OPT_STRING,
+ .help = "Socket path to use for out-of-band control messages",
+ },
+ {
+ .name = "logfile",
+ .type = QEMU_OPT_STRING,
+ .help = "Path to log file",
+ },
+ {
+ .name = "loglevel",
+ .type = QEMU_OPT_NUMBER,
+ .help = "Log level number",
+ },
+ { /* end of list */ },
+};
+
+static const TPMDriverOps tpm_emulator_driver = {
+ .type = TPM_TYPE_EMULATOR,
+ .opts = tpm_emulator_cmdline_opts,
+ .desc = "TPM emulator backend driver",
+
+ .create = tpm_emulator_create,
+ .startup_tpm = tpm_emulator_startup_tpm,
+ .reset = tpm_emulator_reset,
+ .had_startup_error = tpm_emulator_had_startup_error,
+ .cancel_cmd = tpm_emulator_cancel_cmd,
+ .get_tpm_established_flag = tpm_emulator_get_tpm_established_flag,
+ .reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag,
+ .get_tpm_version = tpm_emulator_get_tpm_version,
+ .get_tpm_options = tpm_emulator_get_tpm_options,
+};
+
+static void tpm_emulator_inst_init(Object *obj)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(obj);
+
+ DPRINTF("%s", __func__);
+ tpm_pt->ops = g_new0(TPMEmulatorOptions, 1);
+ tpm_pt->data_ioc = tpm_pt->ctrl_ioc = NULL;
+ tpm_pt->op_executing = tpm_pt->op_canceled = false;
+ tpm_pt->child_running = false;
+ tpm_pt->cur_locty_number = ~0;
+ qemu_mutex_init(&tpm_pt->state_lock);
+}
+
+static void tpm_emulator_inst_finalize(Object *obj)
+{
+ TPMEmulator *tpm_pt = TPM_EMULATOR(obj);
+
+ tpm_emulator_cancel_cmd(TPM_BACKEND(obj));
+ tpm_emulator_shutdown(tpm_pt);
+
+ if (tpm_pt->data_ioc) {
+ qio_channel_close(tpm_pt->data_ioc, NULL);
+ }
+ if (tpm_pt->ctrl_ioc) {
+ qio_channel_close(tpm_pt->ctrl_ioc, NULL);
+ }
+ if (tpm_pt->ops) {
+ qapi_free_TPMEmulatorOptions(tpm_pt->ops);
+ }
+}
+
+static void tpm_emulator_class_init(ObjectClass *klass, void *data)
+{
+ TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
+ tbc->ops = &tpm_emulator_driver;
+ tbc->handle_request = tpm_emulator_handle_request;
+}
+
+static const TypeInfo tpm_emulator_info = {
+ .name = TYPE_TPM_EMULATOR,
+ .parent = TYPE_TPM_BACKEND,
+ .instance_size = sizeof(TPMEmulator),
+ .class_init = tpm_emulator_class_init,
+ .instance_init = tpm_emulator_inst_init,
+ .instance_finalize = tpm_emulator_inst_finalize,
+};
+
+static void tpm_emulator_register(void)
+{
+ type_register_static(&tpm_emulator_info);
+ tpm_register_driver(&tpm_emulator_driver);
+}
+
+type_init(tpm_emulator_register)
diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h
new file mode 100644
index 0000000..af49708
--- /dev/null
+++ b/hw/tpm/tpm_ioctl.h
@@ -0,0 +1,243 @@
+/*
+ * tpm_ioctl.h
+ *
+ * (c) Copyright IBM Corporation 2014, 2015.
+ *
+ * This file is licensed under the terms of the 3-clause BSD license
+ */
+#ifndef _TPM_IOCTL_H_
+#define _TPM_IOCTL_H_
+
+#include <stdint.h>
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+/*
+ * Every response from a command involving a TPM command execution must hold
+ * the ptm_res as the first element.
+ * ptm_res corresponds to the error code of a command executed by the TPM.
+ */
+
+typedef uint32_t ptm_res;
+
+/* PTM_GET_TPMESTABLISHED: get the establishment bit */
+struct ptm_est {
+ union {
+ struct {
+ ptm_res tpm_result;
+ unsigned char bit; /* TPM established bit */
+ } resp; /* response */
+ } u;
+};
+
+/* PTM_RESET_TPMESTABLISHED: reset establishment bit */
+struct ptm_reset_est {
+ union {
+ struct {
+ uint8_t loc; /* locality to use */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/* PTM_INIT */
+struct ptm_init {
+ union {
+ struct {
+ uint32_t init_flags; /* see definitions below */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/* above init_flags */
+#define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0)
+ /* delete volatile state file after reading it */
+
+/* PTM_SET_LOCALITY */
+struct ptm_loc {
+ union {
+ struct {
+ uint8_t loc; /* locality to set */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/* PTM_HASH_DATA: hash given data */
+struct ptm_hdata {
+ union {
+ struct {
+ uint32_t length;
+ uint8_t data[4096];
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/*
+ * size of the TPM state blob to transfer; x86_64 can handle 8k,
+ * ppc64le only ~7k; keep the response below a 4k page size
+ */
+#define PTM_STATE_BLOB_SIZE (3 * 1024)
+
+/*
+ * The following is the data structure to get state blobs from the TPM.
+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple reads
+ * with this ioctl and with adjusted offset are necessary. All bytes
+ * must be transferred and the transfer is done once the last byte has been
+ * returned.
+ * It is possible to use the read() interface for reading the data; however, the
+ * first bytes of the state blob will be part of the response to the ioctl(); a
+ * subsequent read() is only necessary if the total length (totlength) exceeds
+ * the number of received bytes. seek() is not supported.
+ */
+struct ptm_getstate {
+ union {
+ struct {
+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */
+ uint32_t type; /* which blob to pull */
+ uint32_t offset; /* offset from where to read */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */
+ uint32_t totlength; /* total length that will be transferred */
+ uint32_t length; /* number of bytes in following buffer */
+ uint8_t data[PTM_STATE_BLOB_SIZE];
+ } resp; /* response */
+ } u;
+};
+
+/* TPM state blob types */
+#define PTM_BLOB_TYPE_PERMANENT 1
+#define PTM_BLOB_TYPE_VOLATILE 2
+#define PTM_BLOB_TYPE_SAVESTATE 3
+
+/* state_flags above : */
+#define PTM_STATE_FLAG_DECRYPTED 1 /* on input: get decrypted state */
+#define PTM_STATE_FLAG_ENCRYPTED 2 /* on output: state is encrypted */
+
+/*
+ * The following is the data structure to set state blobs in the TPM.
+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple
+ * 'writes' using this ioctl are necessary. The last packet is indicated
+ * by the length being smaller than the PTM_STATE_BLOB_SIZE.
+ * The very first packet may have a length indicator of '0' enabling
+ * a write() with all the bytes from a buffer. If the write() interface
+ * is used, a final ioctl with a non-full buffer must be made to indicate
+ * that all data were transferred (a write with 0 bytes would not work).
+ */
+struct ptm_setstate {
+ union {
+ struct {
+ uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */
+ uint32_t type; /* which blob to set */
+ uint32_t length; /* length of the data;
+ use 0 on the first packet to
+ transfer using write() */
+ uint8_t data[PTM_STATE_BLOB_SIZE];
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ } resp; /* response */
+ } u;
+};
+
+/*
+ * PTM_GET_CONFIG: Data structure to get runtime configuration information
+ * such as which keys are applied.
+ */
+struct ptm_getconfig {
+ union {
+ struct {
+ ptm_res tpm_result;
+ uint32_t flags;
+ } resp; /* response */
+ } u;
+};
+
+#define PTM_CONFIG_FLAG_FILE_KEY 0x1
+#define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2
+
+
+typedef uint64_t ptm_cap;
+typedef struct ptm_est ptm_est;
+typedef struct ptm_reset_est ptm_reset_est;
+typedef struct ptm_loc ptm_loc;
+typedef struct ptm_hdata ptm_hdata;
+typedef struct ptm_init ptm_init;
+typedef struct ptm_getstate ptm_getstate;
+typedef struct ptm_setstate ptm_setstate;
+typedef struct ptm_getconfig ptm_getconfig;
+
+/* capability flags returned by PTM_GET_CAPABILITY */
+#define PTM_CAP_INIT (1)
+#define PTM_CAP_SHUTDOWN (1 << 1)
+#define PTM_CAP_GET_TPMESTABLISHED (1 << 2)
+#define PTM_CAP_SET_LOCALITY (1 << 3)
+#define PTM_CAP_HASHING (1 << 4)
+#define PTM_CAP_CANCEL_TPM_CMD (1 << 5)
+#define PTM_CAP_STORE_VOLATILE (1 << 6)
+#define PTM_CAP_RESET_TPMESTABLISHED (1 << 7)
+#define PTM_CAP_GET_STATEBLOB (1 << 8)
+#define PTM_CAP_SET_STATEBLOB (1 << 9)
+#define PTM_CAP_STOP (1 << 10)
+#define PTM_CAP_GET_CONFIG (1 << 11)
+
+enum {
+ PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap),
+ PTM_INIT = _IOWR('P', 1, ptm_init),
+ PTM_SHUTDOWN = _IOR('P', 2, ptm_res),
+ PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est),
+ PTM_SET_LOCALITY = _IOWR('P', 4, ptm_loc),
+ PTM_HASH_START = _IOR('P', 5, ptm_res),
+ PTM_HASH_DATA = _IOWR('P', 6, ptm_hdata),
+ PTM_HASH_END = _IOR('P', 7, ptm_res),
+ PTM_CANCEL_TPM_CMD = _IOR('P', 8, ptm_res),
+ PTM_STORE_VOLATILE = _IOR('P', 9, ptm_res),
+ PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est),
+ PTM_GET_STATEBLOB = _IOWR('P', 11, ptm_getstate),
+ PTM_SET_STATEBLOB = _IOWR('P', 12, ptm_setstate),
+ PTM_STOP = _IOR('P', 13, ptm_res),
+ PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig),
+};
+
+/*
+ * Commands used by the non-CUSE TPMs
+ *
+ * All messages container big-endian data.
+ *
+ * The return messages only contain the 'resp' part of the unions
+ * in the data structures above. Besides that the limits in the
+ * buffers above (ptm_hdata:u.req.data and ptm_get_state:u.resp.data
+ * and ptm_set_state:u.req.data) are 0xffffffff.
+ */
+enum {
+ CMD_GET_CAPABILITY = 1,
+ CMD_INIT,
+ CMD_SHUTDOWN,
+ CMD_GET_TPMESTABLISHED,
+ CMD_SET_LOCALITY,
+ CMD_HASH_START,
+ CMD_HASH_DATA,
+ CMD_HASH_END,
+ CMD_CANCEL_TPM_CMD,
+ CMD_STORE_VOLATILE,
+ CMD_RESET_TPMESTABLISHED,
+ CMD_GET_STATEBLOB,
+ CMD_SET_STATEBLOB,
+ CMD_STOP,
+ CMD_GET_CONFIG,
+};
+
+#endif /* _TPM_IOCTL_H */
diff --git a/qapi-schema.json b/qapi-schema.json
index 01b087f..89dd9fc 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -5117,10 +5117,12 @@
# An enumeration of TPM types
#
# @passthrough: TPM passthrough type
+# @emulator: Software Emulator TPM type
+# Since: 2.10
#
# Since: 1.5
##
-{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }
+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ] }
##
# @query-tpm-types:
@@ -5134,7 +5136,7 @@
# Example:
#
# -> { "execute": "query-tpm-types" }
-# <- { "return": [ "passthrough" ] }
+# <- { "return": [ "passthrough", "emulator" ] }
#
##
{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }
@@ -5155,16 +5157,49 @@
'*cancel-path' : 'str'} }
##
+# @TPMEmulatorOptions:
+#
+# Information about the TPM emulator
+#
+# @tpmstatedir: TPM emulator state directory
+# @spawn: true if, qemu has to spawn a new emulator process with given @path,
+# otherwise it connects to already rinning emulator with given @data-path
+# and @ctrl-path sockets. (default: 'false')
+# @path: TPM emulator binary path to spawn.(default: 'swtpm')
+# @data-path: path of the unix socket to use for exchanging data messages, if
+# not provided socket pairs are used when @sapwn is true.
+# @ctrl-path: path of the unix socket file to use for exchagning out-of-band
+# control messages, if not provided socket pairs are used when
+# @spawn is true.
+# @logfile: file to use to place TPM emulator logs, if not provided logging is
+# disabled.
+# @loglevel: optional log level number, loglevel is ignored if no logfile
+# provided. (default: 5)
+#
+# Since: 2.10
+##
+{ 'struct': 'TPMEmulatorOptions',
+ 'data': { 'tpmstatedir' : 'str',
+ 'spawn': 'bool',
+ '*path': 'str',
+ '*data-path': 'str',
+ '*ctrl-path': 'str',
+ '*logfile': 'str',
+ '*loglevel': 'uint8' } }
+
+##
# @TpmTypeOptions:
#
# A union referencing different TPM backend types' configuration options
#
# @type: 'passthrough' The configuration options for the TPM passthrough type
+# 'emulator' The configuration options for TPM emulator backend type
#
# Since: 1.5
##
{ 'union': 'TpmTypeOptions',
- 'data': { 'passthrough' : 'TPMPassthroughOptions' } }
+ 'data': { 'passthrough': 'TPMPassthroughOptions',
+ 'emulator': 'TPMEmulatorOptions' } }
##
# @TPMInfo:
diff --git a/qemu-options.hx b/qemu-options.hx
index 787b9c3..726841e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2883,7 +2883,15 @@ DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
"-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n"
" use path to provide path to a character device; default is /dev/tpm0\n"
" use cancel-path to provide path to TPM's cancel sysfs entry; if\n"
- " not provided it will be searched for in /sys/class/misc/tpm?/device\n",
+ " not provided it will be searched for in /sys/class/misc/tpm?/device\n"
+ "-tpmdev emulator,id=id,spawn=on|off,tpmstatedir=dir[,path=emulator-path,data-path=path,ctrl-path=path,logfile=path,loglevel=level]\n"
+ " spawn=on|off controls spawning support\n"
+ " use tpmstatedir to provide path to the tpm state dirctory\n"
+ " use path to provide the emulator binary to launch; default is 'swtpm'\n"
+ " use data-path to provide the socket path for exchanging data messages\n"
+ " use ctrl-path to provide the socket path for sending control messages to software emulator\n"
+ " use logfile to provide where to place the swtpm logs\n"
+ " use loglevel to controls the swtpm log level\n",
QEMU_ARCH_ALL)
STEXI
@@ -2892,8 +2900,8 @@ The general form of a TPM device option is:
@item -tpmdev @var{backend} ,id=@var{id} [,@var{options}]
@findex -tpmdev
-Backend type must be:
-@option{passthrough}.
+Backend type must be either one of the following:
+@option{passthrough}, @option{emulator}.
The specific backend type will determine the applicable options.
The @code{-tpmdev} option creates the TPM backend and requires a
@@ -2943,6 +2951,45 @@ To create a passthrough TPM use the following two options:
Note that the @code{-tpmdev} id is @code{tpm0} and is referenced by
@code{tpmdev=tpm0} in the device option.
+@item -tpmdev emulator, id=@var{id}, tpmstatedir=@var{path}, spawn=@var{on|off}, path=@var{emulator-binary-path}, data-path=@var{path}, ctrl-path=@var{path}, logfile=@var{path}, loglevel=@var{level}
+
+(Linux-host only) Enable access to a TPM emulator using unix domain sockets.
+
+@option{tpmstatedir} specifies the tpm state directory
+
+@option{spawn} specifies if qemu should spawn new emulator process with given @option{path}
+
+@option{path} specifies the emulator binary path to use for spawning
+
+@option{data-path} optional socket path to use for exchanging TPM data with emulator
+
+@option{ctrl-path} optional socket path to use for sending control data to emulator
+
+@option{logfile} optional log file to use to place log messages
+
+@option{loglevel} specifies the log level to use
+
+To create TPM emulator backend device that spawns new swtpm binary and communicate with socket pairs:
+@example
+
+-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=on,path=/usr/local/bin/swtpm,logfile=/tmp/qemu-tpm.log,loglevel=5 -device tpm-tis,tpmdev=tpm0
+
+@end example
+
+To create TPM emulator backend device that spawns new swtpm binary and communicate using unix file system sockets:
+@example
+
+-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=on,path=/usr/local/bin/swtpm,data-path=/tmp/swtpm-data.socket,ctrl-path=/tmp/swtpm-ctrl.socket,logfile=/tmp/qemu-tpm.log,loglevel=5 -device tpm-tis,tpmdev=tpm0
+
+@end example
+
+To create a TOM emulator backend device that connects to already running swtpm binary using file system sockets:
+@example
+
+-tpmdev emulator,id=tpm0,tpmstatedir=/tmp/my-tpm,spawn=off,data-path=/tmp/swtpm-data.socket,ctrl-path=/tmp/swtpm-ctrl.socket,logfile=/tmp/qemu-tpm.log,loglevel=5 -device tpm-tis,tpmdev=tpm0
+
+@end example
+
@end table
ETEXI
diff --git a/tpm.c b/tpm.c
index 84e9667..6d2513c 100644
--- a/tpm.c
+++ b/tpm.c
@@ -25,7 +25,7 @@ static QLIST_HEAD(, TPMBackend) tpm_backends =
#define TPM_MAX_MODELS 1
-#define TPM_MAX_DRIVERS 1
+#define TPM_MAX_DRIVERS 2
static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
NULL,
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (8 preceding siblings ...)
2017-05-02 12:25 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " no-reply
@ 2017-05-04 12:28 ` Stefan Berger
2017-05-05 6:52 ` Amarnath Valluri
9 siblings, 1 reply; 46+ messages in thread
From: Stefan Berger @ 2017-05-04 12:28 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: patrick.ohly, marcandre.lureau, berrange
On 05/02/2017 07:52 AM, Amarnath Valluri wrote:
> Briefly, Theses set of patches introduces:
> - new TPM backend driver to support software TPM emulators(swtpm(1)).
> - and few supported fixes/enhancements/cleanup to existing tpm backend code.
>
> The similar idea was initiated earliar(2) by Stefan Berger(CCed) with slightly
> different approach, using CUSE. As swtpm has excellent support for unix domain
> sockets, hence this implementation uses unix domain sockets to communicate
> with
> swtpm.
I think you would need something like this as well:
https://github.com/stefanberger/qemu-tpm/commit/9d8c9c3f0df288242d03f78d3b103099c1910574
https://github.com/stefanberger/qemu-tpm/commit/b9ea09d2e26eac92b4a1604a7afa695c4fc2735e
>
> When Qemu is configured with 'emulator' tpm backend, it spawns 'swtpm' and
> communicates its via Unix domain sockets.
>
> 1) https://github.com/stefanberger/swtpm
> 2) https://lists.nongnu.org/archive/html/qemu-devel/2016-01/msg00089.html
>
> ** Changes in V2:
> - Made spawnning swtpm optional
> - used QIOChannel instead of plain unix sockets
> - incorporated other fixes pointed in v1 review
>
> ** Changes in v3:
> - Addressed review comments made by Stefan Berger and Deniel P Berrange
>
> Amarnath Valluri (8):
> tpm-backend: Remove unneeded member variable from backend class
> tpm-backend: Move thread handling inside TPMBackend
> tpm-backend: Initialize and free data members in it's own methods
> tpm-backend: Made few interface methods optional
> tmp backend: Add new api to read backend TpmInfo
> tpm-backend: Move realloc_buffer() implementation to base class
> tpm-passthrough: move reusable code to utils
> tpm: Added support for TPM emulator
>
> backends/tpm.c | 121 +++--
> configure | 15 +-
> hmp.c | 31 +-
> hw/tpm/Makefile.objs | 1 +
> hw/tpm/tpm_emulator.c | 943 +++++++++++++++++++++++++++++++++++++++
> hw/tpm/tpm_ioctl.h | 243 ++++++++++
> hw/tpm/tpm_passthrough.c | 221 +++------
> hw/tpm/tpm_util.c | 25 ++
> hw/tpm/tpm_util.h | 4 +
> include/sysemu/tpm_backend.h | 65 ++-
> include/sysemu/tpm_backend_int.h | 41 --
> qapi-schema.json | 67 ++-
> qemu-options.hx | 53 ++-
> tpm.c | 36 +-
> 14 files changed, 1545 insertions(+), 321 deletions(-)
> create mode 100644 hw/tpm/tpm_emulator.c
> create mode 100644 hw/tpm/tpm_ioctl.h
> delete mode 100644 include/sysemu/tpm_backend_int.h
>
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator
2017-05-04 12:28 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " Stefan Berger
@ 2017-05-05 6:52 ` Amarnath Valluri
0 siblings, 0 replies; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-05 6:52 UTC (permalink / raw)
To: Stefan Berger, qemu-devel; +Cc: patrick.ohly, marcandre.lureau, berrange
On 05/04/2017 03:28 PM, Stefan Berger wrote:
> On 05/02/2017 07:52 AM, Amarnath Valluri wrote:
>> Briefly, Theses set of patches introduces:
>> - new TPM backend driver to support software TPM emulators(swtpm(1)).
>> - and few supported fixes/enhancements/cleanup to existing tpm
>> backend code.
>>
>> The similar idea was initiated earliar(2) by Stefan Berger(CCed)
>> with slightly
>> different approach, using CUSE. As swtpm has excellent support for
>> unix domain
>> sockets, hence this implementation uses unix domain sockets to
>> communicate
>> with
>> swtpm.
>
> I think you would need something like this as well:
>
> https://github.com/stefanberger/qemu-tpm/commit/9d8c9c3f0df288242d03f78d3b103099c1910574
>
> https://github.com/stefanberger/qemu-tpm/commit/b9ea09d2e26eac92b4a1604a7afa695c4fc2735e
>
Thanks Stefan, Sure we can take them in once after this patch series get
accepted.
- Amarnath
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v4 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model
2017-05-04 11:31 ` [Qemu-devel] [PATCH v4 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model Amarnath Valluri
@ 2017-05-06 12:27 ` Marc-André Lureau
0 siblings, 0 replies; 46+ messages in thread
From: Marc-André Lureau @ 2017-05-06 12:27 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel
On Thu, May 4, 2017 at 3:29 PM Amarnath Valluri <amarnath.valluri@intel.com>
wrote:
> buffer reallocation is very unlikely to be backend specific. Hence move
> inside
> the tis.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
(Please resend the whole series, so we can easily test and grab it thanks
to patchew)
---
> backends/tpm.c | 9 ---------
> hw/tpm/tpm_passthrough.c | 12 ------------
> hw/tpm/tpm_tis.c | 14 ++++++++++++--
> include/sysemu/tpm_backend.h | 12 ------------
> 4 files changed, 12 insertions(+), 35 deletions(-)
>
> diff --git a/backends/tpm.c b/backends/tpm.c
> index 4ae6129..3519570 100644
> --- a/backends/tpm.c
> +++ b/backends/tpm.c
> @@ -71,15 +71,6 @@ bool tpm_backend_had_startup_error(TPMBackend *s)
> return k->ops->had_startup_error(s);
> }
>
> -size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
> -{
> - TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
> -
> - assert(k->ops->realloc_buffer);
> -
> - return k->ops->realloc_buffer(sb);
> -}
> -
> void tpm_backend_deliver_request(TPMBackend *s)
> {
> g_thread_pool_push(s->thread_pool,
> (gpointer)TPM_BACKEND_CMD_PROCESS_CMD,
> diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
> index c7706e4..4ac47ed 100644
> --- a/hw/tpm/tpm_passthrough.c
> +++ b/hw/tpm/tpm_passthrough.c
> @@ -258,17 +258,6 @@ static bool
> tpm_passthrough_get_startup_error(TPMBackend *tb)
> return tpm_pt->had_startup_error;
> }
>
> -static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
> -{
> - size_t wanted_size = 4096; /* Linux tpm.c buffer size */
> -
> - if (sb->size != wanted_size) {
> - sb->buffer = g_realloc(sb->buffer, wanted_size);
> - sb->size = wanted_size;
> - }
> - return sb->size;
> -}
> -
> static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
> {
> TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
> @@ -475,7 +464,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
> .opts = tpm_passthrough_cmdline_opts,
> .desc = "Passthrough TPM backend driver",
> .create = tpm_passthrough_create,
> - .realloc_buffer = tpm_passthrough_realloc_buffer,
> .reset = tpm_passthrough_reset,
> .had_startup_error = tpm_passthrough_get_startup_error,
> .cancel_cmd = tpm_passthrough_cancel_cmd,
> diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
> index a6440fe..d5118e7 100644
> --- a/hw/tpm/tpm_tis.c
> +++ b/hw/tpm/tpm_tis.c
> @@ -963,6 +963,16 @@ static int tpm_tis_do_startup_tpm(TPMState *s)
> return tpm_backend_startup_tpm(s->be_driver);
> }
>
> +static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb)
> +{
> + size_t wanted_size = 4096; /* Linux tpm.c buffer size */
> +
> + if (sb->size != wanted_size) {
> + sb->buffer = g_realloc(sb->buffer, wanted_size);
> + sb->size = wanted_size;
> + }
> +}
> +
> /*
> * Get the TPMVersion of the backend device being used
> */
> @@ -1010,9 +1020,9 @@ static void tpm_tis_reset(DeviceState *dev)
> tis->loc[c].state = TPM_TIS_STATE_IDLE;
>
> tis->loc[c].w_offset = 0;
> - tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer);
> + tpm_tis_realloc_buffer(&tis->loc[c].w_buffer);
> tis->loc[c].r_offset = 0;
> - tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer);
> + tpm_tis_realloc_buffer(&tis->loc[c].r_buffer);
> }
>
> tpm_tis_do_startup_tpm(s);
> diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
> index 6e5bb8d..bebfba3 100644
> --- a/include/sysemu/tpm_backend.h
> +++ b/include/sysemu/tpm_backend.h
> @@ -85,8 +85,6 @@ struct TPMDriverOps {
> /* returns true if nothing will ever answer TPM requests */
> bool (*had_startup_error)(TPMBackend *t);
>
> - size_t (*realloc_buffer)(TPMSizedBuffer *sb);
> -
> void (*reset)(TPMBackend *t);
>
> void (*cancel_cmd)(TPMBackend *t);
> @@ -132,16 +130,6 @@ int tpm_backend_startup_tpm(TPMBackend *s);
> bool tpm_backend_had_startup_error(TPMBackend *s);
>
> /**
> - * tpm_backend_realloc_buffer:
> - * @s: the backend
> - * @sb: the TPMSizedBuffer to re-allocated to the size suitable for the
> - * backend.
> - *
> - * This function returns the size of the allocated buffer
> - */
> -size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb);
> -
> -/**
> * tpm_backend_deliver_request:
> * @s: the backend to send the request to
> *
> --
> 2.7.4
>
>
> --
Marc-André Lureau
^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [Qemu-devel] [PATCH v4 4/8] tpm-backend: Made few interface methods optional
2017-05-16 7:58 ` [Qemu-devel] [PATCH v4 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
@ 2017-05-24 14:28 ` Stefan Berger
0 siblings, 0 replies; 46+ messages in thread
From: Stefan Berger @ 2017-05-24 14:28 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel
On 05/16/2017 03:58 AM, Amarnath Valluri wrote:
> This allows backend implementations left optional interface methods.
> For mandatory methods assertion checks added.
>
> Took the opportunity to remove unused methods:
> tpm_backend_get_type()
> tpm_backend_get_desc()
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
Reviewed-by: Stefan Berger<stefanb@linux.vnet.ibm.com>
^ permalink raw reply [flat|nested] 46+ messages in thread
* [Qemu-devel] [PATCH v4 4/8] tpm-backend: Made few interface methods optional
2017-05-16 7:58 [Qemu-devel] [PATCH v4 " Amarnath Valluri
@ 2017-05-16 7:58 ` Amarnath Valluri
2017-05-24 14:28 ` Stefan Berger
0 siblings, 1 reply; 46+ messages in thread
From: Amarnath Valluri @ 2017-05-16 7:58 UTC (permalink / raw)
To: qemu-devel; +Cc: Amarnath Valluri
This allows backend implementations left optional interface methods.
For mandatory methods assertion checks added.
Took the opportunity to remove unused methods:
tpm_backend_get_type()
tpm_backend_get_desc()
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
---
backends/tpm.c | 36 +++++++++++++++++-------------------
hw/tpm/tpm_passthrough.c | 23 +----------------------
include/sysemu/tpm_backend.h | 19 +------------------
tpm.c | 2 +-
4 files changed, 20 insertions(+), 60 deletions(-)
diff --git a/backends/tpm.c b/backends/tpm.c
index cf5abf1..05002e6 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -37,20 +37,6 @@ static void tpm_backend_thread_end(TPMBackend *s)
}
}
-enum TpmType tpm_backend_get_type(TPMBackend *s)
-{
- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
-
- return k->ops->type;
-}
-
-const char *tpm_backend_get_desc(TPMBackend *s)
-{
- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
-
- return k->ops->desc();
-}
-
int tpm_backend_init(TPMBackend *s, TPMState *state,
TPMRecvDataCB *datacb)
{
@@ -59,7 +45,7 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
s->tpm_state = state;
s->recv_data_callback = datacb;
- return k->ops->init(s);
+ return k->ops->init ? k->ops->init(s) : 0;
}
int tpm_backend_startup_tpm(TPMBackend *s)
@@ -73,13 +59,15 @@ int tpm_backend_startup_tpm(TPMBackend *s)
NULL);
g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
- return k->ops->startup_tpm(s);
+ return k->ops->startup_tpm ? k->ops->startup_tpm(s) : 0;
}
bool tpm_backend_had_startup_error(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->had_startup_error);
+
return k->ops->had_startup_error(s);
}
@@ -87,6 +75,8 @@ size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->realloc_buffer);
+
return k->ops->realloc_buffer(sb);
}
@@ -100,7 +90,9 @@ void tpm_backend_reset(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- k->ops->reset(s);
+ if (k->ops->reset) {
+ k->ops->reset(s);
+ }
tpm_backend_thread_end(s);
}
@@ -109,6 +101,8 @@ void tpm_backend_cancel_cmd(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->cancel_cmd);
+
k->ops->cancel_cmd(s);
}
@@ -116,20 +110,24 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->get_tpm_established_flag(s);
+ return k->ops->get_tpm_established_flag ?
+ k->ops->get_tpm_established_flag(s) : false;
}
int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
- return k->ops->reset_tpm_established_flag(s, locty);
+ return k->ops->reset_tpm_established_flag ?
+ k->ops->reset_tpm_established_flag(s, locty) : 0;
}
TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
{
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+ assert(k->ops->get_tpm_version);
+
return k->ops->get_tpm_version(s);
}
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index 815a72e..a0459a6 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -227,15 +227,6 @@ static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
}
}
-/*
- * Start the TPM (thread). If it had been started before, then terminate
- * and start it again.
- */
-static int tpm_passthrough_startup_tpm(TPMBackend *tb)
-{
- return 0;
-}
-
static void tpm_passthrough_reset(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -247,11 +238,6 @@ static void tpm_passthrough_reset(TPMBackend *tb)
tpm_pt->had_startup_error = false;
}
-static int tpm_passthrough_init(TPMBackend *tb)
-{
- return 0;
-}
-
static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
{
return false;
@@ -309,11 +295,6 @@ static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
}
}
-static const char *tpm_passthrough_create_desc(void)
-{
- return "Passthrough TPM backend driver";
-}
-
static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
{
TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
@@ -453,10 +434,8 @@ static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
static const TPMDriverOps tpm_passthrough_driver = {
.type = TPM_TYPE_PASSTHROUGH,
.opts = tpm_passthrough_cmdline_opts,
- .desc = tpm_passthrough_create_desc,
+ .desc = "Passthrough TPM backend driver",
.create = tpm_passthrough_create,
- .init = tpm_passthrough_init,
- .startup_tpm = tpm_passthrough_startup_tpm,
.realloc_buffer = tpm_passthrough_realloc_buffer,
.reset = tpm_passthrough_reset,
.had_startup_error = tpm_passthrough_get_startup_error,
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index f61bcfe..d6ae463 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -75,7 +75,7 @@ struct TPMDriverOps {
enum TpmType type;
const QemuOptDesc *opts;
/* get a descriptive text of the backend to display to the user */
- const char *(*desc)(void);
+ const char *desc;
TPMBackend *(*create)(QemuOpts *opts, const char *id);
@@ -99,23 +99,6 @@ struct TPMDriverOps {
TPMVersion (*get_tpm_version)(TPMBackend *t);
};
-
-/**
- * tpm_backend_get_type:
- * @s: the backend
- *
- * Returns the TpmType of the backend.
- */
-enum TpmType tpm_backend_get_type(TPMBackend *s);
-
-/**
- * tpm_backend_get_desc:
- * @s: the backend
- *
- * Returns a human readable description of the backend.
- */
-const char *tpm_backend_get_desc(TPMBackend *s);
-
/**
* tpm_backend_init:
* @s: the backend to initialized
diff --git a/tpm.c b/tpm.c
index 70f74fa..2979508 100644
--- a/tpm.c
+++ b/tpm.c
@@ -102,7 +102,7 @@ static void tpm_display_backend_drivers(void)
for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
fprintf(stderr, "%12s %s\n",
- TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc());
+ TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc);
}
fprintf(stderr, "\n");
}
--
2.7.4
^ permalink raw reply related [flat|nested] 46+ messages in thread
end of thread, other threads:[~2017-05-24 14:28 UTC | newest]
Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-02 11:52 [Qemu-devel] [PATCH v3 0/8] Provide support for the software TPM emulator Amarnath Valluri
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
2017-05-02 11:59 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 2/8] tpm-backend: Move thread handling inside TPMBackend Amarnath Valluri
2017-05-02 12:10 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 3/8] tpm-backend: Initialize and free data members in it's own methods Amarnath Valluri
2017-05-02 12:17 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
2017-05-02 12:29 ` Marc-André Lureau
2017-05-04 8:39 ` Amarnath Valluri
2017-05-04 11:06 ` [Qemu-devel] [PATCH v4 " Amarnath Valluri
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
2017-05-02 13:35 ` Eric Blake
2017-05-04 9:05 ` Amarnath Valluri
2017-05-04 11:17 ` [Qemu-devel] [PATCH v4 " Amarnath Valluri
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 6/8] tpm-backend: Move realloc_buffer() implementation to base class Amarnath Valluri
2017-05-02 15:54 ` Marc-André Lureau
2017-05-04 9:25 ` Amarnath Valluri
2017-05-04 9:32 ` Marc-André Lureau
2017-05-04 11:31 ` [Qemu-devel] [PATCH v4 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model Amarnath Valluri
2017-05-06 12:27 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
2017-05-02 15:54 ` Marc-André Lureau
2017-05-02 11:52 ` [Qemu-devel] [PATCH v3 8/8] tpm: Added support for TPM emulator Amarnath Valluri
2017-05-02 16:05 ` Marc-André Lureau
2017-05-02 16:32 ` Stefan Berger
2017-05-02 16:58 ` Stefan Berger
2017-05-02 17:09 ` Marc-André Lureau
2017-05-02 17:19 ` Stefan Berger
2017-05-02 18:25 ` Patrick Ohly
2017-05-02 18:50 ` Marc-André Lureau
2017-05-02 19:35 ` Stefan Berger
2017-05-03 8:41 ` Daniel P. Berrange
2017-05-03 11:17 ` Dr. David Alan Gilbert
2017-05-03 11:24 ` Marc-André Lureau
2017-05-03 11:29 ` Daniel P. Berrange
2017-05-03 11:37 ` Marc-André Lureau
2017-05-03 14:42 ` Stefan Berger
2017-05-04 9:44 ` Patrick Ohly
2017-05-04 11:08 ` Stefan Berger
2017-05-02 12:25 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " no-reply
2017-05-04 11:35 ` [Qemu-devel] [PATCH v4 8/8] tpm: Added support for " Amarnath Valluri
2017-05-04 12:28 ` [Qemu-devel] [PATCH v3 0/8] Provide support for the software " Stefan Berger
2017-05-05 6:52 ` Amarnath Valluri
2017-05-16 7:58 [Qemu-devel] [PATCH v4 " Amarnath Valluri
2017-05-16 7:58 ` [Qemu-devel] [PATCH v4 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
2017-05-24 14:28 ` 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.