* [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator
@ 2017-07-18 8:48 Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
` (8 more replies)
0 siblings, 9 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:48 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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
** Changes in v4:
- Moved realloc_buffer() to TIS model
- Made TpmInfo related change backwards compatible.
** Changes in v5:
- updated Reviewed-By: tag to git commits
- added migration blocker to TPM emulator backend
** Changes in v6:
- rebased agianst latest master
- Address review comments maded by Stefan Berger
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 tpm-tis model
tpm-passthrough: move reusable code to utils
tpm: Added support for TPM emulator
backends/tpm.c | 117 +++--
configure | 15 +-
hmp.c | 27 +-
hw/tpm/Makefile.objs | 1 +
hw/tpm/tpm_emulator.c | 973 +++++++++++++++++++++++++++++++++++++++
hw/tpm/tpm_ioctl.h | 243 ++++++++++
hw/tpm/tpm_passthrough.c | 238 +++-------
hw/tpm/tpm_tis.c | 14 +-
hw/tpm/tpm_util.c | 25 +
hw/tpm/tpm_util.h | 4 +
include/sysemu/tpm_backend.h | 96 ++--
include/sysemu/tpm_backend_int.h | 41 --
qapi-schema.json | 41 +-
qemu-options.hx | 53 ++-
tpm.c | 38 +-
15 files changed, 1568 insertions(+), 358 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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 1/8] tpm-backend: Remove unneeded member variable from backend class
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 2/8] tpm-backend: Move thread handling inside TPMBackend Amarnath Valluri
` (7 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 2/8] tpm-backend: Move thread handling inside TPMBackend
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 3/8] tpm-backend: Initialize and free data members in it's own methods Amarnath Valluri
` (6 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 3/8] tpm-backend: Initialize and free data members in it's own methods
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 2/8] tpm-backend: Move thread handling inside TPMBackend Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
` (5 subsequent siblings)
8 siblings, 0 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 4/8] tpm-backend: Made few interface methods optional
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (2 preceding siblings ...)
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 3/8] tpm-backend: Initialize and free data members in it's own methods Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 10:15 ` Marc-André Lureau
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
` (4 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger<stefanb@linux.vnet.ibm.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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (3 preceding siblings ...)
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 10:39 ` Marc-André Lureau
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model Amarnath Valluri
` (3 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.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 d970ea9..7a92e88 100644
--- a/hmp.c
+++ b/hmp.c
@@ -966,10 +966,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=" : "",
@@ -977,7 +977,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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (4 preceding siblings ...)
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 10:50 ` Marc-André Lureau
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
` (2 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 7/8] tpm-passthrough: move reusable code to utils
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (5 preceding siblings ...)
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 11:17 ` Marc-André Lureau
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator Amarnath Valluri
2017-07-18 8:59 ` [Qemu-devel] [PATCH v6 0/8] Provide support for the software " no-reply
8 siblings, 1 reply; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, Amarnath Valluri
Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.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 4ac47ed..592fd1f 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] 26+ messages in thread
* [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (6 preceding siblings ...)
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
@ 2017-07-18 8:49 ` Amarnath Valluri
2017-07-18 12:08 ` Marc-André Lureau
` (3 more replies)
2017-07-18 8:59 ` [Qemu-devel] [PATCH v6 0/8] Provide support for the software " no-reply
8 siblings, 4 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-18 8:49 UTC (permalink / raw)
To: qemu-devel; +Cc: stefanb, 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 | 973 ++++++++++++++++++++++++++++++++++++++++++++++++++
hw/tpm/tpm_ioctl.h | 243 +++++++++++++
qapi-schema.json | 41 ++-
qemu-options.hx | 53 ++-
tpm.c | 2 +-
8 files changed, 1339 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 a3f0522..fbf8bca 100755
--- a/configure
+++ b/configure
@@ -3479,10 +3479,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
##########################################
@@ -5306,6 +5311,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 "Live block migration $live_block_migration"
echo "lzo support $lzo"
@@ -5896,6 +5902,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 7a92e88..04916be 100644
--- a/hmp.c
+++ b/hmp.c
@@ -948,6 +948,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) {
@@ -977,6 +978,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..c90914c
--- /dev/null
+++ b/hw/tpm/tpm_emulator.c
@@ -0,0 +1,973 @@
+/*
+ * 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 "migration/migration.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;
+ Error *migration_blocker;
+} 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 void tpm_emulator_block_migration(TPMEmulator *tpm_pt)
+{
+ Error *err = NULL;
+
+ error_setg(&tpm_pt->migration_blocker,
+ "Migration disabled: TPM emulator not yet migratable");
+ migrate_add_blocker(tpm_pt->migration_blocker, &err);
+ if (err) {
+ error_free(err);
+ error_free(tpm_pt->migration_blocker);
+ tpm_pt->migration_blocker = NULL;
+ }
+}
+
+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;
+ }
+
+ tpm_emulator_block_migration(tpm_pt);
+
+ 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);
+ }
+
+ if (tpm_pt->migration_blocker) {
+ migrate_del_blocker(tpm_pt->migration_blocker);
+ error_free(tpm_pt->migration_blocker);
+ }
+}
+
+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 ab438ea..e17d112 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -5202,10 +5202,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:
@@ -5219,7 +5221,7 @@
# Example:
#
# -> { "execute": "query-tpm-types" }
-# <- { "return": [ "passthrough" ] }
+# <- { "return": [ "passthrough", "emulator" ] }
#
##
{ 'command': 'query-tpm-types', 'returns': ['TpmType'] }
@@ -5240,16 +5242,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 2cc70b9..6902617 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3108,7 +3108,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
@@ -3117,8 +3125,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
@@ -3168,6 +3176,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] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
` (7 preceding siblings ...)
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator Amarnath Valluri
@ 2017-07-18 8:59 ` no-reply
8 siblings, 0 replies; 26+ messages in thread
From: no-reply @ 2017-07-18 8:59 UTC (permalink / raw)
To: amarnath.valluri; +Cc: famz, qemu-devel, stefanb
Hi,
This series failed build test on s390x host. Please find the details below.
Type: series
Message-id: 1500367747-8992-1-git-send-email-amarnath.valluri@intel.com
Subject: [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator
=== TEST SCRIPT BEGIN ===
#!/bin/bash
# Testing script will be invoked under the git checkout with
# HEAD pointing to a commit that has the patches applied on top of "base"
# branch
set -e
echo "=== ENV ==="
env
echo "=== PACKAGES ==="
rpm -qa
echo "=== TEST BEGIN ==="
CC=$HOME/bin/cc
INSTALL=$PWD/install
BUILD=$PWD/build
echo -n "Using CC: "
realpath $CC
mkdir -p $BUILD $INSTALL
SRC=$PWD
cd $BUILD
$SRC/configure --cc=$CC --prefix=$INSTALL
make -j4
# XXX: we need reliable clean up
# make check -j4 V=1
make install
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
- [tag update] patchew/1500349150-13240-1-git-send-email-peterx@redhat.com -> patchew/1500349150-13240-1-git-send-email-peterx@redhat.com
* [new tag] patchew/1500367747-8992-1-git-send-email-amarnath.valluri@intel.com -> patchew/1500367747-8992-1-git-send-email-amarnath.valluri@intel.com
Switched to a new branch 'test'
e1c3e1f tpm: Added support for TPM emulator
608c7d9 tpm-passthrough: move reusable code to utils
725e2e8 tpm-backend: Move realloc_buffer() implementation to tpm-tis model
a25bcfd tmp backend: Add new api to read backend TpmInfo
b43bfa8 tpm-backend: Made few interface methods optional
a89b28a tpm-backend: Initialize and free data members in it's own methods
c2e4d83 tpm-backend: Move thread handling inside TPMBackend
6f82e50 tpm-backend: Remove unneeded member variable from backend class
=== OUTPUT BEGIN ===
=== ENV ===
XDG_SESSION_ID=156248
SHELL=/bin/sh
USER=fam
PATCHEW=/home/fam/patchew/patchew-cli -s http://patchew.org --nodebug
PATH=/usr/bin:/bin
PWD=/var/tmp/patchew-tester-tmp-cbg9pgnx/src
LANG=en_US.UTF-8
HOME=/home/fam
SHLVL=2
LOGNAME=fam
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1012/bus
XDG_RUNTIME_DIR=/run/user/1012
_=/usr/bin/env
=== PACKAGES ===
gpg-pubkey-873529b8-54e386ff
xz-libs-5.2.2-2.fc24.s390x
libxshmfence-1.2-3.fc24.s390x
giflib-4.1.6-15.fc24.s390x
trousers-lib-0.3.13-6.fc24.s390x
ncurses-base-6.0-6.20160709.fc25.noarch
gmp-6.1.1-1.fc25.s390x
libidn-1.33-1.fc25.s390x
slang-2.3.0-7.fc25.s390x
libsemanage-2.5-8.fc25.s390x
pkgconfig-0.29.1-1.fc25.s390x
alsa-lib-1.1.1-2.fc25.s390x
yum-metadata-parser-1.1.4-17.fc25.s390x
python3-slip-dbus-0.6.4-4.fc25.noarch
python2-cssselect-0.9.2-1.fc25.noarch
python-fedora-0.8.0-2.fc25.noarch
createrepo_c-libs-0.10.0-6.fc25.s390x
initscripts-9.69-1.fc25.s390x
wget-1.18-2.fc25.s390x
dhcp-client-4.3.5-1.fc25.s390x
parted-3.2-21.fc25.s390x
flex-2.6.0-3.fc25.s390x
colord-libs-1.3.4-1.fc25.s390x
python-osbs-client-0.33-3.fc25.noarch
perl-Pod-Simple-3.35-1.fc25.noarch
python2-simplejson-3.10.0-1.fc25.s390x
brltty-5.4-2.fc25.s390x
librados2-10.2.4-2.fc25.s390x
tcp_wrappers-7.6-83.fc25.s390x
libcephfs_jni1-10.2.4-2.fc25.s390x
nettle-devel-3.3-1.fc25.s390x
bzip2-devel-1.0.6-21.fc25.s390x
libuuid-2.28.2-2.fc25.s390x
pango-1.40.4-1.fc25.s390x
python3-dnf-1.1.10-6.fc25.noarch
cryptsetup-libs-1.7.4-1.fc25.s390x
texlive-kpathsea-doc-svn41139-33.fc25.1.noarch
netpbm-10.77.00-3.fc25.s390x
openssh-7.4p1-4.fc25.s390x
texlive-kpathsea-bin-svn40473-33.20160520.fc25.1.s390x
texlive-graphics-svn41015-33.fc25.1.noarch
texlive-dvipdfmx-def-svn40328-33.fc25.1.noarch
texlive-mfware-svn40768-33.fc25.1.noarch
texlive-texlive-scripts-svn41433-33.fc25.1.noarch
texlive-euro-svn22191.1.1-33.fc25.1.noarch
texlive-etex-svn37057.0-33.fc25.1.noarch
texlive-iftex-svn29654.0.2-33.fc25.1.noarch
texlive-palatino-svn31835.0-33.fc25.1.noarch
texlive-texlive-docindex-svn41430-33.fc25.1.noarch
texlive-xunicode-svn30466.0.981-33.fc25.1.noarch
texlive-koma-script-svn41508-33.fc25.1.noarch
texlive-pst-grad-svn15878.1.06-33.fc25.1.noarch
texlive-pst-blur-svn15878.2.0-33.fc25.1.noarch
texlive-jknapltx-svn19440.0-33.fc25.1.noarch
netpbm-progs-10.77.00-3.fc25.s390x
texinfo-6.1-4.fc25.s390x
openssl-devel-1.0.2k-1.fc25.s390x
python2-sssdconfig-1.15.2-1.fc25.noarch
gdk-pixbuf2-2.36.6-1.fc25.s390x
mesa-libEGL-13.0.4-3.fc25.s390x
pcre-cpp-8.40-6.fc25.s390x
pcre-utf16-8.40-6.fc25.s390x
glusterfs-extra-xlators-3.10.1-1.fc25.s390x
mesa-libGL-devel-13.0.4-3.fc25.s390x
nss-devel-3.29.3-1.1.fc25.s390x
libaio-0.3.110-6.fc24.s390x
libfontenc-1.1.3-3.fc24.s390x
lzo-2.08-8.fc24.s390x
isl-0.14-5.fc24.s390x
libXau-1.0.8-6.fc24.s390x
linux-atm-libs-2.5.1-14.fc24.s390x
libXext-1.3.3-4.fc24.s390x
libXxf86vm-1.1.4-3.fc24.s390x
bison-3.0.4-4.fc24.s390x
perl-srpm-macros-1-20.fc25.noarch
gawk-4.1.3-8.fc25.s390x
libwayland-client-1.12.0-1.fc25.s390x
perl-Exporter-5.72-366.fc25.noarch
perl-version-0.99.17-1.fc25.s390x
fftw-libs-double-3.3.5-3.fc25.s390x
libssh2-1.8.0-1.fc25.s390x
ModemManager-glib-1.6.4-1.fc25.s390x
newt-python3-0.52.19-2.fc25.s390x
python-munch-2.0.4-3.fc25.noarch
python-bugzilla-1.2.2-4.fc25.noarch
libedit-3.1-16.20160618cvs.fc25.s390x
python-pycurl-7.43.0-4.fc25.s390x
createrepo_c-0.10.0-6.fc25.s390x
device-mapper-multipath-libs-0.4.9-83.fc25.s390x
yum-3.4.3-510.fc25.noarch
dhcp-common-4.3.5-1.fc25.noarch
dracut-config-rescue-044-78.fc25.s390x
teamd-1.26-1.fc25.s390x
mozjs17-17.0.0-16.fc25.s390x
libselinux-2.5-13.fc25.s390x
libgo-devel-6.3.1-1.fc25.s390x
NetworkManager-libnm-1.4.4-3.fc25.s390x
python2-pyparsing-2.1.10-1.fc25.noarch
cairo-gobject-1.14.8-1.fc25.s390x
ethtool-4.8-1.fc25.s390x
xorg-x11-proto-devel-7.7-20.fc25.noarch
brlapi-0.6.5-2.fc25.s390x
librados-devel-10.2.4-2.fc25.s390x
libXinerama-devel-1.1.3-6.fc24.s390x
quota-4.03-7.fc25.s390x
lua-posix-33.3.1-3.fc25.s390x
usbredir-devel-0.7.1-2.fc24.s390x
python-libs-2.7.13-1.fc25.s390x
libX11-devel-1.6.4-4.fc25.s390x
python-devel-2.7.13-1.fc25.s390x
libepoxy-1.4.1-1.fc25.s390x
freetype-devel-2.6.5-3.fc25.s390x
python3-dnf-plugins-core-0.1.21-5.fc25.noarch
perl-macros-5.24.1-385.fc25.s390x
texlive-pdftex-doc-svn41149-33.fc25.1.noarch
mariadb-config-10.1.21-3.fc25.s390x
openssh-clients-7.4p1-4.fc25.s390x
iptables-1.6.0-3.fc25.s390x
texlive-texlive.infra-svn41280-33.fc25.1.noarch
texlive-graphics-cfg-svn40269-33.fc25.1.noarch
texlive-bibtex-svn40768-33.fc25.1.noarch
texlive-mfware-bin-svn40473-33.20160520.fc25.1.s390x
texlive-texlive-scripts-bin-svn29741.0-33.20160520.fc25.1.noarch
texlive-sauerj-svn15878.0-33.fc25.1.noarch
texlive-enctex-svn34957.0-33.fc25.1.noarch
texlive-ifetex-svn24853.1.2-33.fc25.1.noarch
texlive-ntgclass-svn15878.2.1a-33.fc25.1.noarch
texlive-tex-gyre-math-svn41264-33.fc25.1.noarch
texlive-bera-svn20031.0-33.fc25.1.noarch
texlive-ms-svn29849.0-33.fc25.1.noarch
texlive-pst-fill-svn15878.1.01-33.fc25.1.noarch
texlive-ctable-svn38672-33.fc25.1.noarch
texlive-extsizes-svn17263.1.4a-33.fc25.1.noarch
texlive-collection-latexrecommended-svn35765.0-33.20160520.fc25.1.noarch
perl-Filter-1.57-1.fc25.s390x
krb5-workstation-1.14.4-7.fc25.s390x
python2-rpm-macros-3-12.fc25.noarch
audit-libs-2.7.4-1.fc25.s390x
libglvnd-egl-0.2.999-14.20170308git8e6e102.fc25.s390x
libglvnd-opengl-0.2.999-14.20170308git8e6e102.fc25.s390x
pcre-devel-8.40-6.fc25.s390x
gdbm-1.13-1.fc25.s390x
mesa-libGLES-devel-13.0.4-3.fc25.s390x
java-1.8.0-openjdk-1.8.0.121-10.b14.fc25.s390x
gpg-pubkey-efe550f5-5220ba41
gpg-pubkey-81b46521-55b3ca9a
filesystem-3.2-37.fc24.s390x
libffi-3.1-9.fc24.s390x
keyutils-libs-1.5.9-8.fc24.s390x
libnfnetlink-1.0.1-8.fc24.s390x
libtheora-1.1.1-14.fc24.s390x
xml-common-0.6.3-44.fc24.noarch
autoconf-2.69-22.fc24.noarch
libXt-1.1.5-3.fc24.s390x
kbd-legacy-2.0.3-3.fc24.noarch
ghostscript-fonts-5.50-35.fc24.noarch
libXevie-1.0.3-11.fc24.s390x
libcap-2.25-2.fc25.s390x
mpfr-3.1.5-1.fc25.s390x
perl-Carp-1.40-365.fc25.noarch
libmnl-1.0.4-1.fc25.s390x
perl-Unicode-EastAsianWidth-1.33-8.fc25.noarch
libwayland-cursor-1.12.0-1.fc25.s390x
python-krbV-1.0.90-12.fc25.s390x
python2-urllib3-1.15.1-3.fc25.noarch
fipscheck-1.4.1-11.fc25.s390x
libndp-1.6-1.fc25.s390x
gnupg2-2.1.13-2.fc25.s390x
libXfixes-5.0.3-1.fc25.s390x
adwaita-icon-theme-3.22.0-1.fc25.noarch
dconf-0.26.0-1.fc25.s390x
ncurses-devel-6.0-6.20160709.fc25.s390x
dejagnu-1.6-1.fc25.noarch
libstdc++-devel-6.3.1-1.fc25.s390x
python-beautifulsoup4-4.5.3-1.fc25.noarch
device-mapper-1.02.136-3.fc25.s390x
subversion-1.9.5-1.fc25.s390x
libtool-ltdl-2.4.6-13.fc25.s390x
libevent-2.0.22-1.fc25.s390x
atk-devel-2.22.0-1.fc25.s390x
libev-4.24-1.fc25.s390x
xorg-x11-fonts-Type1-7.5-16.fc24.noarch
libtasn1-devel-4.10-1.fc25.s390x
vte291-devel-0.46.1-1.fc25.s390x
brlapi-devel-0.6.5-2.fc25.s390x
pulseaudio-libs-10.0-2.fc25.s390x
libnl3-cli-3.2.29-2.fc25.s390x
perl-libs-5.24.1-385.fc25.s390x
glib2-2.50.3-1.fc25.s390x
python3-firewall-0.4.4.4-1.fc25.noarch
python2-rpm-4.13.0.1-1.fc25.s390x
gnutls-3.5.10-1.fc25.s390x
pango-devel-1.40.4-1.fc25.s390x
dnf-1.1.10-6.fc25.noarch
texlive-metafont-bin-svn40987-33.20160520.fc25.1.s390x
texlive-xkeyval-svn35741.2.7a-33.fc25.1.noarch
texlive-euler-svn17261.2.5-33.fc25.1.noarch
texlive-mptopdf-svn41282-33.fc25.1.noarch
texlive-wasy-svn35831.0-33.fc25.1.noarch
texlive-avantgar-svn31835.0-33.fc25.1.noarch
texlive-eurosym-svn17265.1.4_subrfix-33.fc25.1.noarch
texlive-knuth-lib-svn35820.0-33.fc25.1.noarch
texlive-parallel-svn15878.0-33.fc25.1.noarch
texlive-texlive-msg-translations-svn41431-33.fc25.1.noarch
texlive-latex-svn40218-33.fc25.1.noarch
texlive-lualatex-math-svn40621-33.fc25.1.noarch
texlive-auto-pst-pdf-svn23723.0.6-33.fc25.1.noarch
texlive-powerdot-svn38984-33.fc25.1.noarch
texlive-wasysym-svn15878.2.0-33.fc25.1.noarch
ImageMagick-libs-6.9.3.0-6.fc25.s390x
geoclue2-2.4.5-1.fc25.s390x
perl-IO-Socket-IP-0.39-1.fc25.noarch
gdb-7.12.1-47.fc25.s390x
python2-pyasn1-0.2.3-1.fc25.noarch
libglvnd-0.2.999-14.20170308git8e6e102.fc25.s390x
libglvnd-gles-0.2.999-14.20170308git8e6e102.fc25.s390x
gdk-pixbuf2-devel-2.36.6-1.fc25.s390x
libidn2-2.0.0-1.fc25.s390x
system-python-libs-3.5.3-4.fc25.s390x
GeoIP-1.6.10-1.fc25.s390x
at-spi2-core-devel-2.22.1-1.fc25.s390x
gpg-pubkey-34ec9cba-54e38751
gpg-pubkey-030d5aed-55b577f0
basesystem-11-2.fc24.noarch
libmpc-1.0.2-5.fc24.s390x
libunistring-0.9.4-3.fc24.s390x
libmodman-2.0.1-12.fc24.s390x
lsscsi-0.28-3.fc24.s390x
kbd-misc-2.0.3-3.fc24.noarch
rpmconf-base-1.0.18-2.fc25.noarch
libxml2-2.9.3-4.fc25.s390x
kmod-23-1.fc25.s390x
newt-0.52.19-2.fc25.s390x
perl-Text-Unidecode-1.27-3.fc25.noarch
plymouth-core-libs-0.9.3-0.6.20160620git0e65b86c.fc25.s390x
which-2.21-1.fc25.s390x
python3-slip-0.6.4-4.fc25.noarch
python3-systemd-232-1.fc25.s390x
python-lockfile-0.11.0-4.fc25.noarch
python2-requests-2.10.0-4.fc25.noarch
libarchive-3.2.2-1.fc25.s390x
libnghttp2-1.13.0-2.fc25.s390x
python-urlgrabber-3.10.1-9.fc25.noarch
iputils-20161105-1.fc25.s390x
rest-0.8.0-1.fc25.s390x
adwaita-cursor-theme-3.22.0-1.fc25.noarch
authconfig-6.2.10-14.fc25.s390x
expat-devel-2.2.0-1.fc25.s390x
automake-1.15-7.fc25.noarch
shared-mime-info-1.8-1.fc25.s390x
pigz-2.3.4-1.fc25.s390x
device-mapper-libs-1.02.136-3.fc25.s390x
dnsmasq-2.76-2.fc25.s390x
fedora-packager-0.6.0.1-1.fc25.noarch
gcc-c++-6.3.1-1.fc25.s390x
libwebp-0.5.2-1.fc25.s390x
boost-system-1.60.0-10.fc25.s390x
libasyncns-0.8-10.fc24.s390x
libXau-devel-1.0.8-6.fc24.s390x
libverto-libev-0.2.6-6.fc24.s390x
python3-html5lib-0.999-9.fc25.noarch
ttmkfdir-3.0.9-48.fc24.s390x
pulseaudio-libs-glib2-10.0-2.fc25.s390x
wpa_supplicant-2.6-1.fc25.s390x
texlive-lib-2016-33.20160520.fc25.s390x
libXi-devel-1.7.9-1.fc25.s390x
python3-distro-1.0.3-1.fc25.noarch
rpm-plugin-systemd-inhibit-4.13.0.1-1.fc25.s390x
gnutls-c++-3.5.10-1.fc25.s390x
texlive-texlive-common-doc-svn40682-33.fc25.1.noarch
packagedb-cli-2.14.1-1.fc25.noarch
rpcbind-0.2.4-5.fc25.s390x
texlive-metafont-svn40793-33.fc25.1.noarch
texlive-tools-svn40934-33.fc25.1.noarch
texlive-enumitem-svn24146.3.5.2-33.fc25.1.noarch
texlive-mptopdf-bin-svn18674.0-33.20160520.fc25.1.noarch
texlive-underscore-svn18261.0-33.fc25.1.noarch
texlive-anysize-svn15878.0-33.fc25.1.noarch
texlive-euenc-svn19795.0.1h-33.fc25.1.noarch
texlive-kastrup-svn15878.0-33.fc25.1.noarch
texlive-paralist-svn39247-33.fc25.1.noarch
texlive-texlive-en-svn41185-33.fc25.1.noarch
texlive-tipa-svn29349.1.3-33.fc25.1.noarch
texlive-currfile-svn40725-33.fc25.1.noarch
texlive-pst-node-svn40743-33.fc25.1.noarch
texlive-pst-slpe-svn24391.1.31-33.fc25.1.noarch
texlive-typehtml-svn17134.0-33.fc25.1.noarch
SDL2-devel-2.0.5-3.fc25.s390x
perl-Module-CoreList-5.20170320-1.fc25.noarch
libcroco-0.6.11-3.fc25.s390x
publicsuffix-list-dafsa-20170206-1.fc25.noarch
pcre-8.40-6.fc25.s390x
cups-libs-2.2.0-8.fc25.s390x
gtk-update-icon-cache-3.22.11-1.fc25.s390x
libcurl-7.51.0-6.fc25.s390x
python3-libs-3.5.3-4.fc25.s390x
bluez-libs-devel-5.44-1.fc25.s390x
kernel-4.10.8-200.fc25.s390x
fontpackages-filesystem-1.44-17.fc24.noarch
groff-base-1.22.3-8.fc24.s390x
ilmbase-2.2.0-5.fc24.s390x
OpenEXR-libs-2.2.0-5.fc24.s390x
hesiod-3.2.1-6.fc24.s390x
sysfsutils-2.1.0-19.fc24.s390x
ocaml-srpm-macros-2-4.fc24.noarch
mailx-12.5-19.fc24.s390x
ncurses-libs-6.0-6.20160709.fc25.s390x
ipset-libs-6.29-1.fc25.s390x
gmp-devel-6.1.1-1.fc25.s390x
python-pip-8.1.2-2.fc25.noarch
harfbuzz-1.3.2-1.fc25.s390x
python2-iniparse-0.4-20.fc25.noarch
python3-iniparse-0.4-20.fc25.noarch
python3-kickstart-2.32-1.fc25.noarch
perl-Net-SSLeay-1.78-1.fc25.s390x
drpm-0.3.0-3.fc25.s390x
glib-networking-2.50.0-1.fc25.s390x
webkitgtk3-2.4.11-3.fc25.s390x
libXaw-1.0.13-4.fc25.s390x
xorg-x11-font-utils-7.5-32.fc25.s390x
hardlink-1.1-1.fc25.s390x
libcom_err-1.43.3-1.fc25.s390x
python2-dateutil-2.6.0-1.fc25.noarch
libXpm-3.5.12-1.fc25.s390x
python2-smmap-2.0.1-1.fc25.noarch
poppler-data-0.4.7-6.fc25.noarch
nspr-devel-4.13.1-1.fc25.s390x
librbd1-10.2.4-2.fc25.s390x
libsndfile-1.0.27-1.fc25.s390x
perl-Digest-MD5-2.55-2.fc25.s390x
wayland-protocols-devel-1.7-1.fc25.noarch
libacl-devel-2.2.52-11.fc24.s390x
texi2html-5.0-4.fc24.noarch
libxkbcommon-0.7.1-1.fc25.s390x
freetype-2.6.5-3.fc25.s390x
libuuid-devel-2.28.2-2.fc25.s390x
coreutils-common-8.25-16.fc25.s390x
gdb-headless-7.12.1-47.fc25.s390x
libcacard-2.5.3-1.fc25.s390x
perl-threads-shared-1.55-1.fc25.s390x
python2-rpkg-1.49-2.fc25.noarch
libwmf-lite-0.2.8.4-50.fc25.s390x
unbound-libs-1.6.0-6.fc25.s390x
texlive-tetex-svn41059-33.fc25.1.noarch
texlive-thumbpdf-svn34621.3.16-33.fc25.1.noarch
texlive-carlisle-svn18258.0-33.fc25.1.noarch
texlive-makeindex-bin-svn40473-33.20160520.fc25.1.s390x
texlive-pdftex-svn41149-33.fc25.1.noarch
texlive-csquotes-svn39538-33.fc25.1.noarch
texlive-courier-svn35058.0-33.fc25.1.noarch
texlive-helvetic-svn31835.0-33.fc25.1.noarch
texlive-mfnfss-svn19410.0-33.fc25.1.noarch
texlive-sepnum-svn20186.2.0-33.fc25.1.noarch
texlive-utopia-svn15878.0-33.fc25.1.noarch
texlive-luatexbase-svn38550-33.fc25.1.noarch
texlive-pst-3d-svn17257.1.10-33.fc25.1.noarch
texlive-latex-bin-bin-svn14050.0-33.20160520.fc25.1.noarch
texlive-l3experimental-svn41163-33.fc25.1.noarch
bind99-libs-9.9.9-4.P6.fc25.s390x
net-tools-2.0-0.40.20160329git.fc25.s390x
perl-Pod-Perldoc-3.28-1.fc25.noarch
openssl-1.0.2k-1.fc25.s390x
man-pages-4.06-4.fc25.noarch
libdrm-2.4.77-1.fc25.s390x
p11-kit-0.23.2-3.fc25.s390x
glusterfs-cli-3.10.1-1.fc25.s390x
git-core-2.9.3-3.fc25.s390x
python3-3.5.3-4.fc25.s390x
python3-magic-5.29-4.fc25.noarch
p11-kit-trust-0.23.2-3.fc25.s390x
gpg-pubkey-95a43f54-5284415a
dejavu-fonts-common-2.35-3.fc24.noarch
libSM-1.2.2-4.fc24.s390x
diffutils-3.3-13.fc24.s390x
libogg-1.3.2-5.fc24.s390x
hunspell-en-US-0.20140811.1-5.fc24.noarch
libdaemon-0.14-10.fc24.s390x
patch-2.7.5-3.fc24.s390x
libsysfs-2.1.0-19.fc24.s390x
procmail-3.22-39.fc24.s390x
libXdamage-1.1.4-8.fc24.s390x
libotf-0.9.13-7.fc24.s390x
urw-fonts-2.4-22.fc24.noarch
crontabs-1.11-12.20150630git.fc24.noarch
ppp-2.4.7-9.fc24.s390x
polkit-0.113-5.fc24.s390x
cyrus-sasl-2.1.26-26.2.fc24.s390x
zlib-devel-1.2.8-10.fc24.s390x
time-1.7-49.fc24.s390x
gpg-pubkey-fdb19c98-56fd6333
fedora-release-25-1.noarch
libcap-ng-0.7.8-1.fc25.s390x
binutils-2.26.1-1.fc25.s390x
lcms2-2.8-2.fc25.s390x
libcomps-0.1.7-5.fc25.s390x
less-481-6.fc25.s390x
apr-1.5.2-4.fc25.s390x
perl-constant-1.33-367.fc25.noarch
perl-Data-Dumper-2.161-1.fc25.s390x
ipcalc-0.1.8-1.fc25.s390x
libteam-1.26-1.fc25.s390x
gmp-c++-6.1.1-1.fc25.s390x
fontconfig-2.12.1-1.fc25.s390x
enchant-1.6.0-14.fc25.s390x
pyliblzma-0.5.3-16.fc25.s390x
libsepol-devel-2.5-10.fc25.s390x
python3-ordered-set-2.0.0-4.fc25.noarch
python3-rpmconf-1.0.18-2.fc25.noarch
python-ipaddress-1.0.16-3.fc25.noarch
python2-kerberos-1.2.5-1.fc25.s390x
python2-pysocks-1.5.6-5.fc25.noarch
fipscheck-lib-1.4.1-11.fc25.s390x
libatomic_ops-7.4.4-1.fc25.s390x
net-snmp-agent-libs-5.7.3-13.fc25.s390x
dracut-044-78.fc25.s390x
python2-pygpgme-0.3-18.fc25.s390x
libsoup-2.56.0-2.fc25.s390x
orc-0.4.26-1.fc25.s390x
yum-utils-1.1.31-511.fc25.noarch
libXrender-0.9.10-1.fc25.s390x
libXrandr-1.5.1-1.fc25.s390x
go-srpm-macros-2-7.fc25.noarch
gnupg2-smime-2.1.13-2.fc25.s390x
guile-devel-2.0.13-1.fc25.s390x
uboot-tools-2016.09.01-2.fc25.s390x
pykickstart-2.32-1.fc25.noarch
python-bunch-1.0.1-9.fc25.noarch
perl-generators-1.10-1.fc25.noarch
perl-Mozilla-CA-20160104-3.fc25.noarch
glibc-all-langpacks-2.24-4.fc25.s390x
bzip2-libs-1.0.6-21.fc25.s390x
libpng-1.6.27-1.fc25.s390x
desktop-file-utils-0.23-2.fc25.s390x
python2-cccolutils-1.4-1.fc25.s390x
python2-lxml-3.7.2-1.fc25.s390x
redhat-rpm-config-45-1.fc25.noarch
elfutils-libs-0.168-1.fc25.s390x
device-mapper-event-libs-1.02.136-3.fc25.s390x
lvm2-libs-2.02.167-3.fc25.s390x
elfutils-0.168-1.fc25.s390x
python2-gitdb-2.0.0-1.fc25.noarch
gcc-gfortran-6.3.1-1.fc25.s390x
libselinux-python-2.5-13.fc25.s390x
openjpeg2-2.1.2-3.fc25.s390x
js-jquery-2.2.4-1.fc25.noarch
boost-thread-1.60.0-10.fc25.s390x
json-c-0.12-7.fc24.s390x
librbd-devel-10.2.4-2.fc25.s390x
libXcursor-devel-1.1.14-6.fc24.s390x
python3-beautifulsoup4-4.5.3-1.fc25.noarch
latex2html-2012-7.fc24.noarch
lksctp-tools-1.0.16-5.fc24.s390x
vte291-0.46.1-1.fc25.s390x
libfdt-1.4.2-1.fc25.s390x
libXft-devel-2.3.2-4.fc24.s390x
libattr-devel-2.4.47-16.fc24.s390x
libiscsi-devel-1.15.0-2.fc24.s390x
gettext-0.19.8.1-3.fc25.s390x
libjpeg-turbo-devel-1.5.1-0.fc25.s390x
libX11-1.6.4-4.fc25.s390x
pulseaudio-libs-devel-10.0-2.fc25.s390x
ccache-3.3.3-1.fc25.s390x
systemd-libs-231-14.fc25.s390x
nss-softokn-freebl-3.29.3-1.0.fc25.s390x
libepoxy-devel-1.4.1-1.fc25.s390x
krb5-libs-1.14.4-7.fc25.s390x
libmount-2.28.2-2.fc25.s390x
python3-decorator-4.0.11-1.fc25.noarch
rpm-plugin-selinux-4.13.0.1-1.fc25.s390x
perl-threads-2.15-1.fc25.s390x
tzdata-java-2017b-1.fc25.noarch
python-srpm-macros-3-12.fc25.noarch
libsmartcols-2.28.2-2.fc25.s390x
kernel-core-4.10.5-200.fc25.s390x
kernel-modules-4.10.5-200.fc25.s390x
texlive-kpathsea-svn41139-33.fc25.1.noarch
texlive-amsmath-svn41561-33.fc25.1.noarch
texlive-thumbpdf-bin-svn6898.0-33.20160520.fc25.1.noarch
texlive-psnfss-svn33946.9.2a-33.fc25.1.noarch
texlive-subfig-svn15878.1.3-33.fc25.1.noarch
texlive-fancybox-svn18304.1.4-33.fc25.1.noarch
texlive-lua-alt-getopt-svn29349.0.7.0-33.fc25.1.noarch
texlive-natbib-svn20668.8.31b-33.fc25.1.noarch
texlive-pdftex-bin-svn40987-33.20160520.fc25.1.s390x
texlive-xdvi-svn40768-33.fc25.1.noarch
texlive-crop-svn15878.1.5-33.fc25.1.noarch
texlive-babel-english-svn30264.3.3p-33.fc25.1.noarch
texlive-cmextra-svn32831.0-33.fc25.1.noarch
texlive-fancyhdr-svn15878.3.1-33.fc25.1.noarch
texlive-luatex-svn40963-33.fc25.1.noarch
texlive-knuth-local-svn38627-33.fc25.1.noarch
texlive-mflogo-font-svn36898.1.002-33.fc25.1.noarch
texlive-parskip-svn19963.2.0-33.fc25.1.noarch
texlive-section-svn20180.0-33.fc25.1.noarch
texlive-textcase-svn15878.0-33.fc25.1.noarch
texlive-updmap-map-svn41159-33.fc25.1.noarch
texlive-attachfile-svn38830-33.fc25.1.noarch
nss-3.29.3-1.1.fc25.s390x
glusterfs-client-xlators-3.10.1-1.fc25.s390x
libglvnd-glx-0.2.999-14.20170308git8e6e102.fc25.s390x
libtiff-4.0.7-4.fc25.s390x
dbus-devel-1.11.12-1.fc25.s390x
java-1.8.0-openjdk-headless-1.8.0.121-10.b14.fc25.s390x
pcre2-utf16-10.23-5.fc25.s390x
git-core-doc-2.9.3-3.fc25.s390x
iproute-4.10.0-1.fc25.s390x
nfs-utils-2.1.1-3.rc1.fc25.s390x
libglvnd-core-devel-0.2.999-14.20170308git8e6e102.fc25.s390x
python-magic-5.29-4.fc25.noarch
pcre2-devel-10.23-5.fc25.s390x
p11-kit-devel-0.23.2-3.fc25.s390x
texlive-luaotfload-svn40902-33.fc25.1.noarch
texlive-unicode-math-svn38462-33.fc25.1.noarch
texlive-fancyvrb-svn18492.2.8-33.fc25.1.noarch
texlive-pst-pdf-bin-svn7838.0-33.20160520.fc25.1.noarch
texlive-amscls-svn36804.0-33.fc25.1.noarch
texlive-ltxmisc-svn21927.0-33.fc25.1.noarch
texlive-breqn-svn38099.0.98d-33.fc25.1.noarch
texlive-xetex-def-svn40327-33.fc25.1.noarch
openssh-server-7.4p1-4.fc25.s390x
sendmail-8.15.2-8.fc25.s390x
python-firewall-0.4.4.4-1.fc25.noarch
python3-sssdconfig-1.15.2-1.fc25.noarch
tzdata-2017b-1.fc25.noarch
hunspell-1.4.1-2.fc25.s390x
gpg-pubkey-8e1431d5-53bcbac7
zlib-1.2.8-10.fc24.s390x
sed-4.2.2-15.fc24.s390x
psmisc-22.21-8.fc24.s390x
gpm-libs-1.20.7-9.fc24.s390x
zip-3.0-16.fc24.s390x
hostname-3.15-7.fc24.s390x
libyubikey-1.13-2.fc24.s390x
sg3_utils-libs-1.41-3.fc24.s390x
polkit-pkla-compat-0.1-7.fc24.s390x
passwd-0.79-8.fc24.s390x
trousers-0.3.13-6.fc24.s390x
grubby-8.40-3.fc24.s390x
rootfiles-8.1-19.fc24.noarch
nettle-3.3-1.fc25.s390x
jansson-2.9-1.fc25.s390x
libksba-1.3.5-1.fc25.s390x
perl-Text-ParseWords-3.30-365.fc25.noarch
perl-PathTools-3.63-366.fc25.s390x
perl-File-Temp-0.23.04-365.fc25.noarch
fuse-libs-2.9.7-1.fc25.s390x
perl-Pod-Escapes-1.07-365.fc25.noarch
perl-Term-ANSIColor-4.05-2.fc25.noarch
perl-URI-1.71-5.fc25.noarch
libXfont-1.5.2-1.fc25.s390x
python-six-1.10.0-3.fc25.noarch
dbus-glib-0.108-1.fc25.s390x
gobject-introspection-1.50.0-1.fc25.s390x
libpwquality-1.3.0-6.fc25.s390x
python-gobject-base-3.22.0-1.fc25.s390x
python-html5lib-0.999-9.fc25.noarch
python3-dbus-1.2.4-2.fc25.s390x
python3-chardet-2.3.0-1.fc25.noarch
python3-urllib3-1.15.1-3.fc25.noarch
python-offtrac-0.1.0-7.fc25.noarch
python2-cryptography-1.5.3-3.fc25.s390x
python2-requests-kerberos-0.10.0-2.fc25.noarch
libserf-1.3.9-1.fc25.s390x
libdatrie-0.2.9-3.fc25.s390x
s390utils-base-1.36.0-1.fc25.s390x
kpartx-0.4.9-83.fc25.s390x
s390utils-cpuplugd-1.36.0-1.fc25.s390x
rpmconf-1.0.18-2.fc25.noarch
s390utils-osasnmpd-1.36.0-1.fc25.s390x
python-dnf-plugins-extras-common-0.0.12-4.fc25.noarch
fpc-srpm-macros-1.0-1.fc25.noarch
libuser-0.62-4.fc25.s390x
man-db-2.7.5-3.fc25.s390x
sqlite-3.14.2-1.fc25.s390x
python-systemd-doc-232-1.fc25.s390x
libdb-5.3.28-16.fc25.s390x
lz4-1.7.5-1.fc25.s390x
tar-1.29-3.fc25.s390x
emacs-common-25.1-3.fc25.s390x
unzip-6.0-31.fc25.s390x
bodhi-client-0.9.12.2-6.fc25.noarch
glibc-headers-2.24-4.fc25.s390x
cairo-1.14.8-1.fc25.s390x
ca-certificates-2017.2.11-1.0.fc25.noarch
NetworkManager-glib-1.4.4-3.fc25.s390x
gcc-go-6.3.1-1.fc25.s390x
cracklib-dicts-2.9.6-4.fc25.s390x
libselinux-python3-2.5-13.fc25.s390x
python2-enchant-1.6.8-1.fc25.noarch
boost-iostreams-1.60.0-10.fc25.s390x
userspace-rcu-0.9.2-2.fc25.s390x
libXext-devel-1.3.3-4.fc24.s390x
libXrandr-devel-1.5.1-1.fc25.s390x
perl-XML-XPath-1.39-1.fc25.noarch
python3-lxml-3.7.2-1.fc25.s390x
vte-profile-0.46.1-1.fc25.s390x
sqlite-devel-3.14.2-1.fc25.s390x
libiscsi-1.15.0-2.fc24.s390x
fontconfig-devel-2.12.1-1.fc25.s390x
libfdt-devel-1.4.2-1.fc25.s390x
ceph-devel-compat-10.2.4-2.fc25.s390x
zlib-static-1.2.8-10.fc24.s390x
chrpath-0.16-3.fc24.s390x
python-2.7.13-1.fc25.s390x
kernel-core-4.9.5-200.fc25.s390x
info-6.1-4.fc25.s390x
iptables-libs-1.6.0-3.fc25.s390x
bind-license-9.10.4-4.P6.fc25.noarch
lua-5.3.4-1.fc25.s390x
libfdisk-2.28.2-2.fc25.s390x
dnf-plugins-core-0.1.21-5.fc25.noarch
selinux-policy-3.13.1-225.11.fc25.noarch
perl-Errno-1.25-385.fc25.s390x
perl-Storable-2.56-368.fc25.s390x
python2-decorator-4.0.11-1.fc25.noarch
mariadb-common-10.1.21-3.fc25.s390x
systemtap-client-3.1-2.fc25.s390x
libnetfilter_conntrack-1.0.6-2.fc25.s390x
texlive-texlive.infra-bin-svn40312-33.20160520.fc25.1.s390x
texlive-ifluatex-svn41346-33.fc25.1.noarch
texlive-fp-svn15878.0-33.fc25.1.noarch
texlive-latex-fonts-svn28888.0-33.fc25.1.noarch
texlive-bibtex-bin-svn40473-33.20160520.fc25.1.s390x
texlive-glyphlist-svn28576.0-33.fc25.1.noarch
texlive-marvosym-svn29349.2.2a-33.fc25.1.noarch
texlive-tex-bin-svn40987-33.20160520.fc25.1.s390x
texlive-texconfig-svn40768-33.fc25.1.noarch
texlive-wasy2-ps-svn35830.0-33.fc25.1.noarch
texlive-psfrag-svn15878.3.04-33.fc25.1.noarch
texlive-charter-svn15878.0-33.fc25.1.noarch
texlive-ec-svn25033.1.0-33.fc25.1.noarch
texlive-lineno-svn21442.4.41-33.fc25.1.noarch
texlive-hyphen-base-svn41138-33.fc25.1.noarch
texlive-manfnt-font-svn35799.0-33.fc25.1.noarch
texlive-ncntrsbk-svn31835.0-33.fc25.1.noarch
texlive-pst-math-svn34786.0.63-33.fc25.1.noarch
texlive-symbol-svn31835.0-33.fc25.1.noarch
texlive-environ-svn33821.0.3-33.fc25.1.noarch
texlive-algorithms-svn38085.0.1-33.fc25.1.noarch
glusterfs-libs-3.10.1-1.fc25.s390x
mesa-libwayland-egl-13.0.4-3.fc25.s390x
glusterfs-api-3.10.1-1.fc25.s390x
kernel-core-4.10.8-200.fc25.s390x
mesa-libwayland-egl-devel-13.0.4-3.fc25.s390x
nss-tools-3.29.3-1.1.fc25.s390x
pcre2-10.23-5.fc25.s390x
perl-Git-2.9.3-3.fc25.noarch
gssproxy-0.7.0-3.fc25.s390x
glusterfs-server-3.10.1-1.fc25.s390x
libglvnd-devel-0.2.999-14.20170308git8e6e102.fc25.s390x
python3-hawkey-0.6.4-3.fc25.s390x
vim-enhanced-8.0.514-1.fc25.s390x
mesa-libgbm-devel-13.0.4-3.fc25.s390x
texlive-ifplatform-svn21156.0.4-33.fc25.1.noarch
texlive-eso-pic-svn37925.2.0g-33.fc25.1.noarch
texlive-xcolor-svn41044-33.fc25.1.noarch
texlive-pst-eps-svn15878.1.0-33.fc25.1.noarch
texlive-pst-text-svn15878.1.00-33.fc25.1.noarch
texlive-rotating-svn16832.2.16b-33.fc25.1.noarch
texlive-pdfpages-svn40638-33.fc25.1.noarch
texlive-cm-super-svn15878.0-33.fc25.1.noarch
texlive-xetex-svn41438-33.fc25.1.noarch
dnf-yum-1.1.10-6.fc25.noarch
mariadb-libs-10.1.21-3.fc25.s390x
rpmlint-1.9-8.fc25.noarch
systemtap-sdt-devel-3.1-2.fc25.s390x
libseccomp-devel-2.3.2-1.fc25.s390x
telnet-0.17-67.fc25.s390x
gpgme-1.8.0-10.fc25.s390x
apr-util-1.5.4-3.fc24.s390x
rsync-3.1.2-2.fc24.s390x
jbigkit-libs-2.1-5.fc24.s390x
pixman-0.34.0-2.fc24.s390x
dwz-0.12-2.fc24.s390x
expect-5.45-22.fc24.s390x
libsigsegv-2.10-10.fc24.s390x
fakeroot-libs-1.20.2-4.fc24.s390x
m17n-lib-1.7.0-5.fc24.s390x
libverto-0.2.6-6.fc24.s390x
libXmu-1.1.2-4.fc24.s390x
libXcursor-1.1.14-6.fc24.s390x
python-kitchen-1.2.4-2.fc24.noarch
polkit-libs-0.113-5.fc24.s390x
fakeroot-1.20.2-4.fc24.s390x
blktrace-1.1.0-3.fc24.s390x
usermode-1.111-8.fc24.s390x
kbd-2.0.3-3.fc24.s390x
libaio-devel-0.3.110-6.fc24.s390x
web-assets-filesystem-5-4.fc24.noarch
expat-2.2.0-1.fc25.s390x
libgpg-error-1.24-1.fc25.s390x
libgcrypt-1.6.6-1.fc25.s390x
findutils-4.6.0-8.fc25.s390x
libassuan-2.4.3-1.fc25.s390x
libusbx-1.0.21-1.fc25.s390x
libxslt-1.1.28-13.fc25.s390x
libmetalink-0.1.3-1.fc25.s390x
perl-File-Path-2.12-365.fc25.noarch
perl-MIME-Base64-3.15-365.fc25.s390x
ncurses-6.0-6.20160709.fc25.s390x
libwayland-server-1.12.0-1.fc25.s390x
perl-Fedora-VSP-0.001-4.fc25.noarch
perl-libintl-perl-1.26-1.fc25.s390x
shadow-utils-4.2.1-11.fc25.s390x
atk-2.22.0-1.fc25.s390x
pam-1.3.0-1.fc25.s390x
harfbuzz-icu-1.3.2-1.fc25.s390x
libsecret-0.18.5-2.fc25.s390x
s390utils-iucvterm-1.36.0-1.fc25.s390x
python3-requests-2.10.0-4.fc25.noarch
pyusb-1.0.0-2.fc25.noarch
python-enum34-1.0.4-6.fc25.noarch
pyOpenSSL-16.0.0-2.fc25.noarch
pyxattr-0.5.3-8.fc25.s390x
libbabeltrace-1.4.0-3.fc25.s390x
libthai-0.1.25-1.fc25.s390x
deltarpm-3.6-17.fc25.s390x
s390utils-mon_statd-1.36.0-1.fc25.s390x
device-mapper-multipath-0.4.9-83.fc25.s390x
python3-pygpgme-0.3-18.fc25.s390x
libreport-filesystem-2.8.0-1.fc25.s390x
ghc-srpm-macros-1.4.2-4.fc25.noarch
rpmdevtools-8.9-1.fc25.noarch
python-dnf-plugins-extras-migrate-0.0.12-4.fc25.noarch
perl-IO-Socket-SSL-2.038-1.fc25.noarch
perl-File-ShareDir-1.102-7.fc25.noarch
tcl-8.6.6-1.fc25.s390x
glibc-2.24-4.fc25.s390x
elfutils-libelf-0.168-1.fc25.s390x
perl-Scalar-List-Utils-1.47-1.fc25.s390x
bzip2-1.0.6-21.fc25.s390x
libss-1.43.3-1.fc25.s390x
libselinux-utils-2.5-13.fc25.s390x
koji-1.11.0-1.fc25.noarch
python3-enchant-1.6.8-1.fc25.noarch
python2-dockerfile-parse-0.0.5-7.fc25.noarch
systemd-bootchart-231-2.fc25.s390x
gcc-objc-6.3.1-1.fc25.s390x
e2fsprogs-1.43.3-1.fc25.s390x
libstdc++-static-6.3.1-1.fc25.s390x
libpng-devel-1.6.27-1.fc25.s390x
perl-XML-Parser-2.44-5.fc25.s390x
lttng-ust-2.8.1-2.fc25.s390x
libXfixes-devel-5.0.3-1.fc25.s390x
libXcomposite-devel-0.4.4-8.fc24.s390x
quota-nls-4.03-7.fc25.noarch
python3-javapackages-4.7.0-6.1.fc25.noarch
libcephfs_jni-devel-10.2.4-2.fc25.s390x
keyutils-libs-devel-1.5.9-8.fc24.s390x
libicu-devel-57.1-4.fc25.s390x
harfbuzz-devel-1.3.2-1.fc25.s390x
libidn-devel-1.33-1.fc25.s390x
libnfs-1.9.8-2.fc24.s390x
libssh2-devel-1.8.0-1.fc25.s390x
qemu-sanity-check-nodeps-1.1.5-5.fc24.s390x
alsa-lib-devel-1.1.1-2.fc25.s390x
libnl3-3.2.29-2.fc25.s390x
kernel-modules-4.9.5-200.fc25.s390x
libpsl-0.17.0-1.fc25.s390x
lua-libs-5.3.4-1.fc25.s390x
libseccomp-2.3.2-1.fc25.s390x
nss-softokn-freebl-devel-3.29.3-1.0.fc25.s390x
copy-jdk-configs-2.2-2.fc25.noarch
json-glib-1.2.6-1.fc25.s390x
python2-dnf-1.1.10-6.fc25.noarch
bind-libs-lite-9.10.4-4.P6.fc25.s390x
perl-IO-1.36-385.fc25.s390x
python2-GitPython-2.1.3-1.fc25.noarch
linux-firmware-20170313-72.git695f2d6d.fc25.noarch
systemd-container-231-14.fc25.s390x
gnutls-dane-3.5.10-1.fc25.s390x
texlive-tetex-bin-svn36770.0-33.20160520.fc25.1.noarch
texlive-amsfonts-svn29208.3.04-33.fc25.1.noarch
texlive-babel-svn40706-33.fc25.1.noarch
texlive-colortbl-svn29803.v1.0a-33.fc25.1.noarch
texlive-babelbib-svn25245.1.31-33.fc25.1.noarch
texlive-footmisc-svn23330.5.5b-33.fc25.1.noarch
texlive-makeindex-svn40768-33.fc25.1.noarch
texlive-plain-svn40274-33.fc25.1.noarch
texlive-texconfig-bin-svn29741.0-33.20160520.fc25.1.noarch
texlive-zapfding-svn31835.0-33.fc25.1.noarch
texlive-microtype-svn41127-33.fc25.1.noarch
texlive-bookman-svn31835.0-33.fc25.1.noarch
texlive-dvisvgm-def-svn41011-33.fc25.1.noarch
texlive-finstrut-svn21719.0.5-33.fc25.1.noarch
texlive-hyph-utf8-svn41189-33.fc25.1.noarch
texlive-lualibs-svn40370-33.fc25.1.noarch
glusterfs-3.10.1-1.fc25.s390x
mesa-libglapi-13.0.4-3.fc25.s390x
mesa-libgbm-13.0.4-3.fc25.s390x
kernel-modules-4.10.8-200.fc25.s390x
glusterfs-fuse-3.10.1-1.fc25.s390x
openldap-2.4.44-10.fc25.s390x
pcre-utf32-8.40-6.fc25.s390x
git-2.9.3-3.fc25.s390x
python2-gluster-3.10.1-1.fc25.s390x
glusterfs-devel-3.10.1-1.fc25.s390x
mesa-libEGL-devel-13.0.4-3.fc25.s390x
glusterfs-api-devel-3.10.1-1.fc25.s390x
sudo-1.8.19p2-1.fc25.s390x
python2-hawkey-0.6.4-3.fc25.s390x
texlive-mparhack-svn15878.1.4-33.fc25.1.noarch
texlive-pspicture-svn15878.0-33.fc25.1.noarch
texlive-soul-svn15878.2.4-33.fc25.1.noarch
texlive-trimspaces-svn15878.1.1-33.fc25.1.noarch
texlive-varwidth-svn24104.0.92-33.fc25.1.noarch
texlive-geometry-svn19716.5.6-33.fc25.1.noarch
texlive-memoir-svn41203-33.fc25.1.noarch
texlive-pgf-svn40966-33.fc25.1.noarch
texlive-pst-coil-svn37377.1.07-33.fc25.1.noarch
texlive-pst-plot-svn41242-33.fc25.1.noarch
texlive-latex-bin-svn41438-33.fc25.1.noarch
texlive-ucs-svn35853.2.2-33.fc25.1.noarch
texlive-ae-svn15878.1.4-33.fc25.1.noarch
texlive-xetex-bin-svn41091-33.20160520.fc25.1.s390x
fedora-upgrade-26.1-1.fc25.noarch
fedpkg-1.28-1.fc25.noarch
perl-Thread-Queue-3.12-1.fc25.noarch
gstreamer1-plugins-base-1.10.4-1.fc25.s390x
screen-4.5.1-1.fc25.s390x
strace-4.16-1.fc25.s390x
fedora-repos-25-3.noarch
libacl-2.2.52-11.fc24.s390x
cdparanoia-libs-10.2-21.fc24.s390x
ustr-1.0.4-21.fc24.s390x
libusb-0.1.5-7.fc24.s390x
readline-devel-6.3-8.fc24.s390x
chkconfig-1.8-1.fc25.s390x
avahi-libs-0.6.32-4.fc25.s390x
perl-Unicode-Normalize-1.25-365.fc25.s390x
perl-libnet-3.10-1.fc25.noarch
perl-podlators-4.09-1.fc25.noarch
graphite2-1.3.6-1.fc25.s390x
dbus-python-1.2.4-2.fc25.s390x
libgnome-keyring-3.12.0-7.fc25.s390x
python-backports-1.0-8.fc25.s390x
python-pycparser-2.14-7.fc25.noarch
plymouth-scripts-0.9.3-0.6.20160620git0e65b86c.fc25.s390x
cronie-1.5.1-2.fc25.s390x
python2-librepo-1.7.18-3.fc25.s390x
libXv-1.0.11-1.fc25.s390x
python2-ndg_httpsclient-0.4.0-4.fc25.noarch
btrfs-progs-4.6.1-1.fc25.s390x
libgcc-6.3.1-1.fc25.s390x
libgomp-6.3.1-1.fc25.s390x
perl-Encode-2.88-5.fc25.s390x
cracklib-2.9.6-4.fc25.s390x
libobjc-6.3.1-1.fc25.s390x
gcc-6.3.1-1.fc25.s390x
python3-dnf-plugin-system-upgrade-0.7.1-4.fc25.noarch
NetworkManager-1.4.4-3.fc25.s390x
glibc-static-2.24-4.fc25.s390x
boost-random-1.60.0-10.fc25.s390x
libref_array-0.1.5-29.fc25.s390x
libXrender-devel-0.9.10-1.fc25.s390x
javapackages-tools-4.7.0-6.1.fc25.noarch
keyutils-1.5.9-8.fc24.s390x
libcom_err-devel-1.43.3-1.fc25.s390x
graphite2-devel-1.3.6-1.fc25.s390x
lzo-minilzo-2.08-8.fc24.s390x
libusbx-devel-1.0.21-1.fc25.s390x
virglrenderer-devel-0.5.0-1.20160411git61846f92f.fc25.s390x
acpica-tools-20160831-1.fc25.s390x
grep-2.27-2.fc25.s390x
dnf-conf-1.1.10-6.fc25.noarch
crypto-policies-20160921-4.gitf3018dd.fc25.noarch
rpm-build-libs-4.13.0.1-1.fc25.s390x
libnfsidmap-0.27-1.fc25.s390x
systemtap-devel-3.1-2.fc25.s390x
systemd-231-14.fc25.s390x
SDL2-2.0.5-3.fc25.s390x
texlive-etex-pkg-svn39355-33.fc25.1.noarch
texlive-multido-svn18302.1.42-33.fc25.1.noarch
texlive-gsftopk-svn40768-33.fc25.1.noarch
texlive-pst-ovl-svn40873-33.fc25.1.noarch
texlive-ltabptch-svn17533.1.74d-33.fc25.1.noarch
texlive-cite-svn36428.5.5-33.fc25.1.noarch
texlive-fpl-svn15878.1.002-33.fc25.1.noarch
texlive-mathpazo-svn15878.1.003-33.fc25.1.noarch
texlive-rcs-svn15878.0-33.fc25.1.noarch
texlive-type1cm-svn21820.0-33.fc25.1.noarch
texlive-l3kernel-svn41246-33.fc25.1.noarch
texlive-hyperref-svn41396-33.fc25.1.noarch
texlive-pst-tree-svn24142.1.12-33.fc25.1.noarch
texlive-sansmathaccent-svn30187.0-33.fc25.1.noarch
texlive-dvipdfmx-bin-svn40273-33.20160520.fc25.1.s390x
texlive-zapfchan-svn31835.0-33.fc25.1.noarch
firewalld-0.4.4.4-1.fc25.noarch
glib2-static-2.50.3-1.fc25.s390x
libmicrohttpd-0.9.52-3.fc25.s390x
perl-open-1.10-385.fc25.noarch
bash-completion-2.5-1.fc25.noarch
libsolv-0.6.26-3.fc25.s390x
ghostscript-core-9.20-7.fc25.s390x
nss-util-devel-3.29.3-1.1.fc25.s390x
kernel-headers-4.10.8-200.fc25.s390x
system-python-3.5.3-4.fc25.s390x
iproute-tc-4.10.0-1.fc25.s390x
audit-2.7.4-1.fc25.s390x
gpg-pubkey-a29cb19c-53bcbba6
m4-1.4.17-9.fc24.s390x
liblockfile-1.09-4.fc24.s390x
sg3_utils-1.41-3.fc24.s390x
libXinerama-1.1.3-6.fc24.s390x
libXft-2.3.2-4.fc24.s390x
tcp_wrappers-libs-7.6-83.fc25.s390x
perl-Text-Tabs+Wrap-2013.0523-365.fc25.noarch
perl-Error-0.17024-7.fc25.noarch
perl-Term-Cap-1.17-365.fc25.noarch
perl-Pod-Usage-1.69-1.fc25.noarch
device-mapper-persistent-data-0.6.3-1.fc25.s390x
net-snmp-libs-5.7.3-13.fc25.s390x
libgusb-0.2.9-1.fc25.s390x
python3-six-1.10.0-3.fc25.noarch
python3-pysocks-1.5.6-5.fc25.noarch
python-chardet-2.3.0-1.fc25.noarch
python2-cffi-1.7.0-2.fc25.s390x
gc-devel-7.4.4-1.fc25.s390x
plymouth-0.9.3-0.6.20160620git0e65b86c.fc25.s390x
ebtables-2.0.10-21.fc25.s390x
python3-librepo-1.7.18-3.fc25.s390x
net-snmp-5.7.3-13.fc25.s390x
at-spi2-atk-2.22.0-1.fc25.s390x
avahi-autoipd-0.6.32-4.fc25.s390x
libcrypt-nss-2.24-4.fc25.s390x
libgo-6.3.1-1.fc25.s390x
cpp-6.3.1-1.fc25.s390x
glibc-devel-2.24-4.fc25.s390x
emacs-25.1-3.fc25.s390x
pyparsing-2.1.10-1.fc25.noarch
libproxy-0.4.14-1.fc25.s390x
python3-pyparsing-2.1.10-1.fc25.noarch
libcollection-0.7.0-29.fc25.s390x
libcephfs-devel-10.2.4-2.fc25.s390x
libXdamage-devel-1.1.4-8.fc24.s390x
libverto-devel-0.2.6-6.fc24.s390x
snappy-1.1.3-2.fc24.s390x
cairo-gobject-devel-1.14.8-1.fc25.s390x
cyrus-sasl-devel-2.1.26-26.2.fc24.s390x
kernel-devel-4.9.5-200.fc25.s390x
libXi-1.7.9-1.fc25.s390x
distribution-gpg-keys-1.11-1.fc25.noarch
texlive-base-2016-33.20160520.fc25.noarch
gstreamer1-1.10.4-1.fc25.s390x
python3-rpm-4.13.0.1-1.fc25.s390x
systemtap-runtime-3.1-2.fc25.s390x
perl-SelfLoader-1.23-385.fc25.noarch
bind99-license-9.9.9-4.P6.fc25.noarch
texlive-booktabs-svn40846-33.fc25.1.noarch
texlive-lm-svn28119.2.004-33.fc25.1.noarch
texlive-gsftopk-bin-svn40473-33.20160520.fc25.1.s390x
texlive-tex-svn40793-33.fc25.1.noarch
texlive-fancyref-svn15878.0.9c-33.fc25.1.noarch
texlive-chngcntr-svn17157.1.0a-33.fc25.1.noarch
texlive-fix2col-svn38770-33.fc25.1.noarch
texlive-marginnote-svn41382-33.fc25.1.noarch
texlive-pxfonts-svn15878.0-33.fc25.1.noarch
texlive-txfonts-svn15878.0-33.fc25.1.noarch
texlive-l3packages-svn41246-33.fc25.1.noarch
texlive-oberdiek-svn41346-33.fc25.1.noarch
texlive-pst-tools-svn34067.0.05-33.fc25.1.noarch
texlive-tex-gyre-svn18651.2.004-33.fc25.1.noarch
texlive-dvipdfmx-svn41149-33.fc25.1.noarch
texlive-collection-fontsrecommended-svn35830.0-33.20160520.fc25.1.noarch
gnutls-devel-3.5.10-1.fc25.s390x
libcacard-devel-2.5.3-1.fc25.s390x
selinux-policy-targeted-3.13.1-225.11.fc25.noarch
ykpers-1.18.0-2.fc25.s390x
python2-idna-2.5-1.fc25.noarch
dbus-libs-1.11.12-1.fc25.s390x
ghostscript-x11-9.20-7.fc25.s390x
vim-minimal-8.0.514-1.fc25.s390x
libdrm-devel-2.4.77-1.fc25.s390x
file-libs-5.29-4.fc25.s390x
gtk3-devel-3.22.11-1.fc25.s390x
policycoreutils-2.5-20.fc25.s390x
python-async-0.6.1-9.fc22.s390x
dejavu-sans-mono-fonts-2.35-3.fc24.noarch
popt-1.16-7.fc24.s390x
cyrus-sasl-lib-2.1.26-26.2.fc24.s390x
xz-5.2.2-2.fc24.s390x
libpipeline-1.4.1-2.fc24.s390x
pinentry-0.9.7-2.fc24.s390x
pth-2.0.7-27.fc24.s390x
libsepol-2.5-10.fc25.s390x
sqlite-libs-3.14.2-1.fc25.s390x
libxcb-1.12-1.fc25.s390x
libicu-57.1-4.fc25.s390x
perl-Getopt-Long-2.49.1-1.fc25.noarch
avahi-glib-0.6.32-4.fc25.s390x
python3-pip-8.1.2-2.fc25.noarch
python3-libcomps-0.1.7-5.fc25.s390x
python-slip-0.6.4-4.fc25.noarch
python2-libcomps-0.1.7-5.fc25.s390x
gc-7.4.4-1.fc25.s390x
s390utils-cmsfs-1.36.0-1.fc25.s390x
newt-python-0.52.19-2.fc25.s390x
valgrind-3.12.0-1.fc25.s390x
emacs-filesystem-25.1-3.fc25.noarch
libdb-utils-5.3.28-16.fc25.s390x
qt5-srpm-macros-5.7.1-1.fc25.noarch
elfutils-default-yama-scope-0.168-1.fc25.noarch
device-mapper-event-1.02.136-3.fc25.s390x
perl-Class-Inspector-1.31-2.fc25.noarch
poppler-0.45.0-2.fc25.s390x
libbasicobjects-0.1.1-29.fc25.s390x
libradosstriper1-10.2.4-2.fc25.s390x
libXxf86vm-devel-1.1.4-3.fc24.s390x
gsm-1.0.16-1.fc25.s390x
zziplib-0.13.62-7.fc24.s390x
libpaper-1.1.24-12.fc24.s390x
libini_config-1.3.0-29.fc25.s390x
snappy-devel-1.1.3-2.fc24.s390x
libcap-ng-devel-0.7.8-1.fc25.s390x
libxkbcommon-devel-0.7.1-1.fc25.s390x
kernel-4.9.5-200.fc25.s390x
nss-softokn-3.29.3-1.0.fc25.s390x
openssl-libs-1.0.2k-1.fc25.s390x
libkadm5-1.14.4-7.fc25.s390x
rpm-libs-4.13.0.1-1.fc25.s390x
perl-5.24.1-385.fc25.s390x
util-linux-2.28.2-2.fc25.s390x
libICE-1.0.9-8.fc25.s390x
texlive-etoolbox-svn38031.2.2a-33.fc25.1.noarch
texlive-dvips-svn41149-33.fc25.1.noarch
texlive-latexconfig-svn40274-33.fc25.1.noarch
texlive-tex-ini-files-svn40533-33.fc25.1.noarch
texlive-qstest-svn15878.0-33.fc25.1.noarch
texlive-cmap-svn41168-33.fc25.1.noarch
texlive-luatex-bin-svn41091-33.20160520.fc25.1.s390x
texlive-mflogo-svn38628-33.fc25.1.noarch
texlive-sansmath-svn17997.1.1-33.fc25.1.noarch
texlive-unicode-data-svn39808-33.fc25.1.noarch
texlive-luaotfload-bin-svn34647.0-33.20160520.fc25.1.noarch
texlive-listings-svn37534.1.6-33.fc25.1.noarch
texlive-pstricks-svn41321-33.fc25.1.noarch
texlive-metalogo-svn18611.0.12-33.fc25.1.noarch
texlive-collection-latex-svn41011-33.20160520.fc25.1.noarch
kernel-4.10.5-200.fc25.s390x
python2-dnf-plugins-core-0.1.21-5.fc25.noarch
xkeyboard-config-2.20-2.fc25.noarch
nss-util-3.29.3-1.1.fc25.s390x
dbus-1.11.12-1.fc25.s390x
ghostscript-9.20-7.fc25.s390x
vim-filesystem-8.0.514-1.fc25.s390x
jasper-libs-1.900.13-3.fc25.s390x
file-5.29-4.fc25.s390x
curl-7.51.0-6.fc25.s390x
perl-Test-Harness-3.39-1.fc25.noarch
libattr-2.4.47-16.fc24.s390x
acl-2.2.52-11.fc24.s390x
libvisual-0.4.0-20.fc24.s390x
libpcap-1.7.4-2.fc24.s390x
libutempter-1.1.6-8.fc24.s390x
libgudev-230-3.fc24.s390x
popt-devel-1.16-7.fc24.s390x
make-4.1-5.fc24.s390x
hicolor-icon-theme-0.15-3.fc24.noarch
setup-2.10.4-1.fc25.noarch
bash-4.3.43-4.fc25.s390x
nspr-4.13.1-1.fc25.s390x
libjpeg-turbo-1.5.1-0.fc25.s390x
perl-Socket-2.024-1.fc25.s390x
perl-HTTP-Tiny-0.070-1.fc25.noarch
ipset-6.29-1.fc25.s390x
python2-setuptools-25.1.1-1.fc25.noarch
gsettings-desktop-schemas-3.22.0-1.fc25.s390x
python3-setuptools-25.1.1-1.fc25.noarch
python-slip-dbus-0.6.4-4.fc25.noarch
python2-ply-3.8-2.fc25.noarch
dtc-1.4.2-1.fc25.s390x
guile-2.0.13-1.fc25.s390x
cronie-anacron-1.5.1-2.fc25.s390x
libXtst-1.2.3-1.fc25.s390x
iso-codes-3.70-1.fc25.noarch
s390utils-1.36.0-1.fc25.s390x
python-backports-ssl_match_hostname-3.5.0.1-3.fc25.noarch
fedora-cert-0.6.0.1-1.fc25.noarch
libstdc++-6.3.1-1.fc25.s390x
subversion-libs-1.9.5-1.fc25.s390x
libgfortran-6.3.1-1.fc25.s390x
libtasn1-4.10-1.fc25.s390x
dnf-plugin-system-upgrade-0.7.1-4.fc25.noarch
lvm2-2.02.167-3.fc25.s390x
libselinux-devel-2.5-13.fc25.s390x
perl-Time-Local-1.250-1.fc25.noarch
libtirpc-1.0.1-3.rc3.fc25.s390x
libradosstriper-devel-10.2.4-2.fc25.s390x
flac-libs-1.3.2-1.fc25.s390x
perl-Digest-1.17-366.fc25.noarch
teckit-2.5.1-15.fc24.s390x
libpath_utils-0.2.1-29.fc25.s390x
attr-2.4.47-16.fc24.s390x
usbredir-0.7.1-2.fc24.s390x
cairo-devel-1.14.8-1.fc25.s390x
lzo-devel-2.08-8.fc24.s390x
libcap-devel-2.25-2.fc25.s390x
opus-1.1.3-2.fc25.s390x
firewalld-filesystem-0.4.4.4-1.fc25.noarch
coreutils-8.25-16.fc25.s390x
krb5-devel-1.14.4-7.fc25.s390x
rpm-4.13.0.1-1.fc25.s390x
kernel-devel-4.10.5-200.fc25.s390x
systemd-pam-231-14.fc25.s390x
libbsd-0.8.3-1.fc25.s390x
texlive-url-svn32528.3.4-33.fc25.1.noarch
texlive-dvips-bin-svn40987-33.20160520.fc25.1.s390x
texlive-index-svn24099.4.1beta-33.fc25.1.noarch
texlive-setspace-svn24881.6.7a-33.fc25.1.noarch
texlive-mathtools-svn38833-33.fc25.1.noarch
texlive-cm-svn32865.0-33.fc25.1.noarch
texlive-graphics-def-svn41879-33.fc25.1.noarch
texlive-mdwtools-svn15878.1.05.4-33.fc25.1.noarch
texlive-rsfs-svn15878.0-33.fc25.1.noarch
texlive-ucharcat-svn38907-33.fc25.1.noarch
texlive-fontspec-svn41262-33.fc25.1.noarch
texlive-showexpl-svn32737.v0.3l-33.fc25.1.noarch
texlive-pstricks-add-svn40744-33.fc25.1.noarch
texlive-beamer-svn36461.3.36-33.fc25.1.noarch
texlive-collection-basic-svn41149-33.20160520.fc25.1.noarch
mock-1.3.4-1.fc25.noarch
rpm-build-4.13.0.1-1.fc25.s390x
xemacs-filesystem-21.5.34-20.20170124hgf412e9f093d4.fc25.noarch
nss-sysinit-3.29.3-1.1.fc25.s390x
hawkey-0.6.4-3.fc25.s390x
mesa-libGLES-13.0.4-3.fc25.s390x
vim-common-8.0.514-1.fc25.s390x
gdk-pixbuf2-modules-2.36.6-1.fc25.s390x
bluez-libs-5.44-1.fc25.s390x
libcurl-devel-7.51.0-6.fc25.s390x
mc-4.8.19-1.fc25.s390x
gpg-pubkey-a0a7badb-52844296
readline-6.3-8.fc24.s390x
cpio-2.12-3.fc24.s390x
qrencode-libs-3.4.2-6.fc24.s390x
libXcomposite-0.4.4-8.fc24.s390x
procps-ng-3.3.10-11.fc24.s390x
GConf2-3.2.6-16.fc24.s390x
xz-devel-5.2.2-2.fc24.s390x
fedora-logos-22.0.0-3.fc24.s390x
gpg-pubkey-e372e838-56fd7943
kmod-libs-23-1.fc25.s390x
perl-parent-0.236-1.fc25.noarch
perl-TermReadKey-2.37-1.fc25.s390x
dhcp-libs-4.3.5-1.fc25.s390x
ncurses-c++-libs-6.0-6.20160709.fc25.s390x
gzip-1.8-1.fc25.s390x
python3-gobject-base-3.22.0-1.fc25.s390x
python2-yubico-1.3.2-3.fc25.noarch
s390utils-ziomon-1.36.0-1.fc25.s390x
librepo-1.7.18-3.fc25.s390x
librsvg2-2.40.16-2.fc25.s390x
gnat-srpm-macros-4-1.fc25.noarch
python-decoratortools-1.8-12.fc25.noarch
m17n-db-1.7.0-7.fc25.noarch
glibc-common-2.24-4.fc25.s390x
e2fsprogs-libs-1.43.3-1.fc25.s390x
libvorbis-1.3.5-1.fc25.s390x
gcc-gdb-plugin-6.3.1-1.fc25.s390x
perl-Time-HiRes-1.9741-1.fc25.s390x
npth-1.3-1.fc25.s390x
libcephfs1-10.2.4-2.fc25.s390x
wayland-devel-1.12.0-1.fc25.s390x
libxcb-devel-1.12-1.fc25.s390x
perl-encoding-2.19-5.fc25.s390x
python3-cssselect-0.9.2-1.fc25.noarch
gettext-libs-0.19.8.1-3.fc25.s390x
at-spi2-atk-devel-2.22.0-1.fc25.s390x
virglrenderer-0.5.0-1.20160411git61846f92f.fc25.s390x
pixman-devel-0.34.0-2.fc24.s390x
libnfs-devel-1.9.8-2.fc24.s390x
libX11-common-1.6.4-4.fc25.noarch
nss-softokn-devel-3.29.3-1.0.fc25.s390x
libblkid-2.28.2-2.fc25.s390x
bind-libs-9.10.4-4.P6.fc25.s390x
glib2-devel-2.50.3-1.fc25.s390x
systemd-udev-231-14.fc25.s390x
texlive-ifxetex-svn19685.0.5-33.fc25.1.noarch
texlive-caption-svn41409-33.fc25.1.noarch
texlive-float-svn15878.1.3d-33.fc25.1.noarch
texlive-pdftex-def-svn22653.0.06d-33.fc25.1.noarch
texlive-xdvi-bin-svn40750-33.20160520.fc25.1.s390x
texlive-beton-svn15878.0-33.fc25.1.noarch
texlive-filecontents-svn24250.1.3-33.fc25.1.noarch
texlive-lm-math-svn36915.1.959-33.fc25.1.noarch
texlive-pslatex-svn16416.0-33.fc25.1.noarch
texlive-times-svn35058.0-33.fc25.1.noarch
texlive-breakurl-svn29901.1.40-33.fc25.1.noarch
texlive-filehook-svn24280.0.5d-33.fc25.1.noarch
texlive-pst-pdf-svn31660.1.1v-33.fc25.1.noarch
texlive-seminar-svn34011.1.62-33.fc25.1.noarch
texlive-xetexconfig-svn41133-33.fc25.1.noarch
systemtap-3.1-2.fc25.s390x
python-rpm-macros-3-12.fc25.noarch
rpm-devel-4.13.0.1-1.fc25.s390x
nss-pem-1.0.3-3.fc25.s390x
mesa-libGL-13.0.4-3.fc25.s390x
at-spi2-core-2.22.1-1.fc25.s390x
pcre2-utf32-10.23-5.fc25.s390x
gtk3-3.22.11-1.fc25.s390x
GeoIP-GeoLite-data-2017.04-1.fc25.noarch
pcre-static-8.40-6.fc25.s390x
kernel-devel-4.10.8-200.fc25.s390x
=== TEST BEGIN ===
Using CC: /home/fam/bin/cc
Install prefix /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install
BIOS directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/share/qemu
binary directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/bin
library directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/lib
module directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/lib/qemu
libexec directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/libexec
include directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/include
config directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/etc
local state directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/var
Manual directory /var/tmp/patchew-tester-tmp-cbg9pgnx/src/install/share/man
ELF interp prefix /usr/gnemul/qemu-%M
Source path /var/tmp/patchew-tester-tmp-cbg9pgnx/src
C compiler /home/fam/bin/cc
Host C compiler cc
C++ compiler c++
Objective-C compiler /home/fam/bin/cc
ARFLAGS rv
CFLAGS -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -g
QEMU_CFLAGS -I/usr/include/pixman-1 -Werror -DHAS_LIBSSH2_SFTP_FSYNC -pthread -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -DNCURSES_WIDECHAR -D_GNU_SOURCE -m64 -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/include/p11-kit-1 -I/usr/include/libpng16 -I/usr/include/libdrm -I/usr/include/cacard -I/usr/include/nss3 -I/usr/include/nspr4 -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/libusb-1.0
LDFLAGS -Wl,--warn-common -m64 -g
make make
install install
python python -B
smbd /usr/sbin/smbd
module support no
host CPU s390x
host big endian yes
target list aarch64-softmmu alpha-softmmu arm-softmmu cris-softmmu i386-softmmu lm32-softmmu m68k-softmmu microblazeel-softmmu microblaze-softmmu mips64el-softmmu mips64-softmmu mipsel-softmmu mips-softmmu moxie-softmmu nios2-softmmu or1k-softmmu ppc64-softmmu ppcemb-softmmu ppc-softmmu s390x-softmmu sh4eb-softmmu sh4-softmmu sparc64-softmmu sparc-softmmu tricore-softmmu unicore32-softmmu x86_64-softmmu xtensaeb-softmmu xtensa-softmmu aarch64-linux-user alpha-linux-user armeb-linux-user arm-linux-user cris-linux-user hppa-linux-user i386-linux-user m68k-linux-user microblazeel-linux-user microblaze-linux-user mips64el-linux-user mips64-linux-user mipsel-linux-user mips-linux-user mipsn32el-linux-user mipsn32-linux-user nios2-linux-user or1k-linux-user ppc64abi32-linux-user ppc64le-linux-user ppc64-linux-user ppc-linux-user s390x-linux-user sh4eb-linux-user sh4-linux-user sparc32plus-linux-user sparc64-linux-user sparc-linux-user tilegx-linux-user x86_64-linux-user
gprof enabled no
sparse enabled no
strip binaries yes
profiler no
static build no
pixman system
SDL support yes (2.0.5)
GTK support yes (3.22.11)
GTK GL support yes
VTE support yes (0.46.1)
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 yes
virgl support yes
curl support yes
mingw32 support no
Audio drivers oss
Block whitelist (rw)
Block whitelist (ro)
VirtFS support yes
VNC support yes
VNC SASL support yes
VNC JPEG support yes
VNC PNG support yes
xen support no
brlapi support yes
bluez support yes
Documentation yes
PIE no
vde support no
netmap support no
Linux AIO support yes
ATTR/XATTR support yes
Install blobs yes
KVM support yes
HAX support no
TCG support yes
TCG debug enabled no
TCG interpreter no
RDMA support no
fdt support yes
preadv support yes
fdatasync yes
madvise yes
posix_madvise yes
libcap-ng support yes
vhost-net support yes
vhost-scsi support yes
vhost-vsock support yes
Trace backends log
spice support no
rbd support yes
xfsctl support no
smartcard support yes
libusb yes
usb net redir yes
OpenGL support yes
OpenGL dmabufs yes
libiscsi support yes
libnfs support yes
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 yes
gcov gcov
gcov enabled no
TPM support yes
libssh2 support yes
TPM passthrough no
TPM emulator yes
QOM debugging yes
Live block migration yes
lzo support yes
snappy support yes
bzip2 support yes
NUMA host support no
tcmalloc support no
jemalloc support no
avx2 optimization no
replication support yes
VxHS block device no
GEN aarch64-softmmu/config-devices.mak.tmp
GEN alpha-softmmu/config-devices.mak.tmp
GEN arm-softmmu/config-devices.mak.tmp
GEN cris-softmmu/config-devices.mak.tmp
GEN cris-softmmu/config-devices.mak
GEN i386-softmmu/config-devices.mak.tmp
GEN alpha-softmmu/config-devices.mak
GEN arm-softmmu/config-devices.mak
GEN lm32-softmmu/config-devices.mak.tmp
GEN m68k-softmmu/config-devices.mak.tmp
GEN aarch64-softmmu/config-devices.mak
GEN microblazeel-softmmu/config-devices.mak.tmp
GEN i386-softmmu/config-devices.mak
GEN m68k-softmmu/config-devices.mak
GEN lm32-softmmu/config-devices.mak
GEN microblaze-softmmu/config-devices.mak.tmp
GEN mips64el-softmmu/config-devices.mak.tmp
GEN mips64-softmmu/config-devices.mak.tmp
GEN microblazeel-softmmu/config-devices.mak
GEN microblaze-softmmu/config-devices.mak
GEN mipsel-softmmu/config-devices.mak.tmp
GEN mips-softmmu/config-devices.mak.tmp
GEN mips64-softmmu/config-devices.mak
GEN moxie-softmmu/config-devices.mak.tmp
GEN mips64el-softmmu/config-devices.mak
GEN nios2-softmmu/config-devices.mak.tmp
GEN mipsel-softmmu/config-devices.mak
GEN moxie-softmmu/config-devices.mak
GEN or1k-softmmu/config-devices.mak.tmp
GEN mips-softmmu/config-devices.mak
GEN ppc64-softmmu/config-devices.mak.tmp
GEN ppcemb-softmmu/config-devices.mak.tmp
GEN nios2-softmmu/config-devices.mak
GEN or1k-softmmu/config-devices.mak
GEN s390x-softmmu/config-devices.mak.tmp
GEN ppc-softmmu/config-devices.mak.tmp
GEN ppc64-softmmu/config-devices.mak
GEN s390x-softmmu/config-devices.mak
GEN sh4eb-softmmu/config-devices.mak.tmp
GEN ppcemb-softmmu/config-devices.mak
GEN sh4-softmmu/config-devices.mak.tmp
GEN ppc-softmmu/config-devices.mak
GEN sparc64-softmmu/config-devices.mak.tmp
GEN sparc-softmmu/config-devices.mak.tmp
GEN sh4eb-softmmu/config-devices.mak
GEN sparc-softmmu/config-devices.mak
GEN sparc64-softmmu/config-devices.mak
GEN tricore-softmmu/config-devices.mak.tmp
GEN sh4-softmmu/config-devices.mak
GEN unicore32-softmmu/config-devices.mak.tmp
GEN x86_64-softmmu/config-devices.mak.tmp
GEN xtensaeb-softmmu/config-devices.mak.tmp
GEN tricore-softmmu/config-devices.mak
GEN xtensa-softmmu/config-devices.mak.tmp
GEN unicore32-softmmu/config-devices.mak
GEN xtensaeb-softmmu/config-devices.mak
GEN aarch64-linux-user/config-devices.mak.tmp
GEN alpha-linux-user/config-devices.mak.tmp
GEN xtensa-softmmu/config-devices.mak
GEN x86_64-softmmu/config-devices.mak
GEN armeb-linux-user/config-devices.mak.tmp
GEN alpha-linux-user/config-devices.mak
GEN arm-linux-user/config-devices.mak.tmp
GEN aarch64-linux-user/config-devices.mak
GEN cris-linux-user/config-devices.mak.tmp
GEN hppa-linux-user/config-devices.mak.tmp
GEN armeb-linux-user/config-devices.mak
GEN arm-linux-user/config-devices.mak
GEN i386-linux-user/config-devices.mak.tmp
GEN m68k-linux-user/config-devices.mak.tmp
GEN hppa-linux-user/config-devices.mak
GEN cris-linux-user/config-devices.mak
GEN microblazeel-linux-user/config-devices.mak.tmp
GEN microblaze-linux-user/config-devices.mak.tmp
GEN i386-linux-user/config-devices.mak
GEN m68k-linux-user/config-devices.mak
GEN mips64el-linux-user/config-devices.mak.tmp
GEN microblazeel-linux-user/config-devices.mak
GEN mips64-linux-user/config-devices.mak.tmp
GEN mipsel-linux-user/config-devices.mak.tmp
GEN microblaze-linux-user/config-devices.mak
GEN mips-linux-user/config-devices.mak.tmp
GEN mips64el-linux-user/config-devices.mak
GEN mips64-linux-user/config-devices.mak
GEN mipsel-linux-user/config-devices.mak
GEN mipsn32el-linux-user/config-devices.mak.tmp
GEN mipsn32-linux-user/config-devices.mak.tmp
GEN nios2-linux-user/config-devices.mak.tmp
GEN mips-linux-user/config-devices.mak
GEN or1k-linux-user/config-devices.mak.tmp
GEN mipsn32el-linux-user/config-devices.mak
GEN mipsn32-linux-user/config-devices.mak
GEN nios2-linux-user/config-devices.mak
GEN ppc64abi32-linux-user/config-devices.mak.tmp
GEN ppc64le-linux-user/config-devices.mak.tmp
GEN ppc64-linux-user/config-devices.mak.tmp
GEN or1k-linux-user/config-devices.mak
GEN ppc64abi32-linux-user/config-devices.mak
GEN ppc64le-linux-user/config-devices.mak
GEN s390x-linux-user/config-devices.mak.tmp
GEN ppc-linux-user/config-devices.mak.tmp
GEN ppc64-linux-user/config-devices.mak
GEN sh4eb-linux-user/config-devices.mak.tmp
GEN sh4-linux-user/config-devices.mak.tmp
GEN s390x-linux-user/config-devices.mak
GEN ppc-linux-user/config-devices.mak
GEN sparc32plus-linux-user/config-devices.mak.tmp
GEN sh4eb-linux-user/config-devices.mak
GEN sparc64-linux-user/config-devices.mak.tmp
GEN sh4-linux-user/config-devices.mak
GEN sparc-linux-user/config-devices.mak.tmp
GEN tilegx-linux-user/config-devices.mak.tmp
GEN sparc32plus-linux-user/config-devices.mak
GEN sparc64-linux-user/config-devices.mak
GEN x86_64-linux-user/config-devices.mak.tmp
GEN sparc-linux-user/config-devices.mak
GEN tilegx-linux-user/config-devices.mak
GEN config-host.h
GEN qemu-options.def
GEN x86_64-linux-user/config-devices.mak
GEN qmp-commands.h
GEN qapi-types.h
GEN qapi-visit.h
GEN qapi-event.h
GEN qmp-marshal.c
GEN qapi-types.c
GEN qapi-event.c
GEN qapi-visit.c
GEN qmp-introspect.h
GEN qmp-introspect.c
GEN trace/generated-tcg-tracers.h
GEN trace/generated-helpers-wrappers.h
GEN trace/generated-helpers.h
GEN module_block.h
GEN trace/generated-helpers.c
GEN 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 chardev/trace.h
GEN hw/block/trace.h
GEN hw/block/dataplane/trace.h
GEN hw/char/trace.h
GEN hw/intc/trace.h
GEN hw/net/trace.h
GEN hw/virtio/trace.h
GEN hw/audio/trace.h
GEN hw/misc/trace.h
GEN hw/usb/trace.h
GEN hw/scsi/trace.h
GEN hw/nvram/trace.h
GEN hw/display/trace.h
GEN hw/input/trace.h
GEN hw/dma/trace.h
GEN hw/timer/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 accel/tcg/trace.h
GEN accel/kvm/trace.h
GEN trace-root.c
GEN nbd/trace.h
GEN util/trace.c
GEN crypto/trace.c
GEN io/trace.c
GEN migration/trace.c
GEN block/trace.c
GEN chardev/trace.c
GEN hw/block/trace.c
GEN hw/block/dataplane/trace.c
GEN hw/char/trace.c
GEN hw/intc/trace.c
GEN hw/net/trace.c
GEN hw/virtio/trace.c
GEN hw/audio/trace.c
GEN hw/misc/trace.c
GEN hw/usb/trace.c
GEN hw/scsi/trace.c
GEN hw/nvram/trace.c
GEN hw/display/trace.c
GEN hw/input/trace.c
GEN hw/timer/trace.c
GEN hw/dma/trace.c
GEN hw/sparc/trace.c
GEN hw/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 accel/tcg/trace.c
GEN accel/kvm/trace.c
GEN nbd/trace.c
GEN config-all-devices.mak
GEN docs/version.texi
GEN qemu-options.texi
GEN qemu-img-cmds.texi
CC tests/qemu-iotests/socket_scm_helper.o
GEN qemu-monitor.texi
GEN qemu-monitor-info.texi
GEN qemu-img.1
GEN qemu-nbd.8
GEN qemu-ga.8
GEN docs/interop/qemu-qmp-qapi.texi
GEN fsdev/virtfs-proxy-helper.1
GEN docs/interop/qemu-ga-qapi.texi
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
GEN qga/qapi-generated/qga-qapi-visit.c
GEN qga/qapi-generated/qga-qmp-marshal.c
CC qmp-introspect.o
CC qapi-types.o
CC qapi-visit.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/qnum.o
CC qobject/qstring.o
CC qobject/qdict.o
CC qobject/qlist.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/module.o
CC util/path.o
CC util/host-utils.o
CC util/bitmap.o
CC util/bitops.o
CC util/hbitmap.o
CC util/fifo8.o
CC util/acl.o
CC util/cacheinfo.o
CC util/error.o
CC util/qemu-error.o
CC util/id.o
CC util/iov.o
CC util/qemu-config.o
CC util/qemu-sockets.o
CC util/uri.o
CC util/notify.o
CC util/qemu-progress.o
CC util/qemu-option.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/buffer.o
CC util/timed-average.o
CC util/base64.o
CC util/log.o
CC util/qht.o
CC util/qdist.o
CC util/range.o
CC util/stats64.o
CC util/systemd.o
CC trace-root.o
CC util/trace.o
CC crypto/trace.o
CC io/trace.o
CC migration/trace.o
CC block/trace.o
CC chardev/trace.o
CC hw/block/trace.o
CC hw/block/dataplane/trace.o
CC hw/char/trace.o
CC hw/intc/trace.o
CC hw/net/trace.o
CC hw/virtio/trace.o
CC hw/audio/trace.o
CC hw/misc/trace.o
CC hw/usb/trace.o
CC hw/scsi/trace.o
CC hw/nvram/trace.o
CC hw/display/trace.o
CC hw/input/trace.o
CC hw/timer/trace.o
CC hw/dma/trace.o
CC hw/sparc/trace.o
CC hw/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 accel/tcg/trace.o
CC accel/kvm/trace.o
CC nbd/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/linux-aio.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/slirp.o
CC stubs/set-fd-handler.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-monitor-defs.o
CC stubs/target-get-monitor-def.o
CC stubs/pc_madt_cpu_entry.o
CC stubs/vmgenid.o
CC stubs/xen-common.o
CC stubs/xen-hvm.o
CC 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 qemu-io-cmds.o
CC blockjob.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/vpc.o
CC block/bochs.o
CC block/vvfat.o
CC block/dmg.o
CC block/qcow2.o
CC block/qcow2-refcount.o
CC block/qcow2-cluster.o
CC block/qcow2-snapshot.o
CC block/qcow2-cache.o
CC block/qcow2-bitmap.o
CC block/qed.o
CC block/qed-l2-cache.o
CC block/qed-table.o
CC block/qed-cluster.o
CC block/qed-check.o
CC block/vhdx.o
CC block/vhdx-endian.o
CC block/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/file-posix.o
CC block/qapi.o
CC block/linux-aio.o
CC block/mirror.o
CC block/null.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/iscsi-opts.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/iscsi.o
CC block/nfs.o
CC block/curl.o
CC block/rbd.o
CC block/gluster.o
CC block/ssh.o
CC crypto/init.o
CC block/dmg-bz2.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-plain64.o
CC crypto/ivgen-plain.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/container.o
CC qom/object.o
CC qom/qom-qobject.o
CC qom/object_interfaces.o
GEN qemu-img-cmds.h
CC qemu-io.o
CC fsdev/virtfs-proxy-helper.o
CC fsdev/9p-marshal.o
CC fsdev/9p-iov-marshal.o
CC qemu-bridge-helper.o
CC blockdev-nbd.o
CC blockdev.o
CC bootdevice.o
CC iothread.o
CC device-hotplug.o
CC qdev-monitor.o
CC os-posix.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/tpm.o
CC backends/hostmem.o
CC backends/hostmem-ram.o
CC backends/hostmem-file.o
CC backends/cryptodev.o
CC backends/cryptodev-builtin.o
CC block/stream.o
CC chardev/msmouse.o
CC chardev/wctablet.o
CC chardev/testdev.o
CC chardev/baum.o
CC disas/alpha.o
CC disas/arm.o
CXX disas/arm-a64.o
CC disas/cris.o
CC disas/hppa.o
CC disas/m68k.o
CC disas/i386.o
CC disas/microblaze.o
CC disas/mips.o
CC disas/nios2.o
CC disas/moxie.o
CC disas/ppc.o
CC disas/s390.o
CC disas/sh4.o
CC disas/sparc.o
CC disas/lm32.o
CXX disas/libvixl/vixl/utils.o
CXX disas/libvixl/vixl/compiler-intrinsics.o
CXX disas/libvixl/vixl/a64/instructions-a64.o
CXX disas/libvixl/vixl/a64/decoder-a64.o
CXX disas/libvixl/vixl/a64/disasm-a64.o
CC fsdev/qemu-fsdev.o
CC fsdev/qemu-fsdev-opts.o
CC fsdev/qemu-fsdev-throttle.o
CC fsdev/qemu-fsdev-dummy.o
CC hw/9pfs/9p.o
CC hw/9pfs/9p-util.o
CC hw/9pfs/9p-local.o
CC hw/9pfs/9p-xattr.o
CC hw/9pfs/9p-xattr-user.o
CC hw/9pfs/9p-posix-acl.o
CC hw/9pfs/coth.o
CC hw/9pfs/cofs.o
CC hw/9pfs/codir.o
CC hw/9pfs/cofile.o
CC hw/9pfs/coxattr.o
CC hw/9pfs/9p-synth.o
CC hw/9pfs/9p-handle.o
CC hw/9pfs/9p-proxy.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/cs4231.o
CC hw/audio/marvell_88w8618.o
CC hw/audio/milkymist-ac97.o
CC hw/audio/soundhw.o
CC hw/block/block.o
CC hw/block/cdrom.o
CC hw/block/hd-geometry.o
CC hw/block/fdc.o
CC hw/block/m25p80.o
CC hw/block/nand.o
CC hw/block/pflash_cfi01.o
CC hw/block/pflash_cfi02.o
CC hw/block/ecc.o
CC hw/block/onenand.o
CC hw/block/nvme.o
CC hw/bt/core.o
CC hw/bt/l2cap.o
CC hw/bt/sdp.o
CC hw/bt/hci.o
CC hw/bt/hid.o
CC hw/bt/hci-csr.o
CC hw/char/ipoctal232.o
CC hw/char/escc.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/xilinx_uartlite.o
CC hw/char/cadence_uart.o
CC hw/char/etraxfs_ser.o
CC hw/char/debugcon.o
CC hw/char/grlib_apbuart.o
CC hw/char/imx_serial.o
CC hw/char/lm32_juart.o
CC hw/char/lm32_uart.o
CC hw/char/milkymist-uart.o
CC hw/char/sclpconsole.o
CC hw/char/sclpconsole-lm.o
CC hw/core/qdev-properties.o
CC hw/core/qdev.o
CC hw/core/bus.o
CC hw/core/reset.o
CC hw/core/irq.o
CC hw/core/fw-path-provider.o
CC hw/core/hotplug.o
CC hw/core/nmi.o
CC hw/core/empty_slot.o
CC hw/core/stream.o
CC hw/core/ptimer.o
CC hw/core/sysbus.o
CC hw/core/machine.o
CC hw/core/loader-fit.o
CC hw/core/loader.o
CC hw/core/qdev-properties-system.o
CC hw/core/register.o
CC hw/core/or-irq.o
CC hw/core/platform-bus.o
CC hw/cpu/core.o
CC hw/display/ads7846.o
CC hw/display/cirrus_vga.o
CC hw/display/g364fb.o
CC hw/display/jazz_led.o
CC hw/display/pl110.o
CC hw/display/ssd0323.o
CC hw/display/ssd0303.o
CC hw/display/vga-pci.o
CC hw/display/vga-isa.o
CC hw/display/vga-isa-mm.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/milkymist-vgafb.o
CC hw/display/tc6393xb.o
CC hw/display/milkymist-tmu2.o
CC hw/dma/puv3_dma.o
CC hw/dma/rc4030.o
CC hw/dma/pl080.o
CC hw/dma/pl330.o
CC hw/dma/i82374.o
CC hw/dma/i8257.o
CC hw/dma/xilinx_axidma.o
CC hw/dma/xlnx-zynq-devcfg.o
CC hw/dma/etraxfs_dma.o
CC hw/dma/sparc32_dma.o
CC hw/dma/sun4m_iommu.o
CC hw/gpio/max7310.o
CC hw/gpio/pl061.o
CC hw/gpio/puv3_gpio.o
CC hw/gpio/zaurus.o
CC hw/gpio/mpc8xxx.o
CC hw/gpio/gpio_key.o
CC hw/i2c/smbus.o
CC hw/i2c/core.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/cmd646.o
CC hw/ide/macio.o
CC hw/ide/mmio.o
CC hw/ide/via.o
CC hw/ide/microdrive.o
CC hw/ide/ahci.o
CC hw/ide/ich.o
CC hw/input/adb.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/heathrow_pic.o
CC hw/intc/i8259.o
CC hw/intc/pl190.o
CC hw/intc/puv3_intc.o
CC hw/intc/xilinx_intc.o
CC hw/intc/etraxfs_pic.o
CC hw/intc/imx_avic.o
CC hw/intc/lm32_pic.o
CC hw/intc/realview_gic.o
CC hw/intc/slavio_intctl.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/openpic.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_extern.o
CC hw/ipmi/ipmi_bmc_sim.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/isa/i82378.o
CC hw/isa/pc87312.o
CC hw/isa/piix4.o
CC hw/isa/vt82c686.o
CC hw/mem/pc-dimm.o
CC hw/mem/nvdimm.o
CC hw/misc/applesmc.o
CC hw/misc/max111x.o
CC hw/misc/tmp105.o
CC hw/misc/tmp421.o
CC hw/misc/debugexit.o
CC hw/misc/sga.o
CC hw/misc/pc-testdev.o
CC hw/misc/pci-testdev.o
CC hw/misc/edu.o
CC hw/misc/unimp.o
CC hw/misc/arm_l2x0.o
CC hw/misc/arm_integrator_debug.o
CC hw/misc/a9scu.o
CC hw/misc/arm11scu.o
CC hw/misc/puv3_pm.o
CC hw/misc/macio/cuda.o
CC hw/misc/macio/macio.o
CC hw/misc/macio/mac_dbdma.o
CC hw/net/dp8393x.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/opencores_eth.o
CC hw/net/xgmac.o
CC hw/net/mipsnet.o
CC hw/net/xilinx_axienet.o
CC hw/net/imx_fec.o
CC hw/net/allwinner_emac.o
CC hw/net/cadence_gem.o
CC hw/net/stellaris_enet.o
CC hw/net/lance.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/ds1225y.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/nvram/mac_nvram.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-bridge/dec.o
CC hw/pci-host/pam.o
CC hw/pci-host/prep.o
CC hw/pci-host/grackle.o
CC hw/pci-host/uninorth.o
CC hw/pci-host/ppce500.o
CC hw/pci-host/versatile.o
CC hw/pci-host/bonito.o
CC hw/pci-host/apb.o
CC hw/pci-host/piix.o
CC hw/pci-host/q35.o
CC hw/pci-host/gpex.o
CC hw/pci-host/xilinx-pcie.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/xilinx_spi.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/m48t59.o
CC hw/timer/m48t59-isa.o
CC hw/timer/pl031.o
CC hw/timer/puv3_ost.o
CC hw/timer/twl92230.o
CC hw/timer/xilinx_timer.o
CC hw/timer/slavio_timer.o
CC hw/timer/etraxfs_timer.o
CC hw/timer/grlib_gptimer.o
CC hw/timer/imx_epit.o
CC hw/timer/imx_gpt.o
CC hw/timer/milkymist-sysctl.o
CC hw/timer/lm32_timer.o
CC hw/timer/stm32f2xx_timer.o
CC hw/timer/aspeed_timer.o
CC hw/tpm/tpm_tis.o
CC hw/timer/sun4v-rtc.o
CC hw/tpm/tpm_emulator.o
CC hw/tpm/tpm_util.o
CC hw/usb/core.o
CC hw/usb/combined-packet.o
CC hw/usb/bus.o
/var/tmp/patchew-tester-tmp-cbg9pgnx/src/hw/tpm/tpm_emulator.c: In function ‘tpm_emulator_block_migration’:
/var/tmp/patchew-tester-tmp-cbg9pgnx/src/hw/tpm/tpm_emulator.c:676:5: error: implicit declaration of function ‘migrate_add_blocker’ [-Werror=implicit-function-declaration]
migrate_add_blocker(tpm_pt->migration_blocker, &err);
^~~~~~~~~~~~~~~~~~~
/var/tmp/patchew-tester-tmp-cbg9pgnx/src/hw/tpm/tpm_emulator.c:676:5: error: nested extern declaration of ‘migrate_add_blocker’ [-Werror=nested-externs]
/var/tmp/patchew-tester-tmp-cbg9pgnx/src/hw/tpm/tpm_emulator.c: In function ‘tpm_emulator_inst_finalize’:
/var/tmp/patchew-tester-tmp-cbg9pgnx/src/hw/tpm/tpm_emulator.c:946:9: error: implicit declaration of function ‘migrate_del_blocker’ [-Werror=implicit-function-declaration]
migrate_del_blocker(tpm_pt->migration_blocker);
^~~~~~~~~~~~~~~~~~~
/var/tmp/patchew-tester-tmp-cbg9pgnx/src/hw/tpm/tpm_emulator.c:946:9: error: nested extern declaration of ‘migrate_del_blocker’ [-Werror=nested-externs]
cc1: all warnings being treated as errors
/var/tmp/patchew-tester-tmp-cbg9pgnx/src/rules.mak:66: recipe for target 'hw/tpm/tpm_emulator.o' failed
make: *** [hw/tpm/tpm_emulator.o] Error 1
make: *** Waiting for unfinished jobs....
=== 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] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 4/8] tpm-backend: Made few interface methods optional
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
@ 2017-07-18 10:15 ` Marc-André Lureau
2017-07-22 4:32 ` Amarnath Valluri
0 siblings, 1 reply; 26+ messages in thread
From: Marc-André Lureau @ 2017-07-18 10:15 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel; +Cc: stefanb
Hi
On Tue, Jul 18, 2017 at 10:48 AM Amarnath Valluri <
amarnath.valluri@intel.com> 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: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Stefan Berger<stefanb@linux.vnet.ibm.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(-)
>
LINK x86_64-softmmu/qemu-system-x86_64
../tpm.o: In function `qmp_query_tpm_inst':
/home/elmarco/src/qq/tpm.c:261: undefined reference to
`tpm_backend_get_type'
collect2: error: ld returned 1 exit status
> 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
>
>
> --
Marc-André Lureau
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
@ 2017-07-18 10:39 ` Marc-André Lureau
2017-07-18 14:28 ` Eric Blake
0 siblings, 1 reply; 26+ messages in thread
From: Marc-André Lureau @ 2017-07-18 10:39 UTC (permalink / raw)
To: Amarnath Valluri; +Cc: QEMU, Stefan Berger
Hi
On Tue, Jul 18, 2017 at 1:49 AM, Amarnath Valluri
<amarnath.valluri@intel.com> 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.
>
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.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 d970ea9..7a92e88 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -966,10 +966,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=" : "",
> @@ -977,7 +977,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:
I would actually use TPM_TYPE__MAX, so that missing cases can be
caught by compiler.
> 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;
"ops" usually refer to "operations" while "opts" is for options. But
to discard any doubt, please rename "options".
> 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;
One usually prefer to have the true case first.
> + } else {
> + tpm_pt->ops->has_path = true;
> }
>
> + tpm_pt->ops->path = g_strdup(value);
Interestingly, ops->path will be set even if ops->has_path = false. I
am not sure the visitors will handle that case properly (for visit or
dealloc etc). Could you set ops->has_path = true uncondtionnally?
> 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;
>
Shouldn't it also free cancel_path?
> 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;
> + }
> +
There is no check for small allocation failure elsewhere, I would drop that.
> + 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;
> + }
Same here
> + 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
>
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model Amarnath Valluri
@ 2017-07-18 10:50 ` Marc-André Lureau
0 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2017-07-18 10:50 UTC (permalink / raw)
To: Amarnath Valluri; +Cc: QEMU, Stefan Berger
On Tue, Jul 18, 2017 at 1:49 AM, 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: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.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
>
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 7/8] tpm-passthrough: move reusable code to utils
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
@ 2017-07-18 11:17 ` Marc-André Lureau
0 siblings, 0 replies; 26+ messages in thread
From: Marc-André Lureau @ 2017-07-18 11:17 UTC (permalink / raw)
To: Amarnath Valluri; +Cc: QEMU, Stefan Berger
On Tue, Jul 18, 2017 at 1:49 AM, Amarnath Valluri
<amarnath.valluri@intel.com> wrote:
> Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
> Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> ---
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.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 4ac47ed..592fd1f 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
>
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator Amarnath Valluri
@ 2017-07-18 12:08 ` Marc-André Lureau
2017-07-18 13:40 ` Stefan Berger
2017-07-22 4:52 ` Amarnath Valluri
2017-07-18 14:39 ` Stefan Berger
` (2 subsequent siblings)
3 siblings, 2 replies; 26+ messages in thread
From: Marc-André Lureau @ 2017-07-18 12:08 UTC (permalink / raw)
To: Amarnath Valluri; +Cc: QEMU, Stefan Berger
Hi
On Tue, Jul 18, 2017 at 1:49 AM, 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.
>
> 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
I am afraid this isn't enough yet.
> 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 \
We should rather follow the vhost-user pattern: do not deal with
spawning the external swtpm/backend, just use chardev to connect to
it. At least you don't have to deal with process argument details,
management etc that may change version to version.
-chardev socket,id=tpmdata,path=/path/to/socket
-chardev socket,id=tpmctrl,path=/path/to/socket
-tpmdev emulator,id=tpm0,ctrl-chardev=tpmctrl,data-chardev=tpmdata
I suppose the rest of the options were just passed to the emulator.
We may want to have a common way for qemu to spawn helpers with
socketpairs for communication, but I think this is best left for
later, when we identify common patterns. Unless qemu give that up to
the management layer / libvirt etc.
I still don't understand why the protocol would need 2 sockets... If
justified, this could be an protocol implementation details, and extra
socket pairs could be shared between client & server privately. This
would make usage & management easier.
I didn't take a close look at the rest of the patch, as I believe we
are not close to merge it yet, at least not for 2.10. But I intend to
once there is an agreement on the various design decisions.
> -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 | 973 ++++++++++++++++++++++++++++++++++++++++++++++++++
> hw/tpm/tpm_ioctl.h | 243 +++++++++++++
> qapi-schema.json | 41 ++-
> qemu-options.hx | 53 ++-
> tpm.c | 2 +-
> 8 files changed, 1339 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 a3f0522..fbf8bca 100755
> --- a/configure
> +++ b/configure
> @@ -3479,10 +3479,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
>
> ##########################################
> @@ -5306,6 +5311,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 "Live block migration $live_block_migration"
> echo "lzo support $lzo"
> @@ -5896,6 +5902,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 7a92e88..04916be 100644
> --- a/hmp.c
> +++ b/hmp.c
> @@ -948,6 +948,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) {
> @@ -977,6 +978,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..c90914c
> --- /dev/null
> +++ b/hw/tpm/tpm_emulator.c
> @@ -0,0 +1,973 @@
> +/*
> + * 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 "migration/migration.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;
> + Error *migration_blocker;
> +} 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 void tpm_emulator_block_migration(TPMEmulator *tpm_pt)
> +{
> + Error *err = NULL;
> +
> + error_setg(&tpm_pt->migration_blocker,
> + "Migration disabled: TPM emulator not yet migratable");
> + migrate_add_blocker(tpm_pt->migration_blocker, &err);
> + if (err) {
> + error_free(err);
> + error_free(tpm_pt->migration_blocker);
> + tpm_pt->migration_blocker = NULL;
> + }
> +}
> +
> +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;
> + }
> +
> + tpm_emulator_block_migration(tpm_pt);
> +
> + 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);
> + }
> +
> + if (tpm_pt->migration_blocker) {
> + migrate_del_blocker(tpm_pt->migration_blocker);
> + error_free(tpm_pt->migration_blocker);
> + }
> +}
> +
> +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 ab438ea..e17d112 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -5202,10 +5202,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:
> @@ -5219,7 +5221,7 @@
> # Example:
> #
> # -> { "execute": "query-tpm-types" }
> -# <- { "return": [ "passthrough" ] }
> +# <- { "return": [ "passthrough", "emulator" ] }
> #
> ##
> { 'command': 'query-tpm-types', 'returns': ['TpmType'] }
> @@ -5240,16 +5242,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 2cc70b9..6902617 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -3108,7 +3108,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
>
> @@ -3117,8 +3125,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
> @@ -3168,6 +3176,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:
TPM
> +@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
>
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 12:08 ` Marc-André Lureau
@ 2017-07-18 13:40 ` Stefan Berger
2017-07-22 4:52 ` Amarnath Valluri
1 sibling, 0 replies; 26+ messages in thread
From: Stefan Berger @ 2017-07-18 13:40 UTC (permalink / raw)
To: qemu-devel
On 07/18/2017 08:08 AM, Marc-André Lureau wrote:
> Hi
>
> On Tue, Jul 18, 2017 at 1:49 AM, 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.
>>
>> 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
> I am afraid this isn't enough yet.
I'll put a pointer to this here on that page so that content isn't
replicated multiple times.
https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod
Stefan
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo
2017-07-18 10:39 ` Marc-André Lureau
@ 2017-07-18 14:28 ` Eric Blake
2017-07-22 4:30 ` Amarnath Valluri
0 siblings, 1 reply; 26+ messages in thread
From: Eric Blake @ 2017-07-18 14:28 UTC (permalink / raw)
To: Marc-André Lureau, Amarnath Valluri; +Cc: QEMU, Stefan Berger
[-- Attachment #1: Type: text/plain, Size: 2487 bytes --]
On 07/18/2017 05:39 AM, Marc-André Lureau wrote:
> Hi
>
> On Tue, Jul 18, 2017 at 1:49 AM, Amarnath Valluri
> <amarnath.valluri@intel.com> 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.
>>
> One usually prefer to have the true case first.
>
>> + } else {
>> + tpm_pt->ops->has_path = true;
>> }
>>
>> + tpm_pt->ops->path = g_strdup(value);
>
> Interestingly, ops->path will be set even if ops->has_path = false. I
> am not sure the visitors will handle that case properly (for visit or
> dealloc etc). Could you set ops->has_path = true uncondtionnally?
tmp_pt->opt->path is ignored if has_path is false; if it is assigned to
malloc'd memory, then you leak that memory when freeing tpm_pt.
>
>
>
>> 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;
>>
>
> Shouldn't it also free cancel_path?
Even better, don't open-code it. Use
qapi_free_TPMPassthruState(tpm_pt), so that the generated code gets
everything for you.
>> +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;
>> + }
>> +
>
> There is no check for small allocation failure elsewhere, I would drop that.
In fact, g_new0() can't fail (if you're out of memory, it abort()s
instead of returning NULL). Coverity will warn about dead code.
--
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: 619 bytes --]
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator Amarnath Valluri
2017-07-18 12:08 ` Marc-André Lureau
@ 2017-07-18 14:39 ` Stefan Berger
2017-07-20 14:42 ` Valluri, Amarnath
2017-07-18 15:05 ` Stefan Berger
2017-07-26 0:18 ` Stefan Berger
3 siblings, 1 reply; 26+ messages in thread
From: Stefan Berger @ 2017-07-18 14:39 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel
On 07/18/2017 04:49 AM, Amarnath Valluri wrote:
> 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..c90914c
> --- /dev/null
> +++ b/hw/tpm/tpm_emulator.c
> @@ -0,0 +1,973 @@
> +/*
> + * 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 "migration/migration.h"
Missing: migration/blocker.h
Stefan
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator Amarnath Valluri
2017-07-18 12:08 ` Marc-André Lureau
2017-07-18 14:39 ` Stefan Berger
@ 2017-07-18 15:05 ` Stefan Berger
2017-07-26 0:18 ` Stefan Berger
3 siblings, 0 replies; 26+ messages in thread
From: Stefan Berger @ 2017-07-18 15:05 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel
On 07/18/2017 04:49 AM, Amarnath Valluri 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.
>
> 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 \
> [...]
In this description ',spawn,path=/usr/bin/swtpm' is missing. I had to
pass the path even with swtpm being in PATH on the command line but not
for the execv(). In case it didn't find the executable I had to
eliminate g_strfreev(argv) since it also wants to free the array itself,
so it wouldn't end up in a crash.
Stefan
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 14:39 ` Stefan Berger
@ 2017-07-20 14:42 ` Valluri, Amarnath
0 siblings, 0 replies; 26+ messages in thread
From: Valluri, Amarnath @ 2017-07-20 14:42 UTC (permalink / raw)
To: stefanb@linux.vnet.ibm.com, qemu-devel@nongnu.org
On Tue, 2017-07-18 at 10:39 -0400, Stefan Berger wrote:
> On 07/18/2017 04:49 AM, Amarnath Valluri wrote:
> >
> > 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..c90914c
> > --- /dev/null
> > +++ b/hw/tpm/tpm_emulator.c
> > @@ -0,0 +1,973 @@
> > +/*
> > + * 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.or
> > g/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 "migration/migration.h"
> Missing: migration/blocker.h
Oops there was something went wrong while rebasing, i will resend.
- Amarnath
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo
2017-07-18 14:28 ` Eric Blake
@ 2017-07-22 4:30 ` Amarnath Valluri
0 siblings, 0 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-22 4:30 UTC (permalink / raw)
To: Eric Blake; +Cc: Marc-André Lureau, QEMU, Stefan Berger
On Tue, 2017-07-18 at 09:28 -0500, Eric Blake wrote:
> On 07/18/2017 05:39 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Tue, Jul 18, 2017 at 1:49 AM, Amarnath Valluri
> > <amarnath.valluri@intel.com> 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.
> >>
> > One usually prefer to have the true case first.
> >
> >> + } else {
> >> + tpm_pt->ops->has_path = true;
> >> }
> >>
> >> + tpm_pt->ops->path = g_strdup(value);
> >
> > Interestingly, ops->path will be set even if ops->has_path = false. I
> > am not sure the visitors will handle that case properly (for visit or
> > dealloc etc). Could you set ops->has_path = true uncondtionnally?
>
> tmp_pt->opt->path is ignored if has_path is false; if it is assigned to
> malloc'd memory, then you leak that memory when freeing tpm_pt.
Yes, i agree there is memory leak here, i will fix it.
- Amarnath
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 4/8] tpm-backend: Made few interface methods optional
2017-07-18 10:15 ` Marc-André Lureau
@ 2017-07-22 4:32 ` Amarnath Valluri
0 siblings, 0 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-22 4:32 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: qemu-devel, stefanb
On Tue, 2017-07-18 at 10:15 +0000, Marc-André Lureau wrote:
> Hi
>
> On Tue, Jul 18, 2017 at 10:48 AM Amarnath Valluri
> <amarnath.valluri@intel.com> 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: Marc-André Lureau <marcandre.lureau@redhat.com>
> Reviewed-by: Stefan Berger<stefanb@linux.vnet.ibm.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(-)
>
> LINK x86_64-softmmu/qemu-system-x86_64
> ../tpm.o: In function `qmp_query_tpm_inst':
> /home/elmarco/src/qq/tpm.c:261: undefined reference to
> `tpm_backend_get_type'
> collect2: error: ld returned 1 exit status
Thanks Marc, for pointing it out, i will this patch.
- Amarnath
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 12:08 ` Marc-André Lureau
2017-07-18 13:40 ` Stefan Berger
@ 2017-07-22 4:52 ` Amarnath Valluri
1 sibling, 0 replies; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-22 4:52 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: QEMU, Stefan Berger
On Tue, 2017-07-18 at 05:08 -0700, Marc-André Lureau wrote:
> Hi
>
> On Tue, Jul 18, 2017 at 1:49 AM, 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.
> >
> > 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
>
> I am afraid this isn't enough yet.
>
> > 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 \
>
> We should rather follow the vhost-user pattern: do not deal with
> spawning the external swtpm/backend, just use chardev to connect to
> it. At least you don't have to deal with process argument details,
> management etc that may change version to version.
I made the spawning completely optional and it is useful in some
environments, especially makes life easier when multiple QEMU instances
on a system.
One can configure QEMU to connect to already running software emulator
using Unix domain socket paths:
-tpmdev emulator,id=tpm0,data-path=/path/,ctrl-path=/path
- Amarnath
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator Amarnath Valluri
` (2 preceding siblings ...)
2017-07-18 15:05 ` Stefan Berger
@ 2017-07-26 0:18 ` Stefan Berger
2017-07-26 3:49 ` Amarnath Valluri
3 siblings, 1 reply; 26+ messages in thread
From: Stefan Berger @ 2017-07-26 0:18 UTC (permalink / raw)
To: Amarnath Valluri, qemu-devel
On 07/18/2017 04:49 AM, Amarnath Valluri wrote:
> 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..c90914c
> --- /dev/null
> +++ b/hw/tpm/tpm_emulator.c
> @@ -0,0 +1,973 @@
> +/*
> + * 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 "migration/migration.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;
> + Error *migration_blocker;
> +} TPMEmulator;
> +
> +#define TPM_DEFAULT_EMULATOR "swtpm"
> +#define TPM_DEFAULT_LOGLEVEL 5
> +#define TPM_EMULATOR_PIDFILE "/tmp/qemu-tpm.pid"
swtpm will write this file and remove it when it terminates. You may run
into concurrency problems as well. I would extend this name with the pid
of the QEMU process starting swtpm.
Stefan
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-26 0:18 ` Stefan Berger
@ 2017-07-26 3:49 ` Amarnath Valluri
2017-07-26 14:54 ` Dr. David Alan Gilbert
0 siblings, 1 reply; 26+ messages in thread
From: Amarnath Valluri @ 2017-07-26 3:49 UTC (permalink / raw)
To: Stefan Berger; +Cc: qemu-devel
On Tue, 2017-07-25 at 20:18 -0400, Stefan Berger wrote:
> On 07/18/2017 04:49 AM, Amarnath Valluri wrote:
> > 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..c90914c
> > --- /dev/null
> > +++ b/hw/tpm/tpm_emulator.c
> > @@ -0,0 +1,973 @@
> > +/*
> > + * 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 "migration/migration.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;
> > + Error *migration_blocker;
> > +} TPMEmulator;
> > +
> > +#define TPM_DEFAULT_EMULATOR "swtpm"
> > +#define TPM_DEFAULT_LOGLEVEL 5
> > +#define TPM_EMULATOR_PIDFILE "/tmp/qemu-tpm.pid"
>
> swtpm will write this file and remove it when it terminates. You may run
> into concurrency problems as well. I would extend this name with the pid
> of the QEMU process starting swtpm.
Stefan, there was some issue in my reabasing and sent wrong version of
patchset, but i made all the changes you suggested including the pid
file.
But i did not sent the next version as Marc-André Lureau objected the
the idea of spawning swtpm from Qemu. I started exploring his suggestion
of 'chardev'.
I feel like we are back to square one :).
- Amarnath
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator
2017-07-26 3:49 ` Amarnath Valluri
@ 2017-07-26 14:54 ` Dr. David Alan Gilbert
0 siblings, 0 replies; 26+ messages in thread
From: Dr. David Alan Gilbert @ 2017-07-26 14:54 UTC (permalink / raw)
To: Amarnath Valluri; +Cc: Stefan Berger, qemu-devel
* Amarnath Valluri (amarnath.valluri@intel.com) wrote:
> On Tue, 2017-07-25 at 20:18 -0400, Stefan Berger wrote:
> > On 07/18/2017 04:49 AM, Amarnath Valluri wrote:
> > > 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..c90914c
> > > --- /dev/null
> > > +++ b/hw/tpm/tpm_emulator.c
> > > @@ -0,0 +1,973 @@
> > > +/*
> > > + * 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 "migration/migration.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;
> > > + Error *migration_blocker;
> > > +} TPMEmulator;
> > > +
> > > +#define TPM_DEFAULT_EMULATOR "swtpm"
> > > +#define TPM_DEFAULT_LOGLEVEL 5
> > > +#define TPM_EMULATOR_PIDFILE "/tmp/qemu-tpm.pid"
> >
> > swtpm will write this file and remove it when it terminates. You may run
> > into concurrency problems as well. I would extend this name with the pid
> > of the QEMU process starting swtpm.
> Stefan, there was some issue in my reabasing and sent wrong version of
> patchset, but i made all the changes you suggested including the pid
> file.
>
> But i did not sent the next version as Marc-André Lureau objected the
> the idea of spawning swtpm from Qemu. I started exploring his suggestion
> of 'chardev'.
>
> I feel like we are back to square one :).
I agree with Marc-Andre that it's best not to spawn it from qemu; the
way we do pretty much all other external tools is to get something else
to start them up and wire them back in with a chardev.
Dave
> - Amarnath
>
>
>
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2017-07-26 14:55 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-18 8:48 [Qemu-devel] [PATCH v6 0/8] Provide support for the software TPM emulator Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 1/8] tpm-backend: Remove unneeded member variable from backend class Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 2/8] tpm-backend: Move thread handling inside TPMBackend Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 3/8] tpm-backend: Initialize and free data members in it's own methods Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 4/8] tpm-backend: Made few interface methods optional Amarnath Valluri
2017-07-18 10:15 ` Marc-André Lureau
2017-07-22 4:32 ` Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 5/8] tmp backend: Add new api to read backend TpmInfo Amarnath Valluri
2017-07-18 10:39 ` Marc-André Lureau
2017-07-18 14:28 ` Eric Blake
2017-07-22 4:30 ` Amarnath Valluri
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 6/8] tpm-backend: Move realloc_buffer() implementation to tpm-tis model Amarnath Valluri
2017-07-18 10:50 ` Marc-André Lureau
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 7/8] tpm-passthrough: move reusable code to utils Amarnath Valluri
2017-07-18 11:17 ` Marc-André Lureau
2017-07-18 8:49 ` [Qemu-devel] [PATCH v6 8/8] tpm: Added support for TPM emulator Amarnath Valluri
2017-07-18 12:08 ` Marc-André Lureau
2017-07-18 13:40 ` Stefan Berger
2017-07-22 4:52 ` Amarnath Valluri
2017-07-18 14:39 ` Stefan Berger
2017-07-20 14:42 ` Valluri, Amarnath
2017-07-18 15:05 ` Stefan Berger
2017-07-26 0:18 ` Stefan Berger
2017-07-26 3:49 ` Amarnath Valluri
2017-07-26 14:54 ` Dr. David Alan Gilbert
2017-07-18 8:59 ` [Qemu-devel] [PATCH v6 0/8] Provide support for the software " no-reply
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).