[{"id":3682986,"web_url":"http://patchwork.ozlabs.org/comment/3682986/","msgid":"<765f0577-ee8f-4944-93fe-bb93e420668f@linux.ibm.com>","list_archive_url":null,"date":"2026-04-27T20:49:04","subject":"Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer","submitter":{"id":75097,"url":"http://patchwork.ozlabs.org/api/people/75097/","name":"Stefan Berger","email":"stefanb@linux.ibm.com"},"content":"On 4/27/26 4:01 PM, Arun Menon wrote:\n> From: Arun Menon <armenon@redhat.com>\n> \n> The TPM TIS buffer is currently a fixed-size static array. Change this\n> to a dynamically allocated heap block. The buffer size is now determined\n> at runtime by querying the TPM backend.\n\nDo we really need this? I mean for the forseeable future 8kb should be \nsufficient.\n\n> \n> To support VM migration,\n> 1. Replace the static VMSTATE_BUFFER macro with pointer-based variant\n>     VMSTATE_BUFFER_POINTER_UNSAFE, explicitly mentioning the size.\n> 2. Introduce ext_buffer and ext_size in the migration subsection to\n>     track allocation exceeding TPM_TIS_BUFFER_MAX. Allocate ext_buffer\n>     using VMSTATE_VBUFFER_ALLOC_UINT32 only to be freed later after it is\n>     appended to the main buffer.\n> \n> This allows us to migrate to a destination host without breaking\n> backward compatibility. Old QEMU does not include a size field along\n> with the buffer in the migration stream, and therefore the\n> new QEMU is also forced to keep expecting exactly 4096 bytes.\n> \n> Implement a post_load hook that will validate the incoming data size\n> from the migration stream, failing the migration if it exceeds the\n> destination backend capacity. Add unrealize functions for the TIS interface\n> types ISA, SysBus and I2C to ensure that the buffer is safely freed on\n> device destruction.\n> \n> Signed-off-by: Arun Menon <armenon@redhat.com>\n> ---\n> Dependencies:\n> This patch depends on the following patch currently in the mailing list:\n> https://lore.kernel.org/qemu-devel/20260422103018.123608-10-armenon@redhat.com/\n\nI had tried to apply your v5 series to master but could not. Do you have \na git repo where you keep your patches?\n\n> \n> Depends-on: <20260422103018.123608-10-armenon@redhat.com>\n> \n>   hw/tpm/tpm_tis.h        |  6 ++++-\n>   hw/tpm/tpm_tis_common.c | 56 +++++++++++++++++++++++++++++++++++------\n>   hw/tpm/tpm_tis_i2c.c    | 28 +++++++++++++++++++--\n>   hw/tpm/tpm_tis_isa.c    | 31 +++++++++++++++++++++--\n>   hw/tpm/tpm_tis_sysbus.c | 32 +++++++++++++++++++++--\n>   5 files changed, 138 insertions(+), 15 deletions(-)\n> \n> diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h\n> index b2d9c0116c..c736ecedc1 100644\n> --- a/hw/tpm/tpm_tis.h\n> +++ b/hw/tpm/tpm_tis.h\n> @@ -56,7 +56,9 @@ typedef struct TPMLocality {\n>   typedef struct TPMState {\n>       MemoryRegion mmio;\n>   \n> -    unsigned char buffer[TPM_TIS_BUFFER_MAX];\n> +    uint8_t *buffer;\n> +    uint8_t *ext_buffer;\n> +    uint32_t ext_size;\n>       uint16_t rw_offset;\n>   \n>       uint8_t active_locty;\n> @@ -82,6 +84,8 @@ extern const VMStateDescription vmstate_locty;\n>   extern const MemoryRegionOps tpm_tis_memory_ops;\n>   \n>   int tpm_tis_pre_save(TPMState *s);\n> +int tpm_tis_post_load(TPMState *s);\n> +int tpm_tis_ext_buffer_post_load(TPMState *s);\n>   void tpm_tis_reset(TPMState *s, bool ppi_enabled);\n>   enum TPMVersion tpm_tis_get_tpm_version(TPMState *s);\n>   void tpm_tis_request_completed(TPMState *s, int ret);\n> diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c\n> index 43e68410f8..c9c4dd1190 100644\n> --- a/hw/tpm/tpm_tis_common.c\n> +++ b/hw/tpm/tpm_tis_common.c\n> @@ -270,7 +270,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)\n>       uint16_t len;\n>   \n>       if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {\n> -        len = MIN(tpm_cmd_get_size(&s->buffer),\n> +        len = MIN(tpm_cmd_get_size(s->buffer),\n>                     s->be_buffer_size);\n>   \n>           ret = s->buffer[s->rw_offset++];\n> @@ -317,7 +317,7 @@ static void tpm_tis_dump_state(TPMState *s, hwaddr addr)\n>              \"tpm_tis: result buffer : \",\n>              s->rw_offset);\n>       for (idx = 0;\n> -         idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);\n> +         idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);\n>            idx++) {\n>           printf(\"%c%02x%s\",\n>                  s->rw_offset == idx ? '>' : ' ',\n> @@ -383,7 +383,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,\n>           if (s->active_locty == locty) {\n>               if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {\n>                   val = TPM_TIS_BURST_COUNT(\n> -                       MIN(tpm_cmd_get_size(&s->buffer),\n> +                       MIN(tpm_cmd_get_size(s->buffer),\n>                              s->be_buffer_size)\n>                          - s->rw_offset) | s->loc[locty].sts;\n>               } else {\n> @@ -754,7 +754,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,\n>                   /* we have a packet length - see if we have all of it */\n>                   bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID);\n>   \n> -                len = tpm_cmd_get_size(&s->buffer);\n> +                len = tpm_cmd_get_size(s->buffer);\n>                   if (len > s->rw_offset) {\n>                       tpm_tis_sts_set(&s->loc[locty],\n>                                       TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);\n> @@ -818,9 +818,10 @@ void tpm_tis_reset(TPMState *s, bool ppi_enabled)\n>       int c;\n>   \n>       s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);\n> -    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),\n> -                            TPM_TIS_BUFFER_MAX);\n>   \n> +    s->be_buffer_size = tpm_backend_get_buffer_size(s->be_driver);\n> +    s->buffer = g_realloc(s->buffer, MAX(s->be_buffer_size,\n> +                          TPM_TIS_BUFFER_MAX));\n\nWith MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the backend \nsays so -- hm...\n\n>       if (ppi_enabled) {\n>           tpm_ppi_reset(&s->ppi);\n>       }\n> @@ -873,6 +874,45 @@ int tpm_tis_pre_save(TPMState *s)\n>        */\n>       tpm_backend_finish_sync(s->be_driver);\n>   \n> +    if (s->be_buffer_size > TPM_TIS_BUFFER_MAX) {\n> +        s->ext_size = s->be_buffer_size - TPM_TIS_BUFFER_MAX;\n> +        s->ext_buffer = s->buffer + TPM_TIS_BUFFER_MAX;\n> +    } else {\n> +        s->ext_size = 0;\n> +        s->ext_buffer = NULL;\n> +    }\n> +    return 0;\n> +}\n> +\n> +int tpm_tis_post_load(TPMState *s)\n> +{\n> +    if (s->rw_offset > s->be_buffer_size) {\n> +        return -EINVAL;\n> +    }\n> +    return 0;\n> +}\n> +\n> +int tpm_tis_ext_buffer_post_load(TPMState *s)\n> +{\n> +    /*\n> +     * Calculate the maximum extension buffer size allowed, by comparing\n> +     * the destination VM's backend capacity with TPM_TIS_BUFFER_MAX.\n> +     */\n> +    uint32_t max_ext = s->be_buffer_size > TPM_TIS_BUFFER_MAX ?\n> +                       s->be_buffer_size - TPM_TIS_BUFFER_MAX : 0;\n> +\n> +    if (s->ext_size > max_ext) {\n> +        /*\n> +         * Source buffer size is greater than what the destination backend\n> +         * allows\n> +         */\n> +        g_clear_pointer(&s->ext_buffer, g_free);\n> +        return -EINVAL;\n> +    }\n> +    if (s->ext_size > 0) {\n> +        memcpy(s->buffer + TPM_TIS_BUFFER_MAX, s->ext_buffer, s->ext_size);\n> +        g_clear_pointer(&s->ext_buffer, g_free);\n> +    }\n>       return 0;\n>   }\n>   \n> @@ -901,7 +941,7 @@ bool tpm_tis_ext_buffer_migration_needed(struct TPMState *s)\n>       case TPM_TIS_STATE_READY:\n>           return false;\n>       case TPM_TIS_STATE_RECEPTION:\n> -        return s->rw_offset >= 4096;\n> +        return s->rw_offset >= TPM_TIS_BUFFER_MAX;\n\nThis cannot be right.\n\nFor PQC support we extended the 4096 byte buffer from 4096 bytes to 8192 \nbyte but only want to store the 2nd 4096 bytes if necessary and to keep \nbackwards compatibility.\n\nThis function was called to determine whether more than 4096 bytes were \neither written to the buffer by the OS driver or received from the TPM \nas a response so that we now would have to send the additional 2nd 4096 \nbytes. But TPM_TIS_BUFFER_MAX is 8192.\n\n\n\n >       case TPM_TIS_STATE_EXECUTION:>           /*\n>            * TPM is executing: we cannot know the size of TPM response.\n> @@ -909,7 +949,7 @@ bool tpm_tis_ext_buffer_migration_needed(struct TPMState *s)\n>            */\n>           return false;\n>       case TPM_TIS_STATE_COMPLETION:\n> -        return (tpm_cmd_get_size(&s->buffer) >= 4096);\n> +        return (tpm_cmd_get_size(s->buffer) >= TPM_TIS_BUFFER_MAX);\n\nNot good, either.\n\n>       }\n>       return false;\n>   }\n> diff --git a/hw/tpm/tpm_tis_i2c.c b/hw/tpm/tpm_tis_i2c.c\n> index f48938e3a1..41a5486497 100644\n> --- a/hw/tpm/tpm_tis_i2c.c\n> +++ b/hw/tpm/tpm_tis_i2c.c\n> @@ -103,6 +103,10 @@ static int tpm_tis_i2c_post_load(void *opaque, int version_id)\n>   {\n>       TPMStateI2C *i2cst = opaque;\n>   \n> +    if (tpm_tis_post_load(&i2cst->state) < 0) {\n> +        return -1;\n> +    }\n> +\n>       if (i2cst->offset >= 1) {\n>           tpm_tis_i2c_to_tis_reg(i2cst, i2cst->data[0]);\n>       }\n> @@ -117,13 +121,23 @@ static bool tpm_tis_ext_buffer_migration_needed_i2c(void *opaque)\n>       return tpm_tis_ext_buffer_migration_needed(&i2cst->state);\n>   }\n>   \n> +static int tpm_tis_ext_buffer_post_load_i2c(void *opaque, int version_id)\n> +{\n> +    TPMStateI2C *i2cst = opaque;\n> +\n> +    return tpm_tis_ext_buffer_post_load(&i2cst->state);\n> +}\n> +\n>   static const VMStateDescription vmstate_tpm_tis_ext_buffer_i2c = {\n>       .name = \"tpm-tis/ext_buffer\",\n>       .version_id = 0,\n>       .needed = tpm_tis_ext_buffer_migration_needed_i2c,\n>       .pre_save = tpm_tis_i2c_pre_save,\n> +    .post_load = tpm_tis_ext_buffer_post_load_i2c,\n>       .fields = (const VMStateField[]) {\n> -        VMSTATE_BUFFER_START_MIDDLE(state.buffer, TPMStateI2C, 4096),\n\nHere we instructed the buffer to be written from 4096 bytes to 8192 \nbytes, so the 2nd part. I don't think your changes are changing it to \nanything equivalent.\n\n> +        VMSTATE_UINT32(state.ext_size, TPMStateI2C),\n> +        VMSTATE_VBUFFER_ALLOC_UINT32(state.ext_buffer, TPMStateI2C, 0, NULL,\n> +                                     state.ext_size),\n>           VMSTATE_END_OF_LIST()\n>       }\n>   };\n> @@ -134,7 +148,8 @@ static const VMStateDescription vmstate_tpm_tis_i2c = {\n>       .pre_save  = tpm_tis_i2c_pre_save,\n>       .post_load  = tpm_tis_i2c_post_load,\n>       .fields = (const VMStateField[]) {\n> -        VMSTATE_PARTIAL_BUFFER(state.buffer, TPMStateI2C, 4096),\n\nThis was supposed to store the first 4096 bytes of the buffer to keep \nbackwards compatibility. And the 2nd 4096 bytes were only supposed to be \nwritten if found necessary.\n\n> +        VMSTATE_BUFFER_POINTER_UNSAFE(state.buffer, TPMStateI2C, 0,\n> +                                      TPM_TIS_BUFFER_MAX),\n>           VMSTATE_UINT16(state.rw_offset, TPMStateI2C),\n>           VMSTATE_UINT8(state.active_locty, TPMStateI2C),\n>           VMSTATE_UINT8(state.aborting_locty, TPMStateI2C),\n> @@ -535,6 +550,14 @@ static void tpm_tis_i2c_realizefn(DeviceState *dev, Error **errp)\n>       }\n>   }\n>   \n> +static void tpm_tis_i2c_unrealizefn(DeviceState *dev)\n> +{\n> +    TPMStateI2C *i2cst = TPM_TIS_I2C(dev);\n> +    TPMState *state = &i2cst->state;\n> +\n> +    g_clear_pointer(&state->buffer, g_free);\n> +}\n> +\n>   static void tpm_tis_i2c_reset(DeviceState *dev)\n>   {\n>       TPMStateI2C *i2cst = TPM_TIS_I2C(dev);\n> @@ -555,6 +578,7 @@ static void tpm_tis_i2c_class_init(ObjectClass *klass, const void *data)\n>       TPMIfClass *tc = TPM_IF_CLASS(klass);\n>   \n>       dc->realize = tpm_tis_i2c_realizefn;\n> +    dc->unrealize = tpm_tis_i2c_unrealizefn;\n>       device_class_set_legacy_reset(dc, tpm_tis_i2c_reset);\n>       dc->vmsd = &vmstate_tpm_tis_i2c;\n>       device_class_set_props(dc, tpm_tis_i2c_properties);\n> diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c\n> index 4999de1c61..7fbdfb96e6 100644\n> --- a/hw/tpm/tpm_tis_isa.c\n> +++ b/hw/tpm/tpm_tis_isa.c\n> @@ -49,6 +49,12 @@ static int tpm_tis_pre_save_isa(void *opaque)\n>       return tpm_tis_pre_save(&isadev->state);\n>   }\n>   \n> +static int tpm_tis_post_load_isa(void *opaque, int version_id)\n> +{\n> +    TPMStateISA *isadev = opaque;\n> +    return tpm_tis_post_load(&isadev->state);\n> +}\n> +\n>   static bool tpm_tis_ext_buffer_migration_needed_isa(void *opaque)\n>   {\n>       TPMStateISA *isadev = opaque;\n> @@ -56,13 +62,23 @@ static bool tpm_tis_ext_buffer_migration_needed_isa(void *opaque)\n>       return tpm_tis_ext_buffer_migration_needed(&isadev->state);\n>   }\n>   \n> +static int tpm_tis_ext_buffer_post_load_isa(void *opaque, int version_id)\n> +{\n> +    TPMStateISA *isadev = opaque;\n> +\n> +    return tpm_tis_ext_buffer_post_load(&isadev->state);\n> +}\n> +\n>   static const VMStateDescription vmstate_tpm_tis_ext_buffer_isa = {\n>       .name = \"tpm-tis/ext_buffer\",\n>       .version_id = 0,\n>       .needed = tpm_tis_ext_buffer_migration_needed_isa,\n>       .pre_save = tpm_tis_pre_save_isa,\n> +    .post_load = tpm_tis_ext_buffer_post_load_isa,\n>       .fields = (const VMStateField[]) {\n> -        VMSTATE_BUFFER_START_MIDDLE(state.buffer, TPMStateISA, 4096),\n> +        VMSTATE_UINT32(state.ext_size, TPMStateISA),\n> +        VMSTATE_VBUFFER_ALLOC_UINT32(state.ext_buffer, TPMStateISA, 0, NULL,\n> +                                     state.ext_size),\n>           VMSTATE_END_OF_LIST()\n>       }\n>   };\n> @@ -71,8 +87,10 @@ static const VMStateDescription vmstate_tpm_tis_isa = {\n>       .name = \"tpm-tis\",\n>       .version_id = 0,\n>       .pre_save  = tpm_tis_pre_save_isa,\n> +    .post_load = tpm_tis_post_load_isa,\n>       .fields = (const VMStateField[]) {\n> -        VMSTATE_PARTIAL_BUFFER(state.buffer, TPMStateISA, 4096),\n> +        VMSTATE_BUFFER_POINTER_UNSAFE(state.buffer, TPMStateISA, 0,\n> +                                      TPM_TIS_BUFFER_MAX),\n>           VMSTATE_UINT16(state.rw_offset, TPMStateISA),\n>           VMSTATE_UINT8(state.active_locty, TPMStateISA),\n>           VMSTATE_UINT8(state.aborting_locty, TPMStateISA),\n> @@ -157,6 +175,14 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp)\n>                    TPM_PPI_ADDR_BASE, OBJECT(dev));\n>   }\n>   \n> +static void tpm_tis_isa_unrealizefn(DeviceState *dev)\n> +{\n> +    TPMStateISA *isadev = TPM_TIS_ISA(dev);\n> +    TPMState *state = &isadev->state;\n> +\n> +    g_clear_pointer(&state->buffer, g_free);\n> +}\n> +\n>   static void build_tpm_tis_isa_aml(AcpiDevAmlIf *adev, Aml *scope)\n>   {\n>       Aml *dev, *crs;\n> @@ -196,6 +222,7 @@ static void tpm_tis_isa_class_init(ObjectClass *klass, const void *data)\n>       tc->model = TPM_MODEL_TPM_TIS;\n>       tc->ppi_enabled = true;\n>       dc->realize = tpm_tis_isa_realizefn;\n> +    dc->unrealize = tpm_tis_isa_unrealizefn;\n>       device_class_set_legacy_reset(dc, tpm_tis_isa_reset);\n>       tc->request_completed = tpm_tis_isa_request_completed;\n>       tc->get_version = tpm_tis_isa_get_tpm_version;\n> diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c\n> index c29f43bdce..ad8cfa85b1 100644\n> --- a/hw/tpm/tpm_tis_sysbus.c\n> +++ b/hw/tpm/tpm_tis_sysbus.c\n> @@ -49,6 +49,13 @@ static int tpm_tis_pre_save_sysbus(void *opaque)\n>       return tpm_tis_pre_save(&sbdev->state);\n>   }\n>   \n> +static int tpm_tis_post_load_sysbus(void *opaque, int version_id)\n> +{\n> +    TPMStateSysBus *sbdev = opaque;\n> +\n> +    return tpm_tis_post_load(&sbdev->state);\n> +}\n> +\n>   static bool tpm_tis_ext_buffer_migration_needed_sysbus(void *opaque)\n>   {\n>       TPMStateSysBus *sbdev = opaque;\n> @@ -56,13 +63,23 @@ static bool tpm_tis_ext_buffer_migration_needed_sysbus(void *opaque)\n>       return tpm_tis_ext_buffer_migration_needed(&sbdev->state);\n>   }\n>   \n> +static int tpm_tis_ext_buffer_post_load_sysbus(void *opaque, int version_id)\n> +{\n> +    TPMStateSysBus *sbdev = opaque;\n> +\n> +    return tpm_tis_ext_buffer_post_load(&sbdev->state);\n> +}\n> +\n>   static const VMStateDescription vmstate_tpm_tis_ext_buffer_sysbus = {\n>       .name = \"tpm-tis/ext_buffer\",\n>       .version_id = 0,\n>       .needed = tpm_tis_ext_buffer_migration_needed_sysbus,\n>       .pre_save  = tpm_tis_pre_save_sysbus,\n> +    .post_load = tpm_tis_ext_buffer_post_load_sysbus,\n>       .fields = (const VMStateField[]) {\n> -        VMSTATE_BUFFER_START_MIDDLE(state.buffer, TPMStateSysBus, 4096),\n> +        VMSTATE_UINT32(state.ext_size, TPMStateSysBus),\n> +        VMSTATE_VBUFFER_ALLOC_UINT32(state.ext_buffer, TPMStateSysBus, 0,\n> +                                     NULL, state.ext_size),\n>           VMSTATE_END_OF_LIST()\n>       }\n>   };\n> @@ -71,8 +88,10 @@ static const VMStateDescription vmstate_tpm_tis_sysbus = {\n>       .name = \"tpm-tis\",\n>       .version_id = 0,\n>       .pre_save  = tpm_tis_pre_save_sysbus,\n> +    .post_load = tpm_tis_post_load_sysbus,\n>       .fields = (const VMStateField[]) {\n> -        VMSTATE_PARTIAL_BUFFER(state.buffer, TPMStateSysBus, 4096),\n> +        VMSTATE_BUFFER_POINTER_UNSAFE(state.buffer, TPMStateSysBus, 0,\n> +                                      TPM_TIS_BUFFER_MAX),\n>           VMSTATE_UINT16(state.rw_offset, TPMStateSysBus),\n>           VMSTATE_UINT8(state.active_locty, TPMStateSysBus),\n>           VMSTATE_UINT8(state.aborting_locty, TPMStateSysBus),\n> @@ -156,6 +175,14 @@ static void tpm_tis_sysbus_realizefn(DeviceState *dev, Error **errp)\n>       vmstate_register_ram(&s->ppi.ram, dev);\n>   }\n>   \n> +static void tpm_tis_sysbus_unrealizefn(DeviceState *dev)\n> +{\n> +    TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev);\n> +    TPMState *state = &sbdev->state;\n> +\n> +    g_clear_pointer(&state->buffer, g_free);\n> +}\n> +\n>   static void tpm_tis_sysbus_class_init(ObjectClass *klass, const void *data)\n>   {\n>       DeviceClass *dc = DEVICE_CLASS(klass);\n> @@ -166,6 +193,7 @@ static void tpm_tis_sysbus_class_init(ObjectClass *klass, const void *data)\n>       tc->model = TPM_MODEL_TPM_TIS;\n>       tc->ppi_enabled = true;\n>       dc->realize = tpm_tis_sysbus_realizefn;\n> +    dc->unrealize = tpm_tis_sysbus_unrealizefn;\n>       device_class_set_legacy_reset(dc, tpm_tis_sysbus_reset);\n>       tc->request_completed = tpm_tis_sysbus_request_completed;\n>       tc->get_version = tpm_tis_sysbus_get_tpm_version;","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256\n header.s=pp1 header.b=WxE9+Oaa;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4G0F0nm2z1yHX\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 06:49:49 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wHStM-0004yh-G3; Mon, 27 Apr 2026 16:49:20 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <stefanb@linux.ibm.com>)\n id 1wHStG-0004wZ-MF\n for qemu-devel@nongnu.org; Mon, 27 Apr 2026 16:49:15 -0400","from mx0a-001b2d01.pphosted.com ([148.163.156.1])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <stefanb@linux.ibm.com>)\n id 1wHStC-0008D3-AO\n for qemu-devel@nongnu.org; Mon, 27 Apr 2026 16:49:13 -0400","from pps.filterd (m0356517.ppops.net [127.0.0.1])\n by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n 63RIWAc6811499; Mon, 27 Apr 2026 20:49:07 GMT","from ppma12.dal12v.mail.ibm.com\n (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220])\n by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4drnb52fkm-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);\n Mon, 27 Apr 2026 20:49:07 +0000 (GMT)","from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1])\n by ppma12.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id\n 63RKcmuM017681;\n Mon, 27 Apr 2026 20:49:06 GMT","from smtprelay07.wdc07v.mail.ibm.com ([172.16.1.74])\n by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4ds7xq70tc-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);\n Mon, 27 Apr 2026 20:49:06 +0000 (GMT)","from smtpav04.dal12v.mail.ibm.com (smtpav04.dal12v.mail.ibm.com\n [10.241.53.103])\n by smtprelay07.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id\n 63RKn53o33489646\n (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK);\n Mon, 27 Apr 2026 20:49:06 GMT","from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1])\n by IMSVA (Postfix) with ESMTP id AD42758052;\n Mon, 27 Apr 2026 20:49:05 +0000 (GMT)","from smtpav04.dal12v.mail.ibm.com (unknown [127.0.0.1])\n by IMSVA (Postfix) with ESMTP id 5CE585805E;\n Mon, 27 Apr 2026 20:49:05 +0000 (GMT)","from [9.47.158.152] (unknown [9.47.158.152])\n by smtpav04.dal12v.mail.ibm.com (Postfix) with ESMTP;\n Mon, 27 Apr 2026 20:49:05 +0000 (GMT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc\n :content-transfer-encoding:content-type:date:from:in-reply-to\n :message-id:mime-version:references:subject:to; s=pp1; bh=LPeKYL\n MvcY77CiSIPm1Y0H7wBkGochZhwYnfepkhDPo=; b=WxE9+OaaAm7+rgfdLNT95M\n PQR27xZJkVUGyzVn+itKRn5vwyg3l6t/vDnO6cN3P2Ggl9PuNmfizgwe9Xo2p9Pf\n LaaqXuyTR7Iq62sHX375+X2Nic9XUeFg/1xtGAwoQSEtQUnphgIcZdnD/I7aieIQ\n ZZg82N8s4u1y8VipzLC/57DLaYapDAlqYafYIhIOU/4ED+FHXa5vAZtyAfRwNY26\n APIcMXZR+gN5uyY4Ew5JGrqpkvF5vQAjiMqF1pOei5+GZBQWvA346DmK5/BwpoCO\n hsoMLWF1DRcOBiesXB8iTZ9aRpN1LQSktZwS/+lKQ/RH1eLwDam+9OA90vpKlEhQ\n ==","Message-ID":"<765f0577-ee8f-4944-93fe-bb93e420668f@linux.ibm.com>","Date":"Mon, 27 Apr 2026 16:49:04 -0400","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer","To":"Arun Menon <armenon@redhat.com>, qemu-devel@nongnu.org","Cc":"Stefan Berger <stefanb@linux.vnet.ibm.com>","References":"<20260427200134.453022-1-armenon@redhat.com>","Content-Language":"en-US","From":"Stefan Berger <stefanb@linux.ibm.com>","In-Reply-To":"<20260427200134.453022-1-armenon@redhat.com>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-TM-AS-GCONF":"00","X-Authority-Analysis":"v=2.4 cv=AqDeGu9P c=1 sm=1 tr=0 ts=69efcbc3 cx=c_pps\n a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17\n a=IkcTkHD0fZMA:10 a=A5OVakUREuEA:10 a=VkNPw1HP01LnGYTKEx00:22\n a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VwQbUJbxAAAA:8\n a=20KFwNOVAAAA:8 a=SvRv-rtrRAkuRqVAnvwA:9 a=QEXdDO2ut3YA:10","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwNDI3MDIyMSBTYWx0ZWRfXyt9ksJGg8Xkl\n qVcZJ3RYqSsIxSpgIBOGyez6XfeeWBEXC47IdMkacULYlLJzG74/6CQ7t49ZWTViHeXZvove46x\n 3E2yCsV7GoCMdttDFvdRZ2NJ4f9UyKNG2M7cRI0Vm1XrJfNv34k5R++uB1HbK495GfBc1QYA/uA\n PfL78dkKWHeeMAdLi76m+w/bbOQGYJcK9PP4xWrZ0iU7A+oQ106fr37yJ6kv16rIGgInrWNeNZ8\n 4IU54UNd4p//kcXMgOUpBd3D7/+KSv+RyJqPVqGN2J2B7mf1cNDUt90ETlLCA3EROYxIKraLovX\n nPZWSbX/faL8Yc/G0sptFK5VsQmD/PmrLuEL+du3GVHSb2BR8dK4wsFh9cbCaAtZYT6V4dXRH/d\n 9V5KjrTtt4SozQ77t7yHzQ+WR97f3xqmn0IeNV4nvmCGMM6kofNZJN08ZmC5DED3lhKzLfs3o/r\n xrVhkZWv/1nbfe9wrCA==","X-Proofpoint-GUID":"t8lkF1UIzfUPo4eNlG---3ywNNCFptN0","X-Proofpoint-ORIG-GUID":"t8lkF1UIzfUPo4eNlG---3ywNNCFptN0","X-Proofpoint-Virus-Version":"vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-04-27_04,2026-04-21_02,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n adultscore=0 priorityscore=1501 phishscore=0 suspectscore=0 clxscore=1015\n lowpriorityscore=0 spamscore=0 bulkscore=0 impostorscore=0 malwarescore=0\n classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0\n reason=mlx scancount=1 engine=8.22.0-2604200000 definitions=main-2604270221","Received-SPF":"pass client-ip=148.163.156.1;\n envelope-from=stefanb@linux.ibm.com;\n helo=mx0a-001b2d01.pphosted.com","X-Spam_score_int":"-26","X-Spam_score":"-2.7","X-Spam_bar":"--","X-Spam_report":"(-2.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7,\n RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}},{"id":3683163,"web_url":"http://patchwork.ozlabs.org/comment/3683163/","msgid":"<afBbLDmdYFY5feJx@fedora>","list_archive_url":null,"date":"2026-04-28T07:01:00","subject":"Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer","submitter":{"id":91136,"url":"http://patchwork.ozlabs.org/api/people/91136/","name":"Arun Menon","email":"armenon@redhat.com"},"content":"Hi Stefan,\n\nThank you for taking a look.\n\nOn Mon, Apr 27, 2026 at 04:49:04PM -0400, Stefan Berger wrote:\n> \n> \n> On 4/27/26 4:01 PM, Arun Menon wrote:\n> > From: Arun Menon <armenon@redhat.com>\n> > \n> > The TPM TIS buffer is currently a fixed-size static array. Change this\n> > to a dynamically allocated heap block. The buffer size is now determined\n> > at runtime by querying the TPM backend.\n> \n> Do we really need this? I mean for the forseeable future 8kb should be\n> sufficient.\n\nYou are right that 8kb should be sufficient.\nI implemented this to address the TODO mentioned here:\nhttps://github.com/qemu/qemu/commit/e5f62d87e3c03bda6006085cf6303736fb57f5c5\n\nThat is why this patch is  deliberately posted outside the v5 series.\nIt is more about future-proofing than a strict requirement. I thought it\nwas worth addressing while the context was fresh. I am happy to leave it\nout if we prefer that.\n\n> \n> > \n> > To support VM migration,\n> > 1. Replace the static VMSTATE_BUFFER macro with pointer-based variant\n> >     VMSTATE_BUFFER_POINTER_UNSAFE, explicitly mentioning the size.\n> > 2. Introduce ext_buffer and ext_size in the migration subsection to\n> >     track allocation exceeding TPM_TIS_BUFFER_MAX. Allocate ext_buffer\n> >     using VMSTATE_VBUFFER_ALLOC_UINT32 only to be freed later after it is\n> >     appended to the main buffer.\n> > \n> > This allows us to migrate to a destination host without breaking\n> > backward compatibility. Old QEMU does not include a size field along\n> > with the buffer in the migration stream, and therefore the\n> > new QEMU is also forced to keep expecting exactly 4096 bytes.\n> > \n> > Implement a post_load hook that will validate the incoming data size\n> > from the migration stream, failing the migration if it exceeds the\n> > destination backend capacity. Add unrealize functions for the TIS interface\n> > types ISA, SysBus and I2C to ensure that the buffer is safely freed on\n> > device destruction.\n> > \n> > Signed-off-by: Arun Menon <armenon@redhat.com>\n> > ---\n> > Dependencies:\n> > This patch depends on the following patch currently in the mailing list:\n> > https://lore.kernel.org/qemu-devel/20260422103018.123608-10-armenon@redhat.com/\n> \n> I had tried to apply your v5 series to master but could not. Do you have a\n> git repo where you keep your patches?\n\nYes. Here is the repo: https://gitlab.com/armenon/qemu-dev/-/tree/pqc_tpm?ref_type=heads\nI have applied the GByteArray change first, followed by the 10 commits.\n\n> \n> > \n> > Depends-on: <20260422103018.123608-10-armenon@redhat.com>\n> > \n> >   hw/tpm/tpm_tis.h        |  6 ++++-\n> >   hw/tpm/tpm_tis_common.c | 56 +++++++++++++++++++++++++++++++++++------\n> >   hw/tpm/tpm_tis_i2c.c    | 28 +++++++++++++++++++--\n> >   hw/tpm/tpm_tis_isa.c    | 31 +++++++++++++++++++++--\n> >   hw/tpm/tpm_tis_sysbus.c | 32 +++++++++++++++++++++--\n> >   5 files changed, 138 insertions(+), 15 deletions(-)\n> > \n> > diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h\n> > index b2d9c0116c..c736ecedc1 100644\n> > --- a/hw/tpm/tpm_tis.h\n> > +++ b/hw/tpm/tpm_tis.h\n> > @@ -56,7 +56,9 @@ typedef struct TPMLocality {\n> >   typedef struct TPMState {\n> >       MemoryRegion mmio;\n> > -    unsigned char buffer[TPM_TIS_BUFFER_MAX];\n> > +    uint8_t *buffer;\n> > +    uint8_t *ext_buffer;\n> > +    uint32_t ext_size;\n> >       uint16_t rw_offset;\n> >       uint8_t active_locty;\n> > @@ -82,6 +84,8 @@ extern const VMStateDescription vmstate_locty;\n> >   extern const MemoryRegionOps tpm_tis_memory_ops;\n> >   int tpm_tis_pre_save(TPMState *s);\n> > +int tpm_tis_post_load(TPMState *s);\n> > +int tpm_tis_ext_buffer_post_load(TPMState *s);\n> >   void tpm_tis_reset(TPMState *s, bool ppi_enabled);\n> >   enum TPMVersion tpm_tis_get_tpm_version(TPMState *s);\n> >   void tpm_tis_request_completed(TPMState *s, int ret);\n> > diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c\n> > index 43e68410f8..c9c4dd1190 100644\n> > --- a/hw/tpm/tpm_tis_common.c\n> > +++ b/hw/tpm/tpm_tis_common.c\n> > @@ -270,7 +270,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)\n> >       uint16_t len;\n> >       if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {\n> > -        len = MIN(tpm_cmd_get_size(&s->buffer),\n> > +        len = MIN(tpm_cmd_get_size(s->buffer),\n> >                     s->be_buffer_size);\n> >           ret = s->buffer[s->rw_offset++];\n> > @@ -317,7 +317,7 @@ static void tpm_tis_dump_state(TPMState *s, hwaddr addr)\n> >              \"tpm_tis: result buffer : \",\n> >              s->rw_offset);\n> >       for (idx = 0;\n> > -         idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);\n> > +         idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);\n> >            idx++) {\n> >           printf(\"%c%02x%s\",\n> >                  s->rw_offset == idx ? '>' : ' ',\n> > @@ -383,7 +383,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,\n> >           if (s->active_locty == locty) {\n> >               if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {\n> >                   val = TPM_TIS_BURST_COUNT(\n> > -                       MIN(tpm_cmd_get_size(&s->buffer),\n> > +                       MIN(tpm_cmd_get_size(s->buffer),\n> >                              s->be_buffer_size)\n> >                          - s->rw_offset) | s->loc[locty].sts;\n> >               } else {\n> > @@ -754,7 +754,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,\n> >                   /* we have a packet length - see if we have all of it */\n> >                   bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID);\n> > -                len = tpm_cmd_get_size(&s->buffer);\n> > +                len = tpm_cmd_get_size(s->buffer);\n> >                   if (len > s->rw_offset) {\n> >                       tpm_tis_sts_set(&s->loc[locty],\n> >                                       TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);\n> > @@ -818,9 +818,10 @@ void tpm_tis_reset(TPMState *s, bool ppi_enabled)\n> >       int c;\n> >       s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);\n> > -    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),\n> > -                            TPM_TIS_BUFFER_MAX);\n> > +    s->be_buffer_size = tpm_backend_get_buffer_size(s->be_driver);\n> > +    s->buffer = g_realloc(s->buffer, MAX(s->be_buffer_size,\n> > +                          TPM_TIS_BUFFER_MAX));\n> \n> With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the backend says\n> so -- hm...\n\nTPM_TIS_BUFFER_MAX is still 4096.\nIn this patch, I changed hardcoded 4096 value to TPM_TIS_BUFFER_MAX.\n\nSo that the buffer can be allocated adequate space, the size passed to\ng_realloc is : MAX(backend_tpm_size, 4096). The additional part is sent\nusing ext_buffer and ext_size. These are set in the pre_save hook.\n\nWe did change the TPM_BUFSIZE in the kernel:\nhttps://lore.kernel.org/lkml/20260324181244.17741-5-armenon@redhat.com/\nPlease correct me if I am wrong. I might have missed something while\napplying patches on top of the tree.\n\n> \n> >       if (ppi_enabled) {\n> >           tpm_ppi_reset(&s->ppi);\n> >       }\n> > @@ -873,6 +874,45 @@ int tpm_tis_pre_save(TPMState *s)\n> >        */\n> >       tpm_backend_finish_sync(s->be_driver);\n> > +    if (s->be_buffer_size > TPM_TIS_BUFFER_MAX) {\n> > +        s->ext_size = s->be_buffer_size - TPM_TIS_BUFFER_MAX;\n> > +        s->ext_buffer = s->buffer + TPM_TIS_BUFFER_MAX;\n> > +    } else {\n> > +        s->ext_size = 0;\n> > +        s->ext_buffer = NULL;\n> > +    }\n> > +    return 0;\n> > +}\n> > +\n> > +int tpm_tis_post_load(TPMState *s)\n> > +{\n> > +    if (s->rw_offset > s->be_buffer_size) {\n> > +        return -EINVAL;\n> > +    }\n> > +    return 0;\n> > +}\n> > +\n> > +int tpm_tis_ext_buffer_post_load(TPMState *s)\n> > +{\n> > +    /*\n> > +     * Calculate the maximum extension buffer size allowed, by comparing\n> > +     * the destination VM's backend capacity with TPM_TIS_BUFFER_MAX.\n> > +     */\n> > +    uint32_t max_ext = s->be_buffer_size > TPM_TIS_BUFFER_MAX ?\n> > +                       s->be_buffer_size - TPM_TIS_BUFFER_MAX : 0;\n> > +\n> > +    if (s->ext_size > max_ext) {\n> > +        /*\n> > +         * Source buffer size is greater than what the destination backend\n> > +         * allows\n> > +         */\n> > +        g_clear_pointer(&s->ext_buffer, g_free);\n> > +        return -EINVAL;\n> > +    }\n> > +    if (s->ext_size > 0) {\n> > +        memcpy(s->buffer + TPM_TIS_BUFFER_MAX, s->ext_buffer, s->ext_size);\n\n... [1]\n\n> > +        g_clear_pointer(&s->ext_buffer, g_free);\n> > +    }\n> >       return 0;\n> >   }\n> > @@ -901,7 +941,7 @@ bool tpm_tis_ext_buffer_migration_needed(struct TPMState *s)\n> >       case TPM_TIS_STATE_READY:\n> >           return false;\n> >       case TPM_TIS_STATE_RECEPTION:\n> > -        return s->rw_offset >= 4096;\n> > +        return s->rw_offset >= TPM_TIS_BUFFER_MAX;\n> \n> This cannot be right.\n> \n> For PQC support we extended the 4096 byte buffer from 4096 bytes to 8192\n> byte but only want to store the 2nd 4096 bytes if necessary and to keep\n> backwards compatibility.\n> \n\nBecause TPM_TIS_BUFFER_MAX is still 4096, the check\ns->rw_offset >= TPM_TIS_BUFFER_MAX correctly identifies when we have\ndata exceeding the legacy limit.\n\n> This function was called to determine whether more than 4096 bytes were\n> either written to the buffer by the OS driver or received from the TPM as a\n> response so that we now would have to send the additional 2nd 4096 bytes.\n> But TPM_TIS_BUFFER_MAX is 8192.\n> \n> \n\nIf TPM_TIS_BUFFER_MAX stayed 4096, then the comparisons should make sense.\n\n> \n> >       case TPM_TIS_STATE_EXECUTION:>           /*\n> >            * TPM is executing: we cannot know the size of TPM response.\n> > @@ -909,7 +949,7 @@ bool tpm_tis_ext_buffer_migration_needed(struct TPMState *s)\n> >            */\n> >           return false;\n> >       case TPM_TIS_STATE_COMPLETION:\n> > -        return (tpm_cmd_get_size(&s->buffer) >= 4096);\n> > +        return (tpm_cmd_get_size(s->buffer) >= TPM_TIS_BUFFER_MAX);\n> \n> Not good, either.\n\nIf TPM_TIS_BUFFER_MAX stayed 4096, then the comparisons should make sense.\n\n> \n> >       }\n> >       return false;\n> >   }\n> > diff --git a/hw/tpm/tpm_tis_i2c.c b/hw/tpm/tpm_tis_i2c.c\n> > index f48938e3a1..41a5486497 100644\n> > --- a/hw/tpm/tpm_tis_i2c.c\n> > +++ b/hw/tpm/tpm_tis_i2c.c\n> > @@ -103,6 +103,10 @@ static int tpm_tis_i2c_post_load(void *opaque, int version_id)\n> >   {\n> >       TPMStateI2C *i2cst = opaque;\n> > +    if (tpm_tis_post_load(&i2cst->state) < 0) {\n> > +        return -1;\n> > +    }\n> > +\n> >       if (i2cst->offset >= 1) {\n> >           tpm_tis_i2c_to_tis_reg(i2cst, i2cst->data[0]);\n> >       }\n> > @@ -117,13 +121,23 @@ static bool tpm_tis_ext_buffer_migration_needed_i2c(void *opaque)\n> >       return tpm_tis_ext_buffer_migration_needed(&i2cst->state);\n> >   }\n> > +static int tpm_tis_ext_buffer_post_load_i2c(void *opaque, int version_id)\n> > +{\n> > +    TPMStateI2C *i2cst = opaque;\n> > +\n> > +    return tpm_tis_ext_buffer_post_load(&i2cst->state);\n> > +}\n> > +\n> >   static const VMStateDescription vmstate_tpm_tis_ext_buffer_i2c = {\n> >       .name = \"tpm-tis/ext_buffer\",\n> >       .version_id = 0,\n> >       .needed = tpm_tis_ext_buffer_migration_needed_i2c,\n> >       .pre_save = tpm_tis_i2c_pre_save,\n> > +    .post_load = tpm_tis_ext_buffer_post_load_i2c,\n> >       .fields = (const VMStateField[]) {\n> > -        VMSTATE_BUFFER_START_MIDDLE(state.buffer, TPMStateI2C, 4096),\n> \n> Here we instructed the buffer to be written from 4096 bytes to 8192 bytes,\n> so the 2nd part. I don't think your changes are changing it to anything\n> equivalent.\n\nIf TPM_TIS_BUFFER_MAX stayed 4096, then VMSTATE_VBUFFER_ALLOC_UINT32()\nwould create a new buffer of size ext_size (anything more than 4096)\nand allocate the additional buffer into it.\nSubsequently it will memcpy it into the original buffer\nand free it [1].\n\n> \n> > +        VMSTATE_UINT32(state.ext_size, TPMStateI2C),\n> > +        VMSTATE_VBUFFER_ALLOC_UINT32(state.ext_buffer, TPMStateI2C, 0, NULL,\n> > +                                     state.ext_size),\n> >           VMSTATE_END_OF_LIST()\n> >       }\n> >   };\n> > @@ -134,7 +148,8 @@ static const VMStateDescription vmstate_tpm_tis_i2c = {\n> >       .pre_save  = tpm_tis_i2c_pre_save,\n> >       .post_load  = tpm_tis_i2c_post_load,\n> >       .fields = (const VMStateField[]) {\n> > -        VMSTATE_PARTIAL_BUFFER(state.buffer, TPMStateI2C, 4096),\n> \n> This was supposed to store the first 4096 bytes of the buffer to keep\n> backwards compatibility. And the 2nd 4096 bytes were only supposed to be\n> written if found necessary.\n\nIf TPM_TIS_BUFFER_MAX stayed 4096, then this would make sense. Only\nhardcoded 4096 is changed to TPM_TIS_BUFFER_MAX and the macro is changed\nbecause now the buffer is a pointer.\n\n> \n> > +        VMSTATE_BUFFER_POINTER_UNSAFE(state.buffer, TPMStateI2C, 0,\n> > +                                      TPM_TIS_BUFFER_MAX),\n> >           VMSTATE_UINT16(state.rw_offset, TPMStateI2C),\n> >           VMSTATE_UINT8(state.active_locty, TPMStateI2C),\n> >           VMSTATE_UINT8(state.aborting_locty, TPMStateI2C),\n> > @@ -535,6 +550,14 @@ static void tpm_tis_i2c_realizefn(DeviceState *dev, Error **errp)\n> >       }\n> >   }\n> > +static void tpm_tis_i2c_unrealizefn(DeviceState *dev)\n> > +{\n> > +    TPMStateI2C *i2cst = TPM_TIS_I2C(dev);\n> > +    TPMState *state = &i2cst->state;\n> > +\n> > +    g_clear_pointer(&state->buffer, g_free);\n> > +}\n> > +\n> >   static void tpm_tis_i2c_reset(DeviceState *dev)\n> >   {\n> >       TPMStateI2C *i2cst = TPM_TIS_I2C(dev);\n> > @@ -555,6 +578,7 @@ static void tpm_tis_i2c_class_init(ObjectClass *klass, const void *data)\n> >       TPMIfClass *tc = TPM_IF_CLASS(klass);\n> >       dc->realize = tpm_tis_i2c_realizefn;\n> > +    dc->unrealize = tpm_tis_i2c_unrealizefn;\n> >       device_class_set_legacy_reset(dc, tpm_tis_i2c_reset);\n> >       dc->vmsd = &vmstate_tpm_tis_i2c;\n> >       device_class_set_props(dc, tpm_tis_i2c_properties);\n> > diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c\n> > index 4999de1c61..7fbdfb96e6 100644\n> > --- a/hw/tpm/tpm_tis_isa.c\n> > +++ b/hw/tpm/tpm_tis_isa.c\n> > @@ -49,6 +49,12 @@ static int tpm_tis_pre_save_isa(void *opaque)\n> >       return tpm_tis_pre_save(&isadev->state);\n> >   }\n> > +static int tpm_tis_post_load_isa(void *opaque, int version_id)\n> > +{\n> > +    TPMStateISA *isadev = opaque;\n> > +    return tpm_tis_post_load(&isadev->state);\n> > +}\n> > +\n> >   static bool tpm_tis_ext_buffer_migration_needed_isa(void *opaque)\n> >   {\n> >       TPMStateISA *isadev = opaque;\n> > @@ -56,13 +62,23 @@ static bool tpm_tis_ext_buffer_migration_needed_isa(void *opaque)\n> >       return tpm_tis_ext_buffer_migration_needed(&isadev->state);\n> >   }\n> > +static int tpm_tis_ext_buffer_post_load_isa(void *opaque, int version_id)\n> > +{\n> > +    TPMStateISA *isadev = opaque;\n> > +\n> > +    return tpm_tis_ext_buffer_post_load(&isadev->state);\n> > +}\n> > +\n> >   static const VMStateDescription vmstate_tpm_tis_ext_buffer_isa = {\n> >       .name = \"tpm-tis/ext_buffer\",\n> >       .version_id = 0,\n> >       .needed = tpm_tis_ext_buffer_migration_needed_isa,\n> >       .pre_save = tpm_tis_pre_save_isa,\n> > +    .post_load = tpm_tis_ext_buffer_post_load_isa,\n> >       .fields = (const VMStateField[]) {\n> > -        VMSTATE_BUFFER_START_MIDDLE(state.buffer, TPMStateISA, 4096),\n> > +        VMSTATE_UINT32(state.ext_size, TPMStateISA),\n> > +        VMSTATE_VBUFFER_ALLOC_UINT32(state.ext_buffer, TPMStateISA, 0, NULL,\n> > +                                     state.ext_size),\n> >           VMSTATE_END_OF_LIST()\n> >       }\n> >   };\n> > @@ -71,8 +87,10 @@ static const VMStateDescription vmstate_tpm_tis_isa = {\n> >       .name = \"tpm-tis\",\n> >       .version_id = 0,\n> >       .pre_save  = tpm_tis_pre_save_isa,\n> > +    .post_load = tpm_tis_post_load_isa,\n> >       .fields = (const VMStateField[]) {\n> > -        VMSTATE_PARTIAL_BUFFER(state.buffer, TPMStateISA, 4096),\n> > +        VMSTATE_BUFFER_POINTER_UNSAFE(state.buffer, TPMStateISA, 0,\n> > +                                      TPM_TIS_BUFFER_MAX),\n> >           VMSTATE_UINT16(state.rw_offset, TPMStateISA),\n> >           VMSTATE_UINT8(state.active_locty, TPMStateISA),\n> >           VMSTATE_UINT8(state.aborting_locty, TPMStateISA),\n> > @@ -157,6 +175,14 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp)\n> >                    TPM_PPI_ADDR_BASE, OBJECT(dev));\n> >   }\n> > +static void tpm_tis_isa_unrealizefn(DeviceState *dev)\n> > +{\n> > +    TPMStateISA *isadev = TPM_TIS_ISA(dev);\n> > +    TPMState *state = &isadev->state;\n> > +\n> > +    g_clear_pointer(&state->buffer, g_free);\n> > +}\n> > +\n> >   static void build_tpm_tis_isa_aml(AcpiDevAmlIf *adev, Aml *scope)\n> >   {\n> >       Aml *dev, *crs;\n> > @@ -196,6 +222,7 @@ static void tpm_tis_isa_class_init(ObjectClass *klass, const void *data)\n> >       tc->model = TPM_MODEL_TPM_TIS;\n> >       tc->ppi_enabled = true;\n> >       dc->realize = tpm_tis_isa_realizefn;\n> > +    dc->unrealize = tpm_tis_isa_unrealizefn;\n> >       device_class_set_legacy_reset(dc, tpm_tis_isa_reset);\n> >       tc->request_completed = tpm_tis_isa_request_completed;\n> >       tc->get_version = tpm_tis_isa_get_tpm_version;\n> > diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c\n> > index c29f43bdce..ad8cfa85b1 100644\n> > --- a/hw/tpm/tpm_tis_sysbus.c\n> > +++ b/hw/tpm/tpm_tis_sysbus.c\n> > @@ -49,6 +49,13 @@ static int tpm_tis_pre_save_sysbus(void *opaque)\n> >       return tpm_tis_pre_save(&sbdev->state);\n> >   }\n> > +static int tpm_tis_post_load_sysbus(void *opaque, int version_id)\n> > +{\n> > +    TPMStateSysBus *sbdev = opaque;\n> > +\n> > +    return tpm_tis_post_load(&sbdev->state);\n> > +}\n> > +\n> >   static bool tpm_tis_ext_buffer_migration_needed_sysbus(void *opaque)\n> >   {\n> >       TPMStateSysBus *sbdev = opaque;\n> > @@ -56,13 +63,23 @@ static bool tpm_tis_ext_buffer_migration_needed_sysbus(void *opaque)\n> >       return tpm_tis_ext_buffer_migration_needed(&sbdev->state);\n> >   }\n> > +static int tpm_tis_ext_buffer_post_load_sysbus(void *opaque, int version_id)\n> > +{\n> > +    TPMStateSysBus *sbdev = opaque;\n> > +\n> > +    return tpm_tis_ext_buffer_post_load(&sbdev->state);\n> > +}\n> > +\n> >   static const VMStateDescription vmstate_tpm_tis_ext_buffer_sysbus = {\n> >       .name = \"tpm-tis/ext_buffer\",\n> >       .version_id = 0,\n> >       .needed = tpm_tis_ext_buffer_migration_needed_sysbus,\n> >       .pre_save  = tpm_tis_pre_save_sysbus,\n> > +    .post_load = tpm_tis_ext_buffer_post_load_sysbus,\n> >       .fields = (const VMStateField[]) {\n> > -        VMSTATE_BUFFER_START_MIDDLE(state.buffer, TPMStateSysBus, 4096),\n> > +        VMSTATE_UINT32(state.ext_size, TPMStateSysBus),\n> > +        VMSTATE_VBUFFER_ALLOC_UINT32(state.ext_buffer, TPMStateSysBus, 0,\n> > +                                     NULL, state.ext_size),\n> >           VMSTATE_END_OF_LIST()\n> >       }\n> >   };\n> > @@ -71,8 +88,10 @@ static const VMStateDescription vmstate_tpm_tis_sysbus = {\n> >       .name = \"tpm-tis\",\n> >       .version_id = 0,\n> >       .pre_save  = tpm_tis_pre_save_sysbus,\n> > +    .post_load = tpm_tis_post_load_sysbus,\n> >       .fields = (const VMStateField[]) {\n> > -        VMSTATE_PARTIAL_BUFFER(state.buffer, TPMStateSysBus, 4096),\n> > +        VMSTATE_BUFFER_POINTER_UNSAFE(state.buffer, TPMStateSysBus, 0,\n> > +                                      TPM_TIS_BUFFER_MAX),\n> >           VMSTATE_UINT16(state.rw_offset, TPMStateSysBus),\n> >           VMSTATE_UINT8(state.active_locty, TPMStateSysBus),\n> >           VMSTATE_UINT8(state.aborting_locty, TPMStateSysBus),\n> > @@ -156,6 +175,14 @@ static void tpm_tis_sysbus_realizefn(DeviceState *dev, Error **errp)\n> >       vmstate_register_ram(&s->ppi.ram, dev);\n> >   }\n> > +static void tpm_tis_sysbus_unrealizefn(DeviceState *dev)\n> > +{\n> > +    TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev);\n> > +    TPMState *state = &sbdev->state;\n> > +\n> > +    g_clear_pointer(&state->buffer, g_free);\n> > +}\n> > +\n> >   static void tpm_tis_sysbus_class_init(ObjectClass *klass, const void *data)\n> >   {\n> >       DeviceClass *dc = DEVICE_CLASS(klass);\n> > @@ -166,6 +193,7 @@ static void tpm_tis_sysbus_class_init(ObjectClass *klass, const void *data)\n> >       tc->model = TPM_MODEL_TPM_TIS;\n> >       tc->ppi_enabled = true;\n> >       dc->realize = tpm_tis_sysbus_realizefn;\n> > +    dc->unrealize = tpm_tis_sysbus_unrealizefn;\n> >       device_class_set_legacy_reset(dc, tpm_tis_sysbus_reset);\n> >       tc->request_completed = tpm_tis_sysbus_request_completed;\n> >       tc->get_version = tpm_tis_sysbus_get_tpm_version;\n> \n> \n\nWas TPM_TIS_BUFFER_MAX expected to be increased to 8192?\n\nRegards,\nArun Menon","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=ReQ19Zdo;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=google header.b=MJDCZuEY;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4WZT3QZwz1yHv\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 17:01:53 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wHcRm-0006R1-0U; Tue, 28 Apr 2026 03:01:30 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <armenon@redhat.com>)\n id 1wHcRd-0006Q5-T6\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 03:01:22 -0400","from us-smtp-delivery-124.mimecast.com ([170.10.133.124])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <armenon@redhat.com>)\n id 1wHcRY-0006VN-Um\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 03:01:21 -0400","from mail-pj1-f70.google.com (mail-pj1-f70.google.com\n [209.85.216.70]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n us-mta-696-gyE3q9HzN7eaky0GsCcd_g-1; Tue, 28 Apr 2026 03:01:13 -0400","by mail-pj1-f70.google.com with SMTP id\n 98e67ed59e1d1-35da97f6a6dso11187673a91.0\n for <qemu-devel@nongnu.org>; Tue, 28 Apr 2026 00:01:13 -0700 (PDT)","from fedora ([49.36.106.186]) by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2b97acaa6c6sm15830385ad.81.2026.04.28.00.01.04\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 28 Apr 2026 00:01:08 -0700 (PDT)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1777359675;\n h=from:from:reply-to:reply-to:subject:subject:date:date:\n message-id:message-id:to:to:cc:cc:mime-version:mime-version:\n content-type:content-type:in-reply-to:in-reply-to:  references:references;\n bh=QpZCAkJhFmO6LiQ1CYiuDZ2ydVNEljbOaPcNzyv1T5A=;\n b=ReQ19ZdoSkQkIYj7AHQDM4tT7s4oq6NxmbcyCdDAHjYAv04V1iswJZE2xY8YkSiJrZC5cI\n puKH+vmuweImRHZYEmjLPqlTvK/RKuHGHGPHTpbOuKQrATu19NTWLDqmL2zsnjZY8KGDwY\n pr2TsDMEdsfjMZxIIk+TbRZchpv2j/s=","v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=redhat.com; s=google; t=1777359672; x=1777964472; darn=nongnu.org;\n h=in-reply-to:content-disposition:mime-version:references:reply-to\n :message-id:subject:cc:to:from:date:from:to:cc:subject:date\n :message-id:reply-to;\n bh=QpZCAkJhFmO6LiQ1CYiuDZ2ydVNEljbOaPcNzyv1T5A=;\n b=MJDCZuEYlmrY6dy1EiAC6YyGpCI207ZfcduTrq0ereAMT4+ymwTTUvNv0L1N7WmByv\n 3013CueK0dg33ywZwkwB9s8uzQTD88cH/p/z39p3aHlNqcLQoVza4BZzmwYxMGqLxa4b\n ScFIVFeVPc82GRSGNEPbx13Mid1kWtk5GnbnguVkF58zgtZM0jRkvi6CCJQcrhwjLg/J\n 8MjNmsPISzOZ95hMe0t6o2l5iDWc7EZBgh7Nwmre9UBkLR0CNyIJtomW7fFVW8ncDi+x\n meDnad7L98pVab6rgG76FkuCE10UFXF7tsPpanczxs8gb8k1+Hip4eF8YC0VUJBMFeJS\n pC5w=="],"X-MC-Unique":"gyE3q9HzN7eaky0GsCcd_g-1","X-Mimecast-MFC-AGG-ID":"gyE3q9HzN7eaky0GsCcd_g_1777359672","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777359672; x=1777964472;\n h=in-reply-to:content-disposition:mime-version:references:reply-to\n :message-id:subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=QpZCAkJhFmO6LiQ1CYiuDZ2ydVNEljbOaPcNzyv1T5A=;\n b=iXsInivo/A4HpqpfFHCQniFeZEVUGot3WrrDllB6noDbKF6YFVkTnNMUeoYdt9DB+3\n iYZxJBZVSYSEXdZUO1XQ1zs4U3L13fO4sfEQMj+KyCWR7j7N8zMkkS/GWY7K9VMGOc0k\n IExbEe1LoMkXZQ5xiyQ6TLijy2rac/H5kqzgy20AOHb8/EwEyMjQd0Q6VaFanhsdOsMS\n 57drnkX7JbQV7YIJwCrHUXCyFitBZXMo9Y4TgPPx8mwIoCmHpD5qQ50E+Ksv7DSgdzdb\n VmCyM/vjgCyb9+7hFno4AaP8CBr0rgS7xPctDOZinewMedOqHeCuNyGABRKsJYVl7NVK\n Pxkw==","X-Gm-Message-State":"AOJu0Yw5G2QGyU+QwQldgj5mEzf51PFmafV4Ng7s4XSmOC1g/XYObizC\n /HYtbkh71a0whN483vrw23NYnMYEvZmBFV0+OI4Kg/IRlEjHMEK/QOPrUiPltLqCcgtsIvvvIrS\n MSnExVAMojffrXJoJ2vuKGTyLxWwn8M6qKyitiToUjfg/J2iTVPJvQdoa","X-Gm-Gg":"AeBDiete5BpxgAYc+hwg1XdchjXIuR5DVDQc3GO5d0D2KuGxo1r4wNMPH/Ani6CJCC1\n 19Oj/HCGvexeADuXi6OZoAyWHxWYAQOImX+E1L4O8zH3UNM6k6GuUco8sr7TgG+q0qLrCYt93zO\n IfYufWmUKVA8nxhKMRek7AWQVjYBy13Q2uSZYCnYDzdHFyJuV76F3lWR0dJxyMAUzOA7s6f5Oc+\n 2IpbuoPz+2HzqOwnoIdGGQAru0U1sybjrjg8Hd+8WyJ2+17oQ9JfHjZaNf+t8UQrfzBBeovDhQH\n KWL4kja5V2cRxPZl6t6NZBpbsf3Gksc+JuTJeF/6XkCcfEO4cjmbHanarMKFtn3gv//ZX5HJ81F\n V4Ndlp8DCNPZr+zYGiE2f4lo=","X-Received":["by 2002:a17:90b:35c3:b0:35a:189b:43db with SMTP id\n 98e67ed59e1d1-36491fbf094mr2100991a91.4.1777359669559;\n Tue, 28 Apr 2026 00:01:09 -0700 (PDT)","by 2002:a17:90b:35c3:b0:35a:189b:43db with SMTP id\n 98e67ed59e1d1-36491fbf094mr2100897a91.4.1777359668624;\n Tue, 28 Apr 2026 00:01:08 -0700 (PDT)"],"Date":"Tue, 28 Apr 2026 12:31:00 +0530","From":"Arun Menon <armenon@redhat.com>","To":"Stefan Berger <stefanb@linux.ibm.com>","Cc":"qemu-devel@nongnu.org, Stefan Berger <stefanb@linux.vnet.ibm.com>","Subject":"Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer","Message-ID":"<afBbLDmdYFY5feJx@fedora>","References":"<20260427200134.453022-1-armenon@redhat.com>\n <765f0577-ee8f-4944-93fe-bb93e420668f@linux.ibm.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<765f0577-ee8f-4944-93fe-bb93e420668f@linux.ibm.com>","Received-SPF":"pass client-ip=170.10.133.124; envelope-from=armenon@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com","X-Spam_score_int":"-20","X-Spam_score":"-2.1","X-Spam_bar":"--","X-Spam_report":"(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_PASS=-0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Reply-To":"armenon@redhat.com","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}},{"id":3683443,"web_url":"http://patchwork.ozlabs.org/comment/3683443/","msgid":"<84607c2e-1da9-43d2-8a5b-e50e91c0f8ba@linux.ibm.com>","list_archive_url":null,"date":"2026-04-28T12:57:31","subject":"Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer","submitter":{"id":75097,"url":"http://patchwork.ozlabs.org/api/people/75097/","name":"Stefan Berger","email":"stefanb@linux.ibm.com"},"content":"On 4/28/26 3:01 AM, Arun Menon wrote:\n> Hi Stefan,\n> \n> Thank you for taking a look.\n> \n> On Mon, Apr 27, 2026 at 04:49:04PM -0400, Stefan Berger wrote:\n>>\n>>\n>> On 4/27/26 4:01 PM, Arun Menon wrote:\n>>> From: Arun Menon <armenon@redhat.com>\n>>>\n>>> The TPM TIS buffer is currently a fixed-size static array. Change this\n>>> to a dynamically allocated heap block. The buffer size is now determined\n>>> at runtime by querying the TPM backend.\n>>\n>> Do we really need this? I mean for the forseeable future 8kb should be\n>> sufficient.\n> \n> You are right that 8kb should be sufficient.\n> I implemented this to address the TODO mentioned here:\n> https://github.com/qemu/qemu/commit/e5f62d87e3c03bda6006085cf6303736fb57f5c5\n> \n> That is why this patch is  deliberately posted outside the v5 series.\n> It is more about future-proofing than a strict requirement. I thought it\n> was worth addressing while the context was fresh. I am happy to leave it\n> out if we prefer that.\n\nActually, go ahead. It's better than hard coding the size.\n\n> \n>>\n>>>\n>>> To support VM migration,\n>>> 1. Replace the static VMSTATE_BUFFER macro with pointer-based variant\n>>>      VMSTATE_BUFFER_POINTER_UNSAFE, explicitly mentioning the size.\n>>> 2. Introduce ext_buffer and ext_size in the migration subsection to\n>>>      track allocation exceeding TPM_TIS_BUFFER_MAX. Allocate ext_buffer\n>>>      using VMSTATE_VBUFFER_ALLOC_UINT32 only to be freed later after it is\n>>>      appended to the main buffer.\n>>>\n>>> This allows us to migrate to a destination host without breaking\n>>> backward compatibility. Old QEMU does not include a size field along\n>>> with the buffer in the migration stream, and therefore the\n>>> new QEMU is also forced to keep expecting exactly 4096 bytes.\n>>>\n>>> Implement a post_load hook that will validate the incoming data size\n>>> from the migration stream, failing the migration if it exceeds the\n>>> destination backend capacity. Add unrealize functions for the TIS interface\n>>> types ISA, SysBus and I2C to ensure that the buffer is safely freed on\n>>> device destruction.\n>>>\n>>> Signed-off-by: Arun Menon <armenon@redhat.com>\n>>> ---\n>>> Dependencies:\n>>> This patch depends on the following patch currently in the mailing list:\n>>> https://lore.kernel.org/qemu-devel/20260422103018.123608-10-armenon@redhat.com/\n>>\n>> I had tried to apply your v5 series to master but could not. Do you have a\n>> git repo where you keep your patches?\n> \n> Yes. Here is the repo: https://gitlab.com/armenon/qemu-dev/-/tree/pqc_tpm?ref_type=heads\n> I have applied the GByteArray change first, followed by the 10 commits.\n> \n>>\n>>>\n>>> Depends-on: <20260422103018.123608-10-armenon@redhat.com>\n>>>\n>>>    hw/tpm/tpm_tis.h        |  6 ++++-\n>>>    hw/tpm/tpm_tis_common.c | 56 +++++++++++++++++++++++++++++++++++------\n>>>    hw/tpm/tpm_tis_i2c.c    | 28 +++++++++++++++++++--\n>>>    hw/tpm/tpm_tis_isa.c    | 31 +++++++++++++++++++++--\n>>>    hw/tpm/tpm_tis_sysbus.c | 32 +++++++++++++++++++++--\n>>>    5 files changed, 138 insertions(+), 15 deletions(-)\n>>>\n>>> diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h\n>>> index b2d9c0116c..c736ecedc1 100644\n>>> --- a/hw/tpm/tpm_tis.h\n>>> +++ b/hw/tpm/tpm_tis.h\n>>> @@ -56,7 +56,9 @@ typedef struct TPMLocality {\n>>>    typedef struct TPMState {\n>>>        MemoryRegion mmio;\n>>> -    unsigned char buffer[TPM_TIS_BUFFER_MAX];\n>>> +    uint8_t *buffer;\n>>> +    uint8_t *ext_buffer;\n>>> +    uint32_t ext_size;\n>>>        uint16_t rw_offset;\n>>>        uint8_t active_locty;\n>>> @@ -82,6 +84,8 @@ extern const VMStateDescription vmstate_locty;\n>>>    extern const MemoryRegionOps tpm_tis_memory_ops;\n>>>    int tpm_tis_pre_save(TPMState *s);\n>>> +int tpm_tis_post_load(TPMState *s);\n>>> +int tpm_tis_ext_buffer_post_load(TPMState *s);\n>>>    void tpm_tis_reset(TPMState *s, bool ppi_enabled);\n>>>    enum TPMVersion tpm_tis_get_tpm_version(TPMState *s);\n>>>    void tpm_tis_request_completed(TPMState *s, int ret);\n>>> diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c\n>>> index 43e68410f8..c9c4dd1190 100644\n>>> --- a/hw/tpm/tpm_tis_common.c\n>>> +++ b/hw/tpm/tpm_tis_common.c\n>>> @@ -270,7 +270,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)\n>>>        uint16_t len;\n>>>        if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {\n>>> -        len = MIN(tpm_cmd_get_size(&s->buffer),\n>>> +        len = MIN(tpm_cmd_get_size(s->buffer),\n>>>                      s->be_buffer_size);\n>>>            ret = s->buffer[s->rw_offset++];\n>>> @@ -317,7 +317,7 @@ static void tpm_tis_dump_state(TPMState *s, hwaddr addr)\n>>>               \"tpm_tis: result buffer : \",\n>>>               s->rw_offset);\n>>>        for (idx = 0;\n>>> -         idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);\n>>> +         idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);\n>>>             idx++) {\n>>>            printf(\"%c%02x%s\",\n>>>                   s->rw_offset == idx ? '>' : ' ',\n>>> @@ -383,7 +383,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,\n>>>            if (s->active_locty == locty) {\n>>>                if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {\n>>>                    val = TPM_TIS_BURST_COUNT(\n>>> -                       MIN(tpm_cmd_get_size(&s->buffer),\n>>> +                       MIN(tpm_cmd_get_size(s->buffer),\n>>>                               s->be_buffer_size)\n>>>                           - s->rw_offset) | s->loc[locty].sts;\n>>>                } else {\n>>> @@ -754,7 +754,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,\n>>>                    /* we have a packet length - see if we have all of it */\n>>>                    bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID);\n>>> -                len = tpm_cmd_get_size(&s->buffer);\n>>> +                len = tpm_cmd_get_size(s->buffer);\n>>>                    if (len > s->rw_offset) {\n>>>                        tpm_tis_sts_set(&s->loc[locty],\n>>>                                        TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);\n>>> @@ -818,9 +818,10 @@ void tpm_tis_reset(TPMState *s, bool ppi_enabled)\n>>>        int c;\n>>>        s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);\n>>> -    s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),\n>>> -                            TPM_TIS_BUFFER_MAX);\n>>> +    s->be_buffer_size = tpm_backend_get_buffer_size(s->be_driver);\n>>> +    s->buffer = g_realloc(s->buffer, MAX(s->be_buffer_size,\n>>> +                          TPM_TIS_BUFFER_MAX));\n>>\n>> With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the backend says\n>> so -- hm...\n> \n> TPM_TIS_BUFFER_MAX is still 4096.\n\nOh, I had still based my patches on your TPM_TIS_BUFFER_MAX increase to \n8192 bytes. Let me fixes this along with a few other things. I will let \nyou know.\n\nI have another series that I will post now that can be applied to \nmaster. It's adding a test for TIS over I2C but I will need to extend \nthat one also with the large transfer test case then.","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256\n header.s=pp1 header.b=CT4dXg2X;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)"],"Received":["from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g4gTq3NMjz1xrS\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 22:58:21 +1000 (AEST)","from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wHi0S-0004s2-Ni; Tue, 28 Apr 2026 08:57:40 -0400","from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <stefanb@linux.ibm.com>)\n id 1wHi0Q-0004ru-Gy\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 08:57:38 -0400","from mx0a-001b2d01.pphosted.com ([148.163.156.1])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <stefanb@linux.ibm.com>)\n id 1wHi0O-0006lt-AI\n for qemu-devel@nongnu.org; Tue, 28 Apr 2026 08:57:38 -0400","from pps.filterd (m0356517.ppops.net [127.0.0.1])\n by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n 63S6ulRU2943552; Tue, 28 Apr 2026 12:57:34 GMT","from ppma11.dal12v.mail.ibm.com\n (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219])\n by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4drnb55h0m-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);\n Tue, 28 Apr 2026 12:57:33 +0000 (GMT)","from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1])\n by ppma11.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id\n 63SCcoS0012901;\n Tue, 28 Apr 2026 12:57:33 GMT","from smtprelay07.dal12v.mail.ibm.com ([172.16.1.9])\n by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4dsamy9g31-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT);\n Tue, 28 Apr 2026 12:57:33 +0000 (GMT)","from smtpav03.wdc07v.mail.ibm.com (smtpav03.wdc07v.mail.ibm.com\n [10.39.53.230])\n by smtprelay07.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id\n 63SCvWpB12124762\n (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK);\n Tue, 28 Apr 2026 12:57:32 GMT","from smtpav03.wdc07v.mail.ibm.com (unknown [127.0.0.1])\n by IMSVA (Postfix) with ESMTP id 4161858064;\n Tue, 28 Apr 2026 12:57:32 +0000 (GMT)","from smtpav03.wdc07v.mail.ibm.com (unknown [127.0.0.1])\n by IMSVA (Postfix) with ESMTP id DCB465805F;\n Tue, 28 Apr 2026 12:57:31 +0000 (GMT)","from [9.47.158.152] (unknown [9.47.158.152])\n by smtpav03.wdc07v.mail.ibm.com (Postfix) with ESMTP;\n Tue, 28 Apr 2026 12:57:31 +0000 (GMT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc\n :content-transfer-encoding:content-type:date:from:in-reply-to\n :message-id:mime-version:references:subject:to; s=pp1; bh=l3mQZj\n XC4YJigCUt2rxyN+JGJYonLurAvhVLeoJbD8Y=; b=CT4dXg2XebtfydV8D9C+v6\n E2uffpXdbjCl3n25YmCM8ydxQ/GPMlVoxgpW6l9oFovMXbpeOuuNW5SpIzCGvDvF\n Q85zJPdmvj6jMDXCaEegv0X+fiafowHZMS1YlYTBuunGN6sUVquF5qOXZR86ziJl\n Zm7d8t0aXqe9rUeIoQijoFntWE9qo9qhphFduHsgubFGnb7XEmbVjK+Ze9o0ywpk\n qbZpYYC4HwQkUu2TpWqQNcGkxYJbiFClN7whKX+20JXsxilHyQewz+1AVnKehE3M\n GoMU5hfaXxABQIdK00NbggAzdyWw2WCt8AXaSb6Ti1j8qmMmQ0FD9U+vpeRwoeDg\n ==","Message-ID":"<84607c2e-1da9-43d2-8a5b-e50e91c0f8ba@linux.ibm.com>","Date":"Tue, 28 Apr 2026 08:57:31 -0400","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer","To":"armenon@redhat.com","Cc":"qemu-devel@nongnu.org, Stefan Berger <stefanb@linux.vnet.ibm.com>","References":"<20260427200134.453022-1-armenon@redhat.com>\n <765f0577-ee8f-4944-93fe-bb93e420668f@linux.ibm.com>\n <afBbLDmdYFY5feJx@fedora>","Content-Language":"en-US","From":"Stefan Berger <stefanb@linux.ibm.com>","In-Reply-To":"<afBbLDmdYFY5feJx@fedora>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"7bit","X-TM-AS-GCONF":"00","X-Authority-Analysis":"v=2.4 cv=AqDeGu9P c=1 sm=1 tr=0 ts=69f0aebd cx=c_pps\n a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17\n a=IkcTkHD0fZMA:10 a=A5OVakUREuEA:10 a=VkNPw1HP01LnGYTKEx00:22\n a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=NEAV23lmAAAA:8\n a=VwQbUJbxAAAA:8 a=20KFwNOVAAAA:8 a=p0WdMEafAAAA:8 a=Veu011aRk9TlpGnrHNoA:9\n a=QEXdDO2ut3YA:10","X-Proofpoint-Spam-Details-Enc":"AW1haW4tMjYwNDI4MDExOCBTYWx0ZWRfX4TOUZ3zJUUrY\n O2Ymrbw4OuWQsARXNf4+4IIR+1nvIy6SDRJcePYatCLdoTXoqgGz0UyuME4LxI82hMViDaRR+TL\n vAiVDfmcl/8LTaBFnaGMaQNUjb1aDuBshy3wBWf149wylwFfbQD+qSyfyLej3IE2JdvJIRY4R0l\n LEJjLJvmZAN/3jic+Qxn9Mi3iJVKLA44dw7AXiMxHzcz2pPP2oJPgpcZcwFa8jJcu+JhNhzYAUG\n 2OyKLvmEQXZBxBgqOag88fPSdAUVmn//gVSmWBCeyxSaQh8rfANINpzWCXV9AaIrTr5ZK9WsJqM\n Z816FFpQYaT+l8pchCPs/O7hvBQN+qTOP7CsbY+tGY0vnQnwoM84/I79ov13/2dd9PyjkZu9PgR\n mJBIBphJdK95kMVe5QLlDTbQS58ck+3expU6q4vGaOlpmZKKdNy7p5a+3uI/sI1m/P4Dwjul3f+\n hQGfvbbPAB7xRBjUIPw==","X-Proofpoint-GUID":"mJAeKoQavfxzyWqSyUXnptNHVx9n_QSp","X-Proofpoint-ORIG-GUID":"mJAeKoQavfxzyWqSyUXnptNHVx9n_QSp","X-Proofpoint-Virus-Version":"vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-04-28_04,2026-04-28_01,2025-10-01_01","X-Proofpoint-Spam-Details":"rule=outbound_notspam policy=outbound score=0\n adultscore=0 priorityscore=1501 phishscore=0 suspectscore=0 clxscore=1015\n lowpriorityscore=0 spamscore=0 bulkscore=0 impostorscore=0 malwarescore=0\n classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0\n reason=mlx scancount=1 engine=8.22.0-2604200000 definitions=main-2604280118","Received-SPF":"pass client-ip=148.163.156.1;\n envelope-from=stefanb@linux.ibm.com;\n helo=mx0a-001b2d01.pphosted.com","X-Spam_score_int":"-26","X-Spam_score":"-2.7","X-Spam_bar":"--","X-Spam_report":"(-2.7 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7,\n RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no","X-Spam_action":"no action","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"qemu development <qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org"}}]