summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/qemu
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/qemu')
-rw-r--r--meta/recipes-devtools/qemu/qemu/0001-tpm-Clean-up-driver-registration-lookup.patch154
-rw-r--r--meta/recipes-devtools/qemu/qemu/0002-tpm-Clean-up-model-registration-lookup.patch121
-rw-r--r--meta/recipes-devtools/qemu/qemu/0003-tpm-backend-Remove-unneeded-member-variable-from-bac.patch75
-rw-r--r--meta/recipes-devtools/qemu/qemu/0004-tpm-backend-Move-thread-handling-inside-TPMBackend.patch417
-rw-r--r--meta/recipes-devtools/qemu/qemu/0005-tpm-backend-Initialize-and-free-data-members-in-it-s.patch185
-rw-r--r--meta/recipes-devtools/qemu/qemu/0006-tpm-backend-Made-few-interface-methods-optional.patch284
-rw-r--r--meta/recipes-devtools/qemu/qemu/0007-tpm-backend-Add-new-api-to-read-backend-TpmInfo.patch293
-rw-r--r--meta/recipes-devtools/qemu/qemu/0008-tpm-backend-Move-realloc_buffer-implementation-to-tp.patch140
-rw-r--r--meta/recipes-devtools/qemu/qemu/0009-tpm-passthrough-move-reusable-code-to-utils.patch182
-rw-r--r--meta/recipes-devtools/qemu/qemu/0010-tpm-Added-support-for-TPM-emulator.patch1059
-rw-r--r--meta/recipes-devtools/qemu/qemu/0011-tpm-Move-tpm_cleanup-to-right-place.patch43
-rw-r--r--meta/recipes-devtools/qemu/qemu/0012-tpm-Use-EMSGSIZE-instead-of-EBADMSG-to-compile-on-Op.patch67
-rw-r--r--meta/recipes-devtools/qemu/qemu/CVE-2017-17381.patch72
-rw-r--r--meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch72
-rw-r--r--meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch87
-rw-r--r--meta/recipes-devtools/qemu/qemu/linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch35
-rw-r--r--meta/recipes-devtools/qemu/qemu/ppc_locking.patch105
-rw-r--r--meta/recipes-devtools/qemu/qemu_2.11.0.bb (renamed from meta/recipes-devtools/qemu/qemu_2.10.1.bb)20
18 files changed, 63 insertions, 3348 deletions
diff --git a/meta/recipes-devtools/qemu/qemu/0001-tpm-Clean-up-driver-registration-lookup.patch b/meta/recipes-devtools/qemu/qemu/0001-tpm-Clean-up-driver-registration-lookup.patch
deleted file mode 100644
index 1a484b91c3..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0001-tpm-Clean-up-driver-registration-lookup.patch
+++ /dev/null
@@ -1,154 +0,0 @@
1From a0f8d150794164f41cd7288c9ed059bbf21c95ec Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
3Date: Thu, 24 Aug 2017 10:45:58 +0200
4Subject: [PATCH 01/12] tpm: Clean up driver registration & lookup
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9We have a strict separation between enum TpmType and be_drivers[]:
10
11* TpmType may have any number of members. It just happens to have one.
12
13* tpm_register_driver() uses the first empty slot in be_drivers[].
14
15 If you register more than tpm_models[] has space,
16 tpm_register_driver() fails. Its caller silently ignores the
17 failure.
18
19 If you register more than one with a given TpmType,
20 tpm_display_backend_drivers() will shows all of them, but
21 tpm_driver_find_by_type() and tpm_get_backend_driver() will find
22 only the one one that registered first.
23
24Since we only ever register one driver, and be_drivers[] has space for
25just that one, this contraption even works.
26
27Turn be_drivers[] into a straight map from enum TpmType to driver.
28Much simpler, and has a decent chance to actually work should we ever
29acquire additional drivers.
30
31While there, use qapi_enum_parse() in tpm_get_backend_driver().
32
33Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
34Message-Id: <20170822132255.23945-8-marcandre.lureau@redhat.com>
35Reviewed-by: Markus Armbruster <armbru@redhat.com>
36[Rebased, superfluous initializer dropped, commit message rewritten]
37Cc: Stefan Berger <stefanb@us.ibm.com>
38Signed-off-by: Markus Armbruster <armbru@redhat.com>
39Message-Id: <1503564371-26090-4-git-send-email-armbru@redhat.com>
40
41Upstream-Status: Backport
42---
43 include/sysemu/tpm_backend.h | 2 +-
44 tpm.c | 45 +++++++++++++-------------------------------
45 2 files changed, 14 insertions(+), 33 deletions(-)
46
47diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
48index b58f52d39f..1d21c6b19b 100644
49--- a/include/sysemu/tpm_backend.h
50+++ b/include/sysemu/tpm_backend.h
51@@ -227,6 +227,6 @@ TPMBackend *qemu_find_tpm(const char *id);
52
53 const TPMDriverOps *tpm_get_backend_driver(const char *type);
54 int tpm_register_model(enum TpmModel model);
55-int tpm_register_driver(const TPMDriverOps *tdo);
56+void tpm_register_driver(const TPMDriverOps *tdo);
57
58 #endif
59diff --git a/tpm.c b/tpm.c
60index 9a7c7114d3..bb45d0c08e 100644
61--- a/tpm.c
62+++ b/tpm.c
63@@ -14,6 +14,7 @@
64 #include "qemu/osdep.h"
65
66 #include "qapi/qmp/qerror.h"
67+#include "qapi/util.h"
68 #include "sysemu/tpm_backend.h"
69 #include "sysemu/tpm.h"
70 #include "qemu/config-file.h"
71@@ -25,11 +26,8 @@ static QLIST_HEAD(, TPMBackend) tpm_backends =
72
73
74 #define TPM_MAX_MODELS 1
75-#define TPM_MAX_DRIVERS 1
76
77-static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = {
78- NULL,
79-};
80+static TPMDriverOps const *be_drivers[TPM_TYPE__MAX];
81
82 static enum TpmModel tpm_models[TPM_MAX_MODELS] = {
83 TPM_MODEL__MAX,
84@@ -63,31 +61,18 @@ static bool tpm_model_is_registered(enum TpmModel model)
85
86 const TPMDriverOps *tpm_get_backend_driver(const char *type)
87 {
88- int i;
89-
90- for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
91- if (!strcmp(TpmType_lookup[be_drivers[i]->type], type)) {
92- return be_drivers[i];
93- }
94- }
95+ int i = qapi_enum_parse(TpmType_lookup, type, TPM_TYPE__MAX, -1, NULL);
96
97- return NULL;
98+ return i >= 0 ? be_drivers[i] : NULL;
99 }
100
101 #ifdef CONFIG_TPM
102
103-int tpm_register_driver(const TPMDriverOps *tdo)
104+void tpm_register_driver(const TPMDriverOps *tdo)
105 {
106- int i;
107+ assert(!be_drivers[tdo->type]);
108
109- for (i = 0; i < TPM_MAX_DRIVERS; i++) {
110- if (!be_drivers[i]) {
111- be_drivers[i] = tdo;
112- return 0;
113- }
114- }
115- error_report("Could not register TPM driver");
116- return 1;
117+ be_drivers[tdo->type] = tdo;
118 }
119
120 /*
121@@ -100,9 +85,12 @@ static void tpm_display_backend_drivers(void)
122
123 fprintf(stderr, "Supported TPM types (choose only one):\n");
124
125- for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
126+ for (i = 0; i < TPM_TYPE__MAX; i++) {
127+ if (be_drivers[i] == NULL) {
128+ continue;
129+ }
130 fprintf(stderr, "%12s %s\n",
131- TpmType_lookup[be_drivers[i]->type], be_drivers[i]->desc());
132+ TpmType_lookup[i], be_drivers[i]->desc());
133 }
134 fprintf(stderr, "\n");
135 }
136@@ -239,14 +227,7 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg)
137
138 static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
139 {
140- int i;
141-
142- for (i = 0; i < TPM_MAX_DRIVERS && be_drivers[i] != NULL; i++) {
143- if (be_drivers[i]->type == type) {
144- return be_drivers[i];
145- }
146- }
147- return NULL;
148+ return be_drivers[type];
149 }
150
151 static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
152--
1532.11.0
154
diff --git a/meta/recipes-devtools/qemu/qemu/0002-tpm-Clean-up-model-registration-lookup.patch b/meta/recipes-devtools/qemu/qemu/0002-tpm-Clean-up-model-registration-lookup.patch
deleted file mode 100644
index c223ba83b6..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0002-tpm-Clean-up-model-registration-lookup.patch
+++ /dev/null
@@ -1,121 +0,0 @@
1From 89430c64784484214b3c99562520cdffe79cd801 Mon Sep 17 00:00:00 2001
2From: Markus Armbruster <armbru@redhat.com>
3Date: Thu, 24 Aug 2017 10:45:59 +0200
4Subject: [PATCH 02/12] tpm: Clean up model registration & lookup
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9We have a strict separation between enum TpmModel and tpm_models[]:
10
11* TpmModel may have any number of members. It just happens to have one.
12
13* tpm_register_model() uses the first empty slot in tpm_models[].
14
15 If you register more than tpm_models[] has space,
16 tpn_register_model() fails. Its caller silently ignores the
17 failure.
18
19 Register the same TpmModel more than once has no effect other than
20 wasting tpm_models[] slots: tpm_model_is_registered() is happy with
21 the first one it finds.
22
23Since we only ever register one model, and tpm_models[] has space for
24just that one, this contraption even works.
25
26Turn tpm_models[] into a straight map from enum TpmType to bool. Much
27simpler.
28
29Cc: Stefan Berger <stefanb@us.ibm.com>
30Signed-off-by: Markus Armbruster <armbru@redhat.com>
31Message-Id: <1503564371-26090-5-git-send-email-armbru@redhat.com>
32Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
33[Commit message typo fixed]
34
35Upstream-Status: Backport
36---
37 include/sysemu/tpm_backend.h | 2 +-
38 tpm.c | 37 +++++--------------------------------
39 2 files changed, 6 insertions(+), 33 deletions(-)
40
41diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
42index 1d21c6b19b..b0a9731aee 100644
43--- a/include/sysemu/tpm_backend.h
44+++ b/include/sysemu/tpm_backend.h
45@@ -226,7 +226,7 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
46 TPMBackend *qemu_find_tpm(const char *id);
47
48 const TPMDriverOps *tpm_get_backend_driver(const char *type);
49-int tpm_register_model(enum TpmModel model);
50+void tpm_register_model(enum TpmModel model);
51 void tpm_register_driver(const TPMDriverOps *tdo);
52
53 #endif
54diff --git a/tpm.c b/tpm.c
55index bb45d0c08e..2dbea70645 100644
56--- a/tpm.c
57+++ b/tpm.c
58@@ -24,39 +24,12 @@
59 static QLIST_HEAD(, TPMBackend) tpm_backends =
60 QLIST_HEAD_INITIALIZER(tpm_backends);
61
62-
63-#define TPM_MAX_MODELS 1
64-
65 static TPMDriverOps const *be_drivers[TPM_TYPE__MAX];
66+static bool tpm_models[TPM_MODEL__MAX];
67
68-static enum TpmModel tpm_models[TPM_MAX_MODELS] = {
69- TPM_MODEL__MAX,
70-};
71-
72-int tpm_register_model(enum TpmModel model)
73-{
74- int i;
75-
76- for (i = 0; i < TPM_MAX_MODELS; i++) {
77- if (tpm_models[i] == TPM_MODEL__MAX) {
78- tpm_models[i] = model;
79- return 0;
80- }
81- }
82- error_report("Could not register TPM model");
83- return 1;
84-}
85-
86-static bool tpm_model_is_registered(enum TpmModel model)
87+void tpm_register_model(enum TpmModel model)
88 {
89- int i;
90-
91- for (i = 0; i < TPM_MAX_MODELS; i++) {
92- if (tpm_models[i] == model) {
93- return true;
94- }
95- }
96- return false;
97+ tpm_models[model] = true;
98 }
99
100 const TPMDriverOps *tpm_get_backend_driver(const char *type)
101@@ -270,7 +243,7 @@ TPMInfoList *qmp_query_tpm(Error **errp)
102 TPMInfoList *info, *head = NULL, *cur_item = NULL;
103
104 QLIST_FOREACH(drv, &tpm_backends, list) {
105- if (!tpm_model_is_registered(drv->fe_model)) {
106+ if (!tpm_models[drv->fe_model]) {
107 continue;
108 }
109 info = g_new0(TPMInfoList, 1);
110@@ -317,7 +290,7 @@ TpmModelList *qmp_query_tpm_models(Error **errp)
111 TpmModelList *head = NULL, *prev = NULL, *cur_item;
112
113 for (i = 0; i < TPM_MODEL__MAX; i++) {
114- if (!tpm_model_is_registered(i)) {
115+ if (!tpm_models[i]) {
116 continue;
117 }
118 cur_item = g_new0(TpmModelList, 1);
119--
1202.11.0
121
diff --git a/meta/recipes-devtools/qemu/qemu/0003-tpm-backend-Remove-unneeded-member-variable-from-bac.patch b/meta/recipes-devtools/qemu/qemu/0003-tpm-backend-Remove-unneeded-member-variable-from-bac.patch
deleted file mode 100644
index 6b94eba720..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0003-tpm-backend-Remove-unneeded-member-variable-from-bac.patch
+++ /dev/null
@@ -1,75 +0,0 @@
1From cac845f55b8f27e5c90e0f2e3dcbeea7013df67c Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Thu, 30 Mar 2017 15:55:17 +0300
4Subject: [PATCH 03/12] tpm-backend: Remove unneeded member variable from
5 backend class
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10TPMDriverOps inside TPMBackend is not required, as it is supposed to be a class
11member. The only possible reason for keeping in TPMBackend was, to get the
12backend type in tpm.c where dedicated backend api, tpm_backend_get_type() is
13present.
14
15Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
16Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
17Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
18
19Upstream-Status: Backport [fb4b0c6765471dad2363875989e7661ca5f9a608]
20---
21 hw/tpm/tpm_passthrough.c | 4 ----
22 include/sysemu/tpm_backend.h | 1 -
23 tpm.c | 2 +-
24 3 files changed, 1 insertion(+), 6 deletions(-)
25
26diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
27index 9234eb3459..a0baf5f080 100644
28--- a/hw/tpm/tpm_passthrough.c
29+++ b/hw/tpm/tpm_passthrough.c
30@@ -46,8 +46,6 @@
31 #define TPM_PASSTHROUGH(obj) \
32 OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
33
34-static const TPMDriverOps tpm_passthrough_driver;
35-
36 /* data structures */
37 typedef struct TPMPassthruThreadParams {
38 TPMState *tpm_state;
39@@ -462,8 +460,6 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
40 /* let frontend set the fe_model to proper value */
41 tb->fe_model = -1;
42
43- tb->ops = &tpm_passthrough_driver;
44-
45 if (tpm_passthrough_handle_device_opts(opts, tb)) {
46 goto err_exit;
47 }
48diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
49index b0a9731aee..3708413035 100644
50--- a/include/sysemu/tpm_backend.h
51+++ b/include/sysemu/tpm_backend.h
52@@ -50,7 +50,6 @@ struct TPMBackend {
53 enum TpmModel fe_model;
54 char *path;
55 char *cancel_path;
56- const TPMDriverOps *ops;
57
58 QLIST_ENTRY(TPMBackend) list;
59 };
60diff --git a/tpm.c b/tpm.c
61index 2dbea70645..b7166ca200 100644
62--- a/tpm.c
63+++ b/tpm.c
64@@ -212,7 +212,7 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
65 res->model = drv->fe_model;
66 res->options = g_new0(TpmTypeOptions, 1);
67
68- switch (drv->ops->type) {
69+ switch (tpm_backend_get_type(drv)) {
70 case TPM_TYPE_PASSTHROUGH:
71 res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
72 tpo = g_new0(TPMPassthroughOptions, 1);
73--
742.11.0
75
diff --git a/meta/recipes-devtools/qemu/qemu/0004-tpm-backend-Move-thread-handling-inside-TPMBackend.patch b/meta/recipes-devtools/qemu/qemu/0004-tpm-backend-Move-thread-handling-inside-TPMBackend.patch
deleted file mode 100644
index 64e88b6de9..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0004-tpm-backend-Move-thread-handling-inside-TPMBackend.patch
+++ /dev/null
@@ -1,417 +0,0 @@
1From 5767322022d54ceb5a2ed6c650f667a4d24aa150 Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Thu, 30 Mar 2017 16:20:25 +0300
4Subject: [PATCH 04/12] tpm-backend: Move thread handling inside TPMBackend
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Move thread handling inside TPMBackend, this way backend implementations need
10not to maintain their own thread life cycle, instead they needs to implement
11'handle_request()' class method that always been called from a thread.
12
13This change made tpm_backend_int.h kind of useless, hence removed it.
14
15Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
16Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
17Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
18
19Upstream-Status: Backport [b19a5eea5a26e9bd83a48c742172d2a6aa8c4180]
20---
21 backends/tpm.c | 62 +++++++++++++++++++++++++---------------
22 hw/tpm/tpm_passthrough.c | 58 ++++++-------------------------------
23 include/sysemu/tpm_backend.h | 32 +++++++++++++--------
24 include/sysemu/tpm_backend_int.h | 41 --------------------------
25 4 files changed, 67 insertions(+), 126 deletions(-)
26 delete mode 100644 include/sysemu/tpm_backend_int.h
27
28diff --git a/backends/tpm.c b/backends/tpm.c
29index 536f262bb7..ce56c3b74d 100644
30--- a/backends/tpm.c
31+++ b/backends/tpm.c
32@@ -18,7 +18,24 @@
33 #include "qapi/qmp/qerror.h"
34 #include "sysemu/tpm.h"
35 #include "qemu/thread.h"
36-#include "sysemu/tpm_backend_int.h"
37+
38+static void tpm_backend_worker_thread(gpointer data, gpointer user_data)
39+{
40+ TPMBackend *s = TPM_BACKEND(user_data);
41+ TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
42+
43+ assert(k->handle_request != NULL);
44+ k->handle_request(s, (TPMBackendCmd)data);
45+}
46+
47+static void tpm_backend_thread_end(TPMBackend *s)
48+{
49+ if (s->thread_pool) {
50+ g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
51+ g_thread_pool_free(s->thread_pool, FALSE, TRUE);
52+ s->thread_pool = NULL;
53+ }
54+}
55
56 enum TpmType tpm_backend_get_type(TPMBackend *s)
57 {
58@@ -39,6 +56,8 @@ void tpm_backend_destroy(TPMBackend *s)
59 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
60
61 k->ops->destroy(s);
62+
63+ tpm_backend_thread_end(s);
64 }
65
66 int tpm_backend_init(TPMBackend *s, TPMState *state,
67@@ -46,13 +65,23 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
68 {
69 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
70
71- return k->ops->init(s, state, datacb);
72+ s->tpm_state = state;
73+ s->recv_data_callback = datacb;
74+
75+ return k->ops->init(s);
76 }
77
78 int tpm_backend_startup_tpm(TPMBackend *s)
79 {
80 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
81
82+ /* terminate a running TPM */
83+ tpm_backend_thread_end(s);
84+
85+ s->thread_pool = g_thread_pool_new(tpm_backend_worker_thread, s, 1, TRUE,
86+ NULL);
87+ g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
88+
89 return k->ops->startup_tpm(s);
90 }
91
92@@ -72,9 +101,8 @@ size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
93
94 void tpm_backend_deliver_request(TPMBackend *s)
95 {
96- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
97-
98- k->ops->deliver_request(s);
99+ g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD,
100+ NULL);
101 }
102
103 void tpm_backend_reset(TPMBackend *s)
104@@ -82,6 +110,8 @@ void tpm_backend_reset(TPMBackend *s)
105 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
106
107 k->ops->reset(s);
108+
109+ tpm_backend_thread_end(s);
110 }
111
112 void tpm_backend_cancel_cmd(TPMBackend *s)
113@@ -156,29 +186,14 @@ static void tpm_backend_instance_init(Object *obj)
114 tpm_backend_prop_get_opened,
115 tpm_backend_prop_set_opened,
116 NULL);
117-}
118
119-void tpm_backend_thread_deliver_request(TPMBackendThread *tbt)
120-{
121- g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD, NULL);
122 }
123
124-void tpm_backend_thread_create(TPMBackendThread *tbt,
125- GFunc func, gpointer user_data)
126+static void tpm_backend_instance_finalize(Object *obj)
127 {
128- if (!tbt->pool) {
129- tbt->pool = g_thread_pool_new(func, user_data, 1, TRUE, NULL);
130- g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
131- }
132-}
133+ TPMBackend *s = TPM_BACKEND(obj);
134
135-void tpm_backend_thread_end(TPMBackendThread *tbt)
136-{
137- if (tbt->pool) {
138- g_thread_pool_push(tbt->pool, (gpointer)TPM_BACKEND_CMD_END, NULL);
139- g_thread_pool_free(tbt->pool, FALSE, TRUE);
140- tbt->pool = NULL;
141- }
142+ tpm_backend_thread_end(s);
143 }
144
145 static const TypeInfo tpm_backend_info = {
146@@ -186,6 +201,7 @@ static const TypeInfo tpm_backend_info = {
147 .parent = TYPE_OBJECT,
148 .instance_size = sizeof(TPMBackend),
149 .instance_init = tpm_backend_instance_init,
150+ .instance_finalize = tpm_backend_instance_finalize,
151 .class_size = sizeof(TPMBackendClass),
152 .abstract = true,
153 };
154diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
155index a0baf5f080..f50d9cffd7 100644
156--- a/hw/tpm/tpm_passthrough.c
157+++ b/hw/tpm/tpm_passthrough.c
158@@ -30,7 +30,6 @@
159 #include "tpm_int.h"
160 #include "hw/hw.h"
161 #include "hw/i386/pc.h"
162-#include "sysemu/tpm_backend_int.h"
163 #include "tpm_tis.h"
164 #include "tpm_util.h"
165
166@@ -47,20 +46,9 @@
167 OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH)
168
169 /* data structures */
170-typedef struct TPMPassthruThreadParams {
171- TPMState *tpm_state;
172-
173- TPMRecvDataCB *recv_data_callback;
174- TPMBackend *tb;
175-} TPMPassthruThreadParams;
176-
177 struct TPMPassthruState {
178 TPMBackend parent;
179
180- TPMBackendThread tbt;
181-
182- TPMPassthruThreadParams tpm_thread_params;
183-
184 char *tpm_dev;
185 int tpm_fd;
186 bool tpm_executing;
187@@ -214,12 +202,9 @@ static int tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt,
188 selftest_done);
189 }
190
191-static void tpm_passthrough_worker_thread(gpointer data,
192- gpointer user_data)
193+static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
194 {
195- TPMPassthruThreadParams *thr_parms = user_data;
196- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(thr_parms->tb);
197- TPMBackendCmd cmd = (TPMBackendCmd)data;
198+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
199 bool selftest_done = false;
200
201 DPRINTF("tpm_passthrough: processing command type %d\n", cmd);
202@@ -227,12 +212,12 @@ static void tpm_passthrough_worker_thread(gpointer data,
203 switch (cmd) {
204 case TPM_BACKEND_CMD_PROCESS_CMD:
205 tpm_passthrough_unix_transfer(tpm_pt,
206- thr_parms->tpm_state->locty_data,
207+ tb->tpm_state->locty_data,
208 &selftest_done);
209
210- thr_parms->recv_data_callback(thr_parms->tpm_state,
211- thr_parms->tpm_state->locty_number,
212- selftest_done);
213+ tb->recv_data_callback(tb->tpm_state,
214+ tb->tpm_state->locty_number,
215+ selftest_done);
216 break;
217 case TPM_BACKEND_CMD_INIT:
218 case TPM_BACKEND_CMD_END:
219@@ -248,15 +233,6 @@ static void tpm_passthrough_worker_thread(gpointer data,
220 */
221 static int tpm_passthrough_startup_tpm(TPMBackend *tb)
222 {
223- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
224-
225- /* terminate a running TPM */
226- tpm_backend_thread_end(&tpm_pt->tbt);
227-
228- tpm_backend_thread_create(&tpm_pt->tbt,
229- tpm_passthrough_worker_thread,
230- &tpm_pt->tpm_thread_params);
231-
232 return 0;
233 }
234
235@@ -268,20 +244,11 @@ static void tpm_passthrough_reset(TPMBackend *tb)
236
237 tpm_passthrough_cancel_cmd(tb);
238
239- tpm_backend_thread_end(&tpm_pt->tbt);
240-
241 tpm_pt->had_startup_error = false;
242 }
243
244-static int tpm_passthrough_init(TPMBackend *tb, TPMState *s,
245- TPMRecvDataCB *recv_data_cb)
246+static int tpm_passthrough_init(TPMBackend *tb)
247 {
248- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
249-
250- tpm_pt->tpm_thread_params.tpm_state = s;
251- tpm_pt->tpm_thread_params.recv_data_callback = recv_data_cb;
252- tpm_pt->tpm_thread_params.tb = tb;
253-
254 return 0;
255 }
256
257@@ -315,13 +282,6 @@ static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
258 return sb->size;
259 }
260
261-static void tpm_passthrough_deliver_request(TPMBackend *tb)
262-{
263- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
264-
265- tpm_backend_thread_deliver_request(&tpm_pt->tbt);
266-}
267-
268 static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
269 {
270 TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
271@@ -483,8 +443,6 @@ static void tpm_passthrough_destroy(TPMBackend *tb)
272
273 tpm_passthrough_cancel_cmd(tb);
274
275- tpm_backend_thread_end(&tpm_pt->tbt);
276-
277 qemu_close(tpm_pt->tpm_fd);
278 qemu_close(tpm_pt->cancel_fd);
279
280@@ -520,7 +478,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
281 .realloc_buffer = tpm_passthrough_realloc_buffer,
282 .reset = tpm_passthrough_reset,
283 .had_startup_error = tpm_passthrough_get_startup_error,
284- .deliver_request = tpm_passthrough_deliver_request,
285 .cancel_cmd = tpm_passthrough_cancel_cmd,
286 .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
287 .reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
288@@ -540,6 +497,7 @@ static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
289 TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
290
291 tbc->ops = &tpm_passthrough_driver;
292+ tbc->handle_request = tpm_passthrough_handle_request;
293 }
294
295 static const TypeInfo tpm_passthrough_info = {
296diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
297index 3708413035..58308b3687 100644
298--- a/include/sysemu/tpm_backend.h
299+++ b/include/sysemu/tpm_backend.h
300@@ -29,22 +29,24 @@
301
302 typedef struct TPMBackendClass TPMBackendClass;
303 typedef struct TPMBackend TPMBackend;
304-
305 typedef struct TPMDriverOps TPMDriverOps;
306+typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool selftest_done);
307
308-struct TPMBackendClass {
309- ObjectClass parent_class;
310-
311- const TPMDriverOps *ops;
312-
313- void (*opened)(TPMBackend *s, Error **errp);
314-};
315+typedef enum TPMBackendCmd {
316+ TPM_BACKEND_CMD_INIT = 1,
317+ TPM_BACKEND_CMD_PROCESS_CMD,
318+ TPM_BACKEND_CMD_END,
319+ TPM_BACKEND_CMD_TPM_RESET,
320+} TPMBackendCmd;
321
322 struct TPMBackend {
323 Object parent;
324
325 /*< protected >*/
326 bool opened;
327+ TPMState *tpm_state;
328+ GThreadPool *thread_pool;
329+ TPMRecvDataCB *recv_data_callback;
330
331 char *id;
332 enum TpmModel fe_model;
333@@ -54,7 +56,15 @@ struct TPMBackend {
334 QLIST_ENTRY(TPMBackend) list;
335 };
336
337-typedef void (TPMRecvDataCB)(TPMState *, uint8_t locty, bool selftest_done);
338+struct TPMBackendClass {
339+ ObjectClass parent_class;
340+
341+ const TPMDriverOps *ops;
342+
343+ void (*opened)(TPMBackend *s, Error **errp);
344+
345+ void (*handle_request)(TPMBackend *s, TPMBackendCmd cmd);
346+};
347
348 typedef struct TPMSizedBuffer {
349 uint32_t size;
350@@ -71,7 +81,7 @@ struct TPMDriverOps {
351 void (*destroy)(TPMBackend *t);
352
353 /* initialize the backend */
354- int (*init)(TPMBackend *t, TPMState *s, TPMRecvDataCB *datacb);
355+ int (*init)(TPMBackend *t);
356 /* start up the TPM on the backend */
357 int (*startup_tpm)(TPMBackend *t);
358 /* returns true if nothing will ever answer TPM requests */
359@@ -79,8 +89,6 @@ struct TPMDriverOps {
360
361 size_t (*realloc_buffer)(TPMSizedBuffer *sb);
362
363- void (*deliver_request)(TPMBackend *t);
364-
365 void (*reset)(TPMBackend *t);
366
367 void (*cancel_cmd)(TPMBackend *t);
368diff --git a/include/sysemu/tpm_backend_int.h b/include/sysemu/tpm_backend_int.h
369deleted file mode 100644
370index 00639dd7de..0000000000
371--- a/include/sysemu/tpm_backend_int.h
372+++ /dev/null
373@@ -1,41 +0,0 @@
374-/*
375- * common TPM backend driver functions
376- *
377- * Copyright (c) 2012-2013 IBM Corporation
378- * Authors:
379- * Stefan Berger <stefanb@us.ibm.com>
380- *
381- * This library is free software; you can redistribute it and/or
382- * modify it under the terms of the GNU Lesser General Public
383- * License as published by the Free Software Foundation; either
384- * version 2 of the License, or (at your option) any later version.
385- *
386- * This library is distributed in the hope that it will be useful,
387- * but WITHOUT ANY WARRANTY; without even the implied warranty of
388- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
389- * Lesser General Public License for more details.
390- *
391- * You should have received a copy of the GNU Lesser General Public
392- * License along with this library; if not, see <http://www.gnu.org/licenses/>
393- */
394-
395-#ifndef TPM_BACKEND_INT_H
396-#define TPM_BACKEND_INT_H
397-
398-typedef struct TPMBackendThread {
399- GThreadPool *pool;
400-} TPMBackendThread;
401-
402-void tpm_backend_thread_deliver_request(TPMBackendThread *tbt);
403-void tpm_backend_thread_create(TPMBackendThread *tbt,
404- GFunc func, gpointer user_data);
405-void tpm_backend_thread_end(TPMBackendThread *tbt);
406-
407-typedef enum TPMBackendCmd {
408- TPM_BACKEND_CMD_INIT = 1,
409- TPM_BACKEND_CMD_PROCESS_CMD,
410- TPM_BACKEND_CMD_END,
411- TPM_BACKEND_CMD_TPM_RESET,
412-} TPMBackendCmd;
413-
414-#endif /* TPM_BACKEND_INT_H */
415--
4162.11.0
417
diff --git a/meta/recipes-devtools/qemu/qemu/0005-tpm-backend-Initialize-and-free-data-members-in-it-s.patch b/meta/recipes-devtools/qemu/qemu/0005-tpm-backend-Initialize-and-free-data-members-in-it-s.patch
deleted file mode 100644
index 91dd542f45..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0005-tpm-backend-Initialize-and-free-data-members-in-it-s.patch
+++ /dev/null
@@ -1,185 +0,0 @@
1From 83ef052c60de271a97abb7eb9b5a8aeee52659e6 Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Fri, 31 Mar 2017 10:58:11 +0300
4Subject: [PATCH 05/12] tpm-backend: Initialize and free data members in it's
5 own methods
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10Initialize and free TPMBackend data members in it's own instance_init() and
11instance_finalize methods.
12
13Took the opportunity to remove unneeded destroy() method from TpmDriverOps
14interface as TPMBackend is a Qemu Object, we can use object_unref() inplace of
15tpm_backend_destroy() to free the backend object, hence removed destroy() from
16TPMDriverOps interface.
17
18Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
19Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
20Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
21
22Upstream-Status: Backport [f35fe5cb97bbdaa6a6967f2fefc3fc1f79680601]
23---
24 backends/tpm.c | 16 ++++++----------
25 hw/tpm/tpm_passthrough.c | 31 ++++++++++++-------------------
26 include/sysemu/tpm_backend.h | 7 -------
27 tpm.c | 2 +-
28 4 files changed, 19 insertions(+), 37 deletions(-)
29
30diff --git a/backends/tpm.c b/backends/tpm.c
31index ce56c3b74d..cf5abf1582 100644
32--- a/backends/tpm.c
33+++ b/backends/tpm.c
34@@ -51,15 +51,6 @@ const char *tpm_backend_get_desc(TPMBackend *s)
35 return k->ops->desc();
36 }
37
38-void tpm_backend_destroy(TPMBackend *s)
39-{
40- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
41-
42- k->ops->destroy(s);
43-
44- tpm_backend_thread_end(s);
45-}
46-
47 int tpm_backend_init(TPMBackend *s, TPMState *state,
48 TPMRecvDataCB *datacb)
49 {
50@@ -182,17 +173,22 @@ static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp)
51
52 static void tpm_backend_instance_init(Object *obj)
53 {
54+ TPMBackend *s = TPM_BACKEND(obj);
55+
56 object_property_add_bool(obj, "opened",
57 tpm_backend_prop_get_opened,
58 tpm_backend_prop_set_opened,
59 NULL);
60-
61+ s->fe_model = -1;
62 }
63
64 static void tpm_backend_instance_finalize(Object *obj)
65 {
66 TPMBackend *s = TPM_BACKEND(obj);
67
68+ g_free(s->id);
69+ g_free(s->path);
70+ g_free(s->cancel_path);
71 tpm_backend_thread_end(s);
72 }
73
74diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
75index f50d9cffd7..815a72ef9a 100644
76--- a/hw/tpm/tpm_passthrough.c
77+++ b/hw/tpm/tpm_passthrough.c
78@@ -417,8 +417,6 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
79 TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
80
81 tb->id = g_strdup(id);
82- /* let frontend set the fe_model to proper value */
83- tb->fe_model = -1;
84
85 if (tpm_passthrough_handle_device_opts(opts, tb)) {
86 goto err_exit;
87@@ -432,26 +430,11 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
88 return tb;
89
90 err_exit:
91- g_free(tb->id);
92+ object_unref(obj);
93
94 return NULL;
95 }
96
97-static void tpm_passthrough_destroy(TPMBackend *tb)
98-{
99- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
100-
101- tpm_passthrough_cancel_cmd(tb);
102-
103- qemu_close(tpm_pt->tpm_fd);
104- qemu_close(tpm_pt->cancel_fd);
105-
106- g_free(tb->id);
107- g_free(tb->path);
108- g_free(tb->cancel_path);
109- g_free(tpm_pt->tpm_dev);
110-}
111-
112 static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
113 TPM_STANDARD_CMDLINE_OPTS,
114 {
115@@ -472,7 +455,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
116 .opts = tpm_passthrough_cmdline_opts,
117 .desc = tpm_passthrough_create_desc,
118 .create = tpm_passthrough_create,
119- .destroy = tpm_passthrough_destroy,
120 .init = tpm_passthrough_init,
121 .startup_tpm = tpm_passthrough_startup_tpm,
122 .realloc_buffer = tpm_passthrough_realloc_buffer,
123@@ -486,10 +468,21 @@ static const TPMDriverOps tpm_passthrough_driver = {
124
125 static void tpm_passthrough_inst_init(Object *obj)
126 {
127+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
128+
129+ tpm_pt->tpm_fd = -1;
130+ tpm_pt->cancel_fd = -1;
131 }
132
133 static void tpm_passthrough_inst_finalize(Object *obj)
134 {
135+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
136+
137+ tpm_passthrough_cancel_cmd(TPM_BACKEND(obj));
138+
139+ qemu_close(tpm_pt->tpm_fd);
140+ qemu_close(tpm_pt->cancel_fd);
141+ g_free(tpm_pt->tpm_dev);
142 }
143
144 static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
145diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
146index 58308b3687..202ec8d5a2 100644
147--- a/include/sysemu/tpm_backend.h
148+++ b/include/sysemu/tpm_backend.h
149@@ -78,7 +78,6 @@ struct TPMDriverOps {
150 const char *(*desc)(void);
151
152 TPMBackend *(*create)(QemuOpts *opts, const char *id);
153- void (*destroy)(TPMBackend *t);
154
155 /* initialize the backend */
156 int (*init)(TPMBackend *t);
157@@ -118,12 +117,6 @@ enum TpmType tpm_backend_get_type(TPMBackend *s);
158 const char *tpm_backend_get_desc(TPMBackend *s);
159
160 /**
161- * tpm_backend_destroy:
162- * @s: the backend to destroy
163- */
164-void tpm_backend_destroy(TPMBackend *s);
165-
166-/**
167 * tpm_backend_init:
168 * @s: the backend to initialized
169 * @state: TPMState
170diff --git a/tpm.c b/tpm.c
171index b7166ca200..7feb3b43c9 100644
172--- a/tpm.c
173+++ b/tpm.c
174@@ -158,7 +158,7 @@ void tpm_cleanup(void)
175
176 QLIST_FOREACH_SAFE(drv, &tpm_backends, list, next) {
177 QLIST_REMOVE(drv, list);
178- tpm_backend_destroy(drv);
179+ object_unref(OBJECT(drv));
180 }
181 }
182
183--
1842.11.0
185
diff --git a/meta/recipes-devtools/qemu/qemu/0006-tpm-backend-Made-few-interface-methods-optional.patch b/meta/recipes-devtools/qemu/qemu/0006-tpm-backend-Made-few-interface-methods-optional.patch
deleted file mode 100644
index eb456f01c7..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0006-tpm-backend-Made-few-interface-methods-optional.patch
+++ /dev/null
@@ -1,284 +0,0 @@
1From 47e6ef6586401e82e652f3c013a349bba3a0479b Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Thu, 30 Mar 2017 18:04:16 +0300
4Subject: [PATCH 06/12] tpm-backend: Made few interface methods optional
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9This allows backend implementations left optional interface methods.
10For mandatory methods assertion checks added.
11
12Took the opportunity to remove unused methods:
13 - tpm_backend_get_desc()
14 - TPMDriverOps->handle_startup_error
15
16Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
17Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
18Reviewed-by: Stefan Berger<stefanb@linux.vnet.ibm.com>
19
20Upstream-Status: Backport [93330cf542b920b6ea5fea8120a08b76bb353113]
21---
22 backends/tpm.c | 39 ++++++++++++++++++++++++---------------
23 hw/tpm/tpm_passthrough.c | 36 +-----------------------------------
24 include/sysemu/tpm_backend.h | 13 ++-----------
25 tpm.c | 2 +-
26 4 files changed, 28 insertions(+), 62 deletions(-)
27
28diff --git a/backends/tpm.c b/backends/tpm.c
29index cf5abf1582..8911597fab 100644
30--- a/backends/tpm.c
31+++ b/backends/tpm.c
32@@ -44,13 +44,6 @@ enum TpmType tpm_backend_get_type(TPMBackend *s)
33 return k->ops->type;
34 }
35
36-const char *tpm_backend_get_desc(TPMBackend *s)
37-{
38- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
39-
40- return k->ops->desc();
41-}
42-
43 int tpm_backend_init(TPMBackend *s, TPMState *state,
44 TPMRecvDataCB *datacb)
45 {
46@@ -58,12 +51,14 @@ int tpm_backend_init(TPMBackend *s, TPMState *state,
47
48 s->tpm_state = state;
49 s->recv_data_callback = datacb;
50+ s->had_startup_error = false;
51
52- return k->ops->init(s);
53+ return k->ops->init ? k->ops->init(s) : 0;
54 }
55
56 int tpm_backend_startup_tpm(TPMBackend *s)
57 {
58+ int res = 0;
59 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
60
61 /* terminate a running TPM */
62@@ -73,20 +68,24 @@ int tpm_backend_startup_tpm(TPMBackend *s)
63 NULL);
64 g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_INIT, NULL);
65
66- return k->ops->startup_tpm(s);
67+ res = k->ops->startup_tpm ? k->ops->startup_tpm(s) : 0;
68+
69+ s->had_startup_error = (res != 0);
70+
71+ return res;
72 }
73
74 bool tpm_backend_had_startup_error(TPMBackend *s)
75 {
76- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
77-
78- return k->ops->had_startup_error(s);
79+ return s->had_startup_error;
80 }
81
82 size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
83 {
84 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
85
86+ assert(k->ops->realloc_buffer);
87+
88 return k->ops->realloc_buffer(sb);
89 }
90
91@@ -100,15 +99,21 @@ void tpm_backend_reset(TPMBackend *s)
92 {
93 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
94
95- k->ops->reset(s);
96+ if (k->ops->reset) {
97+ k->ops->reset(s);
98+ }
99
100 tpm_backend_thread_end(s);
101+
102+ s->had_startup_error = false;
103 }
104
105 void tpm_backend_cancel_cmd(TPMBackend *s)
106 {
107 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
108
109+ assert(k->ops->cancel_cmd);
110+
111 k->ops->cancel_cmd(s);
112 }
113
114@@ -116,20 +121,24 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s)
115 {
116 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
117
118- return k->ops->get_tpm_established_flag(s);
119+ return k->ops->get_tpm_established_flag ?
120+ k->ops->get_tpm_established_flag(s) : false;
121 }
122
123 int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty)
124 {
125 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
126
127- return k->ops->reset_tpm_established_flag(s, locty);
128+ return k->ops->reset_tpm_established_flag ?
129+ k->ops->reset_tpm_established_flag(s, locty) : 0;
130 }
131
132 TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
133 {
134 TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
135
136+ assert(k->ops->get_tpm_version);
137+
138 return k->ops->get_tpm_version(s);
139 }
140
141diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
142index 815a72ef9a..4c21e52b7c 100644
143--- a/hw/tpm/tpm_passthrough.c
144+++ b/hw/tpm/tpm_passthrough.c
145@@ -54,7 +54,6 @@ struct TPMPassthruState {
146 bool tpm_executing;
147 bool tpm_op_canceled;
148 int cancel_fd;
149- bool had_startup_error;
150
151 TPMVersion tpm_version;
152 };
153@@ -227,29 +226,11 @@ static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
154 }
155 }
156
157-/*
158- * Start the TPM (thread). If it had been started before, then terminate
159- * and start it again.
160- */
161-static int tpm_passthrough_startup_tpm(TPMBackend *tb)
162-{
163- return 0;
164-}
165-
166 static void tpm_passthrough_reset(TPMBackend *tb)
167 {
168- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
169-
170 DPRINTF("tpm_passthrough: CALL TO TPM_RESET!\n");
171
172 tpm_passthrough_cancel_cmd(tb);
173-
174- tpm_pt->had_startup_error = false;
175-}
176-
177-static int tpm_passthrough_init(TPMBackend *tb)
178-{
179- return 0;
180 }
181
182 static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb)
183@@ -264,13 +245,6 @@ static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb,
184 return 0;
185 }
186
187-static bool tpm_passthrough_get_startup_error(TPMBackend *tb)
188-{
189- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
190-
191- return tpm_pt->had_startup_error;
192-}
193-
194 static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
195 {
196 size_t wanted_size = 4096; /* Linux tpm.c buffer size */
197@@ -309,11 +283,6 @@ static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
198 }
199 }
200
201-static const char *tpm_passthrough_create_desc(void)
202-{
203- return "Passthrough TPM backend driver";
204-}
205-
206 static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
207 {
208 TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
209@@ -453,13 +422,10 @@ static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
210 static const TPMDriverOps tpm_passthrough_driver = {
211 .type = TPM_TYPE_PASSTHROUGH,
212 .opts = tpm_passthrough_cmdline_opts,
213- .desc = tpm_passthrough_create_desc,
214+ .desc = "Passthrough TPM backend driver",
215 .create = tpm_passthrough_create,
216- .init = tpm_passthrough_init,
217- .startup_tpm = tpm_passthrough_startup_tpm,
218 .realloc_buffer = tpm_passthrough_realloc_buffer,
219 .reset = tpm_passthrough_reset,
220- .had_startup_error = tpm_passthrough_get_startup_error,
221 .cancel_cmd = tpm_passthrough_cancel_cmd,
222 .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
223 .reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
224diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
225index 202ec8d5a2..9ea707253a 100644
226--- a/include/sysemu/tpm_backend.h
227+++ b/include/sysemu/tpm_backend.h
228@@ -47,6 +47,7 @@ struct TPMBackend {
229 TPMState *tpm_state;
230 GThreadPool *thread_pool;
231 TPMRecvDataCB *recv_data_callback;
232+ bool had_startup_error;
233
234 char *id;
235 enum TpmModel fe_model;
236@@ -75,7 +76,7 @@ struct TPMDriverOps {
237 enum TpmType type;
238 const QemuOptDesc *opts;
239 /* get a descriptive text of the backend to display to the user */
240- const char *(*desc)(void);
241+ const char *desc;
242
243 TPMBackend *(*create)(QemuOpts *opts, const char *id);
244
245@@ -83,8 +84,6 @@ struct TPMDriverOps {
246 int (*init)(TPMBackend *t);
247 /* start up the TPM on the backend */
248 int (*startup_tpm)(TPMBackend *t);
249- /* returns true if nothing will ever answer TPM requests */
250- bool (*had_startup_error)(TPMBackend *t);
251
252 size_t (*realloc_buffer)(TPMSizedBuffer *sb);
253
254@@ -109,14 +108,6 @@ struct TPMDriverOps {
255 enum TpmType tpm_backend_get_type(TPMBackend *s);
256
257 /**
258- * tpm_backend_get_desc:
259- * @s: the backend
260- *
261- * Returns a human readable description of the backend.
262- */
263-const char *tpm_backend_get_desc(TPMBackend *s);
264-
265-/**
266 * tpm_backend_init:
267 * @s: the backend to initialized
268 * @state: TPMState
269diff --git a/tpm.c b/tpm.c
270index 7feb3b43c9..9f4f37da50 100644
271--- a/tpm.c
272+++ b/tpm.c
273@@ -63,7 +63,7 @@ static void tpm_display_backend_drivers(void)
274 continue;
275 }
276 fprintf(stderr, "%12s %s\n",
277- TpmType_lookup[i], be_drivers[i]->desc());
278+ TpmType_lookup[i], be_drivers[i]->desc);
279 }
280 fprintf(stderr, "\n");
281 }
282--
2832.11.0
284
diff --git a/meta/recipes-devtools/qemu/qemu/0007-tpm-backend-Add-new-api-to-read-backend-TpmInfo.patch b/meta/recipes-devtools/qemu/qemu/0007-tpm-backend-Add-new-api-to-read-backend-TpmInfo.patch
deleted file mode 100644
index 6d79ac4d63..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0007-tpm-backend-Add-new-api-to-read-backend-TpmInfo.patch
+++ /dev/null
@@ -1,293 +0,0 @@
1From 5f698395b5de1ab2826f5aad99d757ce31d7c95f Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Mon, 6 Mar 2017 00:10:10 +0200
4Subject: [PATCH 07/12] tpm backend: Add new api to read backend TpmInfo
5
6TPM configuration options are backend implementation details and shall not be
7part of base TPMBackend object, and these shall not be accessed directly outside
8of the class, hence added a new interface method, get_tpm_options() to
9TPMDriverOps., which shall be implemented by the derived classes to return
10configured tpm options.
11
12A new tpm backend api - tpm_backend_query_tpm() which uses _get_tpm_options() to
13prepare TpmInfo.
14
15Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
16Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
17
18Upstream-Status: Backport[f59864ba3aedd26aef7c84545cc1e565caccebf7]
19---
20 backends/tpm.c | 15 +++++++++++--
21 hw/tpm/tpm_passthrough.c | 51 +++++++++++++++++++++++++++-----------------
22 include/sysemu/tpm_backend.h | 15 +++++++++++--
23 tpm.c | 32 +--------------------------
24 4 files changed, 59 insertions(+), 54 deletions(-)
25
26diff --git a/backends/tpm.c b/backends/tpm.c
27index 8911597fab..de313c9d5a 100644
28--- a/backends/tpm.c
29+++ b/backends/tpm.c
30@@ -142,6 +142,19 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
31 return k->ops->get_tpm_version(s);
32 }
33
34+TPMInfo *tpm_backend_query_tpm(TPMBackend *s)
35+{
36+ TPMInfo *info = g_new0(TPMInfo, 1);
37+ TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
38+
39+ info->id = g_strdup(s->id);
40+ info->model = s->fe_model;
41+ info->options = k->ops->get_tpm_options ?
42+ k->ops->get_tpm_options(s) : NULL;
43+
44+ return info;
45+}
46+
47 static bool tpm_backend_prop_get_opened(Object *obj, Error **errp)
48 {
49 TPMBackend *s = TPM_BACKEND(obj);
50@@ -196,8 +209,6 @@ static void tpm_backend_instance_finalize(Object *obj)
51 TPMBackend *s = TPM_BACKEND(obj);
52
53 g_free(s->id);
54- g_free(s->path);
55- g_free(s->cancel_path);
56 tpm_backend_thread_end(s);
57 }
58
59diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
60index 4c21e52b7c..84fc49a4d3 100644
61--- a/hw/tpm/tpm_passthrough.c
62+++ b/hw/tpm/tpm_passthrough.c
63@@ -30,6 +30,7 @@
64 #include "tpm_int.h"
65 #include "hw/hw.h"
66 #include "hw/i386/pc.h"
67+#include "qapi/clone-visitor.h"
68 #include "tpm_tis.h"
69 #include "tpm_util.h"
70
71@@ -49,7 +50,8 @@
72 struct TPMPassthruState {
73 TPMBackend parent;
74
75- char *tpm_dev;
76+ TPMPassthroughOptions *options;
77+ const char *tpm_dev;
78 int tpm_fd;
79 bool tpm_executing;
80 bool tpm_op_canceled;
81@@ -296,15 +298,14 @@ static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb)
82 * in Documentation/ABI/stable/sysfs-class-tpm.
83 * From /dev/tpm0 create /sys/class/misc/tpm0/device/cancel
84 */
85-static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
86+static int tpm_passthrough_open_sysfs_cancel(TPMPassthruState *tpm_pt)
87 {
88- TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
89 int fd = -1;
90 char *dev;
91 char path[PATH_MAX];
92
93- if (tb->cancel_path) {
94- fd = qemu_open(tb->cancel_path, O_WRONLY);
95+ if (tpm_pt->options->cancel_path) {
96+ fd = qemu_open(tpm_pt->options->cancel_path, O_WRONLY);
97 if (fd < 0) {
98 error_report("Could not open TPM cancel path : %s",
99 strerror(errno));
100@@ -319,7 +320,7 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb)
101 dev) < sizeof(path)) {
102 fd = qemu_open(path, O_WRONLY);
103 if (fd >= 0) {
104- tb->cancel_path = g_strdup(path);
105+ tpm_pt->options->cancel_path = g_strdup(path);
106 } else {
107 error_report("tpm_passthrough: Could not open TPM cancel "
108 "path %s : %s", path, strerror(errno));
109@@ -339,17 +340,18 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
110 const char *value;
111
112 value = qemu_opt_get(opts, "cancel-path");
113- tb->cancel_path = g_strdup(value);
114+ if (value) {
115+ tpm_pt->options->cancel_path = g_strdup(value);
116+ tpm_pt->options->has_cancel_path = true;
117+ }
118
119 value = qemu_opt_get(opts, "path");
120- if (!value) {
121- value = TPM_PASSTHROUGH_DEFAULT_DEVICE;
122+ if (value) {
123+ tpm_pt->options->has_path = true;
124+ tpm_pt->options->path = g_strdup(value);
125 }
126
127- tpm_pt->tpm_dev = g_strdup(value);
128-
129- tb->path = g_strdup(tpm_pt->tpm_dev);
130-
131+ tpm_pt->tpm_dev = value ? value : TPM_PASSTHROUGH_DEFAULT_DEVICE;
132 tpm_pt->tpm_fd = qemu_open(tpm_pt->tpm_dev, O_RDWR);
133 if (tpm_pt->tpm_fd < 0) {
134 error_report("Cannot access TPM device using '%s': %s",
135@@ -370,10 +372,8 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb)
136 tpm_pt->tpm_fd = -1;
137
138 err_free_parameters:
139- g_free(tb->path);
140- tb->path = NULL;
141-
142- g_free(tpm_pt->tpm_dev);
143+ qapi_free_TPMPassthroughOptions(tpm_pt->options);
144+ tpm_pt->options = NULL;
145 tpm_pt->tpm_dev = NULL;
146
147 return 1;
148@@ -391,7 +391,7 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id)
149 goto err_exit;
150 }
151
152- tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tb);
153+ tpm_pt->cancel_fd = tpm_passthrough_open_sysfs_cancel(tpm_pt);
154 if (tpm_pt->cancel_fd < 0) {
155 goto err_exit;
156 }
157@@ -404,6 +404,17 @@ err_exit:
158 return NULL;
159 }
160
161+static TpmTypeOptions *tpm_passthrough_get_tpm_options(TPMBackend *tb)
162+{
163+ TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
164+
165+ options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
166+ options->u.passthrough.data = QAPI_CLONE(TPMPassthroughOptions,
167+ TPM_PASSTHROUGH(tb)->options);
168+
169+ return options;
170+}
171+
172 static const QemuOptDesc tpm_passthrough_cmdline_opts[] = {
173 TPM_STANDARD_CMDLINE_OPTS,
174 {
175@@ -430,12 +441,14 @@ static const TPMDriverOps tpm_passthrough_driver = {
176 .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
177 .reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag,
178 .get_tpm_version = tpm_passthrough_get_tpm_version,
179+ .get_tpm_options = tpm_passthrough_get_tpm_options,
180 };
181
182 static void tpm_passthrough_inst_init(Object *obj)
183 {
184 TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj);
185
186+ tpm_pt->options = g_new0(TPMPassthroughOptions, 1);
187 tpm_pt->tpm_fd = -1;
188 tpm_pt->cancel_fd = -1;
189 }
190@@ -448,7 +461,7 @@ static void tpm_passthrough_inst_finalize(Object *obj)
191
192 qemu_close(tpm_pt->tpm_fd);
193 qemu_close(tpm_pt->cancel_fd);
194- g_free(tpm_pt->tpm_dev);
195+ qapi_free_TPMPassthroughOptions(tpm_pt->options);
196 }
197
198 static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
199diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
200index 9ea707253a..e96c1918cc 100644
201--- a/include/sysemu/tpm_backend.h
202+++ b/include/sysemu/tpm_backend.h
203@@ -49,10 +49,9 @@ struct TPMBackend {
204 TPMRecvDataCB *recv_data_callback;
205 bool had_startup_error;
206
207+ /* <public> */
208 char *id;
209 enum TpmModel fe_model;
210- char *path;
211- char *cancel_path;
212
213 QLIST_ENTRY(TPMBackend) list;
214 };
215@@ -96,6 +95,8 @@ struct TPMDriverOps {
216 int (*reset_tpm_established_flag)(TPMBackend *t, uint8_t locty);
217
218 TPMVersion (*get_tpm_version)(TPMBackend *t);
219+
220+ TpmTypeOptions *(*get_tpm_options)(TPMBackend *t);
221 };
222
223
224@@ -214,6 +215,16 @@ void tpm_backend_open(TPMBackend *s, Error **errp);
225 */
226 TPMVersion tpm_backend_get_tpm_version(TPMBackend *s);
227
228+/**
229+ * tpm_backend_query_tpm:
230+ * @s: the backend
231+ *
232+ * Query backend tpm info
233+ *
234+ * Returns newly allocated TPMInfo
235+ */
236+TPMInfo *tpm_backend_query_tpm(TPMBackend *s);
237+
238 TPMBackend *qemu_find_tpm(const char *id);
239
240 const TPMDriverOps *tpm_get_backend_driver(const char *type);
241diff --git a/tpm.c b/tpm.c
242index 9f4f37da50..cac400ef3e 100644
243--- a/tpm.c
244+++ b/tpm.c
245@@ -203,36 +203,6 @@ static const TPMDriverOps *tpm_driver_find_by_type(enum TpmType type)
246 return be_drivers[type];
247 }
248
249-static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv)
250-{
251- TPMInfo *res = g_new0(TPMInfo, 1);
252- TPMPassthroughOptions *tpo;
253-
254- res->id = g_strdup(drv->id);
255- res->model = drv->fe_model;
256- res->options = g_new0(TpmTypeOptions, 1);
257-
258- switch (tpm_backend_get_type(drv)) {
259- case TPM_TYPE_PASSTHROUGH:
260- res->options->type = TPM_TYPE_OPTIONS_KIND_PASSTHROUGH;
261- tpo = g_new0(TPMPassthroughOptions, 1);
262- res->options->u.passthrough.data = tpo;
263- if (drv->path) {
264- tpo->path = g_strdup(drv->path);
265- tpo->has_path = true;
266- }
267- if (drv->cancel_path) {
268- tpo->cancel_path = g_strdup(drv->cancel_path);
269- tpo->has_cancel_path = true;
270- }
271- break;
272- case TPM_TYPE__MAX:
273- break;
274- }
275-
276- return res;
277-}
278-
279 /*
280 * Walk the list of active TPM backends and collect information about them
281 * following the schema description in qapi-schema.json.
282@@ -247,7 +217,7 @@ TPMInfoList *qmp_query_tpm(Error **errp)
283 continue;
284 }
285 info = g_new0(TPMInfoList, 1);
286- info->value = qmp_query_tpm_inst(drv);
287+ info->value = tpm_backend_query_tpm(drv);
288
289 if (!cur_item) {
290 head = cur_item = info;
291--
2922.11.0
293
diff --git a/meta/recipes-devtools/qemu/qemu/0008-tpm-backend-Move-realloc_buffer-implementation-to-tp.patch b/meta/recipes-devtools/qemu/qemu/0008-tpm-backend-Move-realloc_buffer-implementation-to-tp.patch
deleted file mode 100644
index 94cc6c542c..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0008-tpm-backend-Move-realloc_buffer-implementation-to-tp.patch
+++ /dev/null
@@ -1,140 +0,0 @@
1From 02189909fdc5e73b3ca54362084c16f0b67a3fdf Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Fri, 7 Apr 2017 10:57:28 +0300
4Subject: [PATCH 08/12] tpm-backend: Move realloc_buffer() implementation to
5 tpm-tis model
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10buffer reallocation is very unlikely to be backend specific. Hence move inside
11the tis.
12
13Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
14Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
15Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
16
17Upstream-Status: Backport [d0c519bdffa303d141727369e55b157c45b03147]
18---
19 backends/tpm.c | 9 ---------
20 hw/tpm/tpm_passthrough.c | 12 ------------
21 hw/tpm/tpm_tis.c | 14 ++++++++++++--
22 include/sysemu/tpm_backend.h | 12 ------------
23 4 files changed, 12 insertions(+), 35 deletions(-)
24
25diff --git a/backends/tpm.c b/backends/tpm.c
26index de313c9d5a..37c84b7c66 100644
27--- a/backends/tpm.c
28+++ b/backends/tpm.c
29@@ -80,15 +80,6 @@ bool tpm_backend_had_startup_error(TPMBackend *s)
30 return s->had_startup_error;
31 }
32
33-size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb)
34-{
35- TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
36-
37- assert(k->ops->realloc_buffer);
38-
39- return k->ops->realloc_buffer(sb);
40-}
41-
42 void tpm_backend_deliver_request(TPMBackend *s)
43 {
44 g_thread_pool_push(s->thread_pool, (gpointer)TPM_BACKEND_CMD_PROCESS_CMD,
45diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
46index 84fc49a4d3..22d3460550 100644
47--- a/hw/tpm/tpm_passthrough.c
48+++ b/hw/tpm/tpm_passthrough.c
49@@ -247,17 +247,6 @@ static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb,
50 return 0;
51 }
52
53-static size_t tpm_passthrough_realloc_buffer(TPMSizedBuffer *sb)
54-{
55- size_t wanted_size = 4096; /* Linux tpm.c buffer size */
56-
57- if (sb->size != wanted_size) {
58- sb->buffer = g_realloc(sb->buffer, wanted_size);
59- sb->size = wanted_size;
60- }
61- return sb->size;
62-}
63-
64 static void tpm_passthrough_cancel_cmd(TPMBackend *tb)
65 {
66 TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb);
67@@ -435,7 +424,6 @@ static const TPMDriverOps tpm_passthrough_driver = {
68 .opts = tpm_passthrough_cmdline_opts,
69 .desc = "Passthrough TPM backend driver",
70 .create = tpm_passthrough_create,
71- .realloc_buffer = tpm_passthrough_realloc_buffer,
72 .reset = tpm_passthrough_reset,
73 .cancel_cmd = tpm_passthrough_cancel_cmd,
74 .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag,
75diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
76index a6440fef91..d5118e7f60 100644
77--- a/hw/tpm/tpm_tis.c
78+++ b/hw/tpm/tpm_tis.c
79@@ -963,6 +963,16 @@ static int tpm_tis_do_startup_tpm(TPMState *s)
80 return tpm_backend_startup_tpm(s->be_driver);
81 }
82
83+static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb)
84+{
85+ size_t wanted_size = 4096; /* Linux tpm.c buffer size */
86+
87+ if (sb->size != wanted_size) {
88+ sb->buffer = g_realloc(sb->buffer, wanted_size);
89+ sb->size = wanted_size;
90+ }
91+}
92+
93 /*
94 * Get the TPMVersion of the backend device being used
95 */
96@@ -1010,9 +1020,9 @@ static void tpm_tis_reset(DeviceState *dev)
97 tis->loc[c].state = TPM_TIS_STATE_IDLE;
98
99 tis->loc[c].w_offset = 0;
100- tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer);
101+ tpm_tis_realloc_buffer(&tis->loc[c].w_buffer);
102 tis->loc[c].r_offset = 0;
103- tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer);
104+ tpm_tis_realloc_buffer(&tis->loc[c].r_buffer);
105 }
106
107 tpm_tis_do_startup_tpm(s);
108diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
109index e96c1918cc..2c798a1eb4 100644
110--- a/include/sysemu/tpm_backend.h
111+++ b/include/sysemu/tpm_backend.h
112@@ -84,8 +84,6 @@ struct TPMDriverOps {
113 /* start up the TPM on the backend */
114 int (*startup_tpm)(TPMBackend *t);
115
116- size_t (*realloc_buffer)(TPMSizedBuffer *sb);
117-
118 void (*reset)(TPMBackend *t);
119
120 void (*cancel_cmd)(TPMBackend *t);
121@@ -140,16 +138,6 @@ int tpm_backend_startup_tpm(TPMBackend *s);
122 bool tpm_backend_had_startup_error(TPMBackend *s);
123
124 /**
125- * tpm_backend_realloc_buffer:
126- * @s: the backend
127- * @sb: the TPMSizedBuffer to re-allocated to the size suitable for the
128- * backend.
129- *
130- * This function returns the size of the allocated buffer
131- */
132-size_t tpm_backend_realloc_buffer(TPMBackend *s, TPMSizedBuffer *sb);
133-
134-/**
135 * tpm_backend_deliver_request:
136 * @s: the backend to send the request to
137 *
138--
1392.11.0
140
diff --git a/meta/recipes-devtools/qemu/qemu/0009-tpm-passthrough-move-reusable-code-to-utils.patch b/meta/recipes-devtools/qemu/qemu/0009-tpm-passthrough-move-reusable-code-to-utils.patch
deleted file mode 100644
index 8670b8a0d3..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0009-tpm-passthrough-move-reusable-code-to-utils.patch
+++ /dev/null
@@ -1,182 +0,0 @@
1From b8322aaa2f31995e1b7b776e7efae68416573bc3 Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Wed, 29 Mar 2017 15:36:47 +0300
4Subject: [PATCH 09/12] tpm-passthrough: move reusable code to utils
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
10Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
11Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
12
13Upstream-Status: Backport [4a3d80980ebf71d8faf9d0ce2e2e23bdda5728df]
14---
15 hw/tpm/tpm_passthrough.c | 64 ++++--------------------------------------------
16 hw/tpm/tpm_util.c | 25 +++++++++++++++++++
17 hw/tpm/tpm_util.h | 4 +++
18 3 files changed, 34 insertions(+), 59 deletions(-)
19
20diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
21index 22d3460550..e6ace28b04 100644
22--- a/hw/tpm/tpm_passthrough.c
23+++ b/hw/tpm/tpm_passthrough.c
24@@ -68,27 +68,6 @@ typedef struct TPMPassthruState TPMPassthruState;
25
26 static void tpm_passthrough_cancel_cmd(TPMBackend *tb);
27
28-static int tpm_passthrough_unix_write(int fd, const uint8_t *buf, uint32_t len)
29-{
30- int ret, remain;
31-
32- remain = len;
33- while (remain > 0) {
34- ret = write(fd, buf, remain);
35- if (ret < 0) {
36- if (errno != EINTR && errno != EAGAIN) {
37- return -1;
38- }
39- } else if (ret == 0) {
40- break;
41- } else {
42- buf += ret;
43- remain -= ret;
44- }
45- }
46- return len - remain;
47-}
48-
49 static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
50 {
51 int ret;
52@@ -102,45 +81,12 @@ static int tpm_passthrough_unix_read(int fd, uint8_t *buf, uint32_t len)
53 }
54 return ret;
55 }
56-
57-static uint32_t tpm_passthrough_get_size_from_buffer(const uint8_t *buf)
58-{
59- struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)buf;
60-
61- return be32_to_cpu(resp->len);
62-}
63-
64-/*
65- * Write an error message in the given output buffer.
66- */
67-static void tpm_write_fatal_error_response(uint8_t *out, uint32_t out_len)
68-{
69- if (out_len >= sizeof(struct tpm_resp_hdr)) {
70- struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)out;
71-
72- resp->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
73- resp->len = cpu_to_be32(sizeof(struct tpm_resp_hdr));
74- resp->errcode = cpu_to_be32(TPM_FAIL);
75- }
76-}
77-
78-static bool tpm_passthrough_is_selftest(const uint8_t *in, uint32_t in_len)
79-{
80- struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in;
81-
82- if (in_len >= sizeof(*hdr)) {
83- return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest);
84- }
85-
86- return false;
87-}
88-
89 static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
90 const uint8_t *in, uint32_t in_len,
91 uint8_t *out, uint32_t out_len,
92 bool *selftest_done)
93 {
94- int ret;
95+ ssize_t ret;
96 bool is_selftest;
97 const struct tpm_resp_hdr *hdr;
98
99@@ -148,9 +94,9 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
100 tpm_pt->tpm_executing = true;
101 *selftest_done = false;
102
103- is_selftest = tpm_passthrough_is_selftest(in, in_len);
104+ is_selftest = tpm_util_is_selftest(in, in_len);
105
106- ret = tpm_passthrough_unix_write(tpm_pt->tpm_fd, in, in_len);
107+ ret = qemu_write_full(tpm_pt->tpm_fd, (const void *)in, (size_t)in_len);
108 if (ret != in_len) {
109 if (!tpm_pt->tpm_op_canceled || errno != ECANCELED) {
110 error_report("tpm_passthrough: error while transmitting data "
111@@ -170,7 +116,7 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
112 strerror(errno), errno);
113 }
114 } else if (ret < sizeof(struct tpm_resp_hdr) ||
115- tpm_passthrough_get_size_from_buffer(out) != ret) {
116+ be32_to_cpu(((struct tpm_resp_hdr *)out)->len) != ret) {
117 ret = -1;
118 error_report("tpm_passthrough: received invalid response "
119 "packet from TPM");
120@@ -183,7 +129,7 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt,
121
122 err_exit:
123 if (ret < 0) {
124- tpm_write_fatal_error_response(out, out_len);
125+ tpm_util_write_fatal_error_response(out, out_len);
126 }
127
128 tpm_pt->tpm_executing = false;
129diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c
130index 7b35429725..fb929f6e92 100644
131--- a/hw/tpm/tpm_util.c
132+++ b/hw/tpm/tpm_util.c
133@@ -24,6 +24,31 @@
134 #include "tpm_int.h"
135
136 /*
137+ * Write an error message in the given output buffer.
138+ */
139+void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len)
140+{
141+ if (out_len >= sizeof(struct tpm_resp_hdr)) {
142+ struct tpm_resp_hdr *resp = (struct tpm_resp_hdr *)out;
143+
144+ resp->tag = cpu_to_be16(TPM_TAG_RSP_COMMAND);
145+ resp->len = cpu_to_be32(sizeof(struct tpm_resp_hdr));
146+ resp->errcode = cpu_to_be32(TPM_FAIL);
147+ }
148+}
149+
150+bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len)
151+{
152+ struct tpm_req_hdr *hdr = (struct tpm_req_hdr *)in;
153+
154+ if (in_len >= sizeof(*hdr)) {
155+ return (be32_to_cpu(hdr->ordinal) == TPM_ORD_ContinueSelfTest);
156+ }
157+
158+ return false;
159+}
160+
161+/*
162 * A basic test of a TPM device. We expect a well formatted response header
163 * (error response is fine) within one second.
164 */
165diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h
166index df76245e6e..2f7c96146d 100644
167--- a/hw/tpm/tpm_util.h
168+++ b/hw/tpm/tpm_util.h
169@@ -24,6 +24,10 @@
170
171 #include "sysemu/tpm_backend.h"
172
173+void tpm_util_write_fatal_error_response(uint8_t *out, uint32_t out_len);
174+
175+bool tpm_util_is_selftest(const uint8_t *in, uint32_t in_len);
176+
177 int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version);
178
179 #endif /* TPM_TPM_UTIL_H */
180--
1812.11.0
182
diff --git a/meta/recipes-devtools/qemu/qemu/0010-tpm-Added-support-for-TPM-emulator.patch b/meta/recipes-devtools/qemu/qemu/0010-tpm-Added-support-for-TPM-emulator.patch
deleted file mode 100644
index 968e12e88a..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0010-tpm-Added-support-for-TPM-emulator.patch
+++ /dev/null
@@ -1,1059 +0,0 @@
1From 70e73b7c6c7cf982d645db9c81c74588e6b10a2b Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Wed, 29 Mar 2017 15:39:41 +0300
4Subject: [PATCH 10/12] tpm: Added support for TPM emulator
5
6This change introduces a new TPM backend driver that can communicate with
7swtpm(software TPM emulator) using unix domain socket interface. QEMU talks to
8TPM emulator using QEMU's socket-based chardev backend device.
9
10Swtpm uses two Unix sockets for communications, one for plain TPM commands and
11responses, and one for out-of-band control messages. QEMU passes data socket to
12be used over the control channel.
13
14The swtpm and associated tools can be found here:
15 https://github.com/stefanberger/swtpm
16
17The swtpm's control channel protocol specification can be found here:
18 https://github.com/stefanberger/swtpm/wiki/Control-Channel-Specification
19
20Usage:
21 # setup TPM state directory
22 mkdir /tmp/mytpm
23 chown -R tss:root /tmp/mytpm
24 /usr/bin/swtpm_setup --tpm-state /tmp/mytpm --createek
25
26 # Ask qemu to use TPM emulator with given tpm state directory
27 qemu-system-x86_64 \
28 [...] \
29 -chardev socket,id=chrtpm,path=/tmp/swtpm-sock \
30 -tpmdev emulator,id=tpm0,chardev=chrtpm \
31 -device tpm-tis,tpmdev=tpm0 \
32 [...]
33
34Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
35
36Upstream-Status: Backport [f4ede81eed29e6140374177d1f2808248c5b5650]
37---
38 configure | 13 +-
39 hmp.c | 5 +
40 hw/tpm/Makefile.objs | 1 +
41 hw/tpm/tpm_emulator.c | 583 ++++++++++++++++++++++++++++++++++++++++++++++++++
42 hw/tpm/tpm_ioctl.h | 246 +++++++++++++++++++++
43 qapi-schema.json | 18 +-
44 qemu-options.hx | 22 +-
45 7 files changed, 882 insertions(+), 6 deletions(-)
46 create mode 100644 hw/tpm/tpm_emulator.c
47 create mode 100644 hw/tpm/tpm_ioctl.h
48
49diff --git a/configure b/configure
50index dd73cce62f..9a25537096 100755
51--- a/configure
52+++ b/configure
53@@ -3503,6 +3503,12 @@ else
54 tpm_passthrough=no
55 fi
56
57+# TPM emulator is for all posix systems
58+if test "$mingw32" != "yes"; then
59+ tpm_emulator=$tpm
60+else
61+ tpm_emulator=no
62+fi
63 ##########################################
64 # attr probe
65
66@@ -5396,6 +5402,7 @@ echo "gcov enabled $gcov"
67 echo "TPM support $tpm"
68 echo "libssh2 support $libssh2"
69 echo "TPM passthrough $tpm_passthrough"
70+echo "TPM emulator $tpm_emulator"
71 echo "QOM debugging $qom_cast_debug"
72 echo "Live block migration $live_block_migration"
73 echo "lzo support $lzo"
74@@ -5983,12 +5990,16 @@ else
75 echo "HOST_USB=stub" >> $config_host_mak
76 fi
77
78-# TPM passthrough support?
79 if test "$tpm" = "yes"; then
80 echo 'CONFIG_TPM=$(CONFIG_SOFTMMU)' >> $config_host_mak
81+ # TPM passthrough support?
82 if test "$tpm_passthrough" = "yes"; then
83 echo "CONFIG_TPM_PASSTHROUGH=y" >> $config_host_mak
84 fi
85+ # TPM emulator support?
86+ if test "$tpm_emulator" = "yes"; then
87+ echo "CONFIG_TPM_EMULATOR=y" >> $config_host_mak
88+ fi
89 fi
90
91 echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak
92diff --git a/hmp.c b/hmp.c
93index fd80dce758..820aa8f002 100644
94--- a/hmp.c
95+++ b/hmp.c
96@@ -995,6 +995,7 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
97 Error *err = NULL;
98 unsigned int c = 0;
99 TPMPassthroughOptions *tpo;
100+ TPMEmulatorOptions *teo;
101
102 info_list = qmp_query_tpm(&err);
103 if (err) {
104@@ -1024,6 +1025,10 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict)
105 tpo->has_cancel_path ? ",cancel-path=" : "",
106 tpo->has_cancel_path ? tpo->cancel_path : "");
107 break;
108+ case TPM_TYPE_OPTIONS_KIND_EMULATOR:
109+ teo = ti->options->u.emulator.data;
110+ monitor_printf(mon, ",chardev=%s", teo->chardev);
111+ break;
112 case TPM_TYPE_OPTIONS_KIND__MAX:
113 break;
114 }
115diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
116index 64cecc3b67..41f0b7a590 100644
117--- a/hw/tpm/Makefile.objs
118+++ b/hw/tpm/Makefile.objs
119@@ -1,2 +1,3 @@
120 common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
121 common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o tpm_util.o
122+common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o tpm_util.o
123diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
124new file mode 100644
125index 0000000000..433bc4fa8a
126--- /dev/null
127+++ b/hw/tpm/tpm_emulator.c
128@@ -0,0 +1,583 @@
129+/*
130+ * Emulator TPM driver
131+ *
132+ * Copyright (c) 2017 Intel Corporation
133+ * Author: Amarnath Valluri <amarnath.valluri@intel.com>
134+ *
135+ * Copyright (c) 2010 - 2013 IBM Corporation
136+ * Authors:
137+ * Stefan Berger <stefanb@us.ibm.com>
138+ *
139+ * Copyright (C) 2011 IAIK, Graz University of Technology
140+ * Author: Andreas Niederl
141+ *
142+ * This library is free software; you can redistribute it and/or
143+ * modify it under the terms of the GNU Lesser General Public
144+ * License as published by the Free Software Foundation; either
145+ * version 2 of the License, or (at your option) any later version.
146+ *
147+ * This library is distributed in the hope that it will be useful,
148+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
149+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
150+ * Lesser General Public License for more details.
151+ *
152+ * You should have received a copy of the GNU Lesser General Public
153+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
154+ *
155+ */
156+
157+#include "qemu/osdep.h"
158+#include "qemu/error-report.h"
159+#include "qemu/sockets.h"
160+#include "io/channel-socket.h"
161+#include "sysemu/tpm_backend.h"
162+#include "tpm_int.h"
163+#include "hw/hw.h"
164+#include "hw/i386/pc.h"
165+#include "tpm_util.h"
166+#include "tpm_ioctl.h"
167+#include "migration/blocker.h"
168+#include "qapi/error.h"
169+#include "qapi/clone-visitor.h"
170+#include "chardev/char-fe.h"
171+
172+#include <fcntl.h>
173+#include <sys/types.h>
174+#include <sys/stat.h>
175+#include <stdio.h>
176+
177+#define DEBUG_TPM 0
178+
179+#define DPRINTF(fmt, ...) do { \
180+ if (DEBUG_TPM) { \
181+ fprintf(stderr, "tpm-emulator:"fmt"\n", ## __VA_ARGS__); \
182+ } \
183+} while (0)
184+
185+#define TYPE_TPM_EMULATOR "tpm-emulator"
186+#define TPM_EMULATOR(obj) \
187+ OBJECT_CHECK(TPMEmulator, (obj), TYPE_TPM_EMULATOR)
188+
189+#define TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(S, cap) (((S)->caps & (cap)) == (cap))
190+
191+static const TPMDriverOps tpm_emulator_driver;
192+
193+/* data structures */
194+typedef struct TPMEmulator {
195+ TPMBackend parent;
196+
197+ TPMEmulatorOptions *options;
198+ CharBackend ctrl_chr;
199+ QIOChannel *data_ioc;
200+ TPMVersion tpm_version;
201+ ptm_cap caps; /* capabilities of the TPM */
202+ uint8_t cur_locty_number; /* last set locality */
203+ Error *migration_blocker;
204+} TPMEmulator;
205+
206+
207+static int tpm_emulator_ctrlcmd(CharBackend *dev, unsigned long cmd, void *msg,
208+ size_t msg_len_in, size_t msg_len_out)
209+{
210+ uint32_t cmd_no = cpu_to_be32(cmd);
211+ ssize_t n = sizeof(uint32_t) + msg_len_in;
212+ uint8_t *buf = NULL;
213+
214+ buf = g_alloca(n);
215+ memcpy(buf, &cmd_no, sizeof(cmd_no));
216+ memcpy(buf + sizeof(cmd_no), msg, msg_len_in);
217+
218+ n = qemu_chr_fe_write_all(dev, buf, n);
219+ if (n <= 0) {
220+ return -1;
221+ }
222+
223+ if (msg_len_out != 0) {
224+ n = qemu_chr_fe_read_all(dev, msg, msg_len_out);
225+ if (n <= 0) {
226+ return -1;
227+ }
228+ }
229+
230+ return 0;
231+}
232+
233+static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
234+ const uint8_t *in, uint32_t in_len,
235+ uint8_t *out, uint32_t out_len,
236+ bool *selftest_done,
237+ Error **err)
238+{
239+ ssize_t ret;
240+ bool is_selftest = false;
241+ const struct tpm_resp_hdr *hdr = NULL;
242+
243+ if (selftest_done) {
244+ *selftest_done = false;
245+ is_selftest = tpm_util_is_selftest(in, in_len);
246+ }
247+
248+ ret = qio_channel_write(tpm_emu->data_ioc, (char *)in, in_len, err);
249+ if (ret != in_len) {
250+ return -1;
251+ }
252+
253+ ret = qio_channel_read(tpm_emu->data_ioc, (char *)out, out_len, err);
254+ if (ret <= 0 || ret < sizeof(*hdr)) {
255+ return -1;
256+ }
257+
258+ hdr = (struct tpm_resp_hdr *)out;
259+ if (be32_to_cpu(hdr->len) != ret) {
260+ return -1;
261+ }
262+
263+ if (is_selftest) {
264+ *selftest_done = (be32_to_cpu(hdr->errcode) == 0);
265+ }
266+
267+ return 0;
268+}
269+
270+static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number)
271+{
272+ ptm_loc loc;
273+
274+ DPRINTF("%s : locality: 0x%x", __func__, locty_number);
275+
276+ if (tpm_emu->cur_locty_number == locty_number) {
277+ return 0;
278+ }
279+
280+ DPRINTF("setting locality : 0x%x", locty_number);
281+ loc.u.req.loc = locty_number;
282+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SET_LOCALITY, &loc,
283+ sizeof(loc), sizeof(loc)) < 0) {
284+ error_report("tpm-emulator: could not set locality : %s",
285+ strerror(errno));
286+ return -1;
287+ }
288+
289+ loc.u.resp.tpm_result = be32_to_cpu(loc.u.resp.tpm_result);
290+ if (loc.u.resp.tpm_result != 0) {
291+ error_report("tpm-emulator: TPM result for set locality : 0x%x",
292+ loc.u.resp.tpm_result);
293+ return -1;
294+ }
295+
296+ tpm_emu->cur_locty_number = locty_number;
297+
298+ return 0;
299+}
300+
301+static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd cmd)
302+{
303+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
304+ TPMLocality *locty = NULL;
305+ bool selftest_done = false;
306+ Error *err = NULL;
307+
308+ DPRINTF("processing command type %d", cmd);
309+
310+ switch (cmd) {
311+ case TPM_BACKEND_CMD_PROCESS_CMD:
312+ locty = tb->tpm_state->locty_data;
313+ if (tpm_emulator_set_locality(tpm_emu,
314+ tb->tpm_state->locty_number) < 0 ||
315+ tpm_emulator_unix_tx_bufs(tpm_emu, locty->w_buffer.buffer,
316+ locty->w_offset, locty->r_buffer.buffer,
317+ locty->r_buffer.size, &selftest_done,
318+ &err) < 0) {
319+ tpm_util_write_fatal_error_response(locty->r_buffer.buffer,
320+ locty->r_buffer.size);
321+ error_report_err(err);
322+ }
323+
324+ tb->recv_data_callback(tb->tpm_state, tb->tpm_state->locty_number,
325+ selftest_done);
326+
327+ break;
328+ case TPM_BACKEND_CMD_INIT:
329+ case TPM_BACKEND_CMD_END:
330+ case TPM_BACKEND_CMD_TPM_RESET:
331+ /* nothing to do */
332+ break;
333+ }
334+}
335+
336+static int tpm_emulator_probe_caps(TPMEmulator *tpm_emu)
337+{
338+ DPRINTF("%s", __func__);
339+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_GET_CAPABILITY,
340+ &tpm_emu->caps, 0, sizeof(tpm_emu->caps)) < 0) {
341+ error_report("tpm-emulator: probing failed : %s", strerror(errno));
342+ return -1;
343+ }
344+
345+ tpm_emu->caps = be64_to_cpu(tpm_emu->caps);
346+
347+ DPRINTF("capbilities : 0x%lx", tpm_emu->caps);
348+
349+ return 0;
350+}
351+
352+static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
353+{
354+ ptm_cap caps = 0;
355+ const char *tpm = NULL;
356+
357+ /* check for min. required capabilities */
358+ switch (tpm_emu->tpm_version) {
359+ case TPM_VERSION_1_2:
360+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
361+ PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD;
362+ tpm = "1.2";
363+ break;
364+ case TPM_VERSION_2_0:
365+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
366+ PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED |
367+ PTM_CAP_SET_DATAFD;
368+ tpm = "2";
369+ break;
370+ case TPM_VERSION_UNSPEC:
371+ error_report("tpm-emulator: TPM version has not been set");
372+ return -1;
373+ }
374+
375+ if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, caps)) {
376+ error_report("tpm-emulator: TPM does not implement minimum set of "
377+ "required capabilities for TPM %s (0x%x)", tpm, (int)caps);
378+ return -1;
379+ }
380+
381+ return 0;
382+}
383+
384+static int tpm_emulator_startup_tpm(TPMBackend *tb)
385+{
386+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
387+ ptm_init init;
388+ ptm_res res;
389+
390+ DPRINTF("%s", __func__);
391+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_INIT, &init, sizeof(init),
392+ sizeof(init)) < 0) {
393+ error_report("tpm-emulator: could not send INIT: %s",
394+ strerror(errno));
395+ goto err_exit;
396+ }
397+
398+ res = be32_to_cpu(init.u.resp.tpm_result);
399+ if (res) {
400+ error_report("tpm-emulator: TPM result for CMD_INIT: 0x%x", res);
401+ goto err_exit;
402+ }
403+ return 0;
404+
405+err_exit:
406+ return -1;
407+}
408+
409+static bool tpm_emulator_get_tpm_established_flag(TPMBackend *tb)
410+{
411+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
412+ ptm_est est;
413+
414+ DPRINTF("%s", __func__);
415+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_GET_TPMESTABLISHED, &est,
416+ 0, sizeof(est)) < 0) {
417+ error_report("tpm-emulator: Could not get the TPM established flag: %s",
418+ strerror(errno));
419+ return false;
420+ }
421+ DPRINTF("established flag: %0x", est.u.resp.bit);
422+
423+ return (est.u.resp.bit != 0);
424+}
425+
426+static int tpm_emulator_reset_tpm_established_flag(TPMBackend *tb,
427+ uint8_t locty)
428+{
429+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
430+ ptm_reset_est reset_est;
431+ ptm_res res;
432+
433+ /* only a TPM 2.0 will support this */
434+ if (tpm_emu->tpm_version != TPM_VERSION_2_0) {
435+ return 0;
436+ }
437+
438+ reset_est.u.req.loc = tpm_emu->cur_locty_number;
439+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_RESET_TPMESTABLISHED,
440+ &reset_est, sizeof(reset_est),
441+ sizeof(reset_est)) < 0) {
442+ error_report("tpm-emulator: Could not reset the establishment bit: %s",
443+ strerror(errno));
444+ return -1;
445+ }
446+
447+ res = be32_to_cpu(reset_est.u.resp.tpm_result);
448+ if (res) {
449+ error_report("tpm-emulator: TPM result for rest establixhed flag: 0x%x",
450+ res);
451+ return -1;
452+ }
453+
454+ return 0;
455+}
456+
457+static void tpm_emulator_cancel_cmd(TPMBackend *tb)
458+{
459+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
460+ ptm_res res;
461+
462+ if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, PTM_CAP_CANCEL_TPM_CMD)) {
463+ DPRINTF("Backend does not support CANCEL_TPM_CMD");
464+ return;
465+ }
466+
467+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_CANCEL_TPM_CMD, &res, 0,
468+ sizeof(res)) < 0) {
469+ error_report("tpm-emulator: Could not cancel command: %s",
470+ strerror(errno));
471+ } else if (res != 0) {
472+ error_report("tpm-emulator: Failed to cancel TPM: 0x%x",
473+ be32_to_cpu(res));
474+ }
475+}
476+
477+static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
478+{
479+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
480+
481+ return tpm_emu->tpm_version;
482+}
483+
484+static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
485+{
486+ Error *err = NULL;
487+
488+ error_setg(&tpm_emu->migration_blocker,
489+ "Migration disabled: TPM emulator not yet migratable");
490+ migrate_add_blocker(tpm_emu->migration_blocker, &err);
491+ if (err) {
492+ error_report_err(err);
493+ error_free(tpm_emu->migration_blocker);
494+ tpm_emu->migration_blocker = NULL;
495+
496+ return -1;
497+ }
498+
499+ return 0;
500+}
501+
502+static int tpm_emulator_prepare_data_fd(TPMEmulator *tpm_emu)
503+{
504+ ptm_res res;
505+ Error *err = NULL;
506+ int fds[2] = { -1, -1 };
507+
508+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
509+ error_report("tpm-emulator: Failed to create socketpair");
510+ return -1;
511+ }
512+
513+ qemu_chr_fe_set_msgfds(&tpm_emu->ctrl_chr, fds + 1, 1);
514+
515+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SET_DATAFD, &res, 0,
516+ sizeof(res)) || res != 0) {
517+ error_report("tpm-emulator: Failed to send CMD_SET_DATAFD: %s",
518+ strerror(errno));
519+ goto err_exit;
520+ }
521+
522+ tpm_emu->data_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(fds[0], &err));
523+ if (err) {
524+ error_prepend(&err, "tpm-emulator: Failed to create io channel: ");
525+ error_report_err(err);
526+ goto err_exit;
527+ }
528+
529+ closesocket(fds[1]);
530+
531+ return 0;
532+
533+err_exit:
534+ closesocket(fds[0]);
535+ closesocket(fds[1]);
536+ return -1;
537+}
538+
539+static int tpm_emulator_handle_device_opts(TPMEmulator *tpm_emu, QemuOpts *opts)
540+{
541+ const char *value;
542+
543+ value = qemu_opt_get(opts, "chardev");
544+ if (value) {
545+ Error *err = NULL;
546+ Chardev *dev = qemu_chr_find(value);
547+
548+ if (!dev) {
549+ error_report("tpm-emulator: tpm chardev '%s' not found.", value);
550+ goto err;
551+ }
552+
553+ if (!qemu_chr_fe_init(&tpm_emu->ctrl_chr, dev, &err)) {
554+ error_prepend(&err, "tpm-emulator: No valid chardev found at '%s':",
555+ value);
556+ error_report_err(err);
557+ goto err;
558+ }
559+
560+ tpm_emu->options->chardev = g_strdup(value);
561+ }
562+
563+ if (tpm_emulator_prepare_data_fd(tpm_emu) < 0) {
564+ goto err;
565+ }
566+
567+ /* FIXME: tpm_util_test_tpmdev() accepts only on socket fd, as it also used
568+ * by passthrough driver, which not yet using GIOChannel.
569+ */
570+ if (tpm_util_test_tpmdev(QIO_CHANNEL_SOCKET(tpm_emu->data_ioc)->fd,
571+ &tpm_emu->tpm_version)) {
572+ error_report("'%s' is not emulating TPM device. Error: %s",
573+ tpm_emu->options->chardev, strerror(errno));
574+ goto err;
575+ }
576+
577+ DPRINTF("TPM Version %s", tpm_emu->tpm_version == TPM_VERSION_1_2 ? "1.2" :
578+ (tpm_emu->tpm_version == TPM_VERSION_2_0 ? "2.0" : "Unspecified"));
579+
580+ if (tpm_emulator_probe_caps(tpm_emu) ||
581+ tpm_emulator_check_caps(tpm_emu)) {
582+ goto err;
583+ }
584+
585+ return tpm_emulator_block_migration(tpm_emu);
586+
587+err:
588+ DPRINTF("Startup error");
589+ return -1;
590+}
591+
592+static TPMBackend *tpm_emulator_create(QemuOpts *opts, const char *id)
593+{
594+ TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR));
595+
596+ tb->id = g_strdup(id);
597+
598+ if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) {
599+ goto err_exit;
600+ }
601+
602+ return tb;
603+
604+err_exit:
605+ object_unref(OBJECT(tb));
606+
607+ return NULL;
608+}
609+
610+static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb)
611+{
612+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
613+ TpmTypeOptions *options = g_new0(TpmTypeOptions, 1);
614+
615+ options->type = TPM_TYPE_OPTIONS_KIND_EMULATOR;
616+ options->u.emulator.data = QAPI_CLONE(TPMEmulatorOptions, tpm_emu->options);
617+
618+ return options;
619+}
620+
621+static const QemuOptDesc tpm_emulator_cmdline_opts[] = {
622+ TPM_STANDARD_CMDLINE_OPTS,
623+ {
624+ .name = "chardev",
625+ .type = QEMU_OPT_STRING,
626+ .help = "Character device to use for out-of-band control messages",
627+ },
628+ { /* end of list */ },
629+};
630+
631+static const TPMDriverOps tpm_emulator_driver = {
632+ .type = TPM_TYPE_EMULATOR,
633+ .opts = tpm_emulator_cmdline_opts,
634+ .desc = "TPM emulator backend driver",
635+
636+ .create = tpm_emulator_create,
637+ .startup_tpm = tpm_emulator_startup_tpm,
638+ .cancel_cmd = tpm_emulator_cancel_cmd,
639+ .get_tpm_established_flag = tpm_emulator_get_tpm_established_flag,
640+ .reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag,
641+ .get_tpm_version = tpm_emulator_get_tpm_version,
642+ .get_tpm_options = tpm_emulator_get_tpm_options,
643+};
644+
645+static void tpm_emulator_inst_init(Object *obj)
646+{
647+ TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
648+
649+ DPRINTF("%s", __func__);
650+ tpm_emu->options = g_new0(TPMEmulatorOptions, 1);
651+ tpm_emu->cur_locty_number = ~0;
652+}
653+
654+/*
655+ * Gracefully shut down the external TPM
656+ */
657+static void tpm_emulator_shutdown(TPMEmulator *tpm_emu)
658+{
659+ ptm_res res;
660+
661+ if (tpm_emulator_ctrlcmd(&tpm_emu->ctrl_chr, CMD_SHUTDOWN, &res, 0,
662+ sizeof(res)) < 0) {
663+ error_report("tpm-emulator: Could not cleanly shutdown the TPM: %s",
664+ strerror(errno));
665+ } else if (res != 0) {
666+ error_report("tpm-emulator: TPM result for sutdown: 0x%x",
667+ be32_to_cpu(res));
668+ }
669+}
670+
671+static void tpm_emulator_inst_finalize(Object *obj)
672+{
673+ TPMEmulator *tpm_emu = TPM_EMULATOR(obj);
674+
675+ tpm_emulator_shutdown(tpm_emu);
676+
677+ object_unref(OBJECT(tpm_emu->data_ioc));
678+
679+ qemu_chr_fe_deinit(&tpm_emu->ctrl_chr, false);
680+
681+ qapi_free_TPMEmulatorOptions(tpm_emu->options);
682+
683+ if (tpm_emu->migration_blocker) {
684+ migrate_del_blocker(tpm_emu->migration_blocker);
685+ error_free(tpm_emu->migration_blocker);
686+ }
687+}
688+
689+static void tpm_emulator_class_init(ObjectClass *klass, void *data)
690+{
691+ TPMBackendClass *tbc = TPM_BACKEND_CLASS(klass);
692+ tbc->ops = &tpm_emulator_driver;
693+ tbc->handle_request = tpm_emulator_handle_request;
694+}
695+
696+static const TypeInfo tpm_emulator_info = {
697+ .name = TYPE_TPM_EMULATOR,
698+ .parent = TYPE_TPM_BACKEND,
699+ .instance_size = sizeof(TPMEmulator),
700+ .class_init = tpm_emulator_class_init,
701+ .instance_init = tpm_emulator_inst_init,
702+ .instance_finalize = tpm_emulator_inst_finalize,
703+};
704+
705+static void tpm_emulator_register(void)
706+{
707+ type_register_static(&tpm_emulator_info);
708+ tpm_register_driver(&tpm_emulator_driver);
709+}
710+
711+type_init(tpm_emulator_register)
712diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h
713new file mode 100644
714index 0000000000..33564b11de
715--- /dev/null
716+++ b/hw/tpm/tpm_ioctl.h
717@@ -0,0 +1,246 @@
718+/*
719+ * tpm_ioctl.h
720+ *
721+ * (c) Copyright IBM Corporation 2014, 2015.
722+ *
723+ * This file is licensed under the terms of the 3-clause BSD license
724+ */
725+#ifndef _TPM_IOCTL_H_
726+#define _TPM_IOCTL_H_
727+
728+#include <stdint.h>
729+#include <sys/uio.h>
730+#include <sys/types.h>
731+#include <sys/ioctl.h>
732+
733+/*
734+ * Every response from a command involving a TPM command execution must hold
735+ * the ptm_res as the first element.
736+ * ptm_res corresponds to the error code of a command executed by the TPM.
737+ */
738+
739+typedef uint32_t ptm_res;
740+
741+/* PTM_GET_TPMESTABLISHED: get the establishment bit */
742+struct ptm_est {
743+ union {
744+ struct {
745+ ptm_res tpm_result;
746+ unsigned char bit; /* TPM established bit */
747+ } resp; /* response */
748+ } u;
749+};
750+
751+/* PTM_RESET_TPMESTABLISHED: reset establishment bit */
752+struct ptm_reset_est {
753+ union {
754+ struct {
755+ uint8_t loc; /* locality to use */
756+ } req; /* request */
757+ struct {
758+ ptm_res tpm_result;
759+ } resp; /* response */
760+ } u;
761+};
762+
763+/* PTM_INIT */
764+struct ptm_init {
765+ union {
766+ struct {
767+ uint32_t init_flags; /* see definitions below */
768+ } req; /* request */
769+ struct {
770+ ptm_res tpm_result;
771+ } resp; /* response */
772+ } u;
773+};
774+
775+/* above init_flags */
776+#define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0)
777+ /* delete volatile state file after reading it */
778+
779+/* PTM_SET_LOCALITY */
780+struct ptm_loc {
781+ union {
782+ struct {
783+ uint8_t loc; /* locality to set */
784+ } req; /* request */
785+ struct {
786+ ptm_res tpm_result;
787+ } resp; /* response */
788+ } u;
789+};
790+
791+/* PTM_HASH_DATA: hash given data */
792+struct ptm_hdata {
793+ union {
794+ struct {
795+ uint32_t length;
796+ uint8_t data[4096];
797+ } req; /* request */
798+ struct {
799+ ptm_res tpm_result;
800+ } resp; /* response */
801+ } u;
802+};
803+
804+/*
805+ * size of the TPM state blob to transfer; x86_64 can handle 8k,
806+ * ppc64le only ~7k; keep the response below a 4k page size
807+ */
808+#define PTM_STATE_BLOB_SIZE (3 * 1024)
809+
810+/*
811+ * The following is the data structure to get state blobs from the TPM.
812+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple reads
813+ * with this ioctl and with adjusted offset are necessary. All bytes
814+ * must be transferred and the transfer is done once the last byte has been
815+ * returned.
816+ * It is possible to use the read() interface for reading the data; however, the
817+ * first bytes of the state blob will be part of the response to the ioctl(); a
818+ * subsequent read() is only necessary if the total length (totlength) exceeds
819+ * the number of received bytes. seek() is not supported.
820+ */
821+struct ptm_getstate {
822+ union {
823+ struct {
824+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */
825+ uint32_t type; /* which blob to pull */
826+ uint32_t offset; /* offset from where to read */
827+ } req; /* request */
828+ struct {
829+ ptm_res tpm_result;
830+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */
831+ uint32_t totlength; /* total length that will be transferred */
832+ uint32_t length; /* number of bytes in following buffer */
833+ uint8_t data[PTM_STATE_BLOB_SIZE];
834+ } resp; /* response */
835+ } u;
836+};
837+
838+/* TPM state blob types */
839+#define PTM_BLOB_TYPE_PERMANENT 1
840+#define PTM_BLOB_TYPE_VOLATILE 2
841+#define PTM_BLOB_TYPE_SAVESTATE 3
842+
843+/* state_flags above : */
844+#define PTM_STATE_FLAG_DECRYPTED 1 /* on input: get decrypted state */
845+#define PTM_STATE_FLAG_ENCRYPTED 2 /* on output: state is encrypted */
846+
847+/*
848+ * The following is the data structure to set state blobs in the TPM.
849+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple
850+ * 'writes' using this ioctl are necessary. The last packet is indicated
851+ * by the length being smaller than the PTM_STATE_BLOB_SIZE.
852+ * The very first packet may have a length indicator of '0' enabling
853+ * a write() with all the bytes from a buffer. If the write() interface
854+ * is used, a final ioctl with a non-full buffer must be made to indicate
855+ * that all data were transferred (a write with 0 bytes would not work).
856+ */
857+struct ptm_setstate {
858+ union {
859+ struct {
860+ uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */
861+ uint32_t type; /* which blob to set */
862+ uint32_t length; /* length of the data;
863+ use 0 on the first packet to
864+ transfer using write() */
865+ uint8_t data[PTM_STATE_BLOB_SIZE];
866+ } req; /* request */
867+ struct {
868+ ptm_res tpm_result;
869+ } resp; /* response */
870+ } u;
871+};
872+
873+/*
874+ * PTM_GET_CONFIG: Data structure to get runtime configuration information
875+ * such as which keys are applied.
876+ */
877+struct ptm_getconfig {
878+ union {
879+ struct {
880+ ptm_res tpm_result;
881+ uint32_t flags;
882+ } resp; /* response */
883+ } u;
884+};
885+
886+#define PTM_CONFIG_FLAG_FILE_KEY 0x1
887+#define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2
888+
889+
890+typedef uint64_t ptm_cap;
891+typedef struct ptm_est ptm_est;
892+typedef struct ptm_reset_est ptm_reset_est;
893+typedef struct ptm_loc ptm_loc;
894+typedef struct ptm_hdata ptm_hdata;
895+typedef struct ptm_init ptm_init;
896+typedef struct ptm_getstate ptm_getstate;
897+typedef struct ptm_setstate ptm_setstate;
898+typedef struct ptm_getconfig ptm_getconfig;
899+
900+/* capability flags returned by PTM_GET_CAPABILITY */
901+#define PTM_CAP_INIT (1)
902+#define PTM_CAP_SHUTDOWN (1 << 1)
903+#define PTM_CAP_GET_TPMESTABLISHED (1 << 2)
904+#define PTM_CAP_SET_LOCALITY (1 << 3)
905+#define PTM_CAP_HASHING (1 << 4)
906+#define PTM_CAP_CANCEL_TPM_CMD (1 << 5)
907+#define PTM_CAP_STORE_VOLATILE (1 << 6)
908+#define PTM_CAP_RESET_TPMESTABLISHED (1 << 7)
909+#define PTM_CAP_GET_STATEBLOB (1 << 8)
910+#define PTM_CAP_SET_STATEBLOB (1 << 9)
911+#define PTM_CAP_STOP (1 << 10)
912+#define PTM_CAP_GET_CONFIG (1 << 11)
913+#define PTM_CAP_SET_DATAFD (1 << 12)
914+
915+enum {
916+ PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap),
917+ PTM_INIT = _IOWR('P', 1, ptm_init),
918+ PTM_SHUTDOWN = _IOR('P', 2, ptm_res),
919+ PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est),
920+ PTM_SET_LOCALITY = _IOWR('P', 4, ptm_loc),
921+ PTM_HASH_START = _IOR('P', 5, ptm_res),
922+ PTM_HASH_DATA = _IOWR('P', 6, ptm_hdata),
923+ PTM_HASH_END = _IOR('P', 7, ptm_res),
924+ PTM_CANCEL_TPM_CMD = _IOR('P', 8, ptm_res),
925+ PTM_STORE_VOLATILE = _IOR('P', 9, ptm_res),
926+ PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est),
927+ PTM_GET_STATEBLOB = _IOWR('P', 11, ptm_getstate),
928+ PTM_SET_STATEBLOB = _IOWR('P', 12, ptm_setstate),
929+ PTM_STOP = _IOR('P', 13, ptm_res),
930+ PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig),
931+ PTM_SET_DATAFD = _IOR('P', 15, ptm_res),
932+};
933+
934+/*
935+ * Commands used by the non-CUSE TPMs
936+ *
937+ * All messages container big-endian data.
938+ *
939+ * The return messages only contain the 'resp' part of the unions
940+ * in the data structures above. Besides that the limits in the
941+ * buffers above (ptm_hdata:u.req.data and ptm_get_state:u.resp.data
942+ * and ptm_set_state:u.req.data) are 0xffffffff.
943+ */
944+enum {
945+ CMD_GET_CAPABILITY = 1,
946+ CMD_INIT,
947+ CMD_SHUTDOWN,
948+ CMD_GET_TPMESTABLISHED,
949+ CMD_SET_LOCALITY,
950+ CMD_HASH_START,
951+ CMD_HASH_DATA,
952+ CMD_HASH_END,
953+ CMD_CANCEL_TPM_CMD,
954+ CMD_STORE_VOLATILE,
955+ CMD_RESET_TPMESTABLISHED,
956+ CMD_GET_STATEBLOB,
957+ CMD_SET_STATEBLOB,
958+ CMD_STOP,
959+ CMD_GET_CONFIG,
960+ CMD_SET_DATAFD
961+};
962+
963+#endif /* _TPM_IOCTL_H */
964diff --git a/qapi-schema.json b/qapi-schema.json
965index 802ea53d00..78a00bc868 100644
966--- a/qapi-schema.json
967+++ b/qapi-schema.json
968@@ -5314,10 +5314,12 @@
969 # An enumeration of TPM types
970 #
971 # @passthrough: TPM passthrough type
972+# @emulator: Software Emulator TPM type
973+# Since: 2.11
974 #
975 # Since: 1.5
976 ##
977-{ 'enum': 'TpmType', 'data': [ 'passthrough' ] }
978+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'emulator' ] }
979
980 ##
981 # @query-tpm-types:
982@@ -5352,6 +5354,17 @@
983 '*cancel-path' : 'str'} }
984
985 ##
986+# @TPMEmulatorOptions:
987+#
988+# Information about the TPM emulator type
989+#
990+# @chardev: Name of a unix socket chardev
991+#
992+# Since: 2.11
993+##
994+{ 'struct': 'TPMEmulatorOptions', 'data': { 'chardev' : 'str' } }
995+
996+##
997 # @TpmTypeOptions:
998 #
999 # A union referencing different TPM backend types' configuration options
1000@@ -5361,7 +5374,8 @@
1001 # Since: 1.5
1002 ##
1003 { 'union': 'TpmTypeOptions',
1004- 'data': { 'passthrough' : 'TPMPassthroughOptions' } }
1005+ 'data': { 'passthrough' : 'TPMPassthroughOptions',
1006+ 'emulator': 'TPMEmulatorOptions'} }
1007
1008 ##
1009 # @TPMInfo:
1010diff --git a/qemu-options.hx b/qemu-options.hx
1011index 9f6e2adfff..60eb193c23 100644
1012--- a/qemu-options.hx
1013+++ b/qemu-options.hx
1014@@ -3121,7 +3121,9 @@ DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \
1015 "-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n"
1016 " use path to provide path to a character device; default is /dev/tpm0\n"
1017 " use cancel-path to provide path to TPM's cancel sysfs entry; if\n"
1018- " not provided it will be searched for in /sys/class/misc/tpm?/device\n",
1019+ " not provided it will be searched for in /sys/class/misc/tpm?/device\n"
1020+ "-tpmdev emulator,id=id,chardev=dev\n"
1021+ " configure the TPM device using chardev backend\n",
1022 QEMU_ARCH_ALL)
1023 STEXI
1024
1025@@ -3130,8 +3132,8 @@ The general form of a TPM device option is:
1026
1027 @item -tpmdev @var{backend} ,id=@var{id} [,@var{options}]
1028 @findex -tpmdev
1029-Backend type must be:
1030-@option{passthrough}.
1031+Backend type must be either one of the following:
1032+@option{passthrough}, @option{emulator}.
1033
1034 The specific backend type will determine the applicable options.
1035 The @code{-tpmdev} option creates the TPM backend and requires a
1036@@ -3181,6 +3183,20 @@ To create a passthrough TPM use the following two options:
1037 Note that the @code{-tpmdev} id is @code{tpm0} and is referenced by
1038 @code{tpmdev=tpm0} in the device option.
1039
1040+@item -tpmdev emulator, id=@var{id}, chardev=@var{dev}
1041+
1042+(Linux-host only) Enable access to a TPM emulator using Unix domain socket based
1043+chardev backend.
1044+
1045+@option{chardev} specifies the unique ID of a character device backend that provides connection to the software TPM server.
1046+
1047+To create a TPM emulator backend device with chardev socket backend:
1048+@example
1049+
1050+-chardev socket,id=chrtpm,path=/tmp/swtpm-sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0
1051+
1052+@end example
1053+
1054 @end table
1055
1056 ETEXI
1057--
10582.11.0
1059
diff --git a/meta/recipes-devtools/qemu/qemu/0011-tpm-Move-tpm_cleanup-to-right-place.patch b/meta/recipes-devtools/qemu/qemu/0011-tpm-Move-tpm_cleanup-to-right-place.patch
deleted file mode 100644
index f4998e1681..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0011-tpm-Move-tpm_cleanup-to-right-place.patch
+++ /dev/null
@@ -1,43 +0,0 @@
1From 22429d175911af2e57617a30e0ac097af74f2791 Mon Sep 17 00:00:00 2001
2From: Amarnath Valluri <amarnath.valluri@intel.com>
3Date: Fri, 29 Sep 2017 12:57:33 +0300
4Subject: [PATCH 11/12] tpm: Move tpm_cleanup() to right place
5
6As Emulator TPM backend uses chardev, tpm cleanup should happen before chardev
7similar to other vhost-users.
8
9Signed-off-by: Amarnath Valluri <amarnath.valluri@intel.com>
10
11Upstream-Status: Backport [c37cacabf2285b0731b44c1f667781fdd4f2b658]
12---
13 tpm.c | 1 -
14 vl.c | 1 +
15 2 files changed, 1 insertion(+), 1 deletion(-)
16
17diff --git a/tpm.c b/tpm.c
18index cac400ef3e..4a9d3d739e 100644
19--- a/tpm.c
20+++ b/tpm.c
21@@ -173,7 +173,6 @@ int tpm_init(void)
22 return -1;
23 }
24
25- atexit(tpm_cleanup);
26 return 0;
27 }
28
29diff --git a/vl.c b/vl.c
30index 8e247cc2a2..5df0b7f205 100644
31--- a/vl.c
32+++ b/vl.c
33@@ -4797,6 +4797,7 @@ int main(int argc, char **argv, char **envp)
34 res_free();
35
36 /* vhost-user must be cleaned up before chardevs. */
37+ tpm_cleanup();
38 net_cleanup();
39 audio_cleanup();
40 monitor_cleanup();
41--
422.11.0
43
diff --git a/meta/recipes-devtools/qemu/qemu/0012-tpm-Use-EMSGSIZE-instead-of-EBADMSG-to-compile-on-Op.patch b/meta/recipes-devtools/qemu/qemu/0012-tpm-Use-EMSGSIZE-instead-of-EBADMSG-to-compile-on-Op.patch
deleted file mode 100644
index 430fe1b1c4..0000000000
--- a/meta/recipes-devtools/qemu/qemu/0012-tpm-Use-EMSGSIZE-instead-of-EBADMSG-to-compile-on-Op.patch
+++ /dev/null
@@ -1,67 +0,0 @@
1From c559d599c6880caf7aa0f0a60c6c023584e1b8ad Mon Sep 17 00:00:00 2001
2From: Stefan Berger <stefanb@linux.vnet.ibm.com>
3Date: Wed, 11 Oct 2017 08:52:43 -0400
4Subject: [PATCH 12/12] tpm: Use EMSGSIZE instead of EBADMSG to compile on
5 OpenBSD
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10EBADMSG was only added to OpenBSD very recently. To make QEMU compilable
11on older OpenBSD versions use EMSGSIZE instead when a mismatch between
12number of received bytes and message size indicated in the header was
13found.
14
15Return -EMSGSIZE and convert all other errnos in the same functions to
16return the negative errno.
17
18Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
19Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
20
21Upstream-Status: Backport [98979cdca44ba0e21055ee7736694aa5ebb54347]
22---
23 hw/tpm/tpm_util.c | 10 +++++-----
24 1 file changed, 5 insertions(+), 5 deletions(-)
25
26diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c
27index fb929f6e92..73d77965fd 100644
28--- a/hw/tpm/tpm_util.c
29+++ b/hw/tpm/tpm_util.c
30@@ -68,10 +68,10 @@ static int tpm_util_test(int fd,
31
32 n = write(fd, request, requestlen);
33 if (n < 0) {
34- return errno;
35+ return -errno;
36 }
37 if (n != requestlen) {
38- return EFAULT;
39+ return -EFAULT;
40 }
41
42 FD_ZERO(&readfds);
43@@ -80,18 +80,18 @@ static int tpm_util_test(int fd,
44 /* wait for a second */
45 n = select(fd + 1, &readfds, NULL, NULL, &tv);
46 if (n != 1) {
47- return errno;
48+ return -errno;
49 }
50
51 n = read(fd, &buf, sizeof(buf));
52 if (n < sizeof(struct tpm_resp_hdr)) {
53- return EFAULT;
54+ return -EFAULT;
55 }
56
57 resp = (struct tpm_resp_hdr *)buf;
58 /* check the header */
59 if (be32_to_cpu(resp->len) != n) {
60- return EBADMSG;
61+ return -EMSGSIZE;
62 }
63
64 *return_tag = be16_to_cpu(resp->tag);
65--
662.11.0
67
diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2017-17381.patch b/meta/recipes-devtools/qemu/qemu/CVE-2017-17381.patch
deleted file mode 100644
index 416771cdcb..0000000000
--- a/meta/recipes-devtools/qemu/qemu/CVE-2017-17381.patch
+++ /dev/null
@@ -1,72 +0,0 @@
1From 758ead31c7e17bf17a9ef2e0ca1c3e86ab296b43 Mon Sep 17 00:00:00 2001
2From: Prasad J Pandit <pjp@fedoraproject.org>
3Date: Wed, 29 Nov 2017 23:14:27 +0530
4Subject: [PATCH] virtio: check VirtQueue Vring object is set
5
6A guest could attempt to use an uninitialised VirtQueue object
7or unset Vring.align leading to a arithmetic exception. Add check
8to avoid it.
9
10Upstream-Status: Backport
11CVE: CVE-2017-17381
12
13Reported-by: Zhangboxian <zhangboxian@huawei.com>
14Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
15Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
16Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
17Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
18Reviewed-by: Cornelia Huck <cohuck@redhat.com>
19Signed-off-by: Catalin Enache <catalin.enache@windriver.com>
20---
21 hw/virtio/virtio.c | 14 +++++++++++---
22 1 file changed, 11 insertions(+), 3 deletions(-)
23
24diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
25index 703e672..ad564b0 100644
26--- a/hw/virtio/virtio.c
27+++ b/hw/virtio/virtio.c
28@@ -182,7 +182,7 @@ void virtio_queue_update_rings(VirtIODevice *vdev, int n)
29 {
30 VRing *vring = &vdev->vq[n].vring;
31
32- if (!vring->desc) {
33+ if (!vring->num || !vring->desc || !vring->align) {
34 /* not yet setup -> nothing to do */
35 return;
36 }
37@@ -1414,6 +1414,9 @@ void virtio_config_modern_writel(VirtIODevice *vdev,
38
39 void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr)
40 {
41+ if (!vdev->vq[n].vring.num) {
42+ return;
43+ }
44 vdev->vq[n].vring.desc = addr;
45 virtio_queue_update_rings(vdev, n);
46 }
47@@ -1426,6 +1429,9 @@ hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n)
48 void virtio_queue_set_rings(VirtIODevice *vdev, int n, hwaddr desc,
49 hwaddr avail, hwaddr used)
50 {
51+ if (!vdev->vq[n].vring.num) {
52+ return;
53+ }
54 vdev->vq[n].vring.desc = desc;
55 vdev->vq[n].vring.avail = avail;
56 vdev->vq[n].vring.used = used;
57@@ -1494,8 +1500,10 @@ void virtio_queue_set_align(VirtIODevice *vdev, int n, int align)
58 */
59 assert(k->has_variable_vring_alignment);
60
61- vdev->vq[n].vring.align = align;
62- virtio_queue_update_rings(vdev, n);
63+ if (align) {
64+ vdev->vq[n].vring.align = align;
65+ virtio_queue_update_rings(vdev, n);
66+ }
67 }
68
69 static bool virtio_queue_notify_aio_vq(VirtQueue *vq)
70--
712.10.2
72
diff --git a/meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch b/meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch
index 4f8539757a..32809d3085 100644
--- a/meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch
+++ b/meta/recipes-devtools/qemu/qemu/chardev-connect-socket-to-a-spawned-command.patch
@@ -1,6 +1,6 @@
1From aa3aef4cf5f4dd98f9133df085e825ff5da7dcbd Mon Sep 17 00:00:00 2001 1From 3bb3100c22eb30146a69656480bdffeef8663575 Mon Sep 17 00:00:00 2001
2From: Patrick Ohly <patrick.ohly@intel.com> 2From: Alistair Francis <alistair.francis@xilinx.com>
3Date: Fri, 27 Oct 2017 15:23:35 +0200 3Date: Thu, 21 Dec 2017 11:35:16 -0800
4Subject: [PATCH] chardev: connect socket to a spawned command 4Subject: [PATCH] chardev: connect socket to a spawned command
5 5
6The command is started in a shell (sh -c) with stdin connect to QEMU 6The command is started in a shell (sh -c) with stdin connect to QEMU
@@ -44,22 +44,20 @@ as simple as possible.
44Upstream-Status: Inappropriate [embedded specific] 44Upstream-Status: Inappropriate [embedded specific]
45 45
46Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> 46Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
47
48--- 47---
49 chardev/char-socket.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++--- 48 chardev/char-socket.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++---
50 chardev/char.c | 3 ++ 49 chardev/char.c | 3 ++
51 qapi-schema.json | 5 +++ 50 qapi/char.json | 5 +++
52 3 files changed, 90 insertions(+), 4 deletions(-) 51 3 files changed, 90 insertions(+), 4 deletions(-)
53 52
54diff --git a/chardev/char-socket.c b/chardev/char-socket.c 53diff --git a/chardev/char-socket.c b/chardev/char-socket.c
55index 1ae730a4..c366a02a 100644 54index 53eda8ef00..f566107c35 100644
56--- a/chardev/char-socket.c 55--- a/chardev/char-socket.c
57+++ b/chardev/char-socket.c 56+++ b/chardev/char-socket.c
58@@ -854,6 +854,68 @@ static gboolean socket_reconnect_timeout(gpointer opaque) 57@@ -852,6 +852,66 @@ static gboolean socket_reconnect_timeout(gpointer opaque)
59 return false; 58 return false;
60 } 59 }
61 60
62+#ifndef _WIN32
63+static void chardev_open_socket_cmd(Chardev *chr, 61+static void chardev_open_socket_cmd(Chardev *chr,
64+ const char *cmd, 62+ const char *cmd,
65+ Error **errp) 63+ Error **errp)
@@ -119,51 +117,42 @@ index 1ae730a4..c366a02a 100644
119+ object_unref(OBJECT(sioc)); 117+ object_unref(OBJECT(sioc));
120+ } 118+ }
121+} 119+}
122+#endif
123+ 120+
124 static void qmp_chardev_open_socket(Chardev *chr, 121 static void qmp_chardev_open_socket(Chardev *chr,
125 ChardevBackend *backend, 122 ChardevBackend *backend,
126 bool *be_opened, 123 bool *be_opened,
127@@ -861,6 +923,9 @@ static void qmp_chardev_open_socket(Chardev *chr, 124@@ -859,6 +919,7 @@ static void qmp_chardev_open_socket(Chardev *chr,
128 { 125 {
129 SocketChardev *s = SOCKET_CHARDEV(chr); 126 SocketChardev *s = SOCKET_CHARDEV(chr);
130 ChardevSocket *sock = backend->u.socket.data; 127 ChardevSocket *sock = backend->u.socket.data;
131+#ifndef _WIN32
132+ const char *cmd = sock->cmd; 128+ const char *cmd = sock->cmd;
133+#endif
134 bool do_nodelay = sock->has_nodelay ? sock->nodelay : false; 129 bool do_nodelay = sock->has_nodelay ? sock->nodelay : false;
135 bool is_listen = sock->has_server ? sock->server : true; 130 bool is_listen = sock->has_server ? sock->server : true;
136 bool is_telnet = sock->has_telnet ? sock->telnet : false; 131 bool is_telnet = sock->has_telnet ? sock->telnet : false;
137@@ -928,7 +993,15 @@ static void qmp_chardev_open_socket(Chardev *chr, 132@@ -926,7 +987,12 @@ static void qmp_chardev_open_socket(Chardev *chr,
138 s->reconnect_time = reconnect; 133 s->reconnect_time = reconnect;
139 } 134 }
140 135
141- if (s->reconnect_time) { 136- if (s->reconnect_time) {
142+#ifndef _WIN32
143+ if (cmd) { 137+ if (cmd) {
144+ chardev_open_socket_cmd(chr, cmd, errp); 138+ chardev_open_socket_cmd(chr, cmd, errp);
145+ 139+
146+ /* everything ready (or failed permanently) before we return */ 140+ /* everything ready (or failed permanently) before we return */
147+ *be_opened = true; 141+ *be_opened = true;
148+ } else 142+ } else if (s->reconnect_time) {
149+#endif
150+ if (s->reconnect_time) {
151 sioc = qio_channel_socket_new(); 143 sioc = qio_channel_socket_new();
152 tcp_chr_set_client_ioc_name(chr, sioc); 144 tcp_chr_set_client_ioc_name(chr, sioc);
153 qio_channel_socket_connect_async(sioc, s->addr, 145 qio_channel_socket_connect_async(sioc, s->addr,
154@@ -987,11 +1060,27 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, 146@@ -985,11 +1051,22 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
155 const char *host = qemu_opt_get(opts, "host"); 147 const char *host = qemu_opt_get(opts, "host");
156 const char *port = qemu_opt_get(opts, "port"); 148 const char *port = qemu_opt_get(opts, "port");
157 const char *tls_creds = qemu_opt_get(opts, "tls-creds"); 149 const char *tls_creds = qemu_opt_get(opts, "tls-creds");
158+#ifndef _WIN32
159+ const char *cmd = qemu_opt_get(opts, "cmd"); 150+ const char *cmd = qemu_opt_get(opts, "cmd");
160+#endif
161 SocketAddressLegacy *addr; 151 SocketAddressLegacy *addr;
162 ChardevSocket *sock; 152 ChardevSocket *sock;
163 153
164 backend->type = CHARDEV_BACKEND_KIND_SOCKET; 154 backend->type = CHARDEV_BACKEND_KIND_SOCKET;
165- if (!path) { 155- if (!path) {
166+#ifndef _WIN32
167+ if (cmd) { 156+ if (cmd) {
168+ /* 157+ /*
169+ * Here we have to ensure that no options are set which are incompatible with 158+ * Here we have to ensure that no options are set which are incompatible with
@@ -174,57 +163,46 @@ index 1ae730a4..c366a02a 100644
174+ error_setg(errp, "chardev: socket: cmd does not support any additional options"); 163+ error_setg(errp, "chardev: socket: cmd does not support any additional options");
175+ return; 164+ return;
176+ } 165+ }
177+ } else 166+ } else if (!path) {
178+#endif
179+ if (!path) {
180 if (!host) { 167 if (!host) {
181 error_setg(errp, "chardev: socket: no host given"); 168 error_setg(errp, "chardev: socket: no host given");
182 return; 169 return;
183@@ -1023,13 +1112,24 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend, 170@@ -1021,13 +1098,14 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
184 sock->has_reconnect = true; 171 sock->has_reconnect = true;
185 sock->reconnect = reconnect; 172 sock->reconnect = reconnect;
186 sock->tls_creds = g_strdup(tls_creds); 173 sock->tls_creds = g_strdup(tls_creds);
187+#ifndef _WIN32
188+ sock->cmd = g_strdup(cmd); 174+ sock->cmd = g_strdup(cmd);
189+#endif
190 175
191 addr = g_new0(SocketAddressLegacy, 1); 176 addr = g_new0(SocketAddressLegacy, 1);
192+#ifndef _WIN32 177- if (path) {
193+ if (path || cmd) { 178+ if (path || cmd) {
194+#else
195 if (path) {
196+#endif
197 UnixSocketAddress *q_unix; 179 UnixSocketAddress *q_unix;
198 addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX; 180 addr->type = SOCKET_ADDRESS_LEGACY_KIND_UNIX;
199 q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1); 181 q_unix = addr->u.q_unix.data = g_new0(UnixSocketAddress, 1);
200- q_unix->path = g_strdup(path); 182- q_unix->path = g_strdup(path);
201+#ifndef _WIN32
202+ q_unix->path = cmd ? g_strdup_printf("cmd:%s", cmd) : g_strdup(path); 183+ q_unix->path = cmd ? g_strdup_printf("cmd:%s", cmd) : g_strdup(path);
203+#else
204+ q_unix->path = g_strdup(path);
205+#endif
206 } else { 184 } else {
207 addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET; 185 addr->type = SOCKET_ADDRESS_LEGACY_KIND_INET;
208 addr->u.inet.data = g_new(InetSocketAddress, 1); 186 addr->u.inet.data = g_new(InetSocketAddress, 1);
209diff --git a/chardev/char.c b/chardev/char.c 187diff --git a/chardev/char.c b/chardev/char.c
210index 5d283b90..ccb329d4 100644 188index 2ae4f465ec..5d52cd5de5 100644
211--- a/chardev/char.c 189--- a/chardev/char.c
212+++ b/chardev/char.c 190+++ b/chardev/char.c
213@@ -782,6 +782,9 @@ QemuOptsList qemu_chardev_opts = { 191@@ -792,6 +792,9 @@ QemuOptsList qemu_chardev_opts = {
192 },{
214 .name = "path", 193 .name = "path",
215 .type = QEMU_OPT_STRING, 194 .type = QEMU_OPT_STRING,
216 },{ 195+ },{
217+ .name = "cmd", 196+ .name = "cmd",
218+ .type = QEMU_OPT_STRING, 197+ .type = QEMU_OPT_STRING,
219+ },{ 198 },{
220 .name = "host", 199 .name = "host",
221 .type = QEMU_OPT_STRING, 200 .type = QEMU_OPT_STRING,
222 },{ 201diff --git a/qapi/char.json b/qapi/char.json
223diff --git a/qapi-schema.json b/qapi-schema.json 202index ae19dcd1ed..6de0f29bcd 100644
224index 78a00bc8..790b026d 100644 203--- a/qapi/char.json
225--- a/qapi-schema.json 204+++ b/qapi/char.json
226+++ b/qapi-schema.json 205@@ -241,6 +241,10 @@
227@@ -5004,6 +5004,10 @@
228 # 206 #
229 # @addr: socket address to listen on (server=true) 207 # @addr: socket address to listen on (server=true)
230 # or connect to (server=false) 208 # or connect to (server=false)
@@ -235,7 +213,7 @@ index 78a00bc8..790b026d 100644
235 # @tls-creds: the ID of the TLS credentials object (since 2.6) 213 # @tls-creds: the ID of the TLS credentials object (since 2.6)
236 # @server: create server socket (default: true) 214 # @server: create server socket (default: true)
237 # @wait: wait for incoming connection on server 215 # @wait: wait for incoming connection on server
238@@ -5021,6 +5025,7 @@ 216@@ -258,6 +262,7 @@
239 # Since: 1.4 217 # Since: 1.4
240 ## 218 ##
241 { 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy', 219 { 'struct': 'ChardevSocket', 'data': { 'addr' : 'SocketAddressLegacy',
@@ -244,5 +222,5 @@ index 78a00bc8..790b026d 100644
244 '*server' : 'bool', 222 '*server' : 'bool',
245 '*wait' : 'bool', 223 '*wait' : 'bool',
246-- 224--
2472.11.0 2252.14.1
248 226
diff --git a/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch b/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch
deleted file mode 100644
index f593cf9ae0..0000000000
--- a/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch
+++ /dev/null
@@ -1,87 +0,0 @@
1[PATCH] exclude some arm EABI obsolete syscalls
2
3Upstream-Status: Pending
4
5some syscalls are obsolete and no longer available for EABI, exclude them to
6fix the below error:
7 In file included from qemu-seccomp.c:16:0:
8 qemu-seccomp.c:28:7: error: '__NR_select' undeclared here (not in a function)
9 { SCMP_SYS(select), 252 },
10 ^
11 qemu-seccomp.c:36:7: error: '__NR_mmap' undeclared here (not in a function)
12 { SCMP_SYS(mmap), 247 },
13 ^
14 qemu-seccomp.c:57:7: error: '__NR_getrlimit' undeclared here (not in a function)
15 { SCMP_SYS(getrlimit), 245 },
16 ^
17 qemu-seccomp.c:96:7: error: '__NR_time' undeclared here (not in a function)
18 { SCMP_SYS(time), 245 },
19 ^
20 qemu-seccomp.c:185:7: error: '__NR_alarm' undeclared here (not in a function)
21 { SCMP_SYS(alarm), 241 },
22
23please refer source files:
24 arch/arm/include/uapi/asm/unistd.h
25or kernel header:
26 /usr/include/asm/unistd.h
27
28Signed-off-by: Roy.Li <rongqing.li@windriver.com>
29---
30 qemu-seccomp.c | 13 ++++++++-----
31 1 file changed, 8 insertions(+), 5 deletions(-)
32
33diff --git a/qemu-seccomp.c b/qemu-seccomp.c
34index df75d9c..0e577f8 100644
35--- a/qemu-seccomp.c
36+++ b/qemu-seccomp.c
37@@ -35,15 +35,21 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
38 { SCMP_SYS(timer_settime), 255 },
39 { SCMP_SYS(timer_gettime), 254 },
40 { SCMP_SYS(futex), 253 },
41+#if !defined(__ARM_EABI__)
42 { SCMP_SYS(select), 252 },
43+ { SCMP_SYS(time), 245 },
44+ { SCMP_SYS(alarm), 241 },
45+ { SCMP_SYS(getrlimit), 245 },
46+ { SCMP_SYS(mmap), 247 },
47+ { SCMP_SYS(socketcall), 250 },
48+ { SCMP_SYS(ipc), 245 },
49+#endif
50 { SCMP_SYS(recvfrom), 251 },
51 { SCMP_SYS(sendto), 250 },
52- { SCMP_SYS(socketcall), 250 },
53 { SCMP_SYS(read), 249 },
54 { SCMP_SYS(io_submit), 249 },
55 { SCMP_SYS(brk), 248 },
56 { SCMP_SYS(clone), 247 },
57- { SCMP_SYS(mmap), 247 },
58 { SCMP_SYS(mprotect), 246 },
59 { SCMP_SYS(execve), 245 },
60 { SCMP_SYS(open), 245 },
61@@ -58,7 +64,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
62 { SCMP_SYS(bind), 245 },
63 { SCMP_SYS(listen), 245 },
64 { SCMP_SYS(semget), 245 },
65- { SCMP_SYS(ipc), 245 },
66 { SCMP_SYS(gettimeofday), 245 },
67 { SCMP_SYS(readlink), 245 },
68 { SCMP_SYS(access), 245 },
69@@ -104,7 +109,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
70 { SCMP_SYS(times), 245 },
71 { SCMP_SYS(exit), 245 },
72 { SCMP_SYS(clock_gettime), 245 },
73- { SCMP_SYS(time), 245 },
74 { SCMP_SYS(restart_syscall), 245 },
75 { SCMP_SYS(pwrite64), 245 },
76 { SCMP_SYS(nanosleep), 245 },
77@@ -194,7 +198,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
78 { SCMP_SYS(lstat64), 241 },
79 { SCMP_SYS(sendfile64), 241 },
80 { SCMP_SYS(ugetrlimit), 241 },
81- { SCMP_SYS(alarm), 241 },
82 { SCMP_SYS(rt_sigsuspend), 241 },
83 { SCMP_SYS(rt_sigqueueinfo), 241 },
84 { SCMP_SYS(rt_tgsigqueueinfo), 241 },
85--
862.1.4
87
diff --git a/meta/recipes-devtools/qemu/qemu/linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch b/meta/recipes-devtools/qemu/qemu/linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch
new file mode 100644
index 0000000000..d2c52252f6
--- /dev/null
+++ b/meta/recipes-devtools/qemu/qemu/linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch
@@ -0,0 +1,35 @@
1From 4fa4aae4176ef6d8f4d4b8323d061e2433918a26 Mon Sep 17 00:00:00 2001
2From: Alistair Francis <alistair.francis@xilinx.com>
3Date: Wed, 17 Jan 2018 10:51:49 -0800
4Subject: [PATCH] linux-user: Fix webkitgtk hangs on 32-bit x86 target
5
6Since commit "linux-user: Tidy and enforce reserved_va initialization"
7(18e80c55bb6ec17c05ec0ba717ec83933c2bfc07) the Yocto webkitgtk build
8hangs when cross compiling for 32-bit x86 on a 64-bit x86 machine using
9musl.
10
11To fix the issue reduce the MAX_RESERVED_VA macro to be a closer match
12to what it was before the problematic commit.
13
14Upstream-Status: Submitted http://lists.gnu.org/archive/html/qemu-devel/2018-01/msg04185.html
15Signed-off-by: Alistair Francis <alistair.francis@xilinx.com>
16---
17 linux-user/main.c | 2 +-
18 1 file changed, 1 insertion(+), 1 deletion(-)
19
20diff --git a/linux-user/main.c b/linux-user/main.c
21index 450eb3ce65..c7cc0a184e 100644
22--- a/linux-user/main.c
23+++ b/linux-user/main.c
24@@ -77,7 +77,7 @@ do { \
25 (TARGET_LONG_BITS == 32 || defined(TARGET_ABI32))
26 /* There are a number of places where we assign reserved_va to a variable
27 of type abi_ulong and expect it to fit. Avoid the last page. */
28-# define MAX_RESERVED_VA (0xfffffffful & TARGET_PAGE_MASK)
29+# define MAX_RESERVED_VA (0x7ffffffful & TARGET_PAGE_MASK)
30 # else
31 # define MAX_RESERVED_VA (1ul << TARGET_VIRT_ADDR_SPACE_BITS)
32 # endif
33--
342.14.1
35
diff --git a/meta/recipes-devtools/qemu/qemu/ppc_locking.patch b/meta/recipes-devtools/qemu/qemu/ppc_locking.patch
deleted file mode 100644
index 6f722433d4..0000000000
--- a/meta/recipes-devtools/qemu/qemu/ppc_locking.patch
+++ /dev/null
@@ -1,105 +0,0 @@
1I've tracked down what I think is a problem causing qemu-system-ppc
2to hang whilst booting images.
3
4I believe the decrementer timer stops receiving interrupts so
5tasks in our images hang indefinitely as the timer stopped.
6
7It can be summed up with this line of debug:
8
9ppc_set_irq: 0x55b4e0d562f0 n_IRQ 8 level 1 => pending 00000100req 00000004
10
11It should normally read:
12
13ppc_set_irq: 0x55b4e0d562f0 n_IRQ 8 level 1 => pending 00000100req 00000002
14
15The question is why CPU_INTERRUPT_EXITTB ends up being set when the
16lines above this log message clearly sets CPU_INTERRUPT_HARD (via
17cpu_interrupt() ).
18
19I note in cpu.h:
20
21 /* updates protected by BQL */
22 uint32_t interrupt_request;
23
24(for struct CPUState)
25
26The ppc code does "cs->interrupt_request |= CPU_INTERRUPT_EXITTB" in 5
27places, 3 in excp_helper.c and 2 in helper_regs.h. In all cases,
28g_assert(qemu_mutex_iothread_locked()); fails. If I do something like:
29
30if (!qemu_mutex_iothread_locked()) {
31 qemu_mutex_lock_iothread();
32 cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
33 qemu_mutex_unlock_iothread();
34} else {
35 cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
36}
37
38in these call sites then I can no longer lock qemu up with my test
39case.
40
41I suspect the _HARD setting gets overwritten which stops the
42decrementer interrupts being delivered.
43
44Upstream-Status: Submitted [Issue discussed on qemu mailing list 2017/11/20]
45RP 2017/11/20
46
47Index: qemu-2.10.1/target/ppc/excp_helper.c
48===================================================================
49--- qemu-2.10.1.orig/target/ppc/excp_helper.c
50+++ qemu-2.10.1/target/ppc/excp_helper.c
51@@ -207,7 +207,9 @@ static inline void powerpc_excp(PowerPCC
52 "Entering checkstop state\n");
53 }
54 cs->halted = 1;
55- cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
56+ qemu_mutex_lock_iothread();
57+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
58+ qemu_mutex_unlock_iothread();
59 }
60 if (env->msr_mask & MSR_HVB) {
61 /* ISA specifies HV, but can be delivered to guest with HV clear
62@@ -940,7 +942,9 @@ void helper_store_msr(CPUPPCState *env,
63
64 if (excp != 0) {
65 CPUState *cs = CPU(ppc_env_get_cpu(env));
66- cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
67+ qemu_mutex_lock_iothread();
68+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
69+ qemu_mutex_unlock_iothread();
70 raise_exception(env, excp);
71 }
72 }
73@@ -995,7 +999,9 @@ static inline void do_rfi(CPUPPCState *e
74 /* No need to raise an exception here,
75 * as rfi is always the last insn of a TB
76 */
77- cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
78+ qemu_mutex_lock_iothread();
79+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
80+ qemu_mutex_unlock_iothread();
81
82 /* Reset the reservation */
83 env->reserve_addr = -1;
84Index: qemu-2.10.1/target/ppc/helper_regs.h
85===================================================================
86--- qemu-2.10.1.orig/target/ppc/helper_regs.h
87+++ qemu-2.10.1/target/ppc/helper_regs.h
88@@ -114,11 +114,15 @@ static inline int hreg_store_msr(CPUPPCS
89 }
90 if (((value >> MSR_IR) & 1) != msr_ir ||
91 ((value >> MSR_DR) & 1) != msr_dr) {
92- cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
93+ qemu_mutex_lock_iothread();
94+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
95+ qemu_mutex_unlock_iothread();
96 }
97 if ((env->mmu_model & POWERPC_MMU_BOOKE) &&
98 ((value >> MSR_GS) & 1) != msr_gs) {
99- cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
100+ qemu_mutex_lock_iothread();
101+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB);
102+ qemu_mutex_unlock_iothread();
103 }
104 if (unlikely((env->flags & POWERPC_FLAG_TGPR) &&
105 ((value ^ env->msr) & (1 << MSR_TGPR)))) {
diff --git a/meta/recipes-devtools/qemu/qemu_2.10.1.bb b/meta/recipes-devtools/qemu/qemu_2.11.0.bb
index 6c2dd586dd..ccd8917f8d 100644
--- a/meta/recipes-devtools/qemu/qemu_2.10.1.bb
+++ b/meta/recipes-devtools/qemu/qemu_2.11.0.bb
@@ -10,7 +10,6 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=441c28d2cf86e15a37fa47e15a72fbac \
10SRC_URI = "http://wiki.qemu-project.org/download/${BP}.tar.bz2 \ 10SRC_URI = "http://wiki.qemu-project.org/download/${BP}.tar.bz2 \
11 file://powerpc_rom.bin \ 11 file://powerpc_rom.bin \
12 file://disable-grabs.patch \ 12 file://disable-grabs.patch \
13 file://exclude-some-arm-EABI-obsolete-syscalls.patch \
14 file://wacom.patch \ 13 file://wacom.patch \
15 file://add-ptest-in-makefile-v10.patch \ 14 file://add-ptest-in-makefile-v10.patch \
16 file://run-ptest \ 15 file://run-ptest \
@@ -19,22 +18,9 @@ SRC_URI = "http://wiki.qemu-project.org/download/${BP}.tar.bz2 \
19 file://pathlimit.patch \ 18 file://pathlimit.patch \
20 file://qemu-2.5.0-cflags.patch \ 19 file://qemu-2.5.0-cflags.patch \
21 file://glibc-2.25.patch \ 20 file://glibc-2.25.patch \
22 file://0001-tpm-Clean-up-driver-registration-lookup.patch \
23 file://0002-tpm-Clean-up-model-registration-lookup.patch \
24 file://0003-tpm-backend-Remove-unneeded-member-variable-from-bac.patch \
25 file://0004-tpm-backend-Move-thread-handling-inside-TPMBackend.patch \
26 file://0005-tpm-backend-Initialize-and-free-data-members-in-it-s.patch \
27 file://0006-tpm-backend-Made-few-interface-methods-optional.patch \
28 file://0007-tpm-backend-Add-new-api-to-read-backend-TpmInfo.patch \
29 file://0008-tpm-backend-Move-realloc_buffer-implementation-to-tp.patch \
30 file://0009-tpm-passthrough-move-reusable-code-to-utils.patch \
31 file://0010-tpm-Added-support-for-TPM-emulator.patch \
32 file://0011-tpm-Move-tpm_cleanup-to-right-place.patch \
33 file://0012-tpm-Use-EMSGSIZE-instead-of-EBADMSG-to-compile-on-Op.patch \
34 file://chardev-connect-socket-to-a-spawned-command.patch \ 21 file://chardev-connect-socket-to-a-spawned-command.patch \
35 file://apic-fixup-fallthrough-to-PIC.patch \ 22 file://apic-fixup-fallthrough-to-PIC.patch \
36 file://ppc_locking.patch \ 23 file://linux-user-Fix-webkitgtk-hangs-on-32-bit-x86-target.patch \
37 file://CVE-2017-17381.patch \
38 " 24 "
39UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+\..*)\.tar" 25UPSTREAM_CHECK_REGEX = "qemu-(?P<pver>\d+\..*)\.tar"
40 26
@@ -44,8 +30,8 @@ SRC_URI_append_class-native = " \
44 file://cpus.c-qemu_cpu_kick_thread_debugging.patch \ 30 file://cpus.c-qemu_cpu_kick_thread_debugging.patch \
45 " 31 "
46 32
47SRC_URI[md5sum] = "b375373f688bea0cd8865b966dad15e3" 33SRC_URI[md5sum] = "335994a755bc655e88a87aeb36bfc0b9"
48SRC_URI[sha256sum] = "8e040bc7556401ebb3a347a8f7878e9d4028cf71b2744b1a1699f4e741966ba8" 34SRC_URI[sha256sum] = "c4f034c7665a84a1c3be72c8da37f3c31ec063475699df062ab646d8b2e17fcb"
49 35
50COMPATIBLE_HOST_mipsarchn32 = "null" 36COMPATIBLE_HOST_mipsarchn32 = "null"
51COMPATIBLE_HOST_mipsarchn64 = "null" 37COMPATIBLE_HOST_mipsarchn64 = "null"