From 67af320cd653a107c0bbdf0d2e6c51b24403c64d Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:38:59 +0100 Subject: tpm: move TpmIf in include/sysemu/tpm.h This is a better location than hw/tpm, since we are going to use the interface from outside hw/tpm. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- include/sysemu/tpm.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'include') diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index d7a2bd8556..452cdb9cb7 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -27,6 +27,25 @@ typedef enum TPMVersion { TPM_VERSION_2_0 = 2, } TPMVersion; +#define TYPE_TPM_IF "tpm-if" +#define TPM_IF_CLASS(klass) \ + OBJECT_CLASS_CHECK(TPMIfClass, (klass), TYPE_TPM_IF) +#define TPM_IF_GET_CLASS(obj) \ + OBJECT_GET_CLASS(TPMIfClass, (obj), TYPE_TPM_IF) +#define TPM_IF(obj) \ + INTERFACE_CHECK(TPMIf, (obj), TYPE_TPM_IF) + +typedef struct TPMIf { + Object parent_obj; +} TPMIf; + +typedef struct TPMIfClass { + InterfaceClass parent_class; + + /* run in thread pool by backend */ + void (*request_completed)(TPMIf *obj); +} TPMIfClass; + TPMVersion tpm_tis_get_tpm_version(Object *obj); #define TYPE_TPM_TIS "tpm-tis" -- cgit v1.2.3-55-g7522 From 8a89c9ac15981c2d15ce4ee6d6ad67da58824a04 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:00 +0100 Subject: tpm-backend: store TPMIf interface, improve backend_init() Store the TPM interface, the actual object may be different from TPMState. Keep a reference on the interface, and check the backend wasn't already initialized. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- backends/tpm.c | 11 +++++++++-- hw/tpm/tpm_emulator.c | 4 ++-- hw/tpm/tpm_passthrough.c | 4 ++-- hw/tpm/tpm_tis.c | 2 +- include/sysemu/tpm.h | 2 +- include/sysemu/tpm_backend.h | 6 +++--- 6 files changed, 18 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index 1e416d7f90..86f0e7e915 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -43,9 +43,15 @@ enum TpmType tpm_backend_get_type(TPMBackend *s) return k->type; } -int tpm_backend_init(TPMBackend *s, TPMState *state) +int tpm_backend_init(TPMBackend *s, TPMIf *tpmif) { - s->tpm_state = state; + if (s->tpmif) { + return -1; + } + + s->tpmif = tpmif; + object_ref(OBJECT(tpmif)); + s->had_startup_error = false; return 0; @@ -193,6 +199,7 @@ static void tpm_backend_instance_finalize(Object *obj) { TPMBackend *s = TPM_BACKEND(obj); + object_unref(OBJECT(s->tpmif)); g_free(s->id); tpm_backend_thread_end(s); } diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index e1a68104d6..5f88975c25 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -186,7 +186,7 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number, static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd) { TPMEmulator *tpm_emu = TPM_EMULATOR(tb); - TPMIfClass *tic = TPM_IF_GET_CLASS(tb->tpm_state); + TPMIfClass *tic = TPM_IF_GET_CLASS(tb->tpmif); Error *err = NULL; DPRINTF("processing TPM command"); @@ -201,7 +201,7 @@ static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd) goto error; } - tic->request_completed(TPM_IF(tb->tpm_state)); + tic->request_completed(tb->tpmif); return; error: diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index c440aff4b2..2ad74badca 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -139,14 +139,14 @@ err_exit: static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *cmd) { TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - TPMIfClass *tic = TPM_IF_GET_CLASS(tb->tpm_state); + TPMIfClass *tic = TPM_IF_GET_CLASS(tb->tpmif); DPRINTF("tpm_passthrough: processing command %p\n", cmd); tpm_passthrough_unix_tx_bufs(tpm_pt, cmd->in, cmd->in_len, cmd->out, cmd->out_len, &cmd->selftest_done); - tic->request_completed(TPM_IF(tb->tpm_state)); + tic->request_completed(tb->tpmif); } static void tpm_passthrough_reset(TPMBackend *tb) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 880ca1a572..9a2360e250 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -1082,7 +1082,7 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp) s->be_driver->fe_model = TPM_MODEL_TPM_TIS; - if (tpm_backend_init(s->be_driver, s)) { + if (tpm_backend_init(s->be_driver, TPM_IF(s))) { error_setg(errp, "tpm_tis: backend driver with id %s could not be " "initialized", s->backend); return; diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index 452cdb9cb7..fb1719e5e4 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -12,8 +12,8 @@ #ifndef QEMU_TPM_H #define QEMU_TPM_H -#include "qemu/option.h" #include "qom/object.h" +#include "qapi-types.h" typedef struct TPMState TPMState; diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 03ea5a3400..b5f21ed8f1 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -43,8 +43,8 @@ struct TPMBackend { Object parent; /*< protected >*/ + TPMIf *tpmif; bool opened; - TPMState *tpm_state; GThreadPool *thread_pool; bool had_startup_error; @@ -96,14 +96,14 @@ enum TpmType tpm_backend_get_type(TPMBackend *s); /** * tpm_backend_init: * @s: the backend to initialized - * @state: TPMState + * @tpmif: TPM interface * @datacb: callback for sending data to frontend * * Initialize the backend with the given variables. * * Returns 0 on success. */ -int tpm_backend_init(TPMBackend *s, TPMState *state); +int tpm_backend_init(TPMBackend *s, TPMIf *tpmif); /** * tpm_backend_startup_tpm: -- cgit v1.2.3-55-g7522 From 36e8658924cec6427ca00f87ce86f65cfa705d69 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:01 +0100 Subject: tpm-tis: no longer expose TPMState Now that there is an interface instead. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/tpm/tpm_tis.c | 4 ++-- include/sysemu/tpm.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 9a2360e250..4670287f82 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -72,7 +72,7 @@ typedef struct TPMLocality { TPMSizedBuffer r_buffer; } TPMLocality; -struct TPMState { +typedef struct TPMState { ISADevice busdev; MemoryRegion mmio; @@ -94,7 +94,7 @@ struct TPMState { char *backend; TPMBackend *be_driver; TPMVersion be_tpm_version; -}; +} TPMState; #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index fb1719e5e4..7a1713a81e 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -15,8 +15,6 @@ #include "qom/object.h" #include "qapi-types.h" -typedef struct TPMState TPMState; - int tpm_config_parse(QemuOptsList *opts_list, const char *optarg); int tpm_init(void); void tpm_cleanup(void); -- cgit v1.2.3-55-g7522 From 689990598a710519eba37e4eb4d8bdebac1aa562 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:02 +0100 Subject: tpm-be: call request_completed() out of thread Lift from the backend implementation the responsability to call the request_completed() callback outside of thread context. This also simplify frontend/interface work, as they no longer need to care whether the callback is called from a different thread. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- backends/tpm.c | 15 ++++++++++++++- hw/tpm/tpm_emulator.c | 2 -- hw/tpm/tpm_passthrough.c | 3 --- hw/tpm/tpm_tis.c | 34 ++++++++++++---------------------- include/sysemu/tpm.h | 1 - include/sysemu/tpm_backend.h | 1 + 6 files changed, 27 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index 86f0e7e915..58f823d54c 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -18,14 +18,25 @@ #include "qapi/qmp/qerror.h" #include "sysemu/tpm.h" #include "qemu/thread.h" +#include "qemu/main-loop.h" + +static void tpm_backend_request_completed_bh(void *opaque) +{ + TPMBackend *s = TPM_BACKEND(opaque); + TPMIfClass *tic = TPM_IF_GET_CLASS(s->tpmif); + + tic->request_completed(s->tpmif); +} static void tpm_backend_worker_thread(gpointer data, gpointer user_data) { TPMBackend *s = TPM_BACKEND(user_data); - TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); + TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); assert(k->handle_request != NULL); k->handle_request(s, (TPMBackendCmd *)data); + + qemu_bh_schedule(s->bh); } static void tpm_backend_thread_end(TPMBackend *s) @@ -193,6 +204,7 @@ static void tpm_backend_instance_init(Object *obj) tpm_backend_prop_set_opened, NULL); s->fe_model = -1; + s->bh = qemu_bh_new(tpm_backend_request_completed_bh, s); } static void tpm_backend_instance_finalize(Object *obj) @@ -202,6 +214,7 @@ static void tpm_backend_instance_finalize(Object *obj) object_unref(OBJECT(s->tpmif)); g_free(s->id); tpm_backend_thread_end(s); + qemu_bh_delete(s->bh); } static const TypeInfo tpm_backend_info = { diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 5f88975c25..47f37d6cac 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -186,7 +186,6 @@ static int tpm_emulator_set_locality(TPMEmulator *tpm_emu, uint8_t locty_number, static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd) { TPMEmulator *tpm_emu = TPM_EMULATOR(tb); - TPMIfClass *tic = TPM_IF_GET_CLASS(tb->tpmif); Error *err = NULL; DPRINTF("processing TPM command"); @@ -201,7 +200,6 @@ static void tpm_emulator_handle_request(TPMBackend *tb, TPMBackendCmd *cmd) goto error; } - tic->request_completed(tb->tpmif); return; error: diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index 2ad74badca..8c002e4da6 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -139,14 +139,11 @@ err_exit: static void tpm_passthrough_handle_request(TPMBackend *tb, TPMBackendCmd *cmd) { TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - TPMIfClass *tic = TPM_IF_GET_CLASS(tb->tpmif); DPRINTF("tpm_passthrough: processing command %p\n", cmd); tpm_passthrough_unix_tx_bufs(tpm_pt, cmd->in, cmd->in_len, cmd->out, cmd->out_len, &cmd->selftest_done); - - tic->request_completed(tb->tpmif); } static void tpm_passthrough_reset(TPMBackend *tb) diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 4670287f82..95d3afca1d 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -76,7 +76,6 @@ typedef struct TPMState { ISADevice busdev; MemoryRegion mmio; - QEMUBH *bh; uint32_t offset; uint8_t buf[TPM_TIS_BUFFER_MAX]; @@ -410,10 +409,20 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) tpm_tis_abort(s, locty); } -static void tpm_tis_receive_bh(void *opaque) +/* + * Callback from the TPM to indicate that the response was received. + */ +static void tpm_tis_request_completed(TPMIf *ti) { - TPMState *s = opaque; + TPMState *s = TPM(ti); uint8_t locty = s->cmd.locty; + uint8_t l; + + if (s->cmd.selftest_done) { + for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { + s->loc[locty].sts |= TPM_TIS_STS_SELFTEST_DONE; + } + } tpm_tis_sts_set(&s->loc[locty], TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); @@ -431,23 +440,6 @@ static void tpm_tis_receive_bh(void *opaque) TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); } -static void tpm_tis_request_completed(TPMIf *ti) -{ - TPMState *s = TPM(ti); - - bool is_selftest_done = s->cmd.selftest_done; - uint8_t locty = s->cmd.locty; - uint8_t l; - - if (is_selftest_done) { - for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { - s->loc[locty].sts |= TPM_TIS_STS_SELFTEST_DONE; - } - } - - qemu_bh_schedule(s->bh); -} - /* * Read a byte of response data */ @@ -1094,8 +1086,6 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp) return; } - s->bh = qemu_bh_new(tpm_tis_receive_bh, s); - isa_init_irq(&s->busdev, &s->irq, s->irq_num); memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)), diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index 7a1713a81e..e0879620e7 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -40,7 +40,6 @@ typedef struct TPMIf { typedef struct TPMIfClass { InterfaceClass parent_class; - /* run in thread pool by backend */ void (*request_completed)(TPMIf *obj); } TPMIfClass; diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index b5f21ed8f1..c5d1a6818a 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -47,6 +47,7 @@ struct TPMBackend { bool opened; GThreadPool *thread_pool; bool had_startup_error; + QEMUBH *bh; /* */ char *id; -- cgit v1.2.3-55-g7522 From 0bd6c8a9cfa4fd5c25a32ed39f3b8cb786b75b58 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:03 +0100 Subject: tpm-be: report error instead of front-end Backend can give more accurate error description, and lift out the job from the frontend. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- backends/tpm.c | 3 ++- hw/tpm/tpm_tis.c | 4 +--- include/sysemu/tpm_backend.h | 3 ++- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index 58f823d54c..7b108bd5d8 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -54,9 +54,10 @@ enum TpmType tpm_backend_get_type(TPMBackend *s) return k->type; } -int tpm_backend_init(TPMBackend *s, TPMIf *tpmif) +int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error **errp) { if (s->tpmif) { + error_setg(errp, "TPM backend '%s' is already initialized", s->id); return -1; } diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 95d3afca1d..bf291e6eff 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -1074,9 +1074,7 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp) s->be_driver->fe_model = TPM_MODEL_TPM_TIS; - if (tpm_backend_init(s->be_driver, TPM_IF(s))) { - error_setg(errp, "tpm_tis: backend driver with id %s could not be " - "initialized", s->backend); + if (tpm_backend_init(s->be_driver, TPM_IF(s), errp)) { return; } diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index c5d1a6818a..df9ebd0e81 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -99,12 +99,13 @@ enum TpmType tpm_backend_get_type(TPMBackend *s); * @s: the backend to initialized * @tpmif: TPM interface * @datacb: callback for sending data to frontend + * @errp: a pointer to return the #Error object if an error occurs. * * Initialize the backend with the given variables. * * Returns 0 on success. */ -int tpm_backend_init(TPMBackend *s, TPMIf *tpmif); +int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error **errp); /** * tpm_backend_startup_tpm: -- cgit v1.2.3-55-g7522 From 191adc9476371ad94771609d8b9a968d9332a962 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:04 +0100 Subject: tpm-be: ask model to the TPM interface No need to store the mode in the backend, or to let the frontend set it itself. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- backends/tpm.c | 4 ++-- hw/tpm/tpm_tis.c | 3 +-- include/sysemu/tpm.h | 1 + include/sysemu/tpm_backend.h | 1 - tpm.c | 3 ++- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index 7b108bd5d8..0c48d18775 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -148,9 +148,10 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s) { TPMInfo *info = g_new0(TPMInfo, 1); TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); + TPMIfClass *tic = TPM_IF_GET_CLASS(s->tpmif); info->id = g_strdup(s->id); - info->model = s->fe_model; + info->model = tic->model; if (k->get_tpm_options) { info->options = k->get_tpm_options(s); } @@ -204,7 +205,6 @@ static void tpm_backend_instance_init(Object *obj) tpm_backend_prop_get_opened, tpm_backend_prop_set_opened, NULL); - s->fe_model = -1; s->bh = qemu_bh_new(tpm_backend_request_completed_bh, s); } diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index bf291e6eff..a780167feb 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -1072,8 +1072,6 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp) return; } - s->be_driver->fe_model = TPM_MODEL_TPM_TIS; - if (tpm_backend_init(s->be_driver, TPM_IF(s), errp)) { return; } @@ -1108,6 +1106,7 @@ static void tpm_tis_class_init(ObjectClass *klass, void *data) dc->props = tpm_tis_properties; dc->reset = tpm_tis_reset; dc->vmsd = &vmstate_tpm_tis; + tc->model = TPM_MODEL_TPM_TIS; tc->request_completed = tpm_tis_request_completed; } diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index e0879620e7..7b407caf25 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -40,6 +40,7 @@ typedef struct TPMIf { typedef struct TPMIfClass { InterfaceClass parent_class; + enum TpmModel model; void (*request_completed)(TPMIf *obj); } TPMIfClass; diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index df9ebd0e81..665e807a73 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -51,7 +51,6 @@ struct TPMBackend { /* */ char *id; - enum TpmModel fe_model; QLIST_ENTRY(TPMBackend) list; }; diff --git a/tpm.c b/tpm.c index ab5d29e91e..4320f44c9f 100644 --- a/tpm.c +++ b/tpm.c @@ -200,9 +200,10 @@ TPMInfoList *qmp_query_tpm(Error **errp) TPMInfoList *info, *head = NULL, *cur_item = NULL; QLIST_FOREACH(drv, &tpm_backends, list) { - if (!tpm_models[drv->fe_model]) { + if (!drv->tpmif) { continue; } + info = g_new0(TPMInfoList, 1); info->value = tpm_backend_query_tpm(drv); -- cgit v1.2.3-55-g7522 From 3c3ef630621e4cdc5171dcfd19a22b2dc300bcb3 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:05 +0100 Subject: tpm: remove unused opened code Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- backends/tpm.c | 42 ------------------------------------------ include/sysemu/tpm_backend.h | 12 ------------ tpm.c | 6 ------ 3 files changed, 60 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index 0c48d18775..7e636fbc7a 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -159,52 +159,10 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s) return info; } -static bool tpm_backend_prop_get_opened(Object *obj, Error **errp) -{ - TPMBackend *s = TPM_BACKEND(obj); - - return s->opened; -} - -void tpm_backend_open(TPMBackend *s, Error **errp) -{ - object_property_set_bool(OBJECT(s), true, "opened", errp); -} - -static void tpm_backend_prop_set_opened(Object *obj, bool value, Error **errp) -{ - TPMBackend *s = TPM_BACKEND(obj); - TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); - Error *local_err = NULL; - - if (value == s->opened) { - return; - } - - if (!value && s->opened) { - error_setg(errp, QERR_PERMISSION_DENIED); - return; - } - - if (k->opened) { - k->opened(s, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - } - - s->opened = true; -} - static void tpm_backend_instance_init(Object *obj) { TPMBackend *s = TPM_BACKEND(obj); - object_property_add_bool(obj, "opened", - tpm_backend_prop_get_opened, - tpm_backend_prop_set_opened, - NULL); s->bh = qemu_bh_new(tpm_backend_request_completed_bh, s); } diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 665e807a73..904e5b1026 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -80,8 +80,6 @@ struct TPMBackendClass { TpmTypeOptions *(*get_tpm_options)(TPMBackend *t); - void (*opened)(TPMBackend *s, Error **errp); - void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd); }; @@ -171,16 +169,6 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s); */ int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty); -/** - * tpm_backend_open: - * @s: the backend to open - * @errp: a pointer to return the #Error object if an error occurs. - * - * This function will open the backend if it is not already open. Calling this - * function on an already opened backend will not result in an error. - */ -void tpm_backend_open(TPMBackend *s, Error **errp); - /** * tpm_backend_get_tpm_version: * @s: the backend to call into diff --git a/tpm.c b/tpm.c index 4320f44c9f..32d398aadf 100644 --- a/tpm.c +++ b/tpm.c @@ -132,12 +132,6 @@ static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp) return 1; } - tpm_backend_open(drv, &local_err); - if (local_err) { - error_report_err(local_err); - return 1; - } - QLIST_INSERT_HEAD(&tpm_backends, drv, list); return 0; -- cgit v1.2.3-55-g7522 From ebca2df783a5a742bb93784524336d8cbb9e662b Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:07 +0100 Subject: tpm-be: update optional function pointers QEMU code doesn't generally have assert() for mandatory callbacks/function pointers, probably because the crash is pretty obvious. Document the methods instead of going into the code. Make get_tpm_options() mandatory to implement (since all backend implementation have it). Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- backends/tpm.c | 9 +-------- include/sysemu/tpm_backend.h | 5 ++++- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index 7e636fbc7a..7777467c44 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -33,7 +33,6 @@ static void tpm_backend_worker_thread(gpointer data, gpointer user_data) TPMBackend *s = TPM_BACKEND(user_data); TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); - assert(k->handle_request != NULL); k->handle_request(s, (TPMBackendCmd *)data); qemu_bh_schedule(s->bh); @@ -114,8 +113,6 @@ void tpm_backend_cancel_cmd(TPMBackend *s) { TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); - assert(k->cancel_cmd); - k->cancel_cmd(s); } @@ -139,8 +136,6 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s) { TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); - assert(k->get_tpm_version); - return k->get_tpm_version(s); } @@ -152,9 +147,7 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s) info->id = g_strdup(s->id); info->model = tic->model; - if (k->get_tpm_options) { - info->options = k->get_tpm_options(s); - } + info->options = k->get_tpm_options(s); return info; } diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 904e5b1026..ce8dee58cf 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -65,15 +65,18 @@ struct TPMBackendClass { TPMBackend *(*create)(QemuOpts *opts, const char *id); - /* start up the TPM on the backend */ + /* start up the TPM on the backend - optional */ int (*startup_tpm)(TPMBackend *t); + /* optional */ void (*reset)(TPMBackend *t); void (*cancel_cmd)(TPMBackend *t); + /* optional */ bool (*get_tpm_established_flag)(TPMBackend *t); + /* optional */ int (*reset_tpm_established_flag)(TPMBackend *t, uint8_t locty); TPMVersion (*get_tpm_version)(TPMBackend *t); -- cgit v1.2.3-55-g7522 From 9f7c0ef2ffa02b3bf6bc630496b8df67c750edd3 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:09 +0100 Subject: tpm-backend: move set 'id' to common code Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/tpm/tpm_emulator.c | 12 +++--------- hw/tpm/tpm_passthrough.c | 9 +++------ include/sysemu/tpm_backend.h | 2 +- tpm.c | 3 ++- 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 47f37d6cac..94e6660a5a 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -463,22 +463,16 @@ err: return -1; } -static TPMBackend *tpm_emulator_create(QemuOpts *opts, const char *id) +static TPMBackend *tpm_emulator_create(QemuOpts *opts) { TPMBackend *tb = TPM_BACKEND(object_new(TYPE_TPM_EMULATOR)); - tb->id = g_strdup(id); - if (tpm_emulator_handle_device_opts(TPM_EMULATOR(tb), opts)) { - goto err_exit; + object_unref(OBJECT(tb)); + return NULL; } return tb; - -err_exit: - object_unref(OBJECT(tb)); - - return NULL; } static TpmTypeOptions *tpm_emulator_get_tpm_options(TPMBackend *tb) diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index 9326cbfdc9..7371d50739 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -284,13 +284,10 @@ tpm_passthrough_handle_device_opts(TPMPassthruState *tpm_pt, QemuOpts *opts) return 1; } -static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id) +static TPMBackend *tpm_passthrough_create(QemuOpts *opts) { Object *obj = object_new(TYPE_TPM_PASSTHROUGH); - TPMBackend *tb = TPM_BACKEND(obj); - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - - tb->id = g_strdup(id); + TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(obj); if (tpm_passthrough_handle_device_opts(tpm_pt, opts)) { goto err_exit; @@ -301,7 +298,7 @@ static TPMBackend *tpm_passthrough_create(QemuOpts *opts, const char *id) goto err_exit; } - return tb; + return TPM_BACKEND(obj); err_exit: object_unref(obj); diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index ce8dee58cf..1ad27ec374 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -63,7 +63,7 @@ struct TPMBackendClass { /* get a descriptive text of the backend to display to the user */ const char *desc; - TPMBackend *(*create)(QemuOpts *opts, const char *id); + TPMBackend *(*create)(QemuOpts *opts); /* start up the TPM on the backend - optional */ int (*startup_tpm)(TPMBackend *t); diff --git a/tpm.c b/tpm.c index 32d398aadf..520f449234 100644 --- a/tpm.c +++ b/tpm.c @@ -127,11 +127,12 @@ static int tpm_init_tpmdev(void *dummy, QemuOpts *opts, Error **errp) return 1; } - drv = be->create(opts, id); + drv = be->create(opts); if (!drv) { return 1; } + drv->id = g_strdup(id); QLIST_INSERT_HEAD(&tpm_backends, drv, list); return 0; -- cgit v1.2.3-55-g7522 From d36e7db1fbf1a5cff4aa359dfe5c2e5dd97d3e13 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:14 +0100 Subject: tpm: rename qemu_find_tpm() -> qemu_find_tpm_be() find_tpm() will be introduced to lookup the TPM device. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/tpm/tpm_tis.c | 2 +- include/sysemu/tpm_backend.h | 2 +- tpm.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 81b23b78bb..fd1511b8eb 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -1060,7 +1060,7 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp) { TPMState *s = TPM(dev); - s->be_driver = qemu_find_tpm(s->backend); + s->be_driver = qemu_find_tpm_be(s->backend); if (!s->be_driver) { error_setg(errp, "tpm_tis: backend driver with id %s could not be " "found", s->backend); diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 1ad27ec374..c42d83aaef 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -192,7 +192,7 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s); */ TPMInfo *tpm_backend_query_tpm(TPMBackend *s); -TPMBackend *qemu_find_tpm(const char *id); +TPMBackend *qemu_find_tpm_be(const char *id); void tpm_register_model(enum TpmModel model); diff --git a/tpm.c b/tpm.c index 520f449234..4661dfc46e 100644 --- a/tpm.c +++ b/tpm.c @@ -69,7 +69,7 @@ static void tpm_display_backend_drivers(void) /* * Find the TPM with the given Id */ -TPMBackend *qemu_find_tpm(const char *id) +TPMBackend *qemu_find_tpm_be(const char *id) { TPMBackend *drv; -- cgit v1.2.3-55-g7522 From 3dfd5a2a50fc4907728eb83569c84b0d98b56582 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:15 +0100 Subject: tpm: lookup the the TPM interface instead of TIS device This will allow to introduce new devices implementing TPM. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/i386/acpi-build.c | 2 +- include/sysemu/tpm.h | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 73519ab3ac..cdb4aa9835 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -208,7 +208,7 @@ static void acpi_get_misc_info(AcpiMiscInfo *info) } info->has_hpet = hpet_find(); - info->tpm_version = tpm_get_version(); + info->tpm_version = tpm_get_version(tpm_find()); info->pvpanic_port = pvpanic_port(); info->applesmc_io_base = applesmc_port(); } diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index 7b407caf25..2fe0f1e120 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -19,7 +19,7 @@ int tpm_config_parse(QemuOptsList *opts_list, const char *optarg); int tpm_init(void); void tpm_cleanup(void); -typedef enum TPMVersion { +typedef enum TPMVersion { TPM_VERSION_UNSPEC = 0, TPM_VERSION_1_2 = 1, TPM_VERSION_2_0 = 2, @@ -44,20 +44,25 @@ typedef struct TPMIfClass { void (*request_completed)(TPMIf *obj); } TPMIfClass; -TPMVersion tpm_tis_get_tpm_version(Object *obj); - #define TYPE_TPM_TIS "tpm-tis" -static inline TPMVersion tpm_get_version(void) +/* returns NULL unless there is exactly one TPM device */ +static inline TPMIf *tpm_find(void) { -#ifdef CONFIG_TPM - Object *obj = object_resolve_path_type("", TYPE_TPM_TIS, NULL); + Object *obj = object_resolve_path_type("", TYPE_TPM_IF, NULL); + + return TPM_IF(obj); +} - if (obj) { - return tpm_tis_get_tpm_version(obj); +TPMVersion tpm_tis_get_tpm_version(Object *obj); + +static inline TPMVersion tpm_get_version(TPMIf *ti) +{ + if (!ti) { + return TPM_VERSION_UNSPEC; } -#endif - return TPM_VERSION_UNSPEC; + + return tpm_tis_get_tpm_version(OBJECT(ti)); } #endif /* QEMU_TPM_H */ -- cgit v1.2.3-55-g7522 From 9af7a721662de8cdfa7b02b7e9cc2c2c30e7bacb Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:16 +0100 Subject: tpm: add TPM interface to lookup TPM version Do not hardcode TPM device model to lookup version, use an interface instead. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/tpm/tpm_tis.c | 5 +++-- include/sysemu/tpm.h | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index fd1511b8eb..4d13335d23 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -990,9 +990,9 @@ static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb) /* * Get the TPMVersion of the backend device being used */ -TPMVersion tpm_tis_get_tpm_version(Object *obj) +static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti) { - TPMState *s = TPM(obj); + TPMState *s = TPM(ti); if (tpm_backend_had_startup_error(s->be_driver)) { return TPM_VERSION_UNSPEC; @@ -1102,6 +1102,7 @@ static void tpm_tis_class_init(ObjectClass *klass, void *data) dc->reset = tpm_tis_reset; dc->vmsd = &vmstate_tpm_tis; tc->model = TPM_MODEL_TPM_TIS; + tc->get_version = tpm_tis_get_tpm_version; tc->request_completed = tpm_tis_request_completed; } diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index 2fe0f1e120..650b4b8565 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -42,6 +42,7 @@ typedef struct TPMIfClass { enum TpmModel model; void (*request_completed)(TPMIf *obj); + enum TPMVersion (*get_version)(TPMIf *obj); } TPMIfClass; #define TYPE_TPM_TIS "tpm-tis" @@ -54,15 +55,13 @@ static inline TPMIf *tpm_find(void) return TPM_IF(obj); } -TPMVersion tpm_tis_get_tpm_version(Object *obj); - static inline TPMVersion tpm_get_version(TPMIf *ti) { if (!ti) { return TPM_VERSION_UNSPEC; } - return tpm_tis_get_tpm_version(OBJECT(ti)); + return TPM_IF_GET_CLASS(ti)->get_version(ti); } #endif /* QEMU_TPM_H */ -- cgit v1.2.3-55-g7522 From ff5ce21e1b959206f257967d6de2efa6f4e3d188 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:18 +0100 Subject: acpi: change TPM TIS data conditions The device should be exposed if present. It shouldn't have an undefined version (or else backend init failed, and device should fail too). Finally, make the fields specific to TIS device model. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/i386/acpi-build.c | 12 ++++++++---- include/sysemu/tpm.h | 3 +++ 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index cdb4aa9835..dd1420b410 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2038,7 +2038,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, } } - if (misc->tpm_version != TPM_VERSION_UNSPEC) { + if (TPM_IS_TIS(tpm_find())) { aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE, TPM_TIS_ADDR_SIZE, AML_READ_WRITE)); } @@ -2204,7 +2204,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, /* Scan all PCI buses. Generate tables to support hotplug. */ build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en); - if (misc->tpm_version != TPM_VERSION_UNSPEC) { + if (TPM_IS_TIS(tpm_find())) { dev = aml_device("ISA.TPM"); aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31"))); aml_append(dev, aml_name_decl("_STA", aml_int(0xF))); @@ -2281,8 +2281,12 @@ build_tpm2(GArray *table_data, BIOSLinker *linker) tpm2_ptr = acpi_data_push(table_data, sizeof *tpm2_ptr); tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT); - tpm2_ptr->control_area_address = cpu_to_le64(0); - tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO); + if (TPM_IS_TIS(tpm_find())) { + tpm2_ptr->control_area_address = cpu_to_le64(0); + tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO); + } else { + g_warn_if_reached(); + } build_header(linker, table_data, (void *)tpm2_ptr, "TPM2", sizeof(*tpm2_ptr), 4, NULL, NULL); diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h index 650b4b8565..852e02687c 100644 --- a/include/sysemu/tpm.h +++ b/include/sysemu/tpm.h @@ -47,6 +47,9 @@ typedef struct TPMIfClass { #define TYPE_TPM_TIS "tpm-tis" +#define TPM_IS_TIS(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS) + /* returns NULL unless there is exactly one TPM device */ static inline TPMIf *tpm_find(void) { -- cgit v1.2.3-55-g7522 From 493b78303532146c8161b33e878db8af7dca3b81 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:23 +0100 Subject: qdev: add DEFINE_PROP_TPMBE A property to lookup a tpm backend. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/core/qdev-properties-system.c | 64 ++++++++++++++++++++++++++++++++++++++++ include/hw/qdev-properties.h | 3 ++ 2 files changed, 67 insertions(+) (limited to 'include') diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index ec10da7424..c17364655c 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -21,6 +21,7 @@ #include "net/hub.h" #include "qapi/visitor.h" #include "chardev/char-fe.h" +#include "sysemu/tpm_backend.h" #include "sysemu/iothread.h" static void get_pointer(Object *obj, Visitor *v, Property *prop, @@ -236,6 +237,69 @@ const PropertyInfo qdev_prop_chr = { .release = release_chr, }; +/* --- character device --- */ + +static void get_tpm(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + TPMBackend **be = qdev_get_prop_ptr(dev, opaque); + char *p; + + p = g_strdup(*be ? (*be)->id : ""); + visit_type_str(v, name, &p, errp); + g_free(p); +} + +static void set_tpm(Object *obj, Visitor *v, const char *name, void *opaque, + Error **errp) +{ + DeviceState *dev = DEVICE(obj); + Error *local_err = NULL; + Property *prop = opaque; + TPMBackend *s, **be = qdev_get_prop_ptr(dev, prop); + char *str; + + if (dev->realized) { + qdev_prop_set_after_realize(dev, name, errp); + return; + } + + visit_type_str(v, name, &str, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + s = qemu_find_tpm_be(str); + if (s == NULL) { + error_setg(errp, "Property '%s.%s' can't find value '%s'", + object_get_typename(obj), prop->name, str); + } else if (tpm_backend_init(s, TPM_IF(obj), errp) == 0) { + *be = s; /* weak reference, avoid cyclic ref */ + } + g_free(str); +} + +static void release_tpm(Object *obj, const char *name, void *opaque) +{ + DeviceState *dev = DEVICE(obj); + Property *prop = opaque; + TPMBackend **be = qdev_get_prop_ptr(dev, prop); + + if (*be) { + tpm_backend_reset(*be); + } +} + +const PropertyInfo qdev_prop_tpm = { + .name = "str", + .description = "ID of a tpm to use as a backend", + .get = get_tpm, + .set = set_tpm, + .release = release_tpm, +}; + /* --- netdev device --- */ static void get_netdev(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index e2321f1cc1..4d24cdf8d6 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -17,6 +17,7 @@ extern const PropertyInfo qdev_prop_int64; extern const PropertyInfo qdev_prop_size; extern const PropertyInfo qdev_prop_string; extern const PropertyInfo qdev_prop_chr; +extern const PropertyInfo qdev_prop_tpm; extern const PropertyInfo qdev_prop_ptr; extern const PropertyInfo qdev_prop_macaddr; extern const PropertyInfo qdev_prop_on_off_auto; @@ -186,6 +187,8 @@ extern const PropertyInfo qdev_prop_link; #define DEFINE_PROP_CHR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharBackend) +#define DEFINE_PROP_TPMBE(_n, _s, _f) \ + DEFINE_PROP(_n, _s, _f, qdev_prop_tpm, TPMBackend *) #define DEFINE_PROP_STRING(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) #define DEFINE_PROP_NETDEV(_n, _s, _f) \ -- cgit v1.2.3-55-g7522 From d3fd953f06700ebe2d15825d4399f7cd3e31af34 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Mon, 6 Nov 2017 19:39:25 +0100 Subject: tpm: remove tpm_register_model() Query object classes that implements TPMIf instead. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Berger Signed-off-by: Stefan Berger --- hw/tpm/tpm_tis.c | 1 - include/sysemu/tpm_backend.h | 2 -- tpm.c | 20 ++++++-------------- 3 files changed, 6 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 97cd7f5026..98c11a4da1 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -1119,7 +1119,6 @@ static const TypeInfo tpm_tis_info = { static void tpm_tis_register(void) { type_register_static(&tpm_tis_info); - tpm_register_model(TPM_MODEL_TPM_TIS); } type_init(tpm_tis_register) diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index c42d83aaef..590e8b42de 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -194,6 +194,4 @@ TPMInfo *tpm_backend_query_tpm(TPMBackend *s); TPMBackend *qemu_find_tpm_be(const char *id); -void tpm_register_model(enum TpmModel model); - #endif diff --git a/tpm.c b/tpm.c index 4661dfc46e..61a434185a 100644 --- a/tpm.c +++ b/tpm.c @@ -23,13 +23,6 @@ static QLIST_HEAD(, TPMBackend) tpm_backends = QLIST_HEAD_INITIALIZER(tpm_backends); -static bool tpm_models[TPM_MODEL__MAX]; - -void tpm_register_model(enum TpmModel model) -{ - tpm_models[model] = true; -} - static const TPMBackendClass * tpm_be_find_by_type(enum TpmType type) { @@ -236,18 +229,16 @@ TpmTypeList *qmp_query_tpm_types(Error **errp) return head; } - TpmModelList *qmp_query_tpm_models(Error **errp) { - unsigned int i = 0; TpmModelList *head = NULL, *prev = NULL, *cur_item; + GSList *e, *l = object_class_get_list(TYPE_TPM_IF, false); + + for (e = l; e; e = e->next) { + TPMIfClass *c = TPM_IF_CLASS(e->data); - for (i = 0; i < TPM_MODEL__MAX; i++) { - if (!tpm_models[i]) { - continue; - } cur_item = g_new0(TpmModelList, 1); - cur_item->value = i; + cur_item->value = c->model; if (prev) { prev->next = cur_item; @@ -257,6 +248,7 @@ TpmModelList *qmp_query_tpm_models(Error **errp) } prev = cur_item; } + g_slist_free(l); return head; } -- cgit v1.2.3-55-g7522 From b21e6aaf4a1e25c22a603e22ef96b3a31d3013aa Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Fri, 3 Nov 2017 18:10:01 -0400 Subject: tpm: Move getting TPM buffer size to backends Rather than setting the size of the TPM buffer in the front-end, query the backend for the size of the buffer. In this patch we just move the hard-coded buffer size of 4096 to the backends. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- backends/tpm.c | 7 +++++++ hw/tpm/tpm_emulator.c | 6 ++++++ hw/tpm/tpm_passthrough.c | 6 ++++++ hw/tpm/tpm_tis.c | 12 +++++++----- include/sysemu/tpm_backend.h | 12 ++++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index 7777467c44..cb49185d4b 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -139,6 +139,13 @@ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s) return k->get_tpm_version(s); } +size_t tpm_backend_get_buffer_size(TPMBackend *s) +{ + TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); + + return k->get_buffer_size(s); +} + TPMInfo *tpm_backend_query_tpm(TPMBackend *s) { TPMInfo *info = g_new0(TPMInfo, 1); diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 24cb61162f..44a769d86b 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -356,6 +356,11 @@ static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb) return tpm_emu->tpm_version; } +static size_t tpm_emulator_get_buffer_size(TPMBackend *tb) +{ + return 4096; +} + static int tpm_emulator_block_migration(TPMEmulator *tpm_emu) { Error *err = NULL; @@ -556,6 +561,7 @@ static void tpm_emulator_class_init(ObjectClass *klass, void *data) tbc->get_tpm_established_flag = tpm_emulator_get_tpm_established_flag; tbc->reset_tpm_established_flag = tpm_emulator_reset_tpm_established_flag; tbc->get_tpm_version = tpm_emulator_get_tpm_version; + tbc->get_buffer_size = tpm_emulator_get_buffer_size; tbc->get_tpm_options = tpm_emulator_get_tpm_options; tbc->handle_request = tpm_emulator_handle_request; diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c index 73554aa792..daac67d44a 100644 --- a/hw/tpm/tpm_passthrough.c +++ b/hw/tpm/tpm_passthrough.c @@ -199,6 +199,11 @@ static TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb) return tpm_pt->tpm_version; } +static size_t tpm_passthrough_get_buffer_size(TPMBackend *tb) +{ + return 4096; +} + /* * Unless path or file descriptor set has been provided by user, * determine the sysfs cancel file following kernel documentation @@ -354,6 +359,7 @@ static void tpm_passthrough_class_init(ObjectClass *klass, void *data) tbc->reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag; tbc->get_tpm_version = tpm_passthrough_get_tpm_version; + tbc->get_buffer_size = tpm_passthrough_get_buffer_size; tbc->get_tpm_options = tpm_passthrough_get_tpm_options; tbc->handle_request = tpm_passthrough_handle_request; } diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index 98c11a4da1..bd22e699bb 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -88,6 +88,8 @@ typedef struct TPMState { TPMBackend *be_driver; TPMVersion be_tpm_version; + + size_t be_buffer_size; } TPMState; #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) @@ -977,10 +979,9 @@ static int tpm_tis_do_startup_tpm(TPMState *s) return tpm_backend_startup_tpm(s->be_driver); } -static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb) +static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb, + size_t wanted_size) { - size_t wanted_size = 4096; /* Linux tpm.c buffer size */ - if (sb->size != wanted_size) { sb->buffer = g_realloc(sb->buffer, wanted_size); sb->size = wanted_size; @@ -1011,6 +1012,7 @@ static void tpm_tis_reset(DeviceState *dev) int c; s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); + s->be_buffer_size = tpm_backend_get_buffer_size(s->be_driver); tpm_backend_reset(s->be_driver); @@ -1037,9 +1039,9 @@ static void tpm_tis_reset(DeviceState *dev) s->loc[c].state = TPM_TIS_STATE_IDLE; s->loc[c].w_offset = 0; - tpm_tis_realloc_buffer(&s->loc[c].w_buffer); + tpm_tis_realloc_buffer(&s->loc[c].w_buffer, s->be_buffer_size); s->loc[c].r_offset = 0; - tpm_tis_realloc_buffer(&s->loc[c].r_buffer); + tpm_tis_realloc_buffer(&s->loc[c].r_buffer, s->be_buffer_size); } tpm_tis_do_startup_tpm(s); diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 590e8b42de..7c98b6100d 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -81,6 +81,8 @@ struct TPMBackendClass { TPMVersion (*get_tpm_version)(TPMBackend *t); + size_t (*get_buffer_size)(TPMBackend *t); + TpmTypeOptions *(*get_tpm_options)(TPMBackend *t); void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd); @@ -182,6 +184,16 @@ int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty); */ TPMVersion tpm_backend_get_tpm_version(TPMBackend *s); +/** + * tpm_backend_get_buffer_size: + * @s: the backend to call into + * + * Get the TPM's buffer size. + * + * Returns buffer size. + */ +size_t tpm_backend_get_buffer_size(TPMBackend *s); + /** * tpm_backend_query_tpm: * @s: the backend -- cgit v1.2.3-55-g7522 From 9375c44fdfc07c0fef3052a3f25a13197a528902 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Sat, 4 Nov 2017 19:57:15 -0400 Subject: tpm: tpm_emulator: get and set buffer size of device Convert the tpm_emulator backend to get the current buffer size of the external device and set it to the buffer size that the frontend (TIS) requests. Signed-off-by: Stefan Berger Reviewed-by: Marc-André Lureau --- backends/tpm.c | 4 +-- hw/tpm/tpm_emulator.c | 79 +++++++++++++++++++++++++++++++++++++++++--- hw/tpm/tpm_ioctl.h | 28 +++++++++++++++- hw/tpm/tpm_tis.c | 6 ++-- include/sysemu/tpm_backend.h | 6 ++-- 5 files changed, 111 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/backends/tpm.c b/backends/tpm.c index cb49185d4b..91222c5164 100644 --- a/backends/tpm.c +++ b/backends/tpm.c @@ -68,7 +68,7 @@ int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error **errp) return 0; } -int tpm_backend_startup_tpm(TPMBackend *s) +int tpm_backend_startup_tpm(TPMBackend *s, size_t buffersize) { int res = 0; TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); @@ -79,7 +79,7 @@ int tpm_backend_startup_tpm(TPMBackend *s) s->thread_pool = g_thread_pool_new(tpm_backend_worker_thread, s, 1, TRUE, NULL); - res = k->startup_tpm ? k->startup_tpm(s) : 0; + res = k->startup_tpm ? k->startup_tpm(s, buffersize) : 0; s->had_startup_error = (res != 0); diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c index 44a769d86b..3ae8bf6c5a 100644 --- a/hw/tpm/tpm_emulator.c +++ b/hw/tpm/tpm_emulator.c @@ -232,13 +232,14 @@ static int tpm_emulator_check_caps(TPMEmulator *tpm_emu) switch (tpm_emu->tpm_version) { case TPM_VERSION_1_2: caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | - PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD; + PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD | PTM_CAP_STOP | + PTM_CAP_SET_BUFFERSIZE; tpm = "1.2"; break; case TPM_VERSION_2_0: caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED | - PTM_CAP_SET_DATAFD; + PTM_CAP_SET_DATAFD | PTM_CAP_STOP | PTM_CAP_SET_BUFFERSIZE; tpm = "2"; break; case TPM_VERSION_UNSPEC: @@ -255,12 +256,76 @@ static int tpm_emulator_check_caps(TPMEmulator *tpm_emu) return 0; } -static int tpm_emulator_startup_tpm(TPMBackend *tb) +static int tpm_emulator_stop_tpm(TPMBackend *tb) +{ + TPMEmulator *tpm_emu = TPM_EMULATOR(tb); + ptm_res res; + + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) { + error_report("tpm-emulator: Could not stop TPM: %s", + strerror(errno)); + return -1; + } + + res = be32_to_cpu(res); + if (res) { + error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x", res); + return -1; + } + + return 0; +} + +static int tpm_emulator_set_buffer_size(TPMBackend *tb, + size_t wanted_size, + size_t *actual_size) +{ + TPMEmulator *tpm_emu = TPM_EMULATOR(tb); + ptm_setbuffersize psbs; + + if (tpm_emulator_stop_tpm(tb) < 0) { + return -1; + } + + psbs.u.req.buffersize = cpu_to_be32(wanted_size); + + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs, + sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) { + error_report("tpm-emulator: Could not set buffer size: %s", + strerror(errno)); + return -1; + } + + psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result); + if (psbs.u.resp.tpm_result != 0) { + error_report("tpm-emulator: TPM result for set buffer size : 0x%x", + psbs.u.resp.tpm_result); + return -1; + } + + if (actual_size) { + *actual_size = be32_to_cpu(psbs.u.resp.buffersize); + } + + DPRINTF("buffer size: %u, min: %u, max: %u\n", + be32_to_cpu(psbs.u.resp.buffersize), + be32_to_cpu(psbs.u.resp.minsize), + be32_to_cpu(psbs.u.resp.maxsize)); + + return 0; +} + +static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize) { TPMEmulator *tpm_emu = TPM_EMULATOR(tb); ptm_init init; ptm_res res; + if (buffersize != 0 && + tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) { + goto err_exit; + } + DPRINTF("%s", __func__); if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init), sizeof(init)) < 0) { @@ -358,7 +423,13 @@ static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb) static size_t tpm_emulator_get_buffer_size(TPMBackend *tb) { - return 4096; + size_t actual_size; + + if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) { + return 4096; + } + + return actual_size; } static int tpm_emulator_block_migration(TPMEmulator *tpm_emu) diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h index 33564b11de..54c8d345ad 100644 --- a/hw/tpm/tpm_ioctl.h +++ b/hw/tpm/tpm_ioctl.h @@ -169,6 +169,28 @@ struct ptm_getconfig { #define PTM_CONFIG_FLAG_FILE_KEY 0x1 #define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2 +/* + * PTM_SET_BUFFERSIZE: Set the buffer size to be used by the TPM. + * A 0 on input queries for the current buffer size. Any other + * number will try to set the buffer size. The returned number is + * the buffer size that will be used, which can be larger than the + * requested one, if it was below the minimum, or smaller than the + * requested one, if it was above the maximum. + */ +struct ptm_setbuffersize { + union { + struct { + uint32_t buffersize; /* 0 to query for current buffer size */ + } req; /* request */ + struct { + ptm_res tpm_result; + uint32_t buffersize; /* buffer size in use */ + uint32_t minsize; /* min. supported buffer size */ + uint32_t maxsize; /* max. supported buffer size */ + } resp; /* response */ + } u; +}; + typedef uint64_t ptm_cap; typedef struct ptm_est ptm_est; @@ -179,6 +201,7 @@ typedef struct ptm_init ptm_init; typedef struct ptm_getstate ptm_getstate; typedef struct ptm_setstate ptm_setstate; typedef struct ptm_getconfig ptm_getconfig; +typedef struct ptm_setbuffersize ptm_setbuffersize; /* capability flags returned by PTM_GET_CAPABILITY */ #define PTM_CAP_INIT (1) @@ -194,6 +217,7 @@ typedef struct ptm_getconfig ptm_getconfig; #define PTM_CAP_STOP (1 << 10) #define PTM_CAP_GET_CONFIG (1 << 11) #define PTM_CAP_SET_DATAFD (1 << 12) +#define PTM_CAP_SET_BUFFERSIZE (1 << 13) enum { PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap), @@ -212,6 +236,7 @@ enum { PTM_STOP = _IOR('P', 13, ptm_res), PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig), PTM_SET_DATAFD = _IOR('P', 15, ptm_res), + PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize), }; /* @@ -240,7 +265,8 @@ enum { CMD_SET_STATEBLOB, CMD_STOP, CMD_GET_CONFIG, - CMD_SET_DATAFD + CMD_SET_DATAFD, + CMD_SET_BUFFERSIZE, }; #endif /* _TPM_IOCTL_H */ diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index bd22e699bb..b8e811b086 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -974,9 +974,9 @@ static const MemoryRegionOps tpm_tis_memory_ops = { }, }; -static int tpm_tis_do_startup_tpm(TPMState *s) +static int tpm_tis_do_startup_tpm(TPMState *s, uint32_t buffersize) { - return tpm_backend_startup_tpm(s->be_driver); + return tpm_backend_startup_tpm(s->be_driver, buffersize); } static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb, @@ -1044,7 +1044,7 @@ static void tpm_tis_reset(DeviceState *dev) tpm_tis_realloc_buffer(&s->loc[c].r_buffer, s->be_buffer_size); } - tpm_tis_do_startup_tpm(s); + tpm_tis_do_startup_tpm(s, 0); } static const VMStateDescription vmstate_tpm_tis = { diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h index 7c98b6100d..0d6c994a62 100644 --- a/include/sysemu/tpm_backend.h +++ b/include/sysemu/tpm_backend.h @@ -66,7 +66,7 @@ struct TPMBackendClass { TPMBackend *(*create)(QemuOpts *opts); /* start up the TPM on the backend - optional */ - int (*startup_tpm)(TPMBackend *t); + int (*startup_tpm)(TPMBackend *t, size_t buffersize); /* optional */ void (*reset)(TPMBackend *t); @@ -112,10 +112,12 @@ int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error **errp); /** * tpm_backend_startup_tpm: * @s: the backend whose TPM support is to be started + * @buffersize: the buffer size the TPM is supposed to use, + * 0 to leave it as-is * * Returns 0 on success. */ -int tpm_backend_startup_tpm(TPMBackend *s); +int tpm_backend_startup_tpm(TPMBackend *s, size_t buffersize); /** * tpm_backend_had_startup_error: -- cgit v1.2.3-55-g7522