diff mbox series

[v4,2/2] tpm: extend TPM TIS with state migration support

Message ID 1519934373-3629-3-git-send-email-stefanb@linux.vnet.ibm.com
State New
Headers show
Series tpm: Extend TPM with state migration support | expand

Commit Message

Stefan Berger March 1, 2018, 7:59 p.m. UTC
Extend the TPM TIS interface with state migration support.

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.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
---
 hw/tpm/tpm_tis.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

Comments

Marc-André Lureau March 2, 2018, 9:40 a.m. UTC | #1
Hi

On Thu, Mar 1, 2018 at 8:59 PM, Stefan Berger
<stefanb@linux.vnet.ibm.com> wrote:
> Extend the TPM TIS interface with state migration support.
>
> 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.
>
> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> ---
>  hw/tpm/tpm_tis.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
> index 834eef7..5016d28 100644
> --- a/hw/tpm/tpm_tis.c
> +++ b/hw/tpm/tpm_tis.c
> @@ -902,9 +902,61 @@ static void tpm_tis_reset(DeviceState *dev)
>      tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size);
>  }
>
> +/* persistent state handling */
> +
> +static int tpm_tis_pre_save(void *opaque)
> +{
> +    TPMState *s = opaque;
> +    uint8_t locty = s->active_locty;
> +
> +    DPRINTF("tpm_tis: suspend: locty = %d : rw_offset = %u\n",

suspend -> pre_save ?

> +            locty, s->rw_offset);
> +#ifdef DEBUG_TIS
> +    tpm_tis_dump_state(opaque, 0);
> +#endif

To avoid dead code, you could write:

if (DEBUG_TIS) {
...
}


> +
> +    /*
> +     * Synchronize with backend completion.
> +     */
> +    tpm_backend_finish_sync(s->be_driver);
> +
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_locty = {
> +    .name = "loc",

I would use a more descriptive name, such as "tpm-tis/locty"

> +    .version_id = 1,
> +    .minimum_version_id = 0,

It's the first version, make it all 0.

> +    .minimum_version_id_old = 0,

not needed

> +    .fields      = (VMStateField[]) {
> +        VMSTATE_UINT32(state, TPMLocality),
> +        VMSTATE_UINT32(inte, TPMLocality),
> +        VMSTATE_UINT32(ints, TPMLocality),
> +        VMSTATE_UINT8(access, TPMLocality),
> +        VMSTATE_UINT32(sts, TPMLocality),
> +        VMSTATE_UINT32(iface_id, TPMLocality),
> +        VMSTATE_END_OF_LIST(),
> +    }
> +};
> +
>  static const VMStateDescription vmstate_tpm_tis = {
>      .name = "tpm",

It's time to use a more specific name "tpm-tis" ?

> -    .unmigratable = 1,
> +    .version_id = 1,
> +    .minimum_version_id = 0,

It's the first version, make it all 0.

> +    .minimum_version_id_old = 0,

not needed

> +    .pre_save  = tpm_tis_pre_save,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_BUFFER(buffer, TPMState),
> +        VMSTATE_UINT16(rw_offset, TPMState),
> +        VMSTATE_UINT8(active_locty, TPMState),
> +        VMSTATE_UINT8(aborting_locty, TPMState),
> +        VMSTATE_UINT8(next_locty, TPMState),
> +
> +        VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1,
> +                             vmstate_locty, TPMLocality),
> +
> +        VMSTATE_END_OF_LIST()
> +    }
>  };
>
>  static Property tpm_tis_properties[] = {
> --
> 2.5.5
>
>

looks good otherwise
Marc-André Lureau March 28, 2018, 3:41 p.m. UTC | #2
Hi

On Thu, Mar 1, 2018 at 8:59 PM, Stefan Berger
<stefanb@linux.vnet.ibm.com> wrote:
> Extend the TPM TIS interface with state migration support.
>
> 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.
>
> Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
> ---
>  hw/tpm/tpm_tis.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 53 insertions(+), 1 deletion(-)
>
> diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
> index 834eef7..5016d28 100644
> --- a/hw/tpm/tpm_tis.c
> +++ b/hw/tpm/tpm_tis.c
> @@ -902,9 +902,61 @@ static void tpm_tis_reset(DeviceState *dev)
>      tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size);
>  }
>
> +/* persistent state handling */
> +
> +static int tpm_tis_pre_save(void *opaque)
> +{
> +    TPMState *s = opaque;
> +    uint8_t locty = s->active_locty;
> +
> +    DPRINTF("tpm_tis: suspend: locty = %d : rw_offset = %u\n",
> +            locty, s->rw_offset);
> +#ifdef DEBUG_TIS
> +    tpm_tis_dump_state(opaque, 0);
> +#endif
> +
> +    /*
> +     * Synchronize with backend completion.
> +     */
> +    tpm_backend_finish_sync(s->be_driver);
> +
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_locty = {
> +    .name = "loc",
> +    .version_id = 1,
> +    .minimum_version_id = 0,
> +    .minimum_version_id_old = 0,

I don't understand the problem there is leaving all the version fields
to 0, just like CRB.

> +    .fields      = (VMStateField[]) {
> +        VMSTATE_UINT32(state, TPMLocality),
> +        VMSTATE_UINT32(inte, TPMLocality),
> +        VMSTATE_UINT32(ints, TPMLocality),
> +        VMSTATE_UINT8(access, TPMLocality),
> +        VMSTATE_UINT32(sts, TPMLocality),
> +        VMSTATE_UINT32(iface_id, TPMLocality),
> +        VMSTATE_END_OF_LIST(),
> +    }
> +};
> +
>  static const VMStateDescription vmstate_tpm_tis = {
>      .name = "tpm",
> -    .unmigratable = 1,
> +    .version_id = 1,
> +    .minimum_version_id = 0,
> +    .minimum_version_id_old = 0,

same

If you remove the version fields: Reviewed-by: Marc-André Lureau
<marcandre.lureau@redhat.com>



> +    .pre_save  = tpm_tis_pre_save,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_BUFFER(buffer, TPMState),
> +        VMSTATE_UINT16(rw_offset, TPMState),
> +        VMSTATE_UINT8(active_locty, TPMState),
> +        VMSTATE_UINT8(aborting_locty, TPMState),
> +        VMSTATE_UINT8(next_locty, TPMState),
> +
> +        VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1,
> +                             vmstate_locty, TPMLocality),
> +
> +        VMSTATE_END_OF_LIST()
> +    }
>  };
>
>  static Property tpm_tis_properties[] = {
> --
> 2.5.5
>
Stefan Berger March 28, 2018, 11:56 p.m. UTC | #3
On 03/28/2018 11:41 AM, Marc-André Lureau wrote:
> Hi
>
> On Thu, Mar 1, 2018 at 8:59 PM, Stefan Berger
> <stefanb@linux.vnet.ibm.com> wrote:
>> +
>> +static const VMStateDescription vmstate_locty = {
>> +    .name = "loc",
>> +    .version_id = 1,
>> +    .minimum_version_id = 0,
>> +    .minimum_version_id_old = 0,
> I don't understand the problem there is leaving all the version fields
> to 0, just like CRB.
>
>> +    .fields      = (VMStateField[]) {
>> +        VMSTATE_UINT32(state, TPMLocality),
>> +        VMSTATE_UINT32(inte, TPMLocality),
>> +        VMSTATE_UINT32(ints, TPMLocality),
>> +        VMSTATE_UINT8(access, TPMLocality),
>> +        VMSTATE_UINT32(sts, TPMLocality),
>> +        VMSTATE_UINT32(iface_id, TPMLocality),
>> +        VMSTATE_END_OF_LIST(),
>> +    }
>> +};
>> +
>>   static const VMStateDescription vmstate_tpm_tis = {
>>       .name = "tpm",
>> -    .unmigratable = 1,
>> +    .version_id = 1,
>> +    .minimum_version_id = 0,
>> +    .minimum_version_id_old = 0,
> same
>
> If you remove the version fields: Reviewed-by: Marc-André Lureau
> <marcandre.lureau@redhat.com>

This is the error I got when setting .version_id = 0 (on both) and doing 
a localhost migration

qemu-system-x86_64: Missing section footer for tpm-tis
qemu-system-x86_64: load of migration failed: Invalid argument

It must have something to do with the nesting invoked by 
VMSTATE_STRUCT_ARRAY(loc,...) below.



>
>
>
>> +    .pre_save  = tpm_tis_pre_save,
>> +    .fields = (VMStateField[]) {
>> +        VMSTATE_BUFFER(buffer, TPMState),
>> +        VMSTATE_UINT16(rw_offset, TPMState),
>> +        VMSTATE_UINT8(active_locty, TPMState),
>> +        VMSTATE_UINT8(aborting_locty, TPMState),
>> +        VMSTATE_UINT8(next_locty, TPMState),
>> +
>> +        VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1,
>> +                             vmstate_locty, TPMLocality),
>> +
>> +        VMSTATE_END_OF_LIST()
>> +    }
>>   };
>>
>>   static Property tpm_tis_properties[] = {
>> --
>> 2.5.5
>>
Marc-André Lureau March 29, 2018, 5:07 p.m. UTC | #4
Hi

On Thu, Mar 29, 2018 at 1:56 AM, Stefan Berger
<stefanb@linux.vnet.ibm.com> wrote:
> On 03/28/2018 11:41 AM, Marc-André Lureau wrote:
>>
>> Hi
>>
>> On Thu, Mar 1, 2018 at 8:59 PM, Stefan Berger
>> <stefanb@linux.vnet.ibm.com> wrote:
>>>
>>> +
>>> +static const VMStateDescription vmstate_locty = {
>>> +    .name = "loc",
>>> +    .version_id = 1,
>>> +    .minimum_version_id = 0,
>>> +    .minimum_version_id_old = 0,
>>
>> I don't understand the problem there is leaving all the version fields
>> to 0, just like CRB.
>>
>>> +    .fields      = (VMStateField[]) {
>>> +        VMSTATE_UINT32(state, TPMLocality),
>>> +        VMSTATE_UINT32(inte, TPMLocality),
>>> +        VMSTATE_UINT32(ints, TPMLocality),
>>> +        VMSTATE_UINT8(access, TPMLocality),
>>> +        VMSTATE_UINT32(sts, TPMLocality),
>>> +        VMSTATE_UINT32(iface_id, TPMLocality),
>>> +        VMSTATE_END_OF_LIST(),
>>> +    }
>>> +};
>>> +
>>>   static const VMStateDescription vmstate_tpm_tis = {
>>>       .name = "tpm",
>>> -    .unmigratable = 1,
>>> +    .version_id = 1,
>>> +    .minimum_version_id = 0,
>>> +    .minimum_version_id_old = 0,
>>
>> same
>>
>> If you remove the version fields: Reviewed-by: Marc-André Lureau
>> <marcandre.lureau@redhat.com>
>
>
> This is the error I got when setting .version_id = 0 (on both) and doing a
> localhost migration
>
> qemu-system-x86_64: Missing section footer for tpm-tis
> qemu-system-x86_64: load of migration failed: Invalid argument

It's clearly not the most friendly error message, but I debugged it,
you just have to specify the right version for VMSTATE_STRUCT_ARRAY:
0.
        VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 0,
                             vmstate_locty, TPMLocality),

Then it all works with version 0 (or default value)

thanks
>
> It must have something to do with the nesting invoked by
> VMSTATE_STRUCT_ARRAY(loc,...) below.
>
>
>
>
>>
>>
>>
>>> +    .pre_save  = tpm_tis_pre_save,
>>> +    .fields = (VMStateField[]) {
>>> +        VMSTATE_BUFFER(buffer, TPMState),
>>> +        VMSTATE_UINT16(rw_offset, TPMState),
>>> +        VMSTATE_UINT8(active_locty, TPMState),
>>> +        VMSTATE_UINT8(aborting_locty, TPMState),
>>> +        VMSTATE_UINT8(next_locty, TPMState),
>>> +
>>> +        VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1,
>>> +                             vmstate_locty, TPMLocality),
>>> +
>>> +        VMSTATE_END_OF_LIST()
>>> +    }
>>>   };
>>>
>>>   static Property tpm_tis_properties[] = {
>>> --
>>> 2.5.5
>>>
>
>
Stefan Berger April 2, 2018, 12:15 p.m. UTC | #5
On 03/29/2018 01:07 PM, Marc-André Lureau wrote:
> Hi
>
> On Thu, Mar 29, 2018 at 1:56 AM, Stefan Berger
> <stefanb@linux.vnet.ibm.com> wrote:
>> On 03/28/2018 11:41 AM, Marc-André Lureau wrote:
>>> Hi
>>>
>>> On Thu, Mar 1, 2018 at 8:59 PM, Stefan Berger
>>> <stefanb@linux.vnet.ibm.com> wrote:
>>>> +
>>>> +static const VMStateDescription vmstate_locty = {
>>>> +    .name = "loc",
>>>> +    .version_id = 1,
>>>> +    .minimum_version_id = 0,
>>>> +    .minimum_version_id_old = 0,
>>> I don't understand the problem there is leaving all the version fields
>>> to 0, just like CRB.
>>>
>>>> +    .fields      = (VMStateField[]) {
>>>> +        VMSTATE_UINT32(state, TPMLocality),
>>>> +        VMSTATE_UINT32(inte, TPMLocality),
>>>> +        VMSTATE_UINT32(ints, TPMLocality),
>>>> +        VMSTATE_UINT8(access, TPMLocality),
>>>> +        VMSTATE_UINT32(sts, TPMLocality),
>>>> +        VMSTATE_UINT32(iface_id, TPMLocality),
>>>> +        VMSTATE_END_OF_LIST(),
>>>> +    }
>>>> +};
>>>> +
>>>>    static const VMStateDescription vmstate_tpm_tis = {
>>>>        .name = "tpm",
>>>> -    .unmigratable = 1,
>>>> +    .version_id = 1,
>>>> +    .minimum_version_id = 0,
>>>> +    .minimum_version_id_old = 0,
>>> same
>>>
>>> If you remove the version fields: Reviewed-by: Marc-André Lureau
>>> <marcandre.lureau@redhat.com>
>>
>> This is the error I got when setting .version_id = 0 (on both) and doing a
>> localhost migration
>>
>> qemu-system-x86_64: Missing section footer for tpm-tis
>> qemu-system-x86_64: load of migration failed: Invalid argument
> It's clearly not the most friendly error message, but I debugged it,
> you just have to specify the right version for VMSTATE_STRUCT_ARRAY:
> 0.
>          VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 0,
>                               vmstate_locty, TPMLocality),
>
> Then it all works with version 0 (or default value)
>
> thanks
Thanks.
diff mbox series

Patch

diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index 834eef7..5016d28 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -902,9 +902,61 @@  static void tpm_tis_reset(DeviceState *dev)
     tpm_backend_startup_tpm(s->be_driver, s->be_buffer_size);
 }
 
+/* persistent state handling */
+
+static int tpm_tis_pre_save(void *opaque)
+{
+    TPMState *s = opaque;
+    uint8_t locty = s->active_locty;
+
+    DPRINTF("tpm_tis: suspend: locty = %d : rw_offset = %u\n",
+            locty, s->rw_offset);
+#ifdef DEBUG_TIS
+    tpm_tis_dump_state(opaque, 0);
+#endif
+
+    /*
+     * Synchronize with backend completion.
+     */
+    tpm_backend_finish_sync(s->be_driver);
+
+    return 0;
+}
+
+static const VMStateDescription vmstate_locty = {
+    .name = "loc",
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT32(state, TPMLocality),
+        VMSTATE_UINT32(inte, TPMLocality),
+        VMSTATE_UINT32(ints, TPMLocality),
+        VMSTATE_UINT8(access, TPMLocality),
+        VMSTATE_UINT32(sts, TPMLocality),
+        VMSTATE_UINT32(iface_id, TPMLocality),
+        VMSTATE_END_OF_LIST(),
+    }
+};
+
 static const VMStateDescription vmstate_tpm_tis = {
     .name = "tpm",
-    .unmigratable = 1,
+    .version_id = 1,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .pre_save  = tpm_tis_pre_save,
+    .fields = (VMStateField[]) {
+        VMSTATE_BUFFER(buffer, TPMState),
+        VMSTATE_UINT16(rw_offset, TPMState),
+        VMSTATE_UINT8(active_locty, TPMState),
+        VMSTATE_UINT8(aborting_locty, TPMState),
+        VMSTATE_UINT8(next_locty, TPMState),
+
+        VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1,
+                             vmstate_locty, TPMLocality),
+
+        VMSTATE_END_OF_LIST()
+    }
 };
 
 static Property tpm_tis_properties[] = {