Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-05-04 Thread Stefan Berger




On 5/4/26 2:10 PM, Arun Menon wrote:

On Thu, Apr 30, 2026 at 04:43:27PM -0400, Stefan Berger wrote:



On 4/29/26 11:40 PM, Stefan Berger wrote:



On 4/29/26 4:07 PM, Arun Menon wrote:

Hi Stefan,

On Wed, Apr 29, 2026 at 02:15:16PM -0400, Stefan Berger wrote:



On 4/28/26 8:57 AM, Stefan Berger wrote:



On 4/28/26 3:01 AM, Arun Menon wrote:




With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the
backend says
so -- hm...


TPM_TIS_BUFFER_MAX is still 4096.


Oh, I had still based my patches on your TPM_TIS_BUFFER_MAX increase to
8192 bytes. Let me fixes this along with a few other things. I will let
you know.

I have another series that I will post now that can be applied to
master. It's adding a test for TIS over I2C but I will need to extend
that one also with the large transfer test case then.




So I have resolved this issue now along with a few other things.
My branch
is here: https://github.com/stefanberger/qemu-tpm/tree/work-tpm-for-11.1

- I have applied the i2c swtpm test case series first since it could be
easily upstreamed first
- Then your patch "migration/vmstate: Add VMState support for
GByteArray"
- Then the CRB chunk + TIS extended buffer support series. I modified my
patches (last 4 in that series) to
    - increased MAX_TIS_BUFFER_SIZE to 8192
    - added migration blockers dynamically for TIS whenever >4096
bytes are
either in the request or response; remove them later on again
when device
goes into ready state for example
    - added large transfer test also for i2c

Please pick up those patches for v6 posting, or otherwise you
can split your
v5 series up into CRB-only support for v6 and I post my (last 4) patches
later on.



Thank you. I agree. I will post v6 as CRB-only support. The GByteArray
patch is already accepted. The complex TIS changes can be posted
separately later.

Regarding the TIS buffer: I saw you implemented the migration blockers
and 8192-byte increase in your branch. Should I discard my


It's quite dynamic with the blocker being set when 4097 bytes of a TPM
command were received or when a TPM response with > 4096 bytes is
received. The blocker is removed when the device goes into ready state.
The intention is to allow a user to choose an old machine type with a
PQC-enabled swtpm+libtpms and be able to migrate to an older version of
QEMU unless the blocker was set. Correct me if I am wrong in my
thinking...


Another solution would be to limit the 8kb buffer to 4kb for 11.0 and older
machines.


Yes, I have limited this using the post_load hook for the extended part.

+int tpm_tis_ext_buffer_post_load(TPMState *s)
+{
+/*
+ * Calculate the maximum extension buffer size allowed, by comparing
+ * the destination VM's backend capacity with TPM_TIS_BUFFER_MAX.
+ */
+uint32_t max_ext = s->be_buffer_size > TPM_TIS_BUFFER_MAX ?
+   s->be_buffer_size - TPM_TIS_BUFFER_MAX : 0;
+
+if (s->ext_size > max_ext) {
+/*
+ * Source buffer size is greater than what the destination backend
+ * allows
+ */
+g_clear_pointer(&s->ext_buffer, g_free);
+return -EINVAL;
+}
+if (s->ext_size > 0) {
+memcpy(s->buffer + TPM_TIS_BUFFER_MAX, s->ext_buffer, s->ext_size);
+g_clear_pointer(&s->ext_buffer, g_free);
+}

We may use this patch in future if we want to change static to dynamic
buffer array allocation.


I posted now what I have beyond your v6 CRB patches and we can see in 
which order we want to switch to dynamically allocated buffers.





Regards,
Arun Menon







Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-05-04 Thread Arun Menon
On Thu, Apr 30, 2026 at 04:43:27PM -0400, Stefan Berger wrote:
> 
> 
> On 4/29/26 11:40 PM, Stefan Berger wrote:
> > 
> > 
> > On 4/29/26 4:07 PM, Arun Menon wrote:
> > > Hi Stefan,
> > > 
> > > On Wed, Apr 29, 2026 at 02:15:16PM -0400, Stefan Berger wrote:
> > > > 
> > > > 
> > > > On 4/28/26 8:57 AM, Stefan Berger wrote:
> > > > > 
> > > > > 
> > > > > On 4/28/26 3:01 AM, Arun Menon wrote:
> > > > 
> > > > > > > 
> > > > > > > With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the
> > > > > > > backend says
> > > > > > > so -- hm...
> > > > > > 
> > > > > > TPM_TIS_BUFFER_MAX is still 4096.
> > > > > 
> > > > > Oh, I had still based my patches on your TPM_TIS_BUFFER_MAX increase 
> > > > > to
> > > > > 8192 bytes. Let me fixes this along with a few other things. I will 
> > > > > let
> > > > > you know.
> > > > > 
> > > > > I have another series that I will post now that can be applied to
> > > > > master. It's adding a test for TIS over I2C but I will need to extend
> > > > > that one also with the large transfer test case then.
> > > > > 
> > > > > 
> > > > 
> > > > So I have resolved this issue now along with a few other things.
> > > > My branch
> > > > is here: https://github.com/stefanberger/qemu-tpm/tree/work-tpm-for-11.1
> > > > 
> > > > - I have applied the i2c swtpm test case series first since it could be
> > > > easily upstreamed first
> > > > - Then your patch "migration/vmstate: Add VMState support for
> > > > GByteArray"
> > > > - Then the CRB chunk + TIS extended buffer support series. I modified my
> > > > patches (last 4 in that series) to
> > > >    - increased MAX_TIS_BUFFER_SIZE to 8192
> > > >    - added migration blockers dynamically for TIS whenever >4096
> > > > bytes are
> > > > either in the request or response; remove them later on again
> > > > when device
> > > > goes into ready state for example
> > > >    - added large transfer test also for i2c
> > > > 
> > > > Please pick up those patches for v6 posting, or otherwise you
> > > > can split your
> > > > v5 series up into CRB-only support for v6 and I post my (last 4) patches
> > > > later on.
> > > > 
> > > 
> > > Thank you. I agree. I will post v6 as CRB-only support. The GByteArray
> > > patch is already accepted. The complex TIS changes can be posted
> > > separately later.
> > > 
> > > Regarding the TIS buffer: I saw you implemented the migration blockers
> > > and 8192-byte increase in your branch. Should I discard my
> > 
> > It's quite dynamic with the blocker being set when 4097 bytes of a TPM
> > command were received or when a TPM response with > 4096 bytes is
> > received. The blocker is removed when the device goes into ready state.
> > The intention is to allow a user to choose an old machine type with a
> > PQC-enabled swtpm+libtpms and be able to migrate to an older version of
> > QEMU unless the blocker was set. Correct me if I am wrong in my
> > thinking...
> 
> Another solution would be to limit the 8kb buffer to 4kb for 11.0 and older
> machines.

Yes, I have limited this using the post_load hook for the extended part.

+int tpm_tis_ext_buffer_post_load(TPMState *s)
+{
+/*
+ * Calculate the maximum extension buffer size allowed, by comparing
+ * the destination VM's backend capacity with TPM_TIS_BUFFER_MAX.
+ */
+uint32_t max_ext = s->be_buffer_size > TPM_TIS_BUFFER_MAX ?
+   s->be_buffer_size - TPM_TIS_BUFFER_MAX : 0;
+
+if (s->ext_size > max_ext) {
+/*
+ * Source buffer size is greater than what the destination backend
+ * allows
+ */
+g_clear_pointer(&s->ext_buffer, g_free);
+return -EINVAL;
+}
+if (s->ext_size > 0) {
+memcpy(s->buffer + TPM_TIS_BUFFER_MAX, s->ext_buffer, s->ext_size);
+g_clear_pointer(&s->ext_buffer, g_free);
+}

We may use this patch in future if we want to change static to dynamic
buffer array allocation.


Regards,
Arun Menon




Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-04-30 Thread Stefan Berger




On 4/29/26 11:40 PM, Stefan Berger wrote:



On 4/29/26 4:07 PM, Arun Menon wrote:

Hi Stefan,

On Wed, Apr 29, 2026 at 02:15:16PM -0400, Stefan Berger wrote:



On 4/28/26 8:57 AM, Stefan Berger wrote:



On 4/28/26 3:01 AM, Arun Menon wrote:




With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the
backend says
so -- hm...


TPM_TIS_BUFFER_MAX is still 4096.


Oh, I had still based my patches on your TPM_TIS_BUFFER_MAX increase to
8192 bytes. Let me fixes this along with a few other things. I will let
you know.

I have another series that I will post now that can be applied to
master. It's adding a test for TIS over I2C but I will need to extend
that one also with the large transfer test case then.




So I have resolved this issue now along with a few other things. My 
branch

is here: https://github.com/stefanberger/qemu-tpm/tree/work-tpm-for-11.1

- I have applied the i2c swtpm test case series first since it could be
easily upstreamed first
- Then your patch "migration/vmstate: Add VMState support for 
GByteArray"

- Then the CRB chunk + TIS extended buffer support series. I modified my
patches (last 4 in that series) to
   - increased MAX_TIS_BUFFER_SIZE to 8192
   - added migration blockers dynamically for TIS whenever >4096 
bytes are
either in the request or response; remove them later on again when 
device

goes into ready state for example
   - added large transfer test also for i2c

Please pick up those patches for v6 posting, or otherwise you can 
split your

v5 series up into CRB-only support for v6 and I post my (last 4) patches
later on.



Thank you. I agree. I will post v6 as CRB-only support. The GByteArray
patch is already accepted. The complex TIS changes can be posted
separately later.

Regarding the TIS buffer: I saw you implemented the migration blockers
and 8192-byte increase in your branch. Should I discard my


It's quite dynamic with the blocker being set when 4097 bytes of a TPM 
command were received or when a TPM response with > 4096 bytes is 
received. The blocker is removed when the device goes into ready state. 
The intention is to allow a user to choose an old machine type with a 
PQC-enabled swtpm+libtpms and be able to migrate to an older version of 
QEMU unless the blocker was set. Correct me if I am wrong in my thinking...


Another solution would be to limit the 8kb buffer to 4kb for 11.0 and 
older machines.





Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-04-29 Thread Stefan Berger




On 4/29/26 4:07 PM, Arun Menon wrote:

Hi Stefan,

On Wed, Apr 29, 2026 at 02:15:16PM -0400, Stefan Berger wrote:



On 4/28/26 8:57 AM, Stefan Berger wrote:



On 4/28/26 3:01 AM, Arun Menon wrote:




With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the
backend says
so -- hm...


TPM_TIS_BUFFER_MAX is still 4096.


Oh, I had still based my patches on your TPM_TIS_BUFFER_MAX increase to
8192 bytes. Let me fixes this along with a few other things. I will let
you know.

I have another series that I will post now that can be applied to
master. It's adding a test for TIS over I2C but I will need to extend
that one also with the large transfer test case then.




So I have resolved this issue now along with a few other things. My branch
is here: https://github.com/stefanberger/qemu-tpm/tree/work-tpm-for-11.1

- I have applied the i2c swtpm test case series first since it could be
easily upstreamed first
- Then your patch "migration/vmstate: Add VMState support for GByteArray"
- Then the CRB chunk + TIS extended buffer support series. I modified my
patches (last 4 in that series) to
   - increased MAX_TIS_BUFFER_SIZE to 8192
   - added migration blockers dynamically for TIS whenever >4096 bytes are
either in the request or response; remove them later on again when device
goes into ready state for example
   - added large transfer test also for i2c

Please pick up those patches for v6 posting, or otherwise you can split your
v5 series up into CRB-only support for v6 and I post my (last 4) patches
later on.



Thank you. I agree. I will post v6 as CRB-only support. The GByteArray
patch is already accepted. The complex TIS changes can be posted
separately later.

Regarding the TIS buffer: I saw you implemented the migration blockers
and 8192-byte increase in your branch. Should I discard my


It's quite dynamic with the blocker being set when 4097 bytes of a TPM 
command were received or when a TPM response with > 4096 bytes is 
received. The blocker is removed when the device goes into ready state. 
The intention is to allow a user to choose an old machine type with a 
PQC-enabled swtpm+libtpms and be able to migrate to an older version of 
QEMU unless the blocker was set. Correct me if I am wrong in my thinking...



'Dynamically allocate tpm-tis buffer' patch entirely, or do you want to
try and adapt that logic into your TIS follow-up series later?



It may be good to have a dynamically allocate tpm-tis buffer for future 
proofing the TIS, though it would have to support saving a range of the 
bytes in this buffer -- like 1:1 replacement using GByteArray for the 
VMSTATE_PARTIAL_BUFFER and VMSTATE_BUFFER_START_MIDDLE that I am using now.



Since your new migration blockers are based on the 4096/8192 threshold,
it might be simpler to stick with the static approach for now, but let

> me know what you prefer.

It would still be good not to have to worry about buffer size increases 
anymore...





Regards,
Arun Menon










Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-04-29 Thread Arun Menon
Hi Stefan,

On Wed, Apr 29, 2026 at 02:15:16PM -0400, Stefan Berger wrote:
> 
> 
> On 4/28/26 8:57 AM, Stefan Berger wrote:
> > 
> > 
> > On 4/28/26 3:01 AM, Arun Menon wrote:
> 
> > > > 
> > > > With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the
> > > > backend says
> > > > so -- hm...
> > > 
> > > TPM_TIS_BUFFER_MAX is still 4096.
> > 
> > Oh, I had still based my patches on your TPM_TIS_BUFFER_MAX increase to
> > 8192 bytes. Let me fixes this along with a few other things. I will let
> > you know.
> > 
> > I have another series that I will post now that can be applied to
> > master. It's adding a test for TIS over I2C but I will need to extend
> > that one also with the large transfer test case then.
> > 
> > 
> 
> So I have resolved this issue now along with a few other things. My branch
> is here: https://github.com/stefanberger/qemu-tpm/tree/work-tpm-for-11.1
> 
> - I have applied the i2c swtpm test case series first since it could be
> easily upstreamed first
> - Then your patch "migration/vmstate: Add VMState support for GByteArray"
> - Then the CRB chunk + TIS extended buffer support series. I modified my
> patches (last 4 in that series) to
>   - increased MAX_TIS_BUFFER_SIZE to 8192
>   - added migration blockers dynamically for TIS whenever >4096 bytes are
> either in the request or response; remove them later on again when device
> goes into ready state for example
>   - added large transfer test also for i2c
> 
> Please pick up those patches for v6 posting, or otherwise you can split your
> v5 series up into CRB-only support for v6 and I post my (last 4) patches
> later on.
>

Thank you. I agree. I will post v6 as CRB-only support. The GByteArray
patch is already accepted. The complex TIS changes can be posted
separately later.

Regarding the TIS buffer: I saw you implemented the migration blockers
and 8192-byte increase in your branch. Should I discard my
'Dynamically allocate tpm-tis buffer' patch entirely, or do you want to
try and adapt that logic into your TIS follow-up series later?

Since your new migration blockers are based on the 4096/8192 threshold,
it might be simpler to stick with the static approach for now, but let
me know what you prefer.


Regards,
Arun Menon

> 




Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-04-29 Thread Stefan Berger




On 4/28/26 8:57 AM, Stefan Berger wrote:



On 4/28/26 3:01 AM, Arun Menon wrote:




With MAX() it can now be bigger than TPM_TIS_BUFFER_MAX if the 
backend says

so -- hm...


TPM_TIS_BUFFER_MAX is still 4096.


Oh, I had still based my patches on your TPM_TIS_BUFFER_MAX increase to 
8192 bytes. Let me fixes this along with a few other things. I will let 
you know.


I have another series that I will post now that can be applied to 
master. It's adding a test for TIS over I2C but I will need to extend 
that one also with the large transfer test case then.





So I have resolved this issue now along with a few other things. My 
branch is here: 
https://github.com/stefanberger/qemu-tpm/tree/work-tpm-for-11.1


- I have applied the i2c swtpm test case series first since it could be 
easily upstreamed first

- Then your patch "migration/vmstate: Add VMState support for GByteArray"
- Then the CRB chunk + TIS extended buffer support series. I modified my 
patches (last 4 in that series) to

  - increased MAX_TIS_BUFFER_SIZE to 8192
  - added migration blockers dynamically for TIS whenever >4096 bytes 
are either in the request or response; remove them later on again when 
device goes into ready state for example

  - added large transfer test also for i2c

Please pick up those patches for v6 posting, or otherwise you can split 
your v5 series up into CRB-only support for v6 and I post my (last 4) 
patches later on.





Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-04-28 Thread Stefan Berger




On 4/28/26 3:01 AM, Arun Menon wrote:

Hi Stefan,

Thank you for taking a look.

On Mon, Apr 27, 2026 at 04:49:04PM -0400, Stefan Berger wrote:



On 4/27/26 4:01 PM, Arun Menon wrote:

From: Arun Menon 

The TPM TIS buffer is currently a fixed-size static array. Change this
to a dynamically allocated heap block. The buffer size is now determined
at runtime by querying the TPM backend.


Do we really need this? I mean for the forseeable future 8kb should be
sufficient.


You are right that 8kb should be sufficient.
I implemented this to address the TODO mentioned here:
https://github.com/qemu/qemu/commit/e5f62d87e3c03bda6006085cf6303736fb57f5c5

That is why this patch is  deliberately posted outside the v5 series.
It is more about future-proofing than a strict requirement. I thought it
was worth addressing while the context was fresh. I am happy to leave it
out if we prefer that.


Actually, go ahead. It's better than hard coding the size.







To support VM migration,
1. Replace the static VMSTATE_BUFFER macro with pointer-based variant
 VMSTATE_BUFFER_POINTER_UNSAFE, explicitly mentioning the size.
2. Introduce ext_buffer and ext_size in the migration subsection to
 track allocation exceeding TPM_TIS_BUFFER_MAX. Allocate ext_buffer
 using VMSTATE_VBUFFER_ALLOC_UINT32 only to be freed later after it is
 appended to the main buffer.

This allows us to migrate to a destination host without breaking
backward compatibility. Old QEMU does not include a size field along
with the buffer in the migration stream, and therefore the
new QEMU is also forced to keep expecting exactly 4096 bytes.

Implement a post_load hook that will validate the incoming data size
from the migration stream, failing the migration if it exceeds the
destination backend capacity. Add unrealize functions for the TIS interface
types ISA, SysBus and I2C to ensure that the buffer is safely freed on
device destruction.

Signed-off-by: Arun Menon 
---
Dependencies:
This patch depends on the following patch currently in the mailing list:
https://lore.kernel.org/qemu-devel/[email protected]/


I had tried to apply your v5 series to master but could not. Do you have a
git repo where you keep your patches?


Yes. Here is the repo: 
https://gitlab.com/armenon/qemu-dev/-/tree/pqc_tpm?ref_type=heads
I have applied the GByteArray change first, followed by the 10 commits.





Depends-on: <[email protected]>

   hw/tpm/tpm_tis.h|  6 -
   hw/tpm/tpm_tis_common.c | 56 +++--
   hw/tpm/tpm_tis_i2c.c| 28 +++--
   hw/tpm/tpm_tis_isa.c| 31 +--
   hw/tpm/tpm_tis_sysbus.c | 32 +--
   5 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h
index b2d9c0116c..c736ecedc1 100644
--- a/hw/tpm/tpm_tis.h
+++ b/hw/tpm/tpm_tis.h
@@ -56,7 +56,9 @@ typedef struct TPMLocality {
   typedef struct TPMState {
   MemoryRegion mmio;
-unsigned char buffer[TPM_TIS_BUFFER_MAX];
+uint8_t *buffer;
+uint8_t *ext_buffer;
+uint32_t ext_size;
   uint16_t rw_offset;
   uint8_t active_locty;
@@ -82,6 +84,8 @@ extern const VMStateDescription vmstate_locty;
   extern const MemoryRegionOps tpm_tis_memory_ops;
   int tpm_tis_pre_save(TPMState *s);
+int tpm_tis_post_load(TPMState *s);
+int tpm_tis_ext_buffer_post_load(TPMState *s);
   void tpm_tis_reset(TPMState *s, bool ppi_enabled);
   enum TPMVersion tpm_tis_get_tpm_version(TPMState *s);
   void tpm_tis_request_completed(TPMState *s, int ret);
diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
index 43e68410f8..c9c4dd1190 100644
--- a/hw/tpm/tpm_tis_common.c
+++ b/hw/tpm/tpm_tis_common.c
@@ -270,7 +270,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t 
locty)
   uint16_t len;
   if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
-len = MIN(tpm_cmd_get_size(&s->buffer),
+len = MIN(tpm_cmd_get_size(s->buffer),
 s->be_buffer_size);
   ret = s->buffer[s->rw_offset++];
@@ -317,7 +317,7 @@ static void tpm_tis_dump_state(TPMState *s, hwaddr addr)
  "tpm_tis: result buffer : ",
  s->rw_offset);
   for (idx = 0;
- idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);
+ idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);
idx++) {
   printf("%c%02x%s",
  s->rw_offset == idx ? '>' : ' ',
@@ -383,7 +383,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
   if (s->active_locty == locty) {
   if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
   val = TPM_TIS_BURST_COUNT(
-   MIN(tpm_cmd_get_size(&s->buffer),
+   MIN(tpm_cmd_get_size(s->buffer),
  s->be_buffer_size)
  - s->rw_offset) | s-

Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-04-28 Thread Arun Menon
Hi Stefan,

Thank you for taking a look.

On Mon, Apr 27, 2026 at 04:49:04PM -0400, Stefan Berger wrote:
> 
> 
> On 4/27/26 4:01 PM, Arun Menon wrote:
> > From: Arun Menon 
> > 
> > The TPM TIS buffer is currently a fixed-size static array. Change this
> > to a dynamically allocated heap block. The buffer size is now determined
> > at runtime by querying the TPM backend.
> 
> Do we really need this? I mean for the forseeable future 8kb should be
> sufficient.

You are right that 8kb should be sufficient.
I implemented this to address the TODO mentioned here:
https://github.com/qemu/qemu/commit/e5f62d87e3c03bda6006085cf6303736fb57f5c5

That is why this patch is  deliberately posted outside the v5 series.
It is more about future-proofing than a strict requirement. I thought it
was worth addressing while the context was fresh. I am happy to leave it
out if we prefer that.

> 
> > 
> > To support VM migration,
> > 1. Replace the static VMSTATE_BUFFER macro with pointer-based variant
> > VMSTATE_BUFFER_POINTER_UNSAFE, explicitly mentioning the size.
> > 2. Introduce ext_buffer and ext_size in the migration subsection to
> > track allocation exceeding TPM_TIS_BUFFER_MAX. Allocate ext_buffer
> > using VMSTATE_VBUFFER_ALLOC_UINT32 only to be freed later after it is
> > appended to the main buffer.
> > 
> > This allows us to migrate to a destination host without breaking
> > backward compatibility. Old QEMU does not include a size field along
> > with the buffer in the migration stream, and therefore the
> > new QEMU is also forced to keep expecting exactly 4096 bytes.
> > 
> > Implement a post_load hook that will validate the incoming data size
> > from the migration stream, failing the migration if it exceeds the
> > destination backend capacity. Add unrealize functions for the TIS interface
> > types ISA, SysBus and I2C to ensure that the buffer is safely freed on
> > device destruction.
> > 
> > Signed-off-by: Arun Menon 
> > ---
> > Dependencies:
> > This patch depends on the following patch currently in the mailing list:
> > https://lore.kernel.org/qemu-devel/[email protected]/
> 
> I had tried to apply your v5 series to master but could not. Do you have a
> git repo where you keep your patches?

Yes. Here is the repo: 
https://gitlab.com/armenon/qemu-dev/-/tree/pqc_tpm?ref_type=heads
I have applied the GByteArray change first, followed by the 10 commits.

> 
> > 
> > Depends-on: <[email protected]>
> > 
> >   hw/tpm/tpm_tis.h|  6 -
> >   hw/tpm/tpm_tis_common.c | 56 +++--
> >   hw/tpm/tpm_tis_i2c.c| 28 +++--
> >   hw/tpm/tpm_tis_isa.c| 31 +--
> >   hw/tpm/tpm_tis_sysbus.c | 32 +--
> >   5 files changed, 138 insertions(+), 15 deletions(-)
> > 
> > diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h
> > index b2d9c0116c..c736ecedc1 100644
> > --- a/hw/tpm/tpm_tis.h
> > +++ b/hw/tpm/tpm_tis.h
> > @@ -56,7 +56,9 @@ typedef struct TPMLocality {
> >   typedef struct TPMState {
> >   MemoryRegion mmio;
> > -unsigned char buffer[TPM_TIS_BUFFER_MAX];
> > +uint8_t *buffer;
> > +uint8_t *ext_buffer;
> > +uint32_t ext_size;
> >   uint16_t rw_offset;
> >   uint8_t active_locty;
> > @@ -82,6 +84,8 @@ extern const VMStateDescription vmstate_locty;
> >   extern const MemoryRegionOps tpm_tis_memory_ops;
> >   int tpm_tis_pre_save(TPMState *s);
> > +int tpm_tis_post_load(TPMState *s);
> > +int tpm_tis_ext_buffer_post_load(TPMState *s);
> >   void tpm_tis_reset(TPMState *s, bool ppi_enabled);
> >   enum TPMVersion tpm_tis_get_tpm_version(TPMState *s);
> >   void tpm_tis_request_completed(TPMState *s, int ret);
> > diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
> > index 43e68410f8..c9c4dd1190 100644
> > --- a/hw/tpm/tpm_tis_common.c
> > +++ b/hw/tpm/tpm_tis_common.c
> > @@ -270,7 +270,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t 
> > locty)
> >   uint16_t len;
> >   if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
> > -len = MIN(tpm_cmd_get_size(&s->buffer),
> > +len = MIN(tpm_cmd_get_size(s->buffer),
> > s->be_buffer_size);
> >   ret = s->buffer[s->rw_offset++];
> > @@ -317,7 +317,7 @@ static void tpm_tis_dump_state(TPMState *s, hwaddr addr)
> >  "tpm_tis: result buffer : ",
> >  s->rw_offset);
> >   for (idx = 0;
> > - idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);
> > + idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);
> >idx++) {
> >   printf("%c%02x%s",
> >  s->rw_offset == idx ? '>' : ' ',
> > @@ -383,7 +383,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr 
> > addr,
> >   if (s->active_locty == locty) {
> >   if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
> >   val = TPM_TIS_

Re: [PATCH] tpm: Dynamically allocate tpm-tis buffer

2026-04-27 Thread Stefan Berger




On 4/27/26 4:01 PM, Arun Menon wrote:

From: Arun Menon 

The TPM TIS buffer is currently a fixed-size static array. Change this
to a dynamically allocated heap block. The buffer size is now determined
at runtime by querying the TPM backend.


Do we really need this? I mean for the forseeable future 8kb should be 
sufficient.




To support VM migration,
1. Replace the static VMSTATE_BUFFER macro with pointer-based variant
VMSTATE_BUFFER_POINTER_UNSAFE, explicitly mentioning the size.
2. Introduce ext_buffer and ext_size in the migration subsection to
track allocation exceeding TPM_TIS_BUFFER_MAX. Allocate ext_buffer
using VMSTATE_VBUFFER_ALLOC_UINT32 only to be freed later after it is
appended to the main buffer.

This allows us to migrate to a destination host without breaking
backward compatibility. Old QEMU does not include a size field along
with the buffer in the migration stream, and therefore the
new QEMU is also forced to keep expecting exactly 4096 bytes.

Implement a post_load hook that will validate the incoming data size
from the migration stream, failing the migration if it exceeds the
destination backend capacity. Add unrealize functions for the TIS interface
types ISA, SysBus and I2C to ensure that the buffer is safely freed on
device destruction.

Signed-off-by: Arun Menon 
---
Dependencies:
This patch depends on the following patch currently in the mailing list:
https://lore.kernel.org/qemu-devel/[email protected]/


I had tried to apply your v5 series to master but could not. Do you have 
a git repo where you keep your patches?




Depends-on: <[email protected]>

  hw/tpm/tpm_tis.h|  6 -
  hw/tpm/tpm_tis_common.c | 56 +++--
  hw/tpm/tpm_tis_i2c.c| 28 +++--
  hw/tpm/tpm_tis_isa.c| 31 +--
  hw/tpm/tpm_tis_sysbus.c | 32 +--
  5 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h
index b2d9c0116c..c736ecedc1 100644
--- a/hw/tpm/tpm_tis.h
+++ b/hw/tpm/tpm_tis.h
@@ -56,7 +56,9 @@ typedef struct TPMLocality {
  typedef struct TPMState {
  MemoryRegion mmio;
  
-unsigned char buffer[TPM_TIS_BUFFER_MAX];

+uint8_t *buffer;
+uint8_t *ext_buffer;
+uint32_t ext_size;
  uint16_t rw_offset;
  
  uint8_t active_locty;

@@ -82,6 +84,8 @@ extern const VMStateDescription vmstate_locty;
  extern const MemoryRegionOps tpm_tis_memory_ops;
  
  int tpm_tis_pre_save(TPMState *s);

+int tpm_tis_post_load(TPMState *s);
+int tpm_tis_ext_buffer_post_load(TPMState *s);
  void tpm_tis_reset(TPMState *s, bool ppi_enabled);
  enum TPMVersion tpm_tis_get_tpm_version(TPMState *s);
  void tpm_tis_request_completed(TPMState *s, int ret);
diff --git a/hw/tpm/tpm_tis_common.c b/hw/tpm/tpm_tis_common.c
index 43e68410f8..c9c4dd1190 100644
--- a/hw/tpm/tpm_tis_common.c
+++ b/hw/tpm/tpm_tis_common.c
@@ -270,7 +270,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t 
locty)
  uint16_t len;
  
  if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {

-len = MIN(tpm_cmd_get_size(&s->buffer),
+len = MIN(tpm_cmd_get_size(s->buffer),
s->be_buffer_size);
  
  ret = s->buffer[s->rw_offset++];

@@ -317,7 +317,7 @@ static void tpm_tis_dump_state(TPMState *s, hwaddr addr)
 "tpm_tis: result buffer : ",
 s->rw_offset);
  for (idx = 0;
- idx < MIN(tpm_cmd_get_size(&s->buffer), s->be_buffer_size);
+ idx < MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);
   idx++) {
  printf("%c%02x%s",
 s->rw_offset == idx ? '>' : ' ',
@@ -383,7 +383,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
  if (s->active_locty == locty) {
  if ((s->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
  val = TPM_TIS_BURST_COUNT(
-   MIN(tpm_cmd_get_size(&s->buffer),
+   MIN(tpm_cmd_get_size(s->buffer),
 s->be_buffer_size)
 - s->rw_offset) | s->loc[locty].sts;
  } else {
@@ -754,7 +754,7 @@ static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
  /* we have a packet length - see if we have all of it */
  bool need_irq = !(s->loc[locty].sts & TPM_TIS_STS_VALID);
  
-len = tpm_cmd_get_size(&s->buffer);

+len = tpm_cmd_get_size(s->buffer);
  if (len > s->rw_offset) {
  tpm_tis_sts_set(&s->loc[locty],
  TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
@@ -818,9 +818,10 @@ void tpm_tis_reset(TPMState *s, bool ppi_enabled)
  int c;
  
  s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);

-s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),
-