Commit 29315d22b2 for qemu.org

commit 29315d22b25930692b21f76b8c71910196bf960b
Author: Arun Menon <armenon@redhat.com>
Date:   Wed May 6 13:28:10 2026 +0530

    hw/tpm: Add internal buffer state for chunking

    - Introduce GByteArray buffers to hold the command request and response
      data during chunked TPM CRB transactions.
    - Add helper function to clean them.

    Signed-off-by: Arun Menon <armenon@redhat.com>
    Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
    Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
    Link: https://lore.kernel.org/qemu-devel/20260506075813.120781-4-armenon@redhat.com
    Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>

diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index a0f472652e..1c944d7ef2 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -38,10 +38,13 @@ struct CRBState {
     TPMBackend *tpmbe;
     TPMBackendCmd cmd;
     uint32_t regs[TPM_CRB_R_MAX];
+    size_t be_buffer_size;
     MemoryRegion mmio;
     MemoryRegion cmdmem;

-    size_t be_buffer_size;
+    GByteArray *command_buffer;
+    GByteArray *response_buffer;
+    uint32_t response_offset;

     TPMPPI ppi;

@@ -86,6 +89,13 @@ enum crb_cancel {

 #define TPM_CRB_NO_LOCALITY 0xff

+static void tpm_crb_clear_internal_buffers(CRBState *s)
+{
+    g_byte_array_set_size(s->response_buffer, 0);
+    g_byte_array_set_size(s->command_buffer, 0);
+    s->response_offset = 0;
+}
+
 static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
                                   unsigned size)
 {
@@ -135,9 +145,11 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
         }
         break;
     case A_CRB_CTRL_CANCEL:
-        if (val == CRB_CANCEL_INVOKE &&
-            s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
-            tpm_backend_cancel_cmd(s->tpmbe);
+        if (val == CRB_CANCEL_INVOKE) {
+            if (s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
+                tpm_backend_cancel_cmd(s->tpmbe);
+            }
+            tpm_crb_clear_internal_buffers(s);
         }
         break;
     case A_CRB_CTRL_START:
@@ -239,6 +251,7 @@ static void tpm_crb_reset(void *dev)

     tpm_ppi_reset(&s->ppi);
     tpm_backend_reset(s->tpmbe);
+    tpm_crb_clear_internal_buffers(s);

     memset(s->regs, 0, sizeof(s->regs));

@@ -305,6 +318,9 @@ static void tpm_crb_realize(DeviceState *dev, Error **errp)
     memory_region_add_subregion(get_system_memory(),
         TPM_CRB_ADDR_BASE + sizeof(s->regs), &s->cmdmem);

+    s->command_buffer = g_byte_array_new();
+    s->response_buffer = g_byte_array_new();
+
     tpm_ppi_init(&s->ppi, get_system_memory(),
                  TPM_PPI_ADDR_BASE, OBJECT(s));

@@ -315,12 +331,21 @@ static void tpm_crb_realize(DeviceState *dev, Error **errp)
     }
 }

+static void tpm_crb_unrealize(DeviceState *dev)
+{
+    CRBState *s = CRB(dev);
+
+    g_clear_pointer(&s->command_buffer, g_byte_array_unref);
+    g_clear_pointer(&s->response_buffer, g_byte_array_unref);
+}
+
 static void tpm_crb_class_init(ObjectClass *klass, const void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     TPMIfClass *tc = TPM_IF_CLASS(klass);

     dc->realize = tpm_crb_realize;
+    dc->unrealize = tpm_crb_unrealize;
     device_class_set_props(dc, tpm_crb_properties);
     dc->vmsd  = &vmstate_tpm_crb;
     dc->user_creatable = true;