diff mbox

[v2,7/7] tpm: extend TPM CRB with state migration support

Message ID 1509145361-11218-8-git-send-email-stefanb@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Stefan Berger Oct. 27, 2017, 11:02 p.m. UTC
We need to synchronize with the backend thread to make sure that a command
being processed by the external TPM emulator has completed and its
response been received. In case the bottom half did not run, we run the
function it is supposed to run.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
 hw/tpm/tpm_crb.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 68 insertions(+), 5 deletions(-)
diff mbox

Patch

diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 64039eb..a81431e 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -27,6 +27,8 @@ 
 #include "tpm_int.h"
 #include "tpm_util.h"
 
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs))
+
 typedef struct CRBState {
     SysBusDevice parent_obj;
 
@@ -36,6 +38,7 @@  typedef struct CRBState {
     TPMBackend *tpmbe;
     TPMBackendCmd cmd;
     struct crb_regs regs;
+    unsigned char buf[CRB_CTRL_CMD_SIZE];
 } CRBState;
 
 #define CRB(obj) OBJECT_CHECK(CRBState, (obj), TYPE_TPM_CRB)
@@ -64,8 +67,6 @@  typedef struct CRBState {
 #define CRB_INTF_IF_SELECTOR_CRB 0b1
 #define CRB_INTF_IF_SELECTOR_UNLOCKED 0b0
 
-#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - sizeof(struct crb_regs))
-
 enum crb_loc_ctrl {
     CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
     CRB_LOC_CTRL_RELINQUISH = BIT(1),
@@ -227,12 +228,17 @@  static void tpm_crb_reset(DeviceState *dev)
     tpm_backend_startup_tpm(s->tpmbe);
 }
 
+static void _tpm_crb_request_completed(CRBState *s)
+{
+    s->regs.ctrl_start &= ~CRB_START_INVOKE;
+    /* TODO, in case of error: s->regs.ctrl_sts = CRB_CTRL_STS_ERROR */
+}
+
 static void tpm_crb_request_completed(TPMIf *ti)
 {
     CRBState *s = CRB(ti);
 
-    s->regs.ctrl_start &= ~CRB_START_INVOKE;
-    /* TODO, in case of error: s->regs.ctrl_sts = CRB_CTRL_STS_ERROR */
+    _tpm_crb_request_completed(s);
 }
 
 static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
@@ -242,9 +248,66 @@  static enum TPMVersion tpm_crb_get_version(TPMIf *ti)
     return tpm_backend_get_tpm_version(s->tpmbe);
 }
 
+/* persistent state handling */
+
+static int tpm_crb_pre_save(void *opaque)
+{
+    CRBState *s = opaque;
+    void *mem = memory_region_get_ram_ptr(&s->cmdmem);
+
+    /*
+     * Synchronize with backend completion.
+     */
+    tpm_backend_wait_cmd_completed(s->tpmbe);
+
+    if (s->regs.ctrl_start & CRB_START_INVOKE) {
+        _tpm_crb_request_completed(s);
+    }
+
+    memcpy(s->buf, mem, sizeof(s->buf));
+
+    return 0;
+}
+
+static int tpm_crb_post_load(void *opaque,
+                             int version_id __attribute__((unused)))
+{
+    CRBState *s = opaque;
+    void *mem = memory_region_get_ram_ptr(&s->cmdmem);
+
+    memcpy(mem, s->buf, sizeof(s->buf));
+
+    return 0;
+}
+
 static const VMStateDescription vmstate_tpm_crb = {
     .name = "tpm-crb",
-    .unmigratable = 1,
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .pre_save  = tpm_crb_pre_save,
+    .post_load = tpm_crb_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(regs.loc_state, CRBState),
+        VMSTATE_UINT32(regs.loc_ctrl, CRBState),
+        VMSTATE_UINT32(regs.loc_sts, CRBState),
+        VMSTATE_UINT64(regs.intf_id, CRBState),
+        VMSTATE_UINT64(regs.ctrl_ext, CRBState),
+        VMSTATE_UINT32(regs.ctrl_req, CRBState),
+        VMSTATE_UINT32(regs.ctrl_sts, CRBState),
+        VMSTATE_UINT32(regs.ctrl_cancel, CRBState),
+        VMSTATE_UINT32(regs.ctrl_start, CRBState),
+        VMSTATE_UINT32(regs.ctrl_int_enable, CRBState),
+        VMSTATE_UINT32(regs.ctrl_int_sts, CRBState),
+        VMSTATE_UINT32(regs.ctrl_cmd_size, CRBState),
+        VMSTATE_UINT32(regs.ctrl_cmd_pa_low, CRBState),
+        VMSTATE_UINT32(regs.ctrl_rsp_size, CRBState),
+        VMSTATE_UINT64(regs.ctrl_rsp_pa, CRBState),
+
+        VMSTATE_UINT8_ARRAY(buf, CRBState, CRB_CTRL_CMD_SIZE),
+
+        VMSTATE_END_OF_LIST(),
+    }
 };
 
 static Property tpm_crb_properties[] = {