* [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform
@ 2019-12-12 18:07 Stefan Berger
2019-12-12 18:07 ` [PATCH v4 1/8] tpm_spapr: Support TPM for ppc64 using CRQ based interface Stefan Berger
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc; +Cc: marcandre.lureau, Stefan Berger, qemu-devel, david
The following series of patches adds vTPM emulator support for the
ppc64 platform (pSeries).
It can be tested as follows with swtpm/libtpms:
mkdir /tmp/mytpm1
swtpm socket --tpmstate dir=/tmp/mytpm1 \
--ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
--log level=20
If TPM 2 is desired, add --tpm2 as parameter to the above.
In another terminal start QEMU:
sudo ./ppc64-softmmu/qemu-system-ppc64 -display sdl \
-machine pseries,accel=kvm \
-m 1024 -bios slof.bin -boot menu=on \
-nodefaults -device VGA -device pci-ohci -device usb-kbd \
-chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-spapr,tpmdev=tpm0 \
-device spapr-vscsi,id=scsi0,reg=0x00002000 \
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \
-drive file=test.img,format=raw,if=none,id=drive-virtio-disk0
Links:
- libtpms: https://github.com/stefanberger/libtpms/wiki
- swtpm: https://github.com/stefanberger/swtpm/wiki
Changes:
v3->v4:
- addressed comments to v3
- reworked suspend/resume support that requires extensions to backends
v2->v3:
- patch 1: a TPM 2 is identified by IBM,vtpm20 in the compatible node
- patch 1: convert to tracing to display Tx and Rx buffers
- added documentation patch
- added patch to enable TPM device as part of pSeries
v1->v2:
- followed Cedric Le Goater's suggestions to patch 1
- send appropriate CRQ error responses if DMA read or write fails
- renamed tpm_spapr_got_payload to tpm_spapr_process_cmd and
pass endianess-adjusted data pointer from CRQ to it
Regards,
Stefan
Stefan Berger (8):
tpm_spapr: Support TPM for ppc64 using CRQ based interface
tpm_backend: Implement check whether tpm backend is suspended
tpm_emulator: Implement callback for whether we are suspended
tpm_passthrough: Implement callback for whether we are suspended
tpm: Return bool from tpm_backend_finish_sync
tpm_spapr: Support suspend and resume
hw/ppc/Kconfig: Enable TPM_SPAPR as part of PSERIES config
docs: tpm: Add example command line for ppc64 and tpm-spapr
backends/tpm.c | 13 +-
docs/specs/tpm.txt | 20 +-
hw/ppc/Kconfig | 1 +
hw/tpm/Kconfig | 6 +
hw/tpm/Makefile.objs | 1 +
hw/tpm/tpm_emulator.c | 12 +
hw/tpm/tpm_passthrough.c | 6 +
hw/tpm/tpm_spapr.c | 460 +++++++++++++++++++++++++++++++++++
hw/tpm/trace-events | 14 ++
include/sysemu/tpm.h | 3 +
include/sysemu/tpm_backend.h | 16 +-
qapi/tpm.json | 6 +-
12 files changed, 552 insertions(+), 6 deletions(-)
create mode 100644 hw/tpm/tpm_spapr.c
--
2.21.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 1/8] tpm_spapr: Support TPM for ppc64 using CRQ based interface
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 2/8] tpm_backend: Implement check whether tpm backend is suspended Stefan Berger
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc; +Cc: marcandre.lureau, Stefan Berger, qemu-devel, david
Implement support for TPM on ppc64 by implementing the vTPM CRQ interface
as a frontend. It can use the tpm_emulator driver backend with the external
swtpm.
The Linux vTPM driver for ppc64 works with this emulation.
This TPM emulator also handles the TPM 2 case.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index 4c8ee87d67..66a570aac1 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -22,3 +22,9 @@ config TPM_EMULATOR
bool
default y
depends on TPMDEV
+
+config TPM_SPAPR
+ bool
+ default n
+ select TPMDEV
+ depends on PSERIES
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index de0b85d02a..85eb99ae05 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
+obj-$(CONFIG_TPM_SPAPR) += tpm_spapr.o
diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c
new file mode 100644
index 0000000000..c4a67e2403
--- /dev/null
+++ b/hw/tpm/tpm_spapr.c
@@ -0,0 +1,405 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtual TPM
+ *
+ * Copyright (c) 2015, 2017 IBM Corporation.
+ *
+ * Authors:
+ * Stefan Berger <stefanb@linux.vnet.ibm.com>
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+
+#include "sysemu/tpm_backend.h"
+#include "tpm_int.h"
+#include "tpm_util.h"
+
+#include "hw/ppc/spapr.h"
+#include "hw/ppc/spapr_vio.h"
+#include "trace.h"
+
+#define DEBUG_SPAPR 0
+
+#define VIO_SPAPR_VTPM(obj) \
+ OBJECT_CHECK(SPAPRvTPMState, (obj), TYPE_TPM_SPAPR)
+
+typedef struct VioCRQ {
+ uint8_t valid; /* 0x80: cmd; 0xc0: init crq */
+ /* 0x81-0x83: CRQ message response */
+ uint8_t msg; /* see below */
+ uint16_t len; /* len of TPM request; len of TPM response */
+ uint32_t data; /* rtce_dma_handle when sending TPM request */
+ uint64_t reserved;
+} VioCRQ;
+
+typedef union TPMSpaprCRQ {
+ VioCRQ s;
+ uint8_t raw[sizeof(VioCRQ)];
+} TPMSpaprCRQ;
+
+#define SPAPR_VTPM_VALID_INIT_CRQ_COMMAND 0xC0
+#define SPAPR_VTPM_VALID_COMMAND 0x80
+#define SPAPR_VTPM_MSG_RESULT 0x80
+
+/* msg types for valid = SPAPR_VTPM_VALID_INIT_CRQ */
+#define SPAPR_VTPM_INIT_CRQ_RESULT 0x1
+#define SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT 0x2
+
+/* msg types for valid = SPAPR_VTPM_VALID_CMD */
+#define SPAPR_VTPM_GET_VERSION 0x1
+#define SPAPR_VTPM_TPM_COMMAND 0x2
+#define SPAPR_VTPM_GET_RTCE_BUFFER_SIZE 0x3
+#define SPAPR_VTPM_PREPARE_TO_SUSPEND 0x4
+
+/* response error messages */
+#define SPAPR_VTPM_VTPM_ERROR 0xff
+
+/* error codes */
+#define SPAPR_VTPM_ERR_COPY_IN_FAILED 0x3
+#define SPAPR_VTPM_ERR_COPY_OUT_FAILED 0x4
+
+#define MAX_BUFFER_SIZE TARGET_PAGE_SIZE
+
+typedef struct {
+ SpaprVioDevice vdev;
+
+ TPMSpaprCRQ crq; /* track single TPM command */
+
+ uint8_t state;
+#define SPAPR_VTPM_STATE_NONE 0
+#define SPAPR_VTPM_STATE_EXECUTION 1
+#define SPAPR_VTPM_STATE_COMPLETION 2
+
+ unsigned char buffer[MAX_BUFFER_SIZE];
+
+ TPMBackendCmd cmd;
+
+ TPMBackend *be_driver;
+ TPMVersion be_tpm_version;
+
+ size_t be_buffer_size;
+} SPAPRvTPMState;
+
+static void tpm_spapr_show_buffer(const unsigned char *buffer,
+ size_t buffer_size, const char *string)
+{
+ size_t len, i;
+ char *line_buffer, *p;
+
+ len = MIN(tpm_cmd_get_size(buffer), buffer_size);
+
+ /*
+ * allocate enough room for 3 chars per buffer entry plus a
+ * newline after every 16 chars and a final null terminator.
+ */
+ line_buffer = g_malloc(len * 3 + (len / 16) + 1);
+
+ for (i = 0, p = line_buffer; i < len; i++) {
+ if (i && !(i % 16)) {
+ p += sprintf(p, "\n");
+ }
+ p += sprintf(p, "%.2X ", buffer[i]);
+ }
+ trace_tpm_spapr_show_buffer(string, len, line_buffer);
+
+ g_free(line_buffer);
+}
+
+/*
+ * Send a request to the TPM.
+ */
+static void tpm_spapr_tpm_send(SPAPRvTPMState *s)
+{
+ if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) {
+ tpm_spapr_show_buffer(s->buffer, sizeof(s->buffer), "To TPM");
+ }
+
+ s->state = SPAPR_VTPM_STATE_EXECUTION;
+ s->cmd = (TPMBackendCmd) {
+ .locty = 0,
+ .in = s->buffer,
+ .in_len = MIN(tpm_cmd_get_size(s->buffer), sizeof(s->buffer)),
+ .out = s->buffer,
+ .out_len = sizeof(s->buffer),
+ };
+
+ tpm_backend_deliver_request(s->be_driver, &s->cmd);
+}
+
+static int tpm_spapr_process_cmd(SPAPRvTPMState *s, uint64_t dataptr)
+{
+ long rc;
+
+ /* a max. of be_buffer_size bytes can be transported */
+ rc = spapr_vio_dma_read(&s->vdev, dataptr,
+ s->buffer, s->be_buffer_size);
+ if (rc) {
+ error_report("tpm_spapr_got_payload: DMA read failure");
+ }
+ /* let vTPM handle any malformed request */
+ tpm_spapr_tpm_send(s);
+
+ return rc;
+}
+
+static int tpm_spapr_do_crq(struct SpaprVioDevice *dev, uint8_t *crq_data)
+{
+ SPAPRvTPMState *s = VIO_SPAPR_VTPM(dev);
+ TPMSpaprCRQ local_crq;
+ TPMSpaprCRQ *crq = &s->crq; /* requests only */
+ int rc;
+
+ memcpy(&local_crq.raw, crq_data, sizeof(local_crq.raw));
+
+ trace_tpm_spapr_do_crq(local_crq.raw[0], local_crq.raw[1]);
+
+ switch (local_crq.s.valid) {
+ case SPAPR_VTPM_VALID_INIT_CRQ_COMMAND: /* Init command/response */
+
+ /* Respond to initialization request */
+ switch (local_crq.s.msg) {
+ case SPAPR_VTPM_INIT_CRQ_RESULT:
+ trace_tpm_spapr_do_crq_crq_result();
+ memset(local_crq.raw, 0, sizeof(local_crq.raw));
+ local_crq.s.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND;
+ local_crq.s.msg = SPAPR_VTPM_INIT_CRQ_RESULT;
+ spapr_vio_send_crq(dev, local_crq.raw);
+ break;
+
+ case SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT:
+ trace_tpm_spapr_do_crq_crq_complete_result();
+ memset(local_crq.raw, 0, sizeof(local_crq.raw));
+ local_crq.s.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND;
+ local_crq.s.msg = SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT;
+ spapr_vio_send_crq(dev, local_crq.raw);
+ break;
+ }
+
+ break;
+ case SPAPR_VTPM_VALID_COMMAND: /* Payloads */
+ switch (local_crq.s.msg) {
+ case SPAPR_VTPM_TPM_COMMAND:
+ trace_tpm_spapr_do_crq_tpm_command();
+ if (s->state == SPAPR_VTPM_STATE_EXECUTION) {
+ return H_BUSY;
+ }
+ /* this crq is tracked */
+ memcpy(crq->raw, crq_data, sizeof(crq->raw));
+
+ rc = tpm_spapr_process_cmd(s, be32_to_cpu(crq->s.data));
+
+ if (rc == H_SUCCESS) {
+ crq->s.valid = be16_to_cpu(0);
+ } else {
+ local_crq.s.valid = SPAPR_VTPM_MSG_RESULT;
+ local_crq.s.msg = SPAPR_VTPM_VTPM_ERROR;
+ local_crq.s.data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_IN_FAILED);
+ spapr_vio_send_crq(dev, local_crq.raw);
+ }
+ break;
+
+ case SPAPR_VTPM_GET_RTCE_BUFFER_SIZE:
+ trace_tpm_spapr_do_crq_tpm_get_rtce_buffer_size(s->be_buffer_size);
+ local_crq.s.msg |= SPAPR_VTPM_MSG_RESULT;
+ local_crq.s.len = cpu_to_be16(s->be_buffer_size);
+ spapr_vio_send_crq(dev, local_crq.raw);
+ break;
+
+ case SPAPR_VTPM_GET_VERSION:
+ local_crq.s.msg |= SPAPR_VTPM_MSG_RESULT;
+ local_crq.s.len = cpu_to_be16(0);
+ switch (s->be_tpm_version) {
+ case TPM_VERSION_UNSPEC:
+ local_crq.s.data = cpu_to_be32(0);
+ break;
+ case TPM_VERSION_1_2:
+ local_crq.s.data = cpu_to_be32(1);
+ break;
+ case TPM_VERSION_2_0:
+ local_crq.s.data = cpu_to_be32(2);
+ break;
+ }
+ trace_tpm_spapr_do_crq_get_version(be32_to_cpu(local_crq.s.data));
+ spapr_vio_send_crq(dev, local_crq.raw);
+ break;
+
+ case SPAPR_VTPM_PREPARE_TO_SUSPEND:
+ trace_tpm_spapr_do_crq_prepare_to_suspend();
+ local_crq.s.msg |= SPAPR_VTPM_MSG_RESULT;
+ spapr_vio_send_crq(dev, local_crq.raw);
+ break;
+
+ default:
+ trace_tpm_spapr_do_crq_unknown_msg_type(crq->s.msg);
+ }
+ break;
+ default:
+ trace_tpm_spapr_do_crq_unknown_crq(local_crq.raw[0], local_crq.raw[1]);
+ };
+
+ return H_SUCCESS;
+}
+
+static void tpm_spapr_request_completed(TPMIf *ti, int ret)
+{
+ SPAPRvTPMState *s = VIO_SPAPR_VTPM(ti);
+ TPMSpaprCRQ *crq = &s->crq;
+ uint32_t len;
+ int rc;
+
+ s->state = SPAPR_VTPM_STATE_COMPLETION;
+
+ /* a max. of be_buffer_size bytes can be transported */
+ len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);
+ rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->s.data),
+ s->buffer, len);
+
+ if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) {
+ tpm_spapr_show_buffer(s->buffer, len, "From TPM");
+ }
+
+ crq->s.valid = SPAPR_VTPM_MSG_RESULT;
+ if (rc == H_SUCCESS) {
+ crq->s.msg = SPAPR_VTPM_TPM_COMMAND | SPAPR_VTPM_MSG_RESULT;
+ crq->s.len = cpu_to_be16(len);
+ } else {
+ error_report("%s: DMA write failure", __func__);
+ crq->s.msg = SPAPR_VTPM_VTPM_ERROR;
+ crq->s.len = cpu_to_be16(0);
+ crq->s.data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_OUT_FAILED);
+ }
+
+ rc = spapr_vio_send_crq(&s->vdev, crq->raw);
+ if (rc) {
+ error_report("%s: Error sending response", __func__);
+ }
+}
+
+static int tpm_spapr_do_startup_tpm(SPAPRvTPMState *s, size_t buffersize)
+{
+ return tpm_backend_startup_tpm(s->be_driver, buffersize);
+}
+
+static void tpm_spapr_update_deviceclass(SpaprVioDevice *dev)
+{
+ SPAPRvTPMState *s = VIO_SPAPR_VTPM(dev);
+ SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_GET_CLASS(dev);
+
+ switch (s->be_tpm_version) {
+ case TPM_VERSION_UNSPEC:
+ assert(false);
+ break;
+ case TPM_VERSION_1_2:
+ k->dt_name = "vtpm";
+ k->dt_type = "IBM,vtpm";
+ k->dt_compatible = "IBM,vtpm";
+ break;
+ case TPM_VERSION_2_0:
+ k->dt_name = "vtpm";
+ k->dt_type = "IBM,vtpm";
+ k->dt_compatible = "IBM,vtpm20";
+ break;
+ }
+}
+
+static void tpm_spapr_reset(SpaprVioDevice *dev)
+{
+ SPAPRvTPMState *s = VIO_SPAPR_VTPM(dev);
+
+ s->state = SPAPR_VTPM_STATE_NONE;
+
+ s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
+ tpm_spapr_update_deviceclass(dev);
+
+ s->be_buffer_size = MAX(ROUND_UP(tpm_backend_get_buffer_size(s->be_driver),
+ TARGET_PAGE_SIZE),
+ sizeof(s->buffer));
+
+ tpm_backend_reset(s->be_driver);
+ tpm_spapr_do_startup_tpm(s, s->be_buffer_size);
+}
+
+static enum TPMVersion tpm_spapr_get_version(TPMIf *ti)
+{
+ SPAPRvTPMState *s = VIO_SPAPR_VTPM(ti);
+
+ if (tpm_backend_had_startup_error(s->be_driver)) {
+ return TPM_VERSION_UNSPEC;
+ }
+
+ return tpm_backend_get_tpm_version(s->be_driver);
+}
+
+static const VMStateDescription vmstate_spapr_vtpm = {
+ .name = "tpm-spapr",
+ .unmigratable = 1,
+};
+
+static Property tpm_spapr_properties[] = {
+ DEFINE_SPAPR_PROPERTIES(SPAPRvTPMState, vdev),
+ DEFINE_PROP_TPMBE("tpmdev", SPAPRvTPMState, be_driver),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tpm_spapr_realizefn(SpaprVioDevice *dev, Error **errp)
+{
+ SPAPRvTPMState *s = VIO_SPAPR_VTPM(dev);
+
+ if (!tpm_find()) {
+ error_setg(errp, "at most one TPM device is permitted");
+ return;
+ }
+
+ dev->crq.SendFunc = tpm_spapr_do_crq;
+
+ if (!s->be_driver) {
+ error_setg(errp, "'tpmdev' property is required");
+ return;
+ }
+}
+
+static void tpm_spapr_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+ TPMIfClass *tc = TPM_IF_CLASS(klass);
+
+ k->realize = tpm_spapr_realizefn;
+ k->reset = tpm_spapr_reset;
+ k->signal_mask = 0x00000001;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->props = tpm_spapr_properties;
+ k->rtce_window_size = 0x10000000;
+ dc->vmsd = &vmstate_spapr_vtpm;
+
+ tc->model = TPM_MODEL_TPM_SPAPR;
+ tc->get_version = tpm_spapr_get_version;
+ tc->request_completed = tpm_spapr_request_completed;
+}
+
+static const TypeInfo tpm_spapr_info = {
+ .name = TYPE_TPM_SPAPR,
+ .parent = TYPE_VIO_SPAPR_DEVICE,
+ .instance_size = sizeof(SPAPRvTPMState),
+ .class_init = tpm_spapr_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_TPM_IF },
+ { }
+ }
+};
+
+static void tpm_spapr_register_types(void)
+{
+ type_register_static(&tpm_spapr_info);
+}
+
+type_init(tpm_spapr_register_types)
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index 89804bcd64..6278a39618 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -55,3 +55,15 @@ tpm_tis_pre_save(uint8_t locty, uint32_t rw_offset) "locty: %d, rw_offset = %u"
# tpm_ppi.c
tpm_ppi_memset(uint8_t *ptr, size_t size) "memset: %p %zu"
+
+# hw/tpm/tpm_spapr.c
+tpm_spapr_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s"
+tpm_spapr_do_crq(uint8_t raw1, uint8_t raw2) "1st 2 bytes in CRQ: 0x%02x 0x%02x"
+tpm_spapr_do_crq_crq_result(void) "SPAPR_VTPM_INIT_CRQ_RESULT"
+tpm_spapr_do_crq_crq_complete_result(void) "SPAPR_VTPM_INIT_CRQ_COMP_RESULT"
+tpm_spapr_do_crq_tpm_command(void) "got TPM command payload"
+tpm_spapr_do_crq_tpm_get_rtce_buffer_size(size_t buffersize) "response: buffer size is %zu"
+tpm_spapr_do_crq_get_version(uint32_t version) "response: version %u"
+tpm_spapr_do_crq_prepare_to_suspend(void) "response: preparing to suspend"
+tpm_spapr_do_crq_unknown_msg_type(uint8_t type) "Unknown message type 0x%02x"
+tpm_spapr_do_crq_unknown_crq(uint8_t raw1, uint8_t raw2) "unknown CRQ 0x%02x 0x%02x ..."
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 5b541a71c8..15979a3647 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -45,11 +45,14 @@ typedef struct TPMIfClass {
#define TYPE_TPM_TIS "tpm-tis"
#define TYPE_TPM_CRB "tpm-crb"
+#define TYPE_TPM_SPAPR "tpm-spapr"
#define TPM_IS_TIS(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
#define TPM_IS_CRB(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_SPAPR(chr) \
+ object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
/* returns NULL unless there is exactly one TPM device */
static inline TPMIf *tpm_find(void)
diff --git a/qapi/tpm.json b/qapi/tpm.json
index b30323bb6b..63878aa0f4 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -12,11 +12,11 @@
#
# @tpm-tis: TPM TIS model
# @tpm-crb: TPM CRB model (since 2.12)
+# @tpm-spapr: TPM SPAPR model (since 5.0)
#
# Since: 1.5
##
-{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
-
+{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ] }
##
# @query-tpm-models:
#
@@ -29,7 +29,7 @@
# Example:
#
# -> { "execute": "query-tpm-models" }
-# <- { "return": [ "tpm-tis", "tpm-crb" ] }
+# <- { "return": [ "tpm-tis", "tpm-crb", "tpm-spapr" ] }
#
##
{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v4 2/8] tpm_backend: Implement check whether tpm backend is suspended
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
2019-12-12 18:07 ` [PATCH v4 1/8] tpm_spapr: Support TPM for ppc64 using CRQ based interface Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 3/8] tpm_emulator: Implement callback for whether we are suspended Stefan Berger
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc
Cc: marcandre.lureau, Stefan Berger, Stefan Berger, qemu-devel, david
Some frontends need to know whether the backend is suspended.
Implement tpm_backend_is_suspended().
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
diff --git a/backends/tpm.c b/backends/tpm.c
index 375587e743..424c9fd485 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -163,6 +163,13 @@ size_t tpm_backend_get_buffer_size(TPMBackend *s)
return k->get_buffer_size(s);
}
+bool tpm_backend_is_suspended(TPMBackend *s)
+{
+ TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
+
+ return k->is_suspended(s);
+}
+
TPMInfo *tpm_backend_query_tpm(TPMBackend *s)
{
TPMInfo *info = g_new0(TPMInfo, 1);
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index 9e7451fb52..f5d8051b45 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -84,6 +84,8 @@ struct TPMBackendClass {
TpmTypeOptions *(*get_tpm_options)(TPMBackend *t);
void (*handle_request)(TPMBackend *s, TPMBackendCmd *cmd, Error **errp);
+
+ bool (*is_suspended)(TPMBackend *t);
};
/**
@@ -213,6 +215,16 @@ void tpm_backend_finish_sync(TPMBackend *s);
*/
TPMInfo *tpm_backend_query_tpm(TPMBackend *s);
+/**
+ * tpm_backend_is_suspended:
+ * @s: the backend to call into
+ *
+ * Whether the backend is suspended
+ *
+ * Returns true in case the backend is suspended
+ */
+bool tpm_backend_is_suspended(TPMBackend *s);
+
TPMBackend *qemu_find_tpm_be(const char *id);
#endif
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v4 3/8] tpm_emulator: Implement callback for whether we are suspended
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
2019-12-12 18:07 ` [PATCH v4 1/8] tpm_spapr: Support TPM for ppc64 using CRQ based interface Stefan Berger
2019-12-12 18:07 ` [PATCH v4 2/8] tpm_backend: Implement check whether tpm backend is suspended Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
2019-12-12 18:33 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 4/8] tpm_passthrough: " Stefan Berger
` (4 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc
Cc: marcandre.lureau, Stefan Berger, Stefan Berger, qemu-devel, david
Implement the check whether the emulator backend is suspended.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
index 22f9113432..7be7d3a91b 100644
--- a/hw/tpm/tpm_emulator.c
+++ b/hw/tpm/tpm_emulator.c
@@ -80,6 +80,8 @@ typedef struct TPMEmulator {
unsigned int established_flag_cached:1;
TPMBlobBuffers state_blobs;
+
+ bool is_suspended;
} TPMEmulator;
struct tpm_error {
@@ -486,6 +488,13 @@ static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
return actual_size;
}
+static bool tpm_emulator_is_suspended(TPMBackend *tb)
+{
+ TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
+
+ return tpm_emu->is_suspended;
+}
+
static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
{
Error *err = NULL;
@@ -846,6 +855,8 @@ static int tpm_emulator_pre_save(void *opaque)
TPMBackend *tb = opaque;
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
+ tpm_emu->is_suspended = true;
+
trace_tpm_emulator_pre_save();
tpm_backend_finish_sync(tb);
@@ -975,6 +986,7 @@ static void tpm_emulator_class_init(ObjectClass *klass, void *data)
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->is_suspended = tpm_emulator_is_suspended;
tbc->handle_request = tpm_emulator_handle_request;
}
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v4 4/8] tpm_passthrough: Implement callback for whether we are suspended
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
` (2 preceding siblings ...)
2019-12-12 18:07 ` [PATCH v4 3/8] tpm_emulator: Implement callback for whether we are suspended Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 5/8] tpm: Return bool from tpm_backend_finish_sync Stefan Berger
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc
Cc: marcandre.lureau, Stefan Berger, Stefan Berger, qemu-devel, david
Implement the callback for whether the passthrough backend is
suspended. We always respond with false.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c
index f67244b5d4..b759c7d30c 100644
--- a/hw/tpm/tpm_passthrough.c
+++ b/hw/tpm/tpm_passthrough.c
@@ -203,6 +203,11 @@ static size_t tpm_passthrough_get_buffer_size(TPMBackend *tb)
return tpm_pt->tpm_buffersize;
}
+static bool tpm_passthrough_is_suspended(TPMBackend *tb)
+{
+ return false;
+}
+
/*
* Unless path or file descriptor set has been provided by user,
* determine the sysfs cancel file following kernel documentation
@@ -386,6 +391,7 @@ static void tpm_passthrough_class_init(ObjectClass *klass, void *data)
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;
+ tbc->is_suspended = tpm_passthrough_is_suspended;
}
static const TypeInfo tpm_passthrough_info = {
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v4 5/8] tpm: Return bool from tpm_backend_finish_sync
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
` (3 preceding siblings ...)
2019-12-12 18:07 ` [PATCH v4 4/8] tpm_passthrough: " Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 6/8] tpm_spapr: Support suspend and resume Stefan Berger
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc; +Cc: marcandre.lureau, Stefan Berger, qemu-devel, david
Return true in case we had to wait for an outstanding response
to come back, false otherwise.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
diff --git a/backends/tpm.c b/backends/tpm.c
index 424c9fd485..ae4d8c526b 100644
--- a/backends/tpm.c
+++ b/backends/tpm.c
@@ -49,11 +49,15 @@ static int tpm_backend_worker_thread(gpointer data)
return 0;
}
-void tpm_backend_finish_sync(TPMBackend *s)
+bool tpm_backend_finish_sync(TPMBackend *s)
{
+ bool ret = s->cmd != NULL;
+
while (s->cmd) {
aio_poll(qemu_get_aio_context(), true);
}
+
+ return ret;
}
enum TpmType tpm_backend_get_type(TPMBackend *s)
diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h
index f5d8051b45..3ab9f51ba4 100644
--- a/include/sysemu/tpm_backend.h
+++ b/include/sysemu/tpm_backend.h
@@ -202,8 +202,10 @@ size_t tpm_backend_get_buffer_size(TPMBackend *s);
*
* Finish the pending command synchronously (this will call aio_poll()
* on qemu main AIOContext until it ends)
+ *
+ * Returns true in case there was a pending command, false otherwise.
*/
-void tpm_backend_finish_sync(TPMBackend *s);
+bool tpm_backend_finish_sync(TPMBackend *s);
/**
* tpm_backend_query_tpm:
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v4 6/8] tpm_spapr: Support suspend and resume
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
` (4 preceding siblings ...)
2019-12-12 18:07 ` [PATCH v4 5/8] tpm: Return bool from tpm_backend_finish_sync Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 7/8] hw/ppc/Kconfig: Enable TPM_SPAPR as part of PSERIES config Stefan Berger
2019-12-12 18:07 ` [PATCH v4 8/8] docs: tpm: Add example command line for ppc64 and tpm-spapr Stefan Berger
7 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc; +Cc: marcandre.lureau, Stefan Berger, qemu-devel, david
Extend the tpm_spapr frontend with VM suspend and resume support.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c
index c4a67e2403..52e0405ab4 100644
--- a/hw/tpm/tpm_spapr.c
+++ b/hw/tpm/tpm_spapr.c
@@ -87,6 +87,8 @@ typedef struct {
TPMVersion be_tpm_version;
size_t be_buffer_size;
+
+ bool deliver_response; /* whether to deliver response after VM resume */
} SPAPRvTPMState;
static void tpm_spapr_show_buffer(const unsigned char *buffer,
@@ -255,6 +257,14 @@ static void tpm_spapr_request_completed(TPMIf *ti, int ret)
TPMSpaprCRQ *crq = &s->crq;
uint32_t len;
int rc;
+ bool be_suspended;
+
+ be_suspended = tpm_backend_is_suspended(s->be_driver);
+ if (be_suspended) {
+ /* defer delivery of response until .post_load */
+ s->deliver_response |= true;
+ return;
+ }
s->state = SPAPR_VTPM_STATE_COMPLETION;
@@ -316,6 +326,7 @@ static void tpm_spapr_reset(SpaprVioDevice *dev)
SPAPRvTPMState *s = VIO_SPAPR_VTPM(dev);
s->state = SPAPR_VTPM_STATE_NONE;
+ s->deliver_response = false;
s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
tpm_spapr_update_deviceclass(dev);
@@ -339,9 +350,53 @@ static enum TPMVersion tpm_spapr_get_version(TPMIf *ti)
return tpm_backend_get_tpm_version(s->be_driver);
}
+/* persistent state handling */
+
+static int tpm_spapr_pre_save(void *opaque)
+{
+ SPAPRvTPMState *s = opaque;
+
+ s->deliver_response |= tpm_backend_finish_sync(s->be_driver);
+
+ trace_tpm_spapr_pre_save(s->deliver_response);
+ /*
+ * we cannot deliver the results to the VM since DMA would touch VM memory
+ */
+
+ return 0;
+}
+
+static int tpm_spapr_post_load(void *opaque, int version_id)
+{
+ SPAPRvTPMState *s = opaque;
+
+ if (s->deliver_response) {
+ trace_tpm_spapr_post_load();
+ /* deliver the results to the VM via DMA */
+ tpm_spapr_request_completed(TPM_IF(s), 0);
+ s->deliver_response = false;
+ }
+
+ return 0;
+}
+
static const VMStateDescription vmstate_spapr_vtpm = {
.name = "tpm-spapr",
- .unmigratable = 1,
+ .version_id = 1,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .pre_save = tpm_spapr_pre_save,
+ .post_load = tpm_spapr_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_SPAPR_VIO(vdev, SPAPRvTPMState),
+
+ VMSTATE_UINT8(state, SPAPRvTPMState),
+ VMSTATE_BUFFER(buffer, SPAPRvTPMState),
+ /* remember DMA address */
+ VMSTATE_UINT32(crq.s.data, SPAPRvTPMState),
+ VMSTATE_BOOL(deliver_response, SPAPRvTPMState),
+ VMSTATE_END_OF_LIST(),
+ }
};
static Property tpm_spapr_properties[] = {
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index 6278a39618..d109661b96 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -67,3 +67,5 @@ tpm_spapr_do_crq_get_version(uint32_t version) "response: version %u"
tpm_spapr_do_crq_prepare_to_suspend(void) "response: preparing to suspend"
tpm_spapr_do_crq_unknown_msg_type(uint8_t type) "Unknown message type 0x%02x"
tpm_spapr_do_crq_unknown_crq(uint8_t raw1, uint8_t raw2) "unknown CRQ 0x%02x 0x%02x ..."
+tpm_spapr_pre_save(bool v) "TPM response to deliver after resume: %d"
+tpm_spapr_post_load(void) "Delivering TPM response after resume"
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v4 7/8] hw/ppc/Kconfig: Enable TPM_SPAPR as part of PSERIES config
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
` (5 preceding siblings ...)
2019-12-12 18:07 ` [PATCH v4 6/8] tpm_spapr: Support suspend and resume Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 8/8] docs: tpm: Add example command line for ppc64 and tpm-spapr Stefan Berger
7 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc
Cc: marcandre.lureau, Stefan Berger, Stefan Berger, qemu-devel, david
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig
index f927ec9c74..b5b3519158 100644
--- a/hw/ppc/Kconfig
+++ b/hw/ppc/Kconfig
@@ -10,6 +10,7 @@ config PSERIES
select XICS_SPAPR
select XIVE_SPAPR
select MSI_NONBROKEN
+ select TPM_SPAPR
config SPAPR_RNG
bool
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v4 8/8] docs: tpm: Add example command line for ppc64 and tpm-spapr
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
` (6 preceding siblings ...)
2019-12-12 18:07 ` [PATCH v4 7/8] hw/ppc/Kconfig: Enable TPM_SPAPR as part of PSERIES config Stefan Berger
@ 2019-12-12 18:07 ` Stefan Berger
7 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:07 UTC (permalink / raw)
To: qemu-ppc
Cc: marcandre.lureau, Stefan Berger, Stefan Berger, qemu-devel, david
Add an example to the TPM docs for how to add a TPM SPAPR
device model to a QEMU VM emulating a pSeries machine.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt
index 9c8cca042d..9c3e67d8a7 100644
--- a/docs/specs/tpm.txt
+++ b/docs/specs/tpm.txt
@@ -34,6 +34,12 @@ The CRB interface makes a memory mapped IO region in the area 0xfed40000 -
QEMU files related to TPM CRB interface:
- hw/tpm/tpm_crb.c
+
+pSeries (ppc64) machines offer a tpm-spapr device model.
+
+QEMU files related to the SPAPR interface:
+ - hw/tpm/tpm_spapr.c
+
= fw_cfg interface =
The bios/firmware may read the "etc/tpm/config" fw_cfg entry for
@@ -281,7 +287,7 @@ swtpm socket --tpmstate dir=/tmp/mytpm1 \
--log level=20
Command line to start QEMU with the TPM emulator device communicating with
-the swtpm:
+the swtpm (x86):
qemu-system-x86_64 -display sdl -accel kvm \
-m 1024 -boot d -bios bios-256k.bin -boot menu=on \
@@ -289,6 +295,18 @@ qemu-system-x86_64 -display sdl -accel kvm \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0 test.img
+In case a pSeries machine is emulated, use the following command line:
+
+qemu-system-ppc64 -display sdl -machine pseries,accel=kvm \
+ -m 1024 -bios slof.bin -boot menu=on \
+ -nodefaults -device VGA -device pci-ohci -device usb-kbd \
+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
+ -tpmdev emulator,id=tpm0,chardev=chrtpm \
+ -device tpm-spapr,tpmdev=tpm0 \
+ -device spapr-vscsi,id=scsi0,reg=0x00002000 \
+ -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \
+ -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0
+
In case SeaBIOS is used as firmware, it should show the TPM menu item
after entering the menu with 'ESC'.
--
2.21.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v4 3/8] tpm_emulator: Implement callback for whether we are suspended
2019-12-12 18:07 ` [PATCH v4 3/8] tpm_emulator: Implement callback for whether we are suspended Stefan Berger
@ 2019-12-12 18:33 ` Stefan Berger
2019-12-12 20:10 ` Stefan Berger
0 siblings, 1 reply; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 18:33 UTC (permalink / raw)
To: Stefan Berger, qemu-ppc; +Cc: marcandre.lureau, qemu-devel, david
On 12/12/19 1:07 PM, Stefan Berger wrote:
> Implement the check whether the emulator backend is suspended.
>
> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
>
> diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
> index 22f9113432..7be7d3a91b 100644
> --- a/hw/tpm/tpm_emulator.c
> +++ b/hw/tpm/tpm_emulator.c
> @@ -80,6 +80,8 @@ typedef struct TPMEmulator {
> unsigned int established_flag_cached:1;
>
> TPMBlobBuffers state_blobs;
> +
> + bool is_suspended;
> } TPMEmulator;
>
> struct tpm_error {
> @@ -486,6 +488,13 @@ static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
> return actual_size;
> }
>
> +static bool tpm_emulator_is_suspended(TPMBackend *tb)
> +{
> + TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
> +
> + return tpm_emu->is_suspended;
> +}
> +
> static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
> {
> Error *err = NULL;
> @@ -846,6 +855,8 @@ static int tpm_emulator_pre_save(void *opaque)
> TPMBackend *tb = opaque;
> TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
>
> + tpm_emu->is_suspended = true;
This is the most critical part here. It must be true when we receive a
response in the tpm_spapr_request_completed(). The problem is that what
tpm_backend_finish_sync() does is not specific to this backend but more
a global operation that another device could run as well -- none seem to
do this today. So the point is that there could be a race here. This
flag should really be set in '.pre_pre_save,' so before any other device
could poll. Better would be calling a global function that indicates
whether device suspension has started. In this case we could do away
with this and just call that function from the spapr device.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 3/8] tpm_emulator: Implement callback for whether we are suspended
2019-12-12 18:33 ` Stefan Berger
@ 2019-12-12 20:10 ` Stefan Berger
0 siblings, 0 replies; 11+ messages in thread
From: Stefan Berger @ 2019-12-12 20:10 UTC (permalink / raw)
To: Stefan Berger, qemu-ppc; +Cc: marcandre.lureau, qemu-devel, david
On 12/12/19 1:33 PM, Stefan Berger wrote:
> On 12/12/19 1:07 PM, Stefan Berger wrote:
>> Implement the check whether the emulator backend is suspended.
>>
>> Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
>>
>> diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
>> index 22f9113432..7be7d3a91b 100644
>> --- a/hw/tpm/tpm_emulator.c
>> +++ b/hw/tpm/tpm_emulator.c
>> @@ -80,6 +80,8 @@ typedef struct TPMEmulator {
>> unsigned int established_flag_cached:1;
>> TPMBlobBuffers state_blobs;
>> +
>> + bool is_suspended;
>> } TPMEmulator;
>> struct tpm_error {
>> @@ -486,6 +488,13 @@ static size_t
>> tpm_emulator_get_buffer_size(TPMBackend *tb)
>> return actual_size;
>> }
>> +static bool tpm_emulator_is_suspended(TPMBackend *tb)
>> +{
>> + TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
>> +
>> + return tpm_emu->is_suspended;
>> +}
>> +
>> static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)
>> {
>> Error *err = NULL;
>> @@ -846,6 +855,8 @@ static int tpm_emulator_pre_save(void *opaque)
>> TPMBackend *tb = opaque;
>> TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
>> + tpm_emu->is_suspended = true;
>
> This is the most critical part here. It must be true when we receive a
> response in the tpm_spapr_request_completed(). The problem is that
> what tpm_backend_finish_sync() does is not specific to this backend
> but more a global operation that another device could run as well --
> none seem to do this today. So the point is that there could be a race
> here. This flag should really be set in '.pre_pre_save,' so before any
> other device could poll. Better would be calling a global function
> that indicates whether device suspension has started. In this case we
> could do away with this and just call that function from the spapr
> device.
runstate_check(RUN_STATE_FINISH_MIGRATE) seems to be what we need here...
>
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2019-12-12 20:12 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-12 18:07 [PATCH v4 0/8] Add vTPM emulator supportfor ppc64 platform Stefan Berger
2019-12-12 18:07 ` [PATCH v4 1/8] tpm_spapr: Support TPM for ppc64 using CRQ based interface Stefan Berger
2019-12-12 18:07 ` [PATCH v4 2/8] tpm_backend: Implement check whether tpm backend is suspended Stefan Berger
2019-12-12 18:07 ` [PATCH v4 3/8] tpm_emulator: Implement callback for whether we are suspended Stefan Berger
2019-12-12 18:33 ` Stefan Berger
2019-12-12 20:10 ` Stefan Berger
2019-12-12 18:07 ` [PATCH v4 4/8] tpm_passthrough: " Stefan Berger
2019-12-12 18:07 ` [PATCH v4 5/8] tpm: Return bool from tpm_backend_finish_sync Stefan Berger
2019-12-12 18:07 ` [PATCH v4 6/8] tpm_spapr: Support suspend and resume Stefan Berger
2019-12-12 18:07 ` [PATCH v4 7/8] hw/ppc/Kconfig: Enable TPM_SPAPR as part of PSERIES config Stefan Berger
2019-12-12 18:07 ` [PATCH v4 8/8] docs: tpm: Add example command line for ppc64 and tpm-spapr Stefan Berger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).