Re: [PATCH v5 12/14] tests: acpi: implement TPM CRB tests for ARM virt

2023-11-24 Thread Joelle van Dyne
On Fri, Nov 24, 2023 at 8:26 AM Stefan Berger  wrote:
>
>
>
> On 11/24/23 11:21, Joelle van Dyne wrote:
> > On Fri, Nov 24, 2023 at 8:17 AM Stefan Berger  wrote:
> >>
> >>
> >>
> >> On 11/23/23 19:56, Joelle van Dyne wrote:
> >>> On Tue, Nov 14, 2023 at 4:12 PM Stefan Berger  
> >>> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 11/14/23 16:05, Stefan Berger wrote:
> >>>>>
> >>>>>
> >>>>> On 11/14/23 13:03, Stefan Berger wrote:
> >>>>>>
> >>>>>>
> >>>>>> On 11/14/23 04:36, Marc-André Lureau wrote:
> >>>>>>> Hi
> >>>>>>>
> >>>>>>> On Tue, Nov 14, 2023 at 6:12 AM Joelle van Dyne  
> >>>>>>> wrote:
> >>>>>>>>
> >>>>>>>> Signed-off-by: Joelle van Dyne 
> >>>>>>>> Reviewed-by: Stefan Berger 
> >>>>>>>
> >>>>>>> nit: you also added tests for x86, could be a different patch?
> >>>>>>>
> >>>>>>> For arm, the test fails until next patch with:
> >>>>>>>
> >>>>>>> # starting QEMU: exec ./qemu-system-aarch64 -qtest
> >>>>>>> unix:/tmp/qtest-991279.sock -qtest-log /dev/null -chardev
> >>>>>>> socket,path=/tmp/qtest-991279.qmp,id=char0 -mon
> >>>>>>> chardev=char0,mode=control -display none -audio none -machine virt
> >>>>>>> -accel tcg -nodefaults -nographic -drive
> >>>>>>> if=pflash,format=raw,file=pc-bios/edk2-aarch64-code.fd,readonly=on
> >>>>>>> -drive if=pflash,format=raw,file=pc-bios/edk2-arm-vars.fd,snapshot=on
> >>>>>>> -cdrom tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2
> >>>>>>> -cpu cortex-a57 -chardev
> >>>>>>> socket,id=chr,path=/tmp/qemu-test_acpi_virt_tcg_crb-device.KZ3GE2/sock
> >>>>>>> -tpmdev emulator,id=dev,chardev=chr -device tpm-crb-device,tpmdev=dev
> >>>>>>> -accel qtest
> >>>>>>> Warning! zero length expected file
> >>>>>>> 'tests/data/acpi/virt/TPM2.crb-device.tpm2'
> >>>>>>> Warning! zero length expected file
> >>>>>>> 'tests/data/acpi/virt/DSDT.crb-device.tpm2'
> >>>>>>> acpi-test: Warning!  binary file mismatch. Actual
> >>>>>>> [aml:/tmp/aml-GO4ME2], Expected
> >>>>>>> [aml:tests/data/acpi/virt/TPM2.crb-device.tpm2].
> >>>>>>> See source file tests/qtest/bios-tables-test.c for instructions on how
> >>>>>>> to update expected files.
> >>>>>>> acpi-test: Warning!  binary file mismatch. Actual
> >>>>>>> [aml:/tmp/aml-6N4ME2], Expected
> >>>>>>> [aml:tests/data/acpi/virt/DSDT.crb-device.tpm2].
> >>>>>>> See source file tests/qtest/bios-tables-test.c for instructions on how
> >>>>>>> to update expected files.
> >>>>>>> to see ASL diff between mismatched files install IASL, rebuild QEMU
> >>>>>>> from scratch and re-run tests with V=1 environment variable set**
> >>>>>>> ERROR:../tests/qtest/bios-tables-test.c:538:test_acpi_asl: assertion
> >>>>>>> failed: (all_tables_match)
> >>>>>>> not ok /aarch64/acpi/virt/tpm2-crb -
> >>>>>>> ERROR:../tests/qtest/bios-tables-test.c:538:test_acpi_asl: assertion
> >>>>>>> failed: (all_tables_match)
> >>>>>>> Bail out!
> >>>>>>> qemu-system-aarch64: tpm-emulator: Could not cleanly shutdown the TPM:
> >>>>>>> Resource temporarily unavailable
> >>>>>>> Unexpected error in qio_channel_socket_writev() at
> >>>>>>> ../io/channel-socket.c:622:
> >>>>>>> /home/elmarco/src/qemu/buildall/tests/qtest/bios-tables-test: Unable
> >>>>>>> to write to socket: Bad file descriptor
> >>>>>>>
> >>>>>>
> >>>>>> Travis testing on s390x I see the following failures for this patchset
> >>>>>> (search for 'ERROR'):
> >>>>>>
> >>>>>> https://app.travis-ci.com/g

Re: [PATCH v5 12/14] tests: acpi: implement TPM CRB tests for ARM virt

2023-11-24 Thread Joelle van Dyne
On Fri, Nov 24, 2023 at 8:17 AM Stefan Berger  wrote:
>
>
>
> On 11/23/23 19:56, Joelle van Dyne wrote:
> > On Tue, Nov 14, 2023 at 4:12 PM Stefan Berger  wrote:
> >>
> >>
> >>
> >> On 11/14/23 16:05, Stefan Berger wrote:
> >>>
> >>>
> >>> On 11/14/23 13:03, Stefan Berger wrote:
> >>>>
> >>>>
> >>>> On 11/14/23 04:36, Marc-André Lureau wrote:
> >>>>> Hi
> >>>>>
> >>>>> On Tue, Nov 14, 2023 at 6:12 AM Joelle van Dyne  wrote:
> >>>>>>
> >>>>>> Signed-off-by: Joelle van Dyne 
> >>>>>> Reviewed-by: Stefan Berger 
> >>>>>
> >>>>> nit: you also added tests for x86, could be a different patch?
> >>>>>
> >>>>> For arm, the test fails until next patch with:
> >>>>>
> >>>>> # starting QEMU: exec ./qemu-system-aarch64 -qtest
> >>>>> unix:/tmp/qtest-991279.sock -qtest-log /dev/null -chardev
> >>>>> socket,path=/tmp/qtest-991279.qmp,id=char0 -mon
> >>>>> chardev=char0,mode=control -display none -audio none -machine virt
> >>>>> -accel tcg -nodefaults -nographic -drive
> >>>>> if=pflash,format=raw,file=pc-bios/edk2-aarch64-code.fd,readonly=on
> >>>>> -drive if=pflash,format=raw,file=pc-bios/edk2-arm-vars.fd,snapshot=on
> >>>>> -cdrom tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2
> >>>>> -cpu cortex-a57 -chardev
> >>>>> socket,id=chr,path=/tmp/qemu-test_acpi_virt_tcg_crb-device.KZ3GE2/sock
> >>>>> -tpmdev emulator,id=dev,chardev=chr -device tpm-crb-device,tpmdev=dev
> >>>>> -accel qtest
> >>>>> Warning! zero length expected file
> >>>>> 'tests/data/acpi/virt/TPM2.crb-device.tpm2'
> >>>>> Warning! zero length expected file
> >>>>> 'tests/data/acpi/virt/DSDT.crb-device.tpm2'
> >>>>> acpi-test: Warning!  binary file mismatch. Actual
> >>>>> [aml:/tmp/aml-GO4ME2], Expected
> >>>>> [aml:tests/data/acpi/virt/TPM2.crb-device.tpm2].
> >>>>> See source file tests/qtest/bios-tables-test.c for instructions on how
> >>>>> to update expected files.
> >>>>> acpi-test: Warning!  binary file mismatch. Actual
> >>>>> [aml:/tmp/aml-6N4ME2], Expected
> >>>>> [aml:tests/data/acpi/virt/DSDT.crb-device.tpm2].
> >>>>> See source file tests/qtest/bios-tables-test.c for instructions on how
> >>>>> to update expected files.
> >>>>> to see ASL diff between mismatched files install IASL, rebuild QEMU
> >>>>> from scratch and re-run tests with V=1 environment variable set**
> >>>>> ERROR:../tests/qtest/bios-tables-test.c:538:test_acpi_asl: assertion
> >>>>> failed: (all_tables_match)
> >>>>> not ok /aarch64/acpi/virt/tpm2-crb -
> >>>>> ERROR:../tests/qtest/bios-tables-test.c:538:test_acpi_asl: assertion
> >>>>> failed: (all_tables_match)
> >>>>> Bail out!
> >>>>> qemu-system-aarch64: tpm-emulator: Could not cleanly shutdown the TPM:
> >>>>> Resource temporarily unavailable
> >>>>> Unexpected error in qio_channel_socket_writev() at
> >>>>> ../io/channel-socket.c:622:
> >>>>> /home/elmarco/src/qemu/buildall/tests/qtest/bios-tables-test: Unable
> >>>>> to write to socket: Bad file descriptor
> >>>>>
> >>>>
> >>>> Travis testing on s390x I see the following failures for this patchset
> >>>> (search for 'ERROR'):
> >>>>
> >>>> https://app.travis-ci.com/github/stefanberger/qemu-tpm/builds/267230363
> >>>>
> >>>> Summary of Failures:
> >>>>
> >>>> 134/320 qemu:qtest+qtest-aarch64 / qtest-aarch64/tpm-crb-device-test
> >>>> ERROR   0.70s   killed by signal 6 SIGABRT
> >>>>
> >>>> 219/320 qemu:qtest+qtest-x86_64 / qtest-x86_64/tpm-crb-test
> >>>> ERROR   0.88s   killed by signal 6 SIGABRT
> >>>>
> >>>>
> >>>> Summary of Failures:
> >>>>
> >>>> 271/537 qemu:qtest+qtest-i386 / qtest-i386/tpm-crb-test
> >>>> ERROR   0.59s   killed by signal 6 SIGABRT
> >>>>
> &

Re: [PATCH v5 12/14] tests: acpi: implement TPM CRB tests for ARM virt

2023-11-23 Thread Joelle van Dyne
On Tue, Nov 14, 2023 at 4:12 PM Stefan Berger  wrote:
>
>
>
> On 11/14/23 16:05, Stefan Berger wrote:
> >
> >
> > On 11/14/23 13:03, Stefan Berger wrote:
> >>
> >>
> >> On 11/14/23 04:36, Marc-André Lureau wrote:
> >>> Hi
> >>>
> >>> On Tue, Nov 14, 2023 at 6:12 AM Joelle van Dyne  wrote:
> >>>>
> >>>> Signed-off-by: Joelle van Dyne 
> >>>> Reviewed-by: Stefan Berger 
> >>>
> >>> nit: you also added tests for x86, could be a different patch?
> >>>
> >>> For arm, the test fails until next patch with:
> >>>
> >>> # starting QEMU: exec ./qemu-system-aarch64 -qtest
> >>> unix:/tmp/qtest-991279.sock -qtest-log /dev/null -chardev
> >>> socket,path=/tmp/qtest-991279.qmp,id=char0 -mon
> >>> chardev=char0,mode=control -display none -audio none -machine virt
> >>> -accel tcg -nodefaults -nographic -drive
> >>> if=pflash,format=raw,file=pc-bios/edk2-aarch64-code.fd,readonly=on
> >>> -drive if=pflash,format=raw,file=pc-bios/edk2-arm-vars.fd,snapshot=on
> >>> -cdrom tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2
> >>> -cpu cortex-a57 -chardev
> >>> socket,id=chr,path=/tmp/qemu-test_acpi_virt_tcg_crb-device.KZ3GE2/sock
> >>> -tpmdev emulator,id=dev,chardev=chr -device tpm-crb-device,tpmdev=dev
> >>> -accel qtest
> >>> Warning! zero length expected file
> >>> 'tests/data/acpi/virt/TPM2.crb-device.tpm2'
> >>> Warning! zero length expected file
> >>> 'tests/data/acpi/virt/DSDT.crb-device.tpm2'
> >>> acpi-test: Warning!  binary file mismatch. Actual
> >>> [aml:/tmp/aml-GO4ME2], Expected
> >>> [aml:tests/data/acpi/virt/TPM2.crb-device.tpm2].
> >>> See source file tests/qtest/bios-tables-test.c for instructions on how
> >>> to update expected files.
> >>> acpi-test: Warning!  binary file mismatch. Actual
> >>> [aml:/tmp/aml-6N4ME2], Expected
> >>> [aml:tests/data/acpi/virt/DSDT.crb-device.tpm2].
> >>> See source file tests/qtest/bios-tables-test.c for instructions on how
> >>> to update expected files.
> >>> to see ASL diff between mismatched files install IASL, rebuild QEMU
> >>> from scratch and re-run tests with V=1 environment variable set**
> >>> ERROR:../tests/qtest/bios-tables-test.c:538:test_acpi_asl: assertion
> >>> failed: (all_tables_match)
> >>> not ok /aarch64/acpi/virt/tpm2-crb -
> >>> ERROR:../tests/qtest/bios-tables-test.c:538:test_acpi_asl: assertion
> >>> failed: (all_tables_match)
> >>> Bail out!
> >>> qemu-system-aarch64: tpm-emulator: Could not cleanly shutdown the TPM:
> >>> Resource temporarily unavailable
> >>> Unexpected error in qio_channel_socket_writev() at
> >>> ../io/channel-socket.c:622:
> >>> /home/elmarco/src/qemu/buildall/tests/qtest/bios-tables-test: Unable
> >>> to write to socket: Bad file descriptor
> >>>
> >>
> >> Travis testing on s390x I see the following failures for this patchset
> >> (search for 'ERROR'):
> >>
> >> https://app.travis-ci.com/github/stefanberger/qemu-tpm/builds/267230363
> >>
> >> Summary of Failures:
> >>
> >> 134/320 qemu:qtest+qtest-aarch64 / qtest-aarch64/tpm-crb-device-test
> >> ERROR   0.70s   killed by signal 6 SIGABRT
> >>
> >> 219/320 qemu:qtest+qtest-x86_64 / qtest-x86_64/tpm-crb-test
> >> ERROR   0.88s   killed by signal 6 SIGABRT
> >>
> >>
> >> Summary of Failures:
> >>
> >> 271/537 qemu:qtest+qtest-i386 / qtest-i386/tpm-crb-test
> >> ERROR   0.59s   killed by signal 6 SIGABRT
> >>
> >>
> >> My guess is it's an endianess issue on big endian machines due to
> >> reading from the ROM device where we lost the .endianess:
> >>
> >> +const MemoryRegionOps tpm_crb_memory_ops = {
> >> +.read = tpm_crb_mmio_read,
> >> +.write = tpm_crb_mmio_write,
> >> +.endianness = DEVICE_LITTLE_ENDIAN,
> >> +.valid = {
> >> +.min_access_size = 1,
> >> +.max_access_size = 4,
> >> +},
> >> +};
> >>
> >
> > I think we need a 2nd set of registers to support the endianess
> > conversion. It's not exactly nice, though. Basically the saved_regs
> > could be used for this directly, even though I did not do that but
> > introduced n_regs:
> > https://github.com/stefanberger/qemu-tpm/commit/90f6b21c0dd93dbb13d9e80a628f5b631fd07d91
> >
> > This patch allows the tests on s390x to run farther but the execution of
> > the command doesn't seem to work maybe due to command data that were
> > also written in wrong endianess. I don't know. I would have to get
> > access to a big endian / s390 machine to be able to fix it.
> >
> >
>
> The latest version now passes on Travis s390x:
> https://app.travis-ci.com/github/stefanberger/qemu-tpm/builds/267245220
>

Are the tests failing on S390X due to the added code or are they
failing because previously it was untested? I don't think the original
code took account of endianness and that should be fixed, but feels
like it should be in a separate patch set?



Re: [PATCH v5 05/14] tpm_crb: move ACPI table building to device interface

2023-11-14 Thread Joelle van Dyne
On Tue, Nov 14, 2023 at 8:44 AM Stefan Berger  wrote:
>
>
>
> On 11/14/23 11:37, Stefan Berger wrote:
> >
> >
> > On 11/13/23 21:09, Joelle van Dyne wrote:
> >> This logic is similar to TPM TIS ISA device. Since TPM CRB can only
> >> support TPM 2.0 backends, we check for this in realize.
> >>
> >> Signed-off-by: Joelle van Dyne 
> >> ---
> >>   hw/tpm/tpm_crb.h|  2 ++
> >>   hw/i386/acpi-build.c| 16 +---
> >>   hw/tpm/tpm_crb.c| 16 
> >>   hw/tpm/tpm_crb_common.c | 19 +++
> >>   4 files changed, 38 insertions(+), 15 deletions(-)
> >>
> >> diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
> >> index 36863e1664..e6a86e3fd1 100644
> >> --- a/hw/tpm/tpm_crb.h
> >> +++ b/hw/tpm/tpm_crb.h
> >> @@ -73,5 +73,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState
> >> *s, Error **errp);
> >>   void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void
> >> *saved_cmdmem);
> >>   void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
> >> const void *saved_cmdmem);
> >> +void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t baseaddr,
> >> uint32_t size,
> >> +   bool build_ppi);
> >>
> >>   #endif /* TPM_TPM_CRB_H */
> >> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> >> index 80db183b78..7491cee2af 100644
> >> --- a/hw/i386/acpi-build.c
> >> +++ b/hw/i386/acpi-build.c
> >> @@ -1792,21 +1792,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >>
> >>   #ifdef CONFIG_TPM
> >>   if (TPM_IS_CRB(tpm)) {
> >> -dev = aml_device("TPM");
> >> -aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> >> -aml_append(dev, aml_name_decl("_STR",
> >> -  aml_string("TPM 2.0 Device")));
> >> -crs = aml_resource_template();
> >> -aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> >> -   TPM_CRB_ADDR_SIZE,
> >> AML_READ_WRITE));
> >> -aml_append(dev, aml_name_decl("_CRS", crs));
> >> -
> >> -aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
> >> -aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> >> -
> >> -tpm_build_ppi_acpi(tpm, dev);
> >> -
> >> -aml_append(sb_scope, dev);
> >> +call_dev_aml_func(DEVICE(tpm), scope);
> >
> > For an x86_64 VM we have to call it directly otherwise the ACPI table
> > won't be there.
> >
> >  tpm_crb_build_aml(tpm, sb_scope, TPM_CRB_ADDR_BASE,
> > TPM_CRB_ADDR_SIZE, true);
> >
> >
> I looks like a good place for the moved code would be in hw/acpi/tpm.c

The change in v5 is that we call "call_dev_aml_func" which calls
"tpm_crb_build_aml" from tpm_crb.c (later moved to tpm_crb_common.c).
I think it's a better place for it because TPM TIS has a different
ACPI table and both can be handled correctly by call_dev_aml_func. In
the previous versions when we moved TPM CRB to ISA there was no need
to manually call "call_dev_aml_func" because the function for building
the ISA bus called it. However, I think this is still better in case
it is decided in the future to move the CRB device on ISA or another
bus and it makes the code more manageable with more TPM types.



Re: [PATCH v5 00/14] tpm: introduce TPM CRB SysBus device

2023-11-14 Thread Joelle van Dyne
On Tue, Nov 14, 2023 at 1:38 AM Marc-André Lureau
 wrote:
>
> Hi
>
> On Tue, Nov 14, 2023 at 6:10 AM Joelle van Dyne  wrote:
> >
> > The impetus for this patch set is to get TPM 2.0 working on Windows 11 
> > ARM64.
> > Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
> > VMWare's implementation). However, the current TPM CRB device uses a fixed
> > system bus address that is reserved for RAM in ARM64 Virt machines.
> >
> > In the process of adding the TPM CRB SysBus device, we also went ahead and
> > cleaned up some of the existing TPM hardware code and fixed some bugs. We 
> > used
> > the TPM TIS devices as a template for the TPM CRB devices and refactored out
> > common code. We moved the ACPI DSDT generation to the device in order to 
> > handle
> > dynamic base address requirements as well as reduce redundent code in 
> > different
> > machine ACPI generation. We also changed the tpm_crb device to use the ISA 
> > bus
> > instead of depending on the default system bus as the device only was built 
> > for
> > the PC configuration.
> >
> > Another change is that the TPM CRB registers are now mapped in the same way 
> > that
> > the pflash ROM devices are mapped. It is a memory region whose writes are
> > trapped as MMIO accesses. This was needed because Apple Silicon does not 
> > decode
> > LDP (AARCH64 load pair of registers) caused page faults. @agraf suggested 
> > that
> > we do this to avoid having to do AARCH64 decoding in the HVF backend's fault
> > handler.
> >
> > Unfortunately, it seems like the LDP fault still happens on HVF but the 
> > issue
> > seems to be in the HVF backend which needs to be fixed in a separate patch.
> >
> > One last thing that's needed to get Windows 11 to recognize the TPM 2.0 
> > device
> > is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 
> > Virt
> > only recognizes the TPM TIS device through a FDT entry. A workaround is to
> > falsely identify the TPM CRB device as a TPM TIS device in the FDT node but 
> > this
> > causes issues for Linux. A proper fix would involve adding an ACPI device 
> > driver
> > in OVMF.
> >
> > This has been tested on ARM64 with `tpm-crb-device` and on x86_64 with
> > `tpm-crb`. Additional testing should be performed on other architectures 
> > (RISCV
> > and Loongarch for example) as well as migration cases.
> >
> > v5:
> > - Fixed a typo in "tpm_crb: use a single read-as-mem/write-as-mmio mapping"
> > - Fixed ACPI tables not being created for pc CRB device
> >
> > v4:
> > - Fixed broken test blobs
> >
> > v3:
> > - Support backwards and forwards migration of existing tpm-crb device
> > - Dropped patch which moved tpm-crb to ISA bus due to migration concerns
> > - Unified `tpm_sysbus_plug` handler for ARM and Loongarch
> > - Added ACPI table tests for tpm-crb-device
> > - Refactored TPM CRB tests to run on tpm-crb-device for ARM Virt
> >
> > v2:
> > - Fixed an issue where VMstate restore from an older version failed due to 
> > name
> >   collision of the memory block.
> > - In the ACPI table generation for CRB devices, the check for TPM 2.0 
> > backend is
> >   moved to the device realize as CRB does not support TPM 1.0. It will 
> > error in
> >   that case.
> > - Dropped the patch to fix crash when PPI is enabled on TIS SysBus device 
> > since
> >   a separate patch submitted by Stefan Berger disables such an option.
> > - Fixed an issue where we default tpmEstablished=0 when it should be 1.
> > - In TPM CRB SysBus's ACPI entry, we accidently changed _UID from 0 to 1. 
> > This
> >   shouldn't be an issue but we changed it back just in case.
> > - Added a patch to migrate saved VMstate from an older version with the regs
> >   saved separately instead of as a RAM block.
> >
> > Joelle van Dyne (14):
> >   tpm_crb: refactor common code
> >   tpm_crb: CTRL_RSP_ADDR is 64-bits wide
> >   tpm_ppi: refactor memory space initialization
> >   tpm_crb: use a single read-as-mem/write-as-mmio mapping
> >   tpm_crb: move ACPI table building to device interface
> >   tpm-sysbus: add plug handler for TPM on SysBus
> >   hw/arm/virt: connect TPM to platform bus
> >   hw/loongarch/virt: connect TPM to platform bus
> >   tpm_tis_sysbus: move DSDT AML generation to device
> >   tests: acpi: prepare for TPM CRB tests
> >   tpm_crb_sysbus: introduce TPM CRB SysBus device
> >   tests: acpi: implement

[PATCH v5 06/14] tpm-sysbus: add plug handler for TPM on SysBus

2023-11-13 Thread Joelle van Dyne
TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 include/sysemu/tpm.h |  4 
 hw/tpm/tpm-sysbus.c  | 47 
 hw/tpm/meson.build   |  1 +
 3 files changed, 52 insertions(+)
 create mode 100644 hw/tpm/tpm-sysbus.c

diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 1ee568b3b6..ffd300e607 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -12,6 +12,8 @@
 #ifndef QEMU_TPM_H
 #define QEMU_TPM_H
 
+#include "qemu/osdep.h"
+#include "exec/hwaddr.h"
 #include "qapi/qapi-types-tpm.h"
 #include "qom/object.h"
 
@@ -78,6 +80,8 @@ static inline TPMVersion tpm_get_version(TPMIf *ti)
 return TPM_IF_GET_CLASS(ti)->get_version(ti);
 }
 
+void tpm_sysbus_plug(TPMIf *tpmif, Object *pbus, hwaddr pbus_base);
+
 #else /* CONFIG_TPM */
 
 #define tpm_init()  (0)
diff --git a/hw/tpm/tpm-sysbus.c b/hw/tpm/tpm-sysbus.c
new file mode 100644
index 00..732ce34c73
--- /dev/null
+++ b/hw/tpm/tpm-sysbus.c
@@ -0,0 +1,47 @@
+/*
+ * tpm-sysbus.c - Support functions for SysBus TPM devices
+ *
+ * Copyright (c) 2023 QEMU contributors
+ *
+ * Authors:
+ *   Joelle van Dyne 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "sysemu/tpm.h"
+#include "hw/platform-bus.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+
+/**
+ * Called from a machine's pre_plug handler to set the device's physical addr.
+ */
+void tpm_sysbus_plug(TPMIf *tpmif, Object *pbus, hwaddr pbus_base)
+{
+PlatformBusDevice *pbusdev = PLATFORM_BUS_DEVICE(pbus);
+SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+MemoryRegion *sbdev_mr;
+hwaddr tpm_base;
+uint64_t tpm_size;
+
+/* exit early if TPM is not a sysbus device */
+if (!object_dynamic_cast(OBJECT(tpmif), TYPE_SYS_BUS_DEVICE)) {
+return;
+}
+
+assert(object_dynamic_cast(pbus, TYPE_PLATFORM_BUS_DEVICE));
+
+tpm_base = platform_bus_get_mmio_addr(pbusdev, sbdev, 0);
+assert(tpm_base != -1);
+
+tpm_base += pbus_base;
+
+sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+tpm_size = memory_region_size(sbdev_mr);
+
+object_property_set_uint(OBJECT(sbdev), "x-baseaddr",
+ tpm_base, _abort);
+object_property_set_uint(OBJECT(sbdev), "x-size",
+ tpm_size, _abort);
+}
diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
index cb8204d5bc..3060ac05e8 100644
--- a/hw/tpm/meson.build
+++ b/hw/tpm/meson.build
@@ -1,6 +1,7 @@
 system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_tis_common.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_ISA', if_true: files('tpm_tis_isa.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: 
files('tpm_tis_sysbus.c'))
+system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm-sysbus.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
-- 
2.41.0




[PATCH v5 11/14] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-11-13 Thread Joelle van Dyne
This SysBus variant of the CRB interface supports dynamically locating
the MMIO interface so that Virt machines can use it. This interface
is currently the only one supported by QEMU that works on Windows 11
ARM64 as 'tpm-tis-device' does not work with current Windows drivers.
We largely follow that device as a template.

To try out this device with Windows 11 before OVMF is updated, you
will need to modify `sysbus-fdt.c` and change the added line from:

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
```

to

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
```

This change was not included because it can confuse Linux (although
from testing, it seems like Linux is able to properly ignore the
device from the TPM TIS driver and recognize it from the ACPI device
in the TPM CRB driver). A proper fix would require OVMF to recognize
the ACPI device and not depend on the FDT node for recognizing TPM.

The command line to try out this device with SWTPM is:

```
$ qemu-system-aarch64 \
-chardev socket,id=chrtpm0,path=tpm.sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm0 \
-device tpm-crb-device,tpmdev=tpm0
```

along with SWTPM:

```
$ swtpm \
--ctrl type=unixio,path=tpm.sock,terminate \
--tpmstate backend-uri=file://tpm.data \
--tpm2
```

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 docs/specs/tpm.rst  |   1 +
 include/sysemu/tpm.h|   3 +
 hw/acpi/aml-build.c |   7 +-
 hw/arm/virt.c   |   1 +
 hw/core/sysbus-fdt.c|   1 +
 hw/loongarch/virt.c |   1 +
 hw/riscv/virt.c |   1 +
 hw/tpm/tpm_crb_sysbus.c | 162 
 hw/arm/Kconfig  |   1 +
 hw/loongarch/Kconfig|   1 +
 hw/riscv/Kconfig|   1 +
 hw/tpm/Kconfig  |   5 ++
 hw/tpm/meson.build  |   3 +
 13 files changed, 187 insertions(+), 1 deletion(-)
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index 2bc29c9804..95aeb49220 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -46,6 +46,7 @@ operating system.
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
  - ``hw/tpm/tpm_crb_common.c``
+ - ``hw/tpm/tpm_crb_sysbus.c``
 
 SPAPR interface
 ---
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index ffd300e607..bab30fa546 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -49,6 +49,7 @@ struct TPMIfClass {
 #define TYPE_TPM_TIS_ISA"tpm-tis"
 #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
 #define TYPE_TPM_CRB"tpm-crb"
+#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
 #define TYPE_TPM_SPAPR  "tpm-spapr"
 #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
 
@@ -58,6 +59,8 @@ struct TPMIfClass {
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
 #define TPM_IS_CRB(chr) \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_CRB_SYSBUS(chr)  \
+object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
 #define TPM_IS_SPAPR(chr)   \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
 #define TPM_IS_TIS_I2C(chr)  \
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index af66bde0f5..acc654382e 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -31,6 +31,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 {
 uint8_t start_method_params[12] = {};
 unsigned log_addr_offset;
-uint64_t control_area_start_address;
+uint64_t baseaddr, control_area_start_address;
 TPMIf *tpmif = tpm_find();
 uint32_t start_method;
 AcpiTable table = { .sig = "TPM2", .rev = 4,
@@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 } else if (TPM_IS_CRB(tpmif)) {
 control_area_start_address = TPM_CRB_ADDR_CTRL;
 start_method = TPM2_START_METHOD_CRB;
+} else if (TPM_IS_CRB_SYSBUS(tpmif)) {
+baseaddr = object_property_get_uint(OBJECT(tpmif), "x-baseaddr", NULL);
+control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
+start_method = TPM2_START_METHOD_CRB;
 } else {
 g_assert_not_reached();
 }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 36e2506420..e6152a2f51 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2955,6 +2955,7 @@ static void virt_machine_class_init(ObjectClass *oc, void 
*data)
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
 #ifdef CONFIG_TPM
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+machine_class_allow_dynamic_sysbus_de

[PATCH v5 04/14] tpm_crb: use a single read-as-mem/write-as-mmio mapping

2023-11-13 Thread Joelle van Dyne
On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
the exception is not decoded by hardware and we cannot trap the MMIO
read. This led to the idea from @agraf to use the same mapping type as
ROM devices: namely that reads should be seen as memory type and
writes should trap as MMIO.

Once that was done, the second memory mapping of the command buffer
region was redundent and was removed.

A note about the removal of the read trap for `CRB_LOC_STATE`:
The only usage was to return the most up-to-date value for
`tpmEstablished`. However, `tpmEstablished` is only cleared when a
TPM2_HashStart operation is called which only exists for locality 4.
We do not handle locality 4. Indeed, the comment for the write handler
of `CRB_LOC_CTRL` makes the same argument for why it is not calling
the backend to reset the `tpmEstablished` bit (to 1).
As this bit is unused, we do not need to worry about updating it for
reads.

In order to maintain migration compatibility with older versions of
QEMU, we store a copy of the register data and command data which is
used only during save/restore.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.h|   5 +-
 hw/tpm/tpm_crb.c|  30 -
 hw/tpm/tpm_crb_common.c | 145 +++-
 3 files changed, 114 insertions(+), 66 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index da3a0cf256..36863e1664 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -26,9 +26,7 @@
 typedef struct TPMCRBState {
 TPMBackend *tpmbe;
 TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
 MemoryRegion mmio;
-MemoryRegion cmdmem;
 
 size_t be_buffer_size;
 
@@ -72,5 +70,8 @@ enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
 int tpm_crb_pre_save(TPMCRBState *s);
 void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
 void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void 
*saved_cmdmem);
+void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
+  const void *saved_cmdmem);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 598c3e0161..99c64dd72a 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -37,6 +37,10 @@ struct CRBState {
 DeviceState parent_obj;
 
 TPMCRBState state;
+
+/* These states are only for migration */
+uint32_t saved_regs[TPM_CRB_R_MAX];
+MemoryRegion saved_cmdmem;
 };
 typedef struct CRBState CRBState;
 
@@ -57,18 +61,36 @@ static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
 return tpm_crb_get_version(>state);
 }
 
+/**
+ * For migrating to an older version of QEMU
+ */
 static int tpm_crb_none_pre_save(void *opaque)
 {
 CRBState *s = opaque;
+void *saved_cmdmem = memory_region_get_ram_ptr(>saved_cmdmem);
 
+tpm_crb_mem_save(>state, s->saved_regs, saved_cmdmem);
 return tpm_crb_pre_save(>state);
 }
 
+/**
+ * For migrating from an older version of QEMU
+ */
+static int tpm_crb_none_post_load(void *opaque, int version_id)
+{
+CRBState *s = opaque;
+void *saved_cmdmem = memory_region_get_ram_ptr(>saved_cmdmem);
+
+tpm_crb_mem_load(>state, s->saved_regs, saved_cmdmem);
+return 0;
+}
+
 static const VMStateDescription vmstate_tpm_crb_none = {
 .name = "tpm-crb",
 .pre_save = tpm_crb_none_pre_save,
+.post_load = tpm_crb_none_post_load,
 .fields = (VMStateField[]) {
-VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),
+VMSTATE_UINT32_ARRAY(saved_regs, CRBState, TPM_CRB_R_MAX),
 VMSTATE_END_OF_LIST(),
 }
 };
@@ -101,10 +123,12 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
+/* only used for migration */
+memory_region_init_ram(>saved_cmdmem, OBJECT(s),
+"tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+
 memory_region_add_subregion(get_system_memory(),
 TPM_CRB_ADDR_BASE, >state.mmio);
-memory_region_add_subregion(get_system_memory(),
-TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
 memory_region_add_subregion(get_system_memory(),
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index bee0b71fee..f96a8cf299 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -31,31 +31,12 @@
 #include "qom/object.h"
 #include "tpm_crb.h"
 
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
+static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
 {
-TPMCRBState *s = opaque;
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-switch (addr) {
-case A_CRB_LOC_STATE:
-val |= !tp

[PATCH v5 02/14] tpm_crb: CTRL_RSP_ADDR is 64-bits wide

2023-11-13 Thread Joelle van Dyne
The register is actually 64-bits but in order to make this more clear
than the specification, we define two 32-bit registers:
CTRL_RSP_LADDR and CTRL_RSP_HADDR to match the CTRL_CMD_* naming. This
deviates from the specs but is way more clear.

Previously, the only CRB device uses a fixed system address so this
was not an issue. However, once we support SysBus CRB device, the
address can be anywhere in 64-bit space.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 include/hw/acpi/tpm.h  | 3 ++-
 hw/tpm/tpm_crb_common.c| 3 ++-
 tests/qtest/tpm-crb-test.c | 2 +-
 tests/qtest/tpm-util.c | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 579c45f5ba..f60bfe2789 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -174,7 +174,8 @@ REG32(CRB_CTRL_CMD_SIZE, 0x58)
 REG32(CRB_CTRL_CMD_LADDR, 0x5C)
 REG32(CRB_CTRL_CMD_HADDR, 0x60)
 REG32(CRB_CTRL_RSP_SIZE, 0x64)
-REG32(CRB_CTRL_RSP_ADDR, 0x68)
+REG32(CRB_CTRL_RSP_LADDR, 0x68)
+REG32(CRB_CTRL_RSP_HADDR, 0x6C)
 REG32(CRB_DATA_BUFFER, 0x80)
 
 #define TPM_CRB_ADDR_BASE   0xFED4
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index fa463f295f..01b35808f6 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -197,7 +197,8 @@ void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
 s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
 s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
 s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-s->regs[R_CRB_CTRL_RSP_ADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
 
 s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
 CRB_CTRL_CMD_SIZE);
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 396ae3f91c..9d30fe8293 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -28,7 +28,7 @@ static void tpm_crb_test(const void *data)
 uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
 uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
 uint32_t rsize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_SIZE);
-uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 uint8_t locstate = readb(TPM_CRB_ADDR_BASE + A_CRB_LOC_STATE);
 uint32_t locctrl = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL);
 uint32_t locsts = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_STS);
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index 1c0319e6e7..dd02057fc0 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -25,7 +25,7 @@ void tpm_util_crb_transfer(QTestState *s,
unsigned char *rsp, size_t rsp_size)
 {
 uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
-uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 
 qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);
 
-- 
2.41.0




[PATCH v5 08/14] hw/loongarch/virt: connect TPM to platform bus

2023-11-13 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/loongarch/virt.c  | 7 +++
 hw/loongarch/Kconfig | 1 +
 2 files changed, 8 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 4b7dc67a2d..feed0f8bbf 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1004,6 +1004,13 @@ static void 
loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 } else if (memhp_type_supported(dev)) {
 virt_mem_plug(hotplug_dev, dev, errp);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+tpm_sysbus_plug(TPM_IF(dev), OBJECT(lams->platform_bus_dev),
+VIRT_PLATFORM_BUS_BASEADDRESS);
+}
+#endif
 }
 
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 5727efed6d..25da190ffc 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -5,6 +5,7 @@ config LOONGARCH_VIRT
 imply VIRTIO_VGA
 imply PCI_DEVICES
 imply NVDIMM
+imply TPM_TIS_SYSBUS
 select SERIAL
 select VIRTIO_PCI
 select PLATFORM_BUS
-- 
2.41.0




[PATCH v5 03/14] tpm_ppi: refactor memory space initialization

2023-11-13 Thread Joelle van Dyne
Instead of calling `memory_region_add_subregion` directly, we defer to
the caller to do it. This allows us to re-use the code for a SysBus
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_ppi.h| 10 +++---
 hw/tpm/tpm_crb.c|  4 ++--
 hw/tpm/tpm_crb_common.c |  3 +++
 hw/tpm/tpm_ppi.c|  5 +
 hw/tpm/tpm_tis_isa.c|  5 +++--
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h
index bf5d4a300f..30863c6438 100644
--- a/hw/tpm/tpm_ppi.h
+++ b/hw/tpm/tpm_ppi.h
@@ -20,17 +20,13 @@ typedef struct TPMPPI {
 } TPMPPI;
 
 /**
- * tpm_ppi_init:
+ * tpm_ppi_init_memory:
  * @tpmppi: a TPMPPI
- * @m: the address-space / MemoryRegion to use
- * @addr: the address of the PPI region
  * @obj: the owner object
  *
- * Register the TPM PPI memory region at @addr on the given address
- * space for the object @obj.
+ * Creates the TPM PPI memory region.
  **/
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj);
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj);
 
 /**
  * tpm_ppi_reset:
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 3ef4977fb5..598c3e0161 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -107,8 +107,8 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
-tpm_ppi_init(>state.ppi, get_system_memory(),
- TPM_PPI_ADDR_BASE, OBJECT(s));
+memory_region_add_subregion(get_system_memory(),
+TPM_PPI_ADDR_BASE, >state.ppi.ram);
 }
 
 if (xen_enabled()) {
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 01b35808f6..bee0b71fee 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -214,4 +214,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp)
 "tpm-crb-mmio", sizeof(s->regs));
 memory_region_init_ram(>cmdmem, obj,
 "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+if (s->ppi_enabled) {
+tpm_ppi_init_memory(>ppi, obj);
+}
 }
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 7f74e26ec6..40cab59afa 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -44,14 +44,11 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
 }
 }
 
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj)
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj)
 {
 tpmppi->buf = qemu_memalign(qemu_real_host_page_size(),
 HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
 memory_region_init_ram_device_ptr(>ram, obj, "tpm-ppi",
   TPM_PPI_ADDR_SIZE, tpmppi->buf);
 vmstate_register_ram(>ram, DEVICE(obj));
-
-memory_region_add_subregion(m, addr, >ram);
 }
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 0367401586..d596f38c0f 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -134,8 +134,9 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error 
**errp)
 TPM_TIS_ADDR_BASE, >mmio);
 
 if (s->ppi_enabled) {
-tpm_ppi_init(>ppi, isa_address_space(ISA_DEVICE(dev)),
- TPM_PPI_ADDR_BASE, OBJECT(dev));
+tpm_ppi_init_memory(>ppi, OBJECT(dev));
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
+TPM_PPI_ADDR_BASE, >ppi.ram);
 }
 }
 
-- 
2.41.0




[PATCH v5 12/14] tests: acpi: implement TPM CRB tests for ARM virt

2023-11-13 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 tests/qtest/bios-tables-test.c | 43 --
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 71af5cf69f..bb4ebf00c1 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1447,6 +1447,28 @@ static void test_acpi_piix4_tcg_numamem(void)
 
 uint64_t tpm_tis_base_addr;
 
+static test_data tcg_tpm_test_data(const char *machine)
+{
+if (g_strcmp0(machine, "virt") == 0) {
+test_data data = {
+.machine = "virt",
+.tcg_only = true,
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.cd =
+   
"tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+return data;
+} else {
+test_data data = {
+.machine = machine,
+};
+return data;
+}
+}
+
 static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
   uint64_t base, enum TPMVersion tpm_version)
 {
@@ -1454,7 +1476,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
   machine, tpm_if);
 char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL);
 TPMTestState test;
-test_data data = {};
+test_data data = tcg_tpm_test_data(machine);
 GThread *thread;
 const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
 char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
@@ -1474,13 +1496,14 @@ static void test_acpi_tcg_tpm(const char *machine, 
const char *tpm_if,
 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, );
 tpm_emu_test_wait_cond();
 
-data.machine = machine;
 data.variant = variant;
 
 args = g_strdup_printf(
+" %s"
 " -chardev socket,id=chr,path=%s"
 " -tpmdev emulator,id=dev,chardev=chr"
 " -device tpm-%s,tpmdev=dev",
+g_strcmp0(machine, "virt") == 0 ? "-cpu cortex-a57" : "",
 test.addr->u.q_unix.path, tpm_if);
 
 test_acpi_one(args, );
@@ -1506,6 +1529,16 @@ static void test_acpi_q35_tcg_tpm12_tis(void)
 test_acpi_tcg_tpm("q35", "tis", 0xFED4, TPM_VERSION_1_2);
 }
 
+static void test_acpi_q35_tcg_tpm2_crb(void)
+{
+test_acpi_tcg_tpm("q35", "crb", 0xFED4, TPM_VERSION_2_0);
+}
+
+static void test_acpi_virt_tcg_tpm2_crb(void)
+{
+test_acpi_tcg_tpm("virt", "crb-device", 0xFED4, TPM_VERSION_2_0);
+}
+
 static void test_acpi_tcg_dimm_pxm(const char *machine)
 {
 test_data data = {};
@@ -2212,6 +2245,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/tpm12-tis",
test_acpi_q35_tcg_tpm12_tis);
 }
+if (tpm_model_is_available("-machine q35", "tpm-crb")) {
+qtest_add_func("acpi/q35/tpm2-crb", 
test_acpi_q35_tcg_tpm2_crb);
+}
 qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge);
 qtest_add_func("acpi/q35/no-acpi-hotplug",
test_acpi_q35_tcg_no_acpi_hotplug);
@@ -2301,6 +2337,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/virt/viot", test_acpi_virt_viot);
 }
 }
+if (tpm_model_is_available("-machine virt", "tpm-crb")) {
+qtest_add_func("acpi/virt/tpm2-crb", test_acpi_virt_tcg_tpm2_crb);
+}
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.41.0




[PATCH v5 01/14] tpm_crb: refactor common code

2023-11-13 Thread Joelle van Dyne
In preparation for the SysBus variant, we move common code styled
after the TPM TIS devices.

To maintain compatibility, we do not rename the existing tpm-crb
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 docs/specs/tpm.rst  |   1 +
 hw/tpm/tpm_crb.h|  76 +++
 hw/tpm/tpm_crb.c| 270 ++--
 hw/tpm/tpm_crb_common.c | 216 
 hw/tpm/meson.build  |   1 +
 hw/tpm/trace-events |   2 +-
 6 files changed, 331 insertions(+), 235 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index efe124a148..2bc29c9804 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -45,6 +45,7 @@ operating system.
 
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
+ - ``hw/tpm/tpm_crb_common.c``
 
 SPAPR interface
 ---
diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
new file mode 100644
index 00..da3a0cf256
--- /dev/null
+++ b/hw/tpm/tpm_crb.h
@@ -0,0 +1,76 @@
+/*
+ * tpm_crb.h - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Marc-André Lureau 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+#ifndef TPM_TPM_CRB_H
+#define TPM_TPM_CRB_H
+
+#include "exec/memory.h"
+#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_ppi.h"
+
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
+
+typedef struct TPMCRBState {
+TPMBackend *tpmbe;
+TPMBackendCmd cmd;
+uint32_t regs[TPM_CRB_R_MAX];
+MemoryRegion mmio;
+MemoryRegion cmdmem;
+
+size_t be_buffer_size;
+
+bool ppi_enabled;
+TPMPPI ppi;
+} TPMCRBState;
+
+#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
+#define CRB_INTF_VERSION_CRB 0b1
+#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
+#define CRB_INTF_CAP_IDLE_FAST 0b0
+#define CRB_INTF_CAP_XFER_SIZE_64 0b11
+#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
+#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
+#define CRB_INTF_IF_SELECTOR_CRB 0b1
+
+enum crb_loc_ctrl {
+CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+CRB_LOC_CTRL_RELINQUISH = BIT(1),
+CRB_LOC_CTRL_SEIZE = BIT(2),
+CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
+};
+
+enum crb_ctrl_req {
+CRB_CTRL_REQ_CMD_READY = BIT(0),
+CRB_CTRL_REQ_GO_IDLE = BIT(1),
+};
+
+enum crb_start {
+CRB_START_INVOKE = BIT(0),
+};
+
+enum crb_cancel {
+CRB_CANCEL_INVOKE = BIT(0),
+};
+
+#define TPM_CRB_NO_LOCALITY 0xff
+
+void tpm_crb_request_completed(TPMCRBState *s, int ret);
+enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
+int tpm_crb_pre_save(TPMCRBState *s);
+void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
+void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+
+#endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index ea930da545..3ef4977fb5 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -31,257 +31,62 @@
 #include "tpm_ppi.h"
 #include "trace.h"
 #include "qom/object.h"
+#include "tpm_crb.h"
 
 struct CRBState {
 DeviceState parent_obj;
 
-TPMBackend *tpmbe;
-TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
-MemoryRegion mmio;
-MemoryRegion cmdmem;
-
-size_t be_buffer_size;
-
-bool ppi_enabled;
-TPMPPI ppi;
+TPMCRBState state;
 };
 typedef struct CRBState CRBState;
 
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  TYPE_TPM_CRB)
 
-#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
-#define CRB_INTF_VERSION_CRB 0b1
-#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
-#define CRB_INTF_CAP_IDLE_FAST 0b0
-#define CRB_INTF_CAP_XFER_SIZE_64 0b11
-#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
-#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
-#define CRB_INTF_IF_SELECTOR_CRB 0b1
-
-#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
-
-enum crb_loc_ctrl {
-CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
-CRB_LOC_CTRL_RELINQUISH = BIT(1),
-CRB_LOC_CTRL_SEIZE = BIT(2),
-CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
-};
-
-enum crb_ctrl_req {
-CRB_CTRL_REQ_CMD_READY = BIT(0),
-CRB_CTRL_REQ_GO_IDLE = BIT(1),
-};
-
-enum crb_start {
-CRB_START_INVOKE = BIT(0),
-};
-
-enum crb_cancel {
-CRB_CANCEL_INVOKE = BIT(0),
-};
-
-#define TPM_CRB_NO_LOCALITY 0xff
-
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
-{
-CRBState *s = CRB(opaque);
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-s

[PATCH v5 05/14] tpm_crb: move ACPI table building to device interface

2023-11-13 Thread Joelle van Dyne
This logic is similar to TPM TIS ISA device. Since TPM CRB can only
support TPM 2.0 backends, we check for this in realize.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.h|  2 ++
 hw/i386/acpi-build.c| 16 +---
 hw/tpm/tpm_crb.c| 16 
 hw/tpm/tpm_crb_common.c | 19 +++
 4 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index 36863e1664..e6a86e3fd1 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -73,5 +73,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp);
 void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void 
*saved_cmdmem);
 void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
   const void *saved_cmdmem);
+void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t baseaddr, uint32_t size,
+   bool build_ppi);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 80db183b78..7491cee2af 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1792,21 +1792,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 
 #ifdef CONFIG_TPM
 if (TPM_IS_CRB(tpm)) {
-dev = aml_device("TPM");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR",
-  aml_string("TPM 2.0 Device")));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
-   TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-
-aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
-aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-
-tpm_build_ppi_acpi(tpm, dev);
-
-aml_append(sb_scope, dev);
+call_dev_aml_func(DEVICE(tpm), scope);
 }
 #endif
 
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 99c64dd72a..8d57295b15 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -19,6 +19,8 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
+#include "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
@@ -121,6 +123,11 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
+if (tpm_crb_none_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
+error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
+return;
+}
+
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
 /* only used for migration */
@@ -142,10 +149,17 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
+static void build_tpm_crb_none_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+tpm_crb_build_aml(TPM_IF(adev), scope, TPM_CRB_ADDR_BASE, 
TPM_CRB_ADDR_SIZE,
+  true);
+}
+
 static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 TPMIfClass *tc = TPM_IF_CLASS(klass);
+AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
 
 dc->realize = tpm_crb_none_realize;
 device_class_set_props(dc, tpm_crb_none_properties);
@@ -154,6 +168,7 @@ static void tpm_crb_none_class_init(ObjectClass *klass, 
void *data)
 tc->model = TPM_MODEL_TPM_CRB;
 tc->get_version = tpm_crb_none_get_version;
 tc->request_completed = tpm_crb_none_request_completed;
+adevc->build_dev_aml = build_tpm_crb_none_aml;
 
 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
@@ -166,6 +181,7 @@ static const TypeInfo tpm_crb_none_info = {
 .class_init  = tpm_crb_none_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_TPM_IF },
+{ TYPE_ACPI_DEV_AML_IF },
 { }
 }
 };
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index f96a8cf299..09ca55eece 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -241,3 +241,22 @@ void tpm_crb_mem_load(TPMCRBState *s, const uint32_t 
*saved_regs,
 memcpy(regs, saved_regs, A_CRB_DATA_BUFFER);
 memcpy([R_CRB_DATA_BUFFER], saved_cmdmem, CRB_CTRL_CMD_SIZE);
 }
+
+void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t baseaddr, uint32_t size,
+   bool build_ppi)
+{
+Aml *dev, *crs;
+
+dev = aml_device("TPM");
+aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(baseaddr, size, AML_READ_WRITE));
+aml_append(dev, aml_name_decl("_CRS", crs));
+if (build_ppi) {
+tpm_build_ppi_acpi(ti, dev);
+}
+aml_append(scope, dev);
+}
-- 
2.41.0




[PATCH v5 10/14] tests: acpi: prepare for TPM CRB tests

2023-11-13 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 4 
 tests/data/acpi/q35/DSDT.crb.tpm2   | 0
 tests/data/acpi/q35/TPM2.crb.tpm2   | 0
 tests/data/acpi/virt/DSDT.crb-device.tpm2   | 0
 tests/data/acpi/virt/TPM2.crb-device.tpm2   | 0
 5 files changed, 4 insertions(+)
 create mode 100644 tests/data/acpi/q35/DSDT.crb.tpm2
 create mode 100644 tests/data/acpi/q35/TPM2.crb.tpm2
 create mode 100644 tests/data/acpi/virt/DSDT.crb-device.tpm2
 create mode 100644 tests/data/acpi/virt/TPM2.crb-device.tpm2

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..c2d1924c2f 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,5 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/q35/DSDT.crb.tpm2",
+"tests/data/acpi/q35/TPM2.crb.tpm2",
+"tests/data/acpi/virt/DSDT.crb.tpm2",
+"tests/data/acpi/virt/TPM2.crb.tpm2",
diff --git a/tests/data/acpi/q35/DSDT.crb.tpm2 
b/tests/data/acpi/q35/DSDT.crb.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/q35/TPM2.crb.tpm2 
b/tests/data/acpi/q35/TPM2.crb.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/DSDT.crb-device.tpm2 
b/tests/data/acpi/virt/DSDT.crb-device.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/TPM2.crb-device.tpm2 
b/tests/data/acpi/virt/TPM2.crb-device.tpm2
new file mode 100644
index 00..e69de29bb2
-- 
2.41.0




[PATCH v5 13/14] tests: acpi: updated expected blobs for TPM CRB

2023-11-13 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Tested-by: Stefan Berger 
---
 tests/qtest/bios-tables-test-allowed-diff.h |   4 
 tests/data/acpi/q35/DSDT.crb.tpm2   | Bin 0 -> 8355 bytes
 tests/data/acpi/q35/TPM2.crb.tpm2   | Bin 0 -> 76 bytes
 tests/data/acpi/virt/DSDT.crb-device.tpm2   | Bin 0 -> 5276 bytes
 tests/data/acpi/virt/TPM2.crb-device.tpm2   | Bin 0 -> 76 bytes
 5 files changed, 4 deletions(-)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index c2d1924c2f..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,5 +1 @@
 /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/q35/DSDT.crb.tpm2",
-"tests/data/acpi/q35/TPM2.crb.tpm2",
-"tests/data/acpi/virt/DSDT.crb.tpm2",
-"tests/data/acpi/virt/TPM2.crb.tpm2",
diff --git a/tests/data/acpi/q35/DSDT.crb.tpm2 
b/tests/data/acpi/q35/DSDT.crb.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fb89ae0ac6d4346e33156e9e4d3718698a0a1a8e
 100644
GIT binary patch
literal 8355
zcmb7JOKcm*8J^`sS}m8-l3H7S#U`8>eWXYzJ1?|oP;!?qOOz=tWv8G4E+waxod8)R
zF%Ty(AS*!P_|$}T&?B8HKyU4-*Ba=hz4_JvJ@wE_u0;`_qJIC(jyR
z|M_Nj=UdMBf#3Umi815V>Lsrkl?YJV~mdJ*J)+0vi^==Z48WDDr5BTC~XclT0V1EX9t%8FLUoL=J{8a$7|Wqc45(S`t5`0mW9UwnDx
z{mR3i|KnHp-m)?PoX4+;-wP3ag&&31>2U0PF}iNtCOSX2JYM`_#7~Phht5PHwLGvz
z6Qx?-d&^zP*8HHIAHOoX!J`}kkI_Fg!iy?@uC#YS-
zrTUv~WpJ%1@T%q7MVzRvwYx^{k)ToFRo6D!rB2I#qtrL5tKJH8@o#Z>=UiuU)T
zZ9+u1jO^nXCjd(3^l0?srP<%;MljIp6xo$K)N^k)t=pcpkO!Uqsv2HV7CxINlr
zqfHxQv(Ii1jp6O#EyJ39I>6&|+UO?|M4RF=n4OkaXRbZKuMuri#S%~yOl!FkU<(jlNIwB^beO&;Npl_0M3hZoCl~3
ziHZCio8nAh*I0HosF6cTDsyZD_r=#g~be#xQodr#2LDN~#bs|)C
z7B!tkO=nTpiBQ$KsOenPbS~;T5vn>}O{c5rbakBwRh>sPokujCM|7PCRh>sQokumD
zM|GVDRh_UgF=z2vX-U($r0Ybe>O7|DJf`V9rt3tg>O9Vwm3SsR
zevCb#F;8gB6FL*2$~>ttPioAQIuoJFJf${Mq@ssF`vFwO=K`)$^IEADxgmc6rq#`0~J_lpbC@>R6w5?C_?l`8mPd=5!FOi>6pZnBSr>_
z5Iy2p7^uL;QLK?O$v_2EhN?~_b28vL+A{i(`sS^e$&14RiI>`0?KQW
zfg+STVW0xbnJ`cVN(L_XQ0jz%3M^;BKouw%sDN@N87M+|Jz<~%%b74x1xf}g
zpqxnticso=feI{V!ax-$8K{7ACK)I~sS^e$&14RiI>`0?L_Wpa`W-7^uKf}LawZulLa7r5DzKah
z16818paRO7WS|J8P8g`bawZH^fs%m=C})y^B9uB|paRR8Fi-_b1}dPONd}5g>V$y`
zEN8+%6(|{~fN~}oC_Az;Y%GRDqI#3Mglifg+ST
zVW0xbnJ`cVN(L_XQ0jz%3M^;BKouw%sDN@N87M-j69y`}VUmF=OcK^?eeK12m6?d_<
zj{pDTxsR-!ZMJ94?O8eZrPjLForCRm%Y}I>_t^}a<4Xy**ga~qviNRAA8lI;jE<0~
zTkh|!#_awW!I5bG}{N(Y6b*5YULY%UFlVwi&>a>HxeJ4!S7Ce9g-&<9;uZ#e
zD`2c%0eSC#5jUcHL`snx6Q^y=0A
zZkx1=wHT~I#oDdZA>|dr0>%4qDQNDga`FdQwkt{!Ri1H1ke1n&7
zB+54qDBp<7H6%l<>Y}^13d0xaZ+z{XZRzJ
zA9}9ibjioqD(LC(zA%wav`tMn@mv=5ba;uFNGIB+rki-q7WH&^vzSOH+NP$Pcy3%h
z9bPvk(uuaI=_a0oBYHZ#gG{6oZBx@t+}B6-ba*kDNGIB+rkl7=m-KXaTbW2F+Vpfz
z+Z4B9w`6y(g5bLpfY&`$@Xvls$wAsJ@o85ys!qRAYy?VG&^FA-|#xCEAc~m7dzp*X5f9Ho3R9MOD)Yc5IwH6p&
zw|&{b%6pl<>IO@DUfaj!AFQ~1S0QW1s5|*u7Yb`Tk)QE@g!d1R8fDVaH#%h+!
z)D5w%l64DSul~!_*cxrKPdrGy?lxzzZBUu(KYR7Xj4G4_(7J!J8O0*n2^l3%kc7xu
zzIL4Kd4LSlTdQ3uruHMY6@{6NuM#Qc~
zMi{Z-SF84KMxk+k3r%6Pl`P2xCmV55#!L5;t+*^(UytWTLu(*7yA3rxSa&+CJ
zt-I96A-g$5uO7TQet81M?+jeNEh`;O3=B?!cXNxj-D(-J??wqX*%n=LXxr*9PZu|l
z3;nsdIenPhbKa$(XCE-k)9;pv{209G`joMWtW>gwo+j-P81RGuqX`
zeQoa1-Hj)pUFj8amdUViL9fH^JT?}4ITFLRuitP_;^DzGFsPN!v-pXp2Z`<}r+q{`
zS$sc;Pa+p{)}Qa@SqgI$KKt}#G>pggW7{y%ZrIp?VeC7cer!L9^VmLO>_2>SkDsTv
z>HU3ro2E~SY1@7#cDDW~@OyFQ;p_LF$5vsSO|+3Z+7^RQ?L#r9pIt8l
zonp_G?>ts8-HEA;+LbvBlXS0Q<;1kf=djXDX~w`FWPkT!rqk?n`COPtfpHcQS7~x{+9&8L_IGnZxjZlj6~7BLKMu;Ti2zs3VDRu@*=N|@
z#KC!aaDfh>+zska!DnbbZ*|vGR%qFdm*GYFcYgX}n#vH8>{tMuj3mv1td
z*?NtR>-5#2ucq1GeQBlYqcdVlJPl7IO|f|$vyL>3kcG^^?RJe_!|?zpBr*FKs+w
zE#Rd_VVPF;ENvb4ch9eOddo6*2IB<>!{00g>sa}Q@j?27v}vB*;hE2Sm)cJ_S)iwL
z9;Y9tnR(XXoO9it_oO#D)FJ2PsUsFK!#v9j>drz?uf*e?Vi-zlsKyOxG!Wk
HVR!t0z{JvO

literal 0
HcmV?d1

diff --git a/tests/data/acpi/q35/TPM2.crb.tpm2 
b/tests/data/acpi/q35/TPM2.crb.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9d89c5becc0fc4558a0556daf46e152181f2eb51
 100644
GIT binary patch
literal 76
zcmWFu@HO|?Wja`Jcf2v%^42yj*a0!E-1hz+7az=7e)KM>6hB2WNG#ec9c0JCKY
A0RR91

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/DSDT.crb-device.tpm2 
b/tests/data/acpi/virt/DSDT.crb-device.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1b3a8ef4cb3ab093402f4bdb2a349b3d0d015ad5
 100644
GIT binary patch
literal 5276
zcmZvg%WoT16o>D`lh__VVmr?JVHZlpGaB1Xla{u`9y^IkoEVSWAf=KkRYjC+Dp6G`
z6;jBeh3;r1RxE-P3H}TuR_xfZV9kbqfF0&{=guVOsAr^%=gi#m@$qf?%?
zrAB^f?0Q>%x$$Y`T^iQu8F~^Y@MZ
z8Dg384@p$$Wyp1!mgX@-7}qI7uG5Ufm?MlElp)t?R$?p=#!bqQ>vUXVED^>>
zlp)t?PGXb^W1TYOI?YRrHwdFn8FHN#B*sO;Xi$b+rxOz65@C3RQI+eoC^6n9j3#Bs
zbvh|A-X)9{Wyp0pB{AM7j19_=>vURTEEC2iWyp0pBQadU*rE)%PG==Xl`z_rA=l}g
z#JEftwWPqgrkH1nd8W80Lh6}jo@wTZmXCTOq@Ee(nPHw8?un3kW|?P}d7?$6o(QSuIP)B5
zp5xpTA@#)18B^my73Y{IT1x7Pkb35sXP$ZHxhF#E

[PATCH v5 14/14] tests: add TPM-CRB sysbus tests for aarch64

2023-11-13 Thread Joelle van Dyne
- Factor out common test code from tpm-crb-test.c -> tpm-tests.c
- Store device addr in `tpm_device_base_addr` (unify with TIS tests)
- Add new tests for aarch64

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 tests/qtest/tpm-tests.h |   2 +
 tests/qtest/tpm-util.h  |   4 +-
 tests/qtest/bios-tables-test.c  |   4 +-
 tests/qtest/tpm-crb-device-swtpm-test.c |  72 ++
 tests/qtest/tpm-crb-device-test.c   |  71 ++
 tests/qtest/tpm-crb-swtpm-test.c|   2 +
 tests/qtest/tpm-crb-test.c  | 121 +---
 tests/qtest/tpm-tests.c | 121 
 tests/qtest/tpm-tis-device-swtpm-test.c |   2 +-
 tests/qtest/tpm-tis-device-test.c   |   2 +-
 tests/qtest/tpm-tis-i2c-test.c  |   3 +
 tests/qtest/tpm-tis-swtpm-test.c|   2 +-
 tests/qtest/tpm-tis-test.c  |   2 +-
 tests/qtest/tpm-util.c  |  16 ++--
 tests/qtest/meson.build |   4 +
 15 files changed, 295 insertions(+), 133 deletions(-)
 create mode 100644 tests/qtest/tpm-crb-device-swtpm-test.c
 create mode 100644 tests/qtest/tpm-crb-device-test.c

diff --git a/tests/qtest/tpm-tests.h b/tests/qtest/tpm-tests.h
index 07ba60d26e..c1bfb2f914 100644
--- a/tests/qtest/tpm-tests.h
+++ b/tests/qtest/tpm-tests.h
@@ -24,4 +24,6 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
const char *ifmodel,
const char *machine_options);
 
+void tpm_test_crb(const void *data);
+
 #endif /* TESTS_TPM_TESTS_H */
diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h
index 0cb28dd6e5..c99380684e 100644
--- a/tests/qtest/tpm-util.h
+++ b/tests/qtest/tpm-util.h
@@ -15,10 +15,10 @@
 
 #include "io/channel-socket.h"
 
-extern uint64_t tpm_tis_base_addr;
+extern uint64_t tpm_device_base_addr;
 
 #define TIS_REG(LOCTY, REG) \
-(tpm_tis_base_addr + ((LOCTY) << 12) + REG)
+(tpm_device_base_addr + ((LOCTY) << 12) + REG)
 
 typedef void (tx_func)(QTestState *s,
const unsigned char *req, size_t req_size,
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index bb4ebf00c1..01e0a4aa00 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1445,7 +1445,7 @@ static void test_acpi_piix4_tcg_numamem(void)
 free_test_data();
 }
 
-uint64_t tpm_tis_base_addr;
+uint64_t tpm_device_base_addr;
 
 static test_data tcg_tpm_test_data(const char *machine)
 {
@@ -1481,7 +1481,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
 const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
 char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
 
-tpm_tis_base_addr = base;
+tpm_device_base_addr = base;
 
 module_call_init(MODULE_INIT_QOM);
 
diff --git a/tests/qtest/tpm-crb-device-swtpm-test.c 
b/tests/qtest/tpm-crb-device-swtpm-test.c
new file mode 100644
index 00..332add5ca6
--- /dev/null
+++ b/tests/qtest/tpm-crb-device-swtpm-test.c
@@ -0,0 +1,72 @@
+/*
+ * QTest testcase for TPM CRB talking to external swtpm and swtpm migration
+ *
+ * Copyright (c) 2018 IBM Corporation
+ *  with parts borrowed from migration-test.c that is:
+ * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *   Stefan Berger 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "libqtest.h"
+#include "qemu/module.h"
+#include "tpm-tests.h"
+#include "hw/acpi/tpm.h"
+
+uint64_t tpm_device_base_addr = 0xc00;
+#define MACHINE_OPTIONS "-machine virt,gic-version=max -accel tcg"
+
+typedef struct TestState {
+char *src_tpm_path;
+char *dst_tpm_path;
+char *uri;
+} TestState;
+
+static void tpm_crb_swtpm_test(const void *data)
+{
+const TestState *ts = data;
+
+tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer,
+"tpm-crb-device", MACHINE_OPTIONS);
+}
+
+static void tpm_crb_swtpm_migration_test(const void *data)
+{
+const TestState *ts = data;
+
+tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri,
+  tpm_util_crb_transfer, "tpm-crb-device",
+  MACHINE_OPTIONS);
+}
+
+int main(int argc, char **argv)
+{
+int ret;
+TestState ts = { 0 };
+
+ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XX", NULL);
+ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XX", NULL);
+ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path);
+
+module_call_in

[PATCH v5 09/14] tpm_tis_sysbus: move DSDT AML generation to device

2023-11-13 Thread Joelle van Dyne
This reduces redundant code in different machine types with ACPI table
generation. Additionally, this will allow us to support different TPM
interfaces with the same AML logic. Finally, this matches up with the
TPM TIS ISA implementation.

Ideally, we would be able to call `qbus_build_aml` and avoid any TPM
specific code in the ACPI table generation. However, currently we
still have to call `build_tpm2` anyways and it does not look like
most other ACPI devices support the `ACPI_DEV_AML_IF` interface.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/arm/virt-acpi-build.c  | 38 ++
 hw/loongarch/acpi-build.c | 38 ++
 hw/tpm/tpm_tis_sysbus.c   | 37 +
 3 files changed, 41 insertions(+), 72 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 8bc35a483c..499d30eb5d 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/aml-build.h"
@@ -208,41 +209,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const 
MemMapEntry *gpio_memmap,
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 #define ID_MAPPING_ENTRY_SIZE 20
 #define SMMU_V3_ENTRY_SIZE 68
 #define ROOT_COMPLEX_ENTRY_SIZE 36
@@ -891,7 +857,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 
 acpi_dsdt_add_power_button(scope);
 #ifdef CONFIG_TPM
-acpi_dsdt_add_tpm(scope, vms);
+call_dev_aml_func(DEVICE(tpm_find()), scope);
 #endif
 
 aml_append(dsdt, scope);
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index ae292fc543..1969bfc8f9 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -14,6 +14,7 @@
 #include "target/loongarch/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "migration/vmstate.h"
@@ -328,41 +329,6 @@ static void build_flash_aml(Aml *scope, 
LoongArchMachineState *lams)
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 /* build DSDT */
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
@@ -379,7 +345,7 @@ build_dsdt(GArray *table_data, BIOSLi

[PATCH v5 00/14] tpm: introduce TPM CRB SysBus device

2023-11-13 Thread Joelle van Dyne
The impetus for this patch set is to get TPM 2.0 working on Windows 11 ARM64.
Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
VMWare's implementation). However, the current TPM CRB device uses a fixed
system bus address that is reserved for RAM in ARM64 Virt machines.

In the process of adding the TPM CRB SysBus device, we also went ahead and
cleaned up some of the existing TPM hardware code and fixed some bugs. We used
the TPM TIS devices as a template for the TPM CRB devices and refactored out
common code. We moved the ACPI DSDT generation to the device in order to handle
dynamic base address requirements as well as reduce redundent code in different
machine ACPI generation. We also changed the tpm_crb device to use the ISA bus
instead of depending on the default system bus as the device only was built for
the PC configuration.

Another change is that the TPM CRB registers are now mapped in the same way that
the pflash ROM devices are mapped. It is a memory region whose writes are
trapped as MMIO accesses. This was needed because Apple Silicon does not decode
LDP (AARCH64 load pair of registers) caused page faults. @agraf suggested that
we do this to avoid having to do AARCH64 decoding in the HVF backend's fault
handler.

Unfortunately, it seems like the LDP fault still happens on HVF but the issue
seems to be in the HVF backend which needs to be fixed in a separate patch.

One last thing that's needed to get Windows 11 to recognize the TPM 2.0 device
is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 Virt
only recognizes the TPM TIS device through a FDT entry. A workaround is to
falsely identify the TPM CRB device as a TPM TIS device in the FDT node but this
causes issues for Linux. A proper fix would involve adding an ACPI device driver
in OVMF.

This has been tested on ARM64 with `tpm-crb-device` and on x86_64 with
`tpm-crb`. Additional testing should be performed on other architectures (RISCV
and Loongarch for example) as well as migration cases.

v5:
- Fixed a typo in "tpm_crb: use a single read-as-mem/write-as-mmio mapping"
- Fixed ACPI tables not being created for pc CRB device

v4:
- Fixed broken test blobs

v3:
- Support backwards and forwards migration of existing tpm-crb device
- Dropped patch which moved tpm-crb to ISA bus due to migration concerns
- Unified `tpm_sysbus_plug` handler for ARM and Loongarch
- Added ACPI table tests for tpm-crb-device
- Refactored TPM CRB tests to run on tpm-crb-device for ARM Virt

v2:
- Fixed an issue where VMstate restore from an older version failed due to name
  collision of the memory block.
- In the ACPI table generation for CRB devices, the check for TPM 2.0 backend is
  moved to the device realize as CRB does not support TPM 1.0. It will error in
  that case.
- Dropped the patch to fix crash when PPI is enabled on TIS SysBus device since
  a separate patch submitted by Stefan Berger disables such an option.
- Fixed an issue where we default tpmEstablished=0 when it should be 1.
- In TPM CRB SysBus's ACPI entry, we accidently changed _UID from 0 to 1. This
  shouldn't be an issue but we changed it back just in case.
- Added a patch to migrate saved VMstate from an older version with the regs
  saved separately instead of as a RAM block.

Joelle van Dyne (14):
  tpm_crb: refactor common code
  tpm_crb: CTRL_RSP_ADDR is 64-bits wide
  tpm_ppi: refactor memory space initialization
  tpm_crb: use a single read-as-mem/write-as-mmio mapping
  tpm_crb: move ACPI table building to device interface
  tpm-sysbus: add plug handler for TPM on SysBus
  hw/arm/virt: connect TPM to platform bus
  hw/loongarch/virt: connect TPM to platform bus
  tpm_tis_sysbus: move DSDT AML generation to device
  tests: acpi: prepare for TPM CRB tests
  tpm_crb_sysbus: introduce TPM CRB SysBus device
  tests: acpi: implement TPM CRB tests for ARM virt
  tests: acpi: updated expected blobs for TPM CRB
  tests: add TPM-CRB sysbus tests for aarch64

 docs/specs/tpm.rst|   2 +
 hw/tpm/tpm_crb.h  |  79 ++
 hw/tpm/tpm_ppi.h  |  10 +-
 include/hw/acpi/tpm.h |   3 +-
 include/sysemu/tpm.h  |   7 +
 tests/qtest/tpm-tests.h   |   2 +
 tests/qtest/tpm-util.h|   4 +-
 hw/acpi/aml-build.c   |   7 +-
 hw/arm/virt-acpi-build.c  |  38 +--
 hw/arm/virt.c |   8 +
 hw/core/sysbus-fdt.c  |   1 +
 hw/i386/acpi-build.c  |  16 +-
 hw/loongarch/acpi-build.c |  38 +--
 hw/loongarch/virt.c   |   8 +
 hw/riscv/virt.c   |   1 +
 hw/tpm/tpm-sysbus.c   |  47 
 hw/tpm/tpm_crb.c  | 302 ++
 hw/tpm/tpm_crb_common.c   | 262 +++
 hw/tpm/tpm_cr

[PATCH v5 07/14] hw/arm/virt: connect TPM to platform bus

2023-11-13 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/arm/virt.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 85e3c5ba9d..36e2506420 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2811,6 +2811,13 @@ static void virt_machine_device_plug_cb(HotplugHandler 
*hotplug_dev,
 vms->virtio_iommu_bdf = pci_get_bdf(pdev);
 create_virtio_iommu_dt_bindings(vms);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+tpm_sysbus_plug(TPM_IF(dev), OBJECT(vms->platform_bus_dev),
+vms->memmap[VIRT_PLATFORM_BUS].base);
+}
+#endif
 }
 
 static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
-- 
2.41.0




Re: [PATCH v4 04/14] tpm_crb: use a single read-as-mem/write-as-mmio mapping

2023-11-13 Thread Joelle van Dyne
On Wed, Nov 1, 2023 at 2:25 PM Stefan Berger  wrote:
>
>
>
> On 10/31/23 00:00, Joelle van Dyne wrote:
> > On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
> > the exception is not decoded by hardware and we cannot trap the MMIO
> > read. This led to the idea from @agraf to use the same mapping type as
> > ROM devices: namely that reads should be seen as memory type and
> > writes should trap as MMIO.
> >
> > Once that was done, the second memory mapping of the command buffer
> > region was redundent and was removed.
> >
> > A note about the removal of the read trap for `CRB_LOC_STATE`:
> > The only usage was to return the most up-to-date value for
> > `tpmEstablished`. However, `tpmEstablished` is only cleared when a
> > TPM2_HashStart operation is called which only exists for locality 4.
> > We do not handle locality 4. Indeed, the comment for the write handler
> > of `CRB_LOC_CTRL` makes the same argument for why it is not calling
> > the backend to reset the `tpmEstablished` bit (to 1).
> > As this bit is unused, we do not need to worry about updating it for
> > reads.
> >
> > In order to maintain migration compatibility with older versions of
> > QEMU, we store a copy of the register data and command data which is
> > used only during save/restore.
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
>
> > diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
> > index bee0b71fee..605e8576e9 100644
> > --- a/hw/tpm/tpm_crb_common.c
> > +++ b/hw/tpm/tpm_crb_common.c
> > @@ -31,31 +31,12 @@
> >   #include "qom/object.h"
> >   #include "tpm_crb.h"
> >
> > -static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
> > -  unsigned size)
> > +static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
> >   {
> > -TPMCRBState *s = opaque;
> > -void *regs = (void *)>regs + (addr & ~3);
> > -unsigned offset = addr & 3;
> > -uint32_t val = *(uint32_t *)regs >> (8 * offset);
> > -
> > -switch (addr) {
> > -case A_CRB_LOC_STATE:
> > -val |= !tpm_backend_get_tpm_established_flag(s->tpmbe);
> > -break;
> > -}
> > -
> > -trace_tpm_crb_mmio_read(addr, size, val);
> > -
> > -return val;
> > -}
> > -
> > -static uint8_t tpm_crb_get_active_locty(TPMCRBState *s)
> > -{
> > -if (!ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, locAssigned)) {
> > +if (!ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, locAssigned)) {
> >   return TPM_CRB_NO_LOCALITY;
> >   }
> > -return ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, activeLocality);
> > +return ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, activeLocality);
> >   }
> >
> >   static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
> > @@ -63,35 +44,47 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr 
> > addr,
> >   {
> >   TPMCRBState *s = opaque;
> >   uint8_t locty =  addr >> 12;
> > +uint32_t *regs;
> > +void *mem;
> >
> >   trace_tpm_crb_mmio_write(addr, size, val);
> > +regs = memory_region_get_ram_ptr(>mmio);
> > +mem = [R_CRB_DATA_BUFFER];
> > +assert(regs);
> > +
> > +if (addr >= A_CRB_DATA_BUFFER) {
>
>
> Can you write here /* receive TPM command bytes */ ?
Will do.

>
>
> > +assert(addr + size <= TPM_CRB_ADDR_SIZE);
> > +assert(size <= sizeof(val));
> > +memcpy(mem + addr - A_CRB_DATA_BUFFER, , size);
>
> > +memory_region_set_dirty(>mmio, addr, size);
> > +return;
> > +}
> >
> >   switch (addr) {
> >   case A_CRB_CTRL_REQ:
> >   switch (val) {
> >   case CRB_CTRL_REQ_CMD_READY:
> > -ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
> > +ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
> >tpmIdle, 0);
> >   break;
> >   case CRB_CTRL_REQ_GO_IDLE:
> > -ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
> > +ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
> >tpmIdle, 1);
> >   break;
> >   }
> >   break;
> >   case A_CRB_CTRL_CANCEL:
> >   if (val == CRB_CANCEL_INVOKE &&
> > -s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
> > +regs[R_CRB_CTRL_START] &

Re: [PATCH v4 05/14] tpm_crb: move ACPI table building to device interface

2023-11-02 Thread Joelle van Dyne
On Thu, Nov 2, 2023 at 11:50 AM Stefan Berger  wrote:
>
>
>
> On 10/31/23 00:00, Joelle van Dyne wrote:
> > This logic is similar to TPM TIS ISA device. Since TPM CRB can only
> > support TPM 2.0 backends, we check for this in realize.
>
> The problem on x86_64 is that the creation of the ACPI doesn't seem to
> get invoked. The device then ends up not working under Linux. The
> problem seems to be
>
> .parent = TYPE_DEVICE
>
> When I change this to TYPE_ISA_DEVICE it starts generating the ACPI
> table. I am not sure what other side effects this may have, though.
Ah sorry, this is probably a side effect of the patch I dropped where
the bus was moved back from ISA to SysBus. The patch was dropped
because people complained that the side effects of a new device
appearing on the ISA bus during migration is unknown. That means we
will probably have to add some logic to call the ACPI build methods on
non-ISA devices.

>
> Stefan
> >
> > Signed-off-by: Joelle van Dyne 
> > Reviewed-by: Stefan Berger 
> > ---
> >   hw/tpm/tpm_crb.h|  2 ++
> >   hw/i386/acpi-build.c| 23 ---
> >   hw/tpm/tpm_crb.c| 16 
> >   hw/tpm/tpm_crb_common.c | 19 +++
> >   4 files changed, 37 insertions(+), 23 deletions(-)
> >
> > diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
> > index 36863e1664..e6a86e3fd1 100644
> > --- a/hw/tpm/tpm_crb.h
> > +++ b/hw/tpm/tpm_crb.h
> > @@ -73,5 +73,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, 
> > Error **errp);
> >   void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void 
> > *saved_cmdmem);
> >   void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
> > const void *saved_cmdmem);
> > +void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t baseaddr, uint32_t 
> > size,
> > +   bool build_ppi);
> >
> >   #endif /* TPM_TPM_CRB_H */
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 80db183b78..ce3f7b2d91 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >   uint32_t nr_mem = machine->ram_slots;
> >   int root_bus_limit = 0xFF;
> >   PCIBus *bus = NULL;
> > -#ifdef CONFIG_TPM
> > -TPMIf *tpm = tpm_find();
> > -#endif
> >   bool cxl_present = false;
> >   int i;
> >   VMBusBridge *vmbus_bridge = vmbus_bridge_find();
> > @@ -1790,26 +1787,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >   }
> >   }
> >
> > -#ifdef CONFIG_TPM
> > -if (TPM_IS_CRB(tpm)) {
> > -dev = aml_device("TPM");
> > -aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > -aml_append(dev, aml_name_decl("_STR",
> > -  aml_string("TPM 2.0 Device")));
> > -crs = aml_resource_template();
> > -aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> > -   TPM_CRB_ADDR_SIZE, 
> > AML_READ_WRITE));
> > -aml_append(dev, aml_name_decl("_CRS", crs));
> > -
> > -aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
> > -aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > -
> > -tpm_build_ppi_acpi(tpm, dev);
> > -
> > -aml_append(sb_scope, dev);
> > -}
> > -#endif
> > -
> >   if (pcms->sgx_epc.size != 0) {
> >   uint64_t epc_base = pcms->sgx_epc.base;
> >   uint64_t epc_size = pcms->sgx_epc.size;
> > diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> > index 99c64dd72a..8d57295b15 100644
> > --- a/hw/tpm/tpm_crb.c
> > +++ b/hw/tpm/tpm_crb.c
> > @@ -19,6 +19,8 @@
> >   #include "qemu/module.h"
> >   #include "qapi/error.h"
> >   #include "exec/address-spaces.h"
> > +#include "hw/acpi/acpi_aml_interface.h"
> > +#include "hw/acpi/tpm.h"
> >   #include "hw/qdev-properties.h"
> >   #include "hw/pci/pci_ids.h"
> >   #include "hw/acpi/tpm.h"
> > @@ -121,6 +123,11 @@ static void tpm_crb_none_realize(DeviceState *dev, 
> > Error **errp)
> >   return;
> >   }
> >
> > +if (tpm_crb_none_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> > +error_setg(errp, "TPM CRB only supports 

[PATCH v4 13/14] tests: acpi: updated expected blobs for TPM CRB

2023-10-30 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
---
 tests/qtest/bios-tables-test-allowed-diff.h |   4 
 tests/data/acpi/q35/DSDT.crb.tpm2   | Bin 0 -> 8355 bytes
 tests/data/acpi/q35/TPM2.crb.tpm2   | Bin 0 -> 76 bytes
 tests/data/acpi/virt/DSDT.crb-device.tpm2   | Bin 0 -> 5276 bytes
 tests/data/acpi/virt/TPM2.crb-device.tpm2   | Bin 0 -> 76 bytes
 5 files changed, 4 deletions(-)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index c2d1924c2f..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,5 +1 @@
 /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/q35/DSDT.crb.tpm2",
-"tests/data/acpi/q35/TPM2.crb.tpm2",
-"tests/data/acpi/virt/DSDT.crb.tpm2",
-"tests/data/acpi/virt/TPM2.crb.tpm2",
diff --git a/tests/data/acpi/q35/DSDT.crb.tpm2 
b/tests/data/acpi/q35/DSDT.crb.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fb89ae0ac6d4346e33156e9e4d3718698a0a1a8e
 100644
GIT binary patch
literal 8355
zcmb7JOKcm*8J^`sS}m8-l3H7S#U`8>eWXYzJ1?|oP;!?qOOz=tWv8G4E+waxod8)R
zF%Ty(AS*!P_|$}T&?B8HKyU4-*Ba=hz4_JvJ@wE_u0;`_qJIC(jyR
z|M_Nj=UdMBf#3Umi815V>Lsrkl?YJV~mdJ*J)+0vi^==Z48WDDr5BTC~XclT0V1EX9t%8FLUoL=J{8a$7|Wqc45(S`t5`0mW9UwnDx
z{mR3i|KnHp-m)?PoX4+;-wP3ag&&31>2U0PF}iNtCOSX2JYM`_#7~Phht5PHwLGvz
z6Qx?-d&^zP*8HHIAHOoX!J`}kkI_Fg!iy?@uC#YS-
zrTUv~WpJ%1@T%q7MVzRvwYx^{k)ToFRo6D!rB2I#qtrL5tKJH8@o#Z>=UiuU)T
zZ9+u1jO^nXCjd(3^l0?srP<%;MljIp6xo$K)N^k)t=pcpkO!Uqsv2HV7CxINlr
zqfHxQv(Ii1jp6O#EyJ39I>6&|+UO?|M4RF=n4OkaXRbZKuMuri#S%~yOl!FkU<(jlNIwB^beO&;Npl_0M3hZoCl~3
ziHZCio8nAh*I0HosF6cTDsyZD_r=#g~be#xQodr#2LDN~#bs|)C
z7B!tkO=nTpiBQ$KsOenPbS~;T5vn>}O{c5rbakBwRh>sPokujCM|7PCRh>sQokumD
zM|GVDRh_UgF=z2vX-U($r0Ybe>O7|DJf`V9rt3tg>O9Vwm3SsR
zevCb#F;8gB6FL*2$~>ttPioAQIuoJFJf${Mq@ssF`vFwO=K`)$^IEADxgmc6rq#`0~J_lpbC@>R6w5?C_?l`8mPd=5!FOi>6pZnBSr>_
z5Iy2p7^uL;QLK?O$v_2EhN?~_b28vL+A{i(`sS^e$&14RiI>`0?KQW
zfg+STVW0xbnJ`cVN(L_XQ0jz%3M^;BKouw%sDN@N87M+|Jz<~%%b74x1xf}g
zpqxnticso=feI{V!ax-$8K{7ACK)I~sS^e$&14RiI>`0?L_Wpa`W-7^uKf}LawZulLa7r5DzKah
z16818paRO7WS|J8P8g`bawZH^fs%m=C})y^B9uB|paRR8Fi-_b1}dPONd}5g>V$y`
zEN8+%6(|{~fN~}oC_Az;Y%GRDqI#3Mglifg+ST
zVW0xbnJ`cVN(L_XQ0jz%3M^;BKouw%sDN@N87M-j69y`}VUmF=OcK^?eeK12m6?d_<
zj{pDTxsR-!ZMJ94?O8eZrPjLForCRm%Y}I>_t^}a<4Xy**ga~qviNRAA8lI;jE<0~
zTkh|!#_awW!I5bG}{N(Y6b*5YULY%UFlVwi&>a>HxeJ4!S7Ce9g-&<9;uZ#e
zD`2c%0eSC#5jUcHL`snx6Q^y=0A
zZkx1=wHT~I#oDdZA>|dr0>%4qDQNDga`FdQwkt{!Ri1H1ke1n&7
zB+54qDBp<7H6%l<>Y}^13d0xaZ+z{XZRzJ
zA9}9ibjioqD(LC(zA%wav`tMn@mv=5ba;uFNGIB+rki-q7WH&^vzSOH+NP$Pcy3%h
z9bPvk(uuaI=_a0oBYHZ#gG{6oZBx@t+}B6-ba*kDNGIB+rkl7=m-KXaTbW2F+Vpfz
z+Z4B9w`6y(g5bLpfY&`$@Xvls$wAsJ@o85ys!qRAYy?VG&^FA-|#xCEAc~m7dzp*X5f9Ho3R9MOD)Yc5IwH6p&
zw|&{b%6pl<>IO@DUfaj!AFQ~1S0QW1s5|*u7Yb`Tk)QE@g!d1R8fDVaH#%h+!
z)D5w%l64DSul~!_*cxrKPdrGy?lxzzZBUu(KYR7Xj4G4_(7J!J8O0*n2^l3%kc7xu
zzIL4Kd4LSlTdQ3uruHMY6@{6NuM#Qc~
zMi{Z-SF84KMxk+k3r%6Pl`P2xCmV55#!L5;t+*^(UytWTLu(*7yA3rxSa&+CJ
zt-I96A-g$5uO7TQet81M?+jeNEh`;O3=B?!cXNxj-D(-J??wqX*%n=LXxr*9PZu|l
z3;nsdIenPhbKa$(XCE-k)9;pv{209G`joMWtW>gwo+j-P81RGuqX`
zeQoa1-Hj)pUFj8amdUViL9fH^JT?}4ITFLRuitP_;^DzGFsPN!v-pXp2Z`<}r+q{`
zS$sc;Pa+p{)}Qa@SqgI$KKt}#G>pggW7{y%ZrIp?VeC7cer!L9^VmLO>_2>SkDsTv
z>HU3ro2E~SY1@7#cDDW~@OyFQ;p_LF$5vsSO|+3Z+7^RQ?L#r9pIt8l
zonp_G?>ts8-HEA;+LbvBlXS0Q<;1kf=djXDX~w`FWPkT!rqk?n`COPtfpHcQS7~x{+9&8L_IGnZxjZlj6~7BLKMu;Ti2zs3VDRu@*=N|@
z#KC!aaDfh>+zska!DnbbZ*|vGR%qFdm*GYFcYgX}n#vH8>{tMuj3mv1td
z*?NtR>-5#2ucq1GeQBlYqcdVlJPl7IO|f|$vyL>3kcG^^?RJe_!|?zpBr*FKs+w
zE#Rd_VVPF;ENvb4ch9eOddo6*2IB<>!{00g>sa}Q@j?27v}vB*;hE2Sm)cJ_S)iwL
z9;Y9tnR(XXoO9it_oO#D)FJ2PsUsFK!#v9j>drz?uf*e?Vi-zlsKyOxG!Wk
HVR!t0z{JvO

literal 0
HcmV?d1

diff --git a/tests/data/acpi/q35/TPM2.crb.tpm2 
b/tests/data/acpi/q35/TPM2.crb.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9d89c5becc0fc4558a0556daf46e152181f2eb51
 100644
GIT binary patch
literal 76
zcmWFu@HO|?Wja`Jcf2v%^42yj*a0!E-1hz+7az=7e)KM>6hB2WNG#ec9c0JCKY
A0RR91

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/DSDT.crb-device.tpm2 
b/tests/data/acpi/virt/DSDT.crb-device.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..1b3a8ef4cb3ab093402f4bdb2a349b3d0d015ad5
 100644
GIT binary patch
literal 5276
zcmZvg%WoT16o>D`lh__VVmr?JVHZlpGaB1Xla{u`9y^IkoEVSWAf=KkRYjC+Dp6G`
z6;jBeh3;r1RxE-P3H}TuR_xfZV9kbqfF0&{=guVOsAr^%=gi#m@$qf?%?
zrAB^f?0Q>%x$$Y`T^iQu8F~^Y@MZ
z8Dg384@p$$Wyp1!mgX@-7}qI7uG5Ufm?MlElp)t?R$?p=#!bqQ>vUXVED^>>
zlp)t?PGXb^W1TYOI?YRrHwdFn8FHN#B*sO;Xi$b+rxOz65@C3RQI+eoC^6n9j3#Bs
zbvh|A-X)9{Wyp0pB{AM7j19_=>vURTEEC2iWyp0pBQadU*rE)%PG==Xl`z_rA=l}g
z#JEftwWPqgrkH1nd8W80Lh6}jo@wTZmXCTOq@Ee(nPHw8?un3kW|?P}d7?$6o(QSuIP)B5
zp5xpTA@#)18B^my73Y{IT1x7Pkb35sXP$ZHxhF#ESzw+8=7|=RdLpEr6U=jhc}{Ro

[PATCH v4 07/14] hw/arm/virt: connect TPM to platform bus

2023-10-30 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/arm/virt.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 529f1c089c..f1a161b0ea 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2806,6 +2806,13 @@ static void virt_machine_device_plug_cb(HotplugHandler 
*hotplug_dev,
 vms->virtio_iommu_bdf = pci_get_bdf(pdev);
 create_virtio_iommu_dt_bindings(vms);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+tpm_sysbus_plug(TPM_IF(dev), OBJECT(vms->platform_bus_dev),
+vms->memmap[VIRT_PLATFORM_BUS].base);
+}
+#endif
 }
 
 static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
-- 
2.41.0




[PATCH v4 01/14] tpm_crb: refactor common code

2023-10-30 Thread Joelle van Dyne
In preparation for the SysBus variant, we move common code styled
after the TPM TIS devices.

To maintain compatibility, we do not rename the existing tpm-crb
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 docs/specs/tpm.rst  |   1 +
 hw/tpm/tpm_crb.h|  76 +++
 hw/tpm/tpm_crb.c| 270 ++--
 hw/tpm/tpm_crb_common.c | 216 
 hw/tpm/meson.build  |   1 +
 hw/tpm/trace-events |   2 +-
 6 files changed, 331 insertions(+), 235 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index efe124a148..2bc29c9804 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -45,6 +45,7 @@ operating system.
 
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
+ - ``hw/tpm/tpm_crb_common.c``
 
 SPAPR interface
 ---
diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
new file mode 100644
index 00..da3a0cf256
--- /dev/null
+++ b/hw/tpm/tpm_crb.h
@@ -0,0 +1,76 @@
+/*
+ * tpm_crb.h - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Marc-André Lureau 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+#ifndef TPM_TPM_CRB_H
+#define TPM_TPM_CRB_H
+
+#include "exec/memory.h"
+#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_ppi.h"
+
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
+
+typedef struct TPMCRBState {
+TPMBackend *tpmbe;
+TPMBackendCmd cmd;
+uint32_t regs[TPM_CRB_R_MAX];
+MemoryRegion mmio;
+MemoryRegion cmdmem;
+
+size_t be_buffer_size;
+
+bool ppi_enabled;
+TPMPPI ppi;
+} TPMCRBState;
+
+#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
+#define CRB_INTF_VERSION_CRB 0b1
+#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
+#define CRB_INTF_CAP_IDLE_FAST 0b0
+#define CRB_INTF_CAP_XFER_SIZE_64 0b11
+#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
+#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
+#define CRB_INTF_IF_SELECTOR_CRB 0b1
+
+enum crb_loc_ctrl {
+CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+CRB_LOC_CTRL_RELINQUISH = BIT(1),
+CRB_LOC_CTRL_SEIZE = BIT(2),
+CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
+};
+
+enum crb_ctrl_req {
+CRB_CTRL_REQ_CMD_READY = BIT(0),
+CRB_CTRL_REQ_GO_IDLE = BIT(1),
+};
+
+enum crb_start {
+CRB_START_INVOKE = BIT(0),
+};
+
+enum crb_cancel {
+CRB_CANCEL_INVOKE = BIT(0),
+};
+
+#define TPM_CRB_NO_LOCALITY 0xff
+
+void tpm_crb_request_completed(TPMCRBState *s, int ret);
+enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
+int tpm_crb_pre_save(TPMCRBState *s);
+void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
+void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+
+#endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index ea930da545..3ef4977fb5 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -31,257 +31,62 @@
 #include "tpm_ppi.h"
 #include "trace.h"
 #include "qom/object.h"
+#include "tpm_crb.h"
 
 struct CRBState {
 DeviceState parent_obj;
 
-TPMBackend *tpmbe;
-TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
-MemoryRegion mmio;
-MemoryRegion cmdmem;
-
-size_t be_buffer_size;
-
-bool ppi_enabled;
-TPMPPI ppi;
+TPMCRBState state;
 };
 typedef struct CRBState CRBState;
 
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  TYPE_TPM_CRB)
 
-#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
-#define CRB_INTF_VERSION_CRB 0b1
-#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
-#define CRB_INTF_CAP_IDLE_FAST 0b0
-#define CRB_INTF_CAP_XFER_SIZE_64 0b11
-#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
-#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
-#define CRB_INTF_IF_SELECTOR_CRB 0b1
-
-#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
-
-enum crb_loc_ctrl {
-CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
-CRB_LOC_CTRL_RELINQUISH = BIT(1),
-CRB_LOC_CTRL_SEIZE = BIT(2),
-CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
-};
-
-enum crb_ctrl_req {
-CRB_CTRL_REQ_CMD_READY = BIT(0),
-CRB_CTRL_REQ_GO_IDLE = BIT(1),
-};
-
-enum crb_start {
-CRB_START_INVOKE = BIT(0),
-};
-
-enum crb_cancel {
-CRB_CANCEL_INVOKE = BIT(0),
-};
-
-#define TPM_CRB_NO_LOCALITY 0xff
-
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
-{
-CRBState *s = CRB(opaque);
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-s

[PATCH v4 06/14] tpm-sysbus: add plug handler for TPM on SysBus

2023-10-30 Thread Joelle van Dyne
TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne 
---
 include/sysemu/tpm.h |  4 
 hw/tpm/tpm-sysbus.c  | 47 
 hw/tpm/meson.build   |  1 +
 3 files changed, 52 insertions(+)
 create mode 100644 hw/tpm/tpm-sysbus.c

diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 1ee568b3b6..ffd300e607 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -12,6 +12,8 @@
 #ifndef QEMU_TPM_H
 #define QEMU_TPM_H
 
+#include "qemu/osdep.h"
+#include "exec/hwaddr.h"
 #include "qapi/qapi-types-tpm.h"
 #include "qom/object.h"
 
@@ -78,6 +80,8 @@ static inline TPMVersion tpm_get_version(TPMIf *ti)
 return TPM_IF_GET_CLASS(ti)->get_version(ti);
 }
 
+void tpm_sysbus_plug(TPMIf *tpmif, Object *pbus, hwaddr pbus_base);
+
 #else /* CONFIG_TPM */
 
 #define tpm_init()  (0)
diff --git a/hw/tpm/tpm-sysbus.c b/hw/tpm/tpm-sysbus.c
new file mode 100644
index 00..732ce34c73
--- /dev/null
+++ b/hw/tpm/tpm-sysbus.c
@@ -0,0 +1,47 @@
+/*
+ * tpm-sysbus.c - Support functions for SysBus TPM devices
+ *
+ * Copyright (c) 2023 QEMU contributors
+ *
+ * Authors:
+ *   Joelle van Dyne 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "sysemu/tpm.h"
+#include "hw/platform-bus.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+
+/**
+ * Called from a machine's pre_plug handler to set the device's physical addr.
+ */
+void tpm_sysbus_plug(TPMIf *tpmif, Object *pbus, hwaddr pbus_base)
+{
+PlatformBusDevice *pbusdev = PLATFORM_BUS_DEVICE(pbus);
+SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+MemoryRegion *sbdev_mr;
+hwaddr tpm_base;
+uint64_t tpm_size;
+
+/* exit early if TPM is not a sysbus device */
+if (!object_dynamic_cast(OBJECT(tpmif), TYPE_SYS_BUS_DEVICE)) {
+return;
+}
+
+assert(object_dynamic_cast(pbus, TYPE_PLATFORM_BUS_DEVICE));
+
+tpm_base = platform_bus_get_mmio_addr(pbusdev, sbdev, 0);
+assert(tpm_base != -1);
+
+tpm_base += pbus_base;
+
+sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+tpm_size = memory_region_size(sbdev_mr);
+
+object_property_set_uint(OBJECT(sbdev), "x-baseaddr",
+ tpm_base, _abort);
+object_property_set_uint(OBJECT(sbdev), "x-size",
+ tpm_size, _abort);
+}
diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
index cb8204d5bc..3060ac05e8 100644
--- a/hw/tpm/meson.build
+++ b/hw/tpm/meson.build
@@ -1,6 +1,7 @@
 system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_tis_common.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_ISA', if_true: files('tpm_tis_isa.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: 
files('tpm_tis_sysbus.c'))
+system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm-sysbus.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
-- 
2.41.0




[PATCH v4 08/14] hw/loongarch/virt: connect TPM to platform bus

2023-10-30 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/loongarch/virt.c  | 7 +++
 hw/loongarch/Kconfig | 1 +
 2 files changed, 8 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 4b7dc67a2d..feed0f8bbf 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1004,6 +1004,13 @@ static void 
loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 } else if (memhp_type_supported(dev)) {
 virt_mem_plug(hotplug_dev, dev, errp);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+tpm_sysbus_plug(TPM_IF(dev), OBJECT(lams->platform_bus_dev),
+VIRT_PLATFORM_BUS_BASEADDRESS);
+}
+#endif
 }
 
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 5727efed6d..25da190ffc 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -5,6 +5,7 @@ config LOONGARCH_VIRT
 imply VIRTIO_VGA
 imply PCI_DEVICES
 imply NVDIMM
+imply TPM_TIS_SYSBUS
 select SERIAL
 select VIRTIO_PCI
 select PLATFORM_BUS
-- 
2.41.0




[PATCH v4 05/14] tpm_crb: move ACPI table building to device interface

2023-10-30 Thread Joelle van Dyne
This logic is similar to TPM TIS ISA device. Since TPM CRB can only
support TPM 2.0 backends, we check for this in realize.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_crb.h|  2 ++
 hw/i386/acpi-build.c| 23 ---
 hw/tpm/tpm_crb.c| 16 
 hw/tpm/tpm_crb_common.c | 19 +++
 4 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index 36863e1664..e6a86e3fd1 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -73,5 +73,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp);
 void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void 
*saved_cmdmem);
 void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
   const void *saved_cmdmem);
+void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t baseaddr, uint32_t size,
+   bool build_ppi);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 80db183b78..ce3f7b2d91 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 uint32_t nr_mem = machine->ram_slots;
 int root_bus_limit = 0xFF;
 PCIBus *bus = NULL;
-#ifdef CONFIG_TPM
-TPMIf *tpm = tpm_find();
-#endif
 bool cxl_present = false;
 int i;
 VMBusBridge *vmbus_bridge = vmbus_bridge_find();
@@ -1790,26 +1787,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 }
 
-#ifdef CONFIG_TPM
-if (TPM_IS_CRB(tpm)) {
-dev = aml_device("TPM");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR",
-  aml_string("TPM 2.0 Device")));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
-   TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-
-aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
-aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-
-tpm_build_ppi_acpi(tpm, dev);
-
-aml_append(sb_scope, dev);
-}
-#endif
-
 if (pcms->sgx_epc.size != 0) {
 uint64_t epc_base = pcms->sgx_epc.base;
 uint64_t epc_size = pcms->sgx_epc.size;
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 99c64dd72a..8d57295b15 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -19,6 +19,8 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
+#include "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
@@ -121,6 +123,11 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
+if (tpm_crb_none_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
+error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
+return;
+}
+
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
 /* only used for migration */
@@ -142,10 +149,17 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
+static void build_tpm_crb_none_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+tpm_crb_build_aml(TPM_IF(adev), scope, TPM_CRB_ADDR_BASE, 
TPM_CRB_ADDR_SIZE,
+  true);
+}
+
 static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 TPMIfClass *tc = TPM_IF_CLASS(klass);
+AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
 
 dc->realize = tpm_crb_none_realize;
 device_class_set_props(dc, tpm_crb_none_properties);
@@ -154,6 +168,7 @@ static void tpm_crb_none_class_init(ObjectClass *klass, 
void *data)
 tc->model = TPM_MODEL_TPM_CRB;
 tc->get_version = tpm_crb_none_get_version;
 tc->request_completed = tpm_crb_none_request_completed;
+adevc->build_dev_aml = build_tpm_crb_none_aml;
 
 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
@@ -166,6 +181,7 @@ static const TypeInfo tpm_crb_none_info = {
 .class_init  = tpm_crb_none_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_TPM_IF },
+{ TYPE_ACPI_DEV_AML_IF },
 { }
 }
 };
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 605e8576e9..4fff0c6b59 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -239,3 +239,22 @@ void tpm_crb_mem_load(TPMCRBState *s, const uint32_t 
*saved_regs,
 memcpy(regs, saved_regs, TPM_CRB_R_MAX);
 memcpy([R_CRB_DATA_BUFFER], saved_cmdmem, A_CRB_DATA_BUFFER);
 }
+
+void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t ba

[PATCH v4 10/14] tests: acpi: prepare for TPM CRB tests

2023-10-30 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 4 
 tests/data/acpi/q35/DSDT.crb.tpm2   | 0
 tests/data/acpi/q35/TPM2.crb.tpm2   | 0
 tests/data/acpi/virt/DSDT.crb-device.tpm2   | 0
 tests/data/acpi/virt/TPM2.crb-device.tpm2   | 0
 5 files changed, 4 insertions(+)
 create mode 100644 tests/data/acpi/q35/DSDT.crb.tpm2
 create mode 100644 tests/data/acpi/q35/TPM2.crb.tpm2
 create mode 100644 tests/data/acpi/virt/DSDT.crb-device.tpm2
 create mode 100644 tests/data/acpi/virt/TPM2.crb-device.tpm2

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..c2d1924c2f 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,5 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/q35/DSDT.crb.tpm2",
+"tests/data/acpi/q35/TPM2.crb.tpm2",
+"tests/data/acpi/virt/DSDT.crb.tpm2",
+"tests/data/acpi/virt/TPM2.crb.tpm2",
diff --git a/tests/data/acpi/q35/DSDT.crb.tpm2 
b/tests/data/acpi/q35/DSDT.crb.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/q35/TPM2.crb.tpm2 
b/tests/data/acpi/q35/TPM2.crb.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/DSDT.crb-device.tpm2 
b/tests/data/acpi/virt/DSDT.crb-device.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/TPM2.crb-device.tpm2 
b/tests/data/acpi/virt/TPM2.crb-device.tpm2
new file mode 100644
index 00..e69de29bb2
-- 
2.41.0




[PATCH v4 00/14] tpm: introduce TPM CRB SysBus device

2023-10-30 Thread Joelle van Dyne
The impetus for this patch set is to get TPM 2.0 working on Windows 11 ARM64.
Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
VMWare's implementation). However, the current TPM CRB device uses a fixed
system bus address that is reserved for RAM in ARM64 Virt machines.

In the process of adding the TPM CRB SysBus device, we also went ahead and
cleaned up some of the existing TPM hardware code and fixed some bugs. We used
the TPM TIS devices as a template for the TPM CRB devices and refactored out
common code. We moved the ACPI DSDT generation to the device in order to handle
dynamic base address requirements as well as reduce redundent code in different
machine ACPI generation. We also changed the tpm_crb device to use the ISA bus
instead of depending on the default system bus as the device only was built for
the PC configuration.

Another change is that the TPM CRB registers are now mapped in the same way that
the pflash ROM devices are mapped. It is a memory region whose writes are
trapped as MMIO accesses. This was needed because Apple Silicon does not decode
LDP (AARCH64 load pair of registers) caused page faults. @agraf suggested that
we do this to avoid having to do AARCH64 decoding in the HVF backend's fault
handler.

Unfortunately, it seems like the LDP fault still happens on HVF but the issue
seems to be in the HVF backend which needs to be fixed in a separate patch.

One last thing that's needed to get Windows 11 to recognize the TPM 2.0 device
is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 Virt
only recognizes the TPM TIS device through a FDT entry. A workaround is to
falsely identify the TPM CRB device as a TPM TIS device in the FDT node but this
causes issues for Linux. A proper fix would involve adding an ACPI device driver
in OVMF.

This has been tested on ARM64 with `tpm-crb-device` and on x86_64 with
`tpm-crb`. Additional testing should be performed on other architectures (RISCV
and Loongarch for example) as well as migration cases.

v4:
- Fixed broken test blobs

v3:
- Support backwards and forwards migration of existing tpm-crb device
- Dropped patch which moved tpm-crb to ISA bus due to migration concerns
- Unified `tpm_sysbus_plug` handler for ARM and Loongarch
- Added ACPI table tests for tpm-crb-device
- Refactored TPM CRB tests to run on tpm-crb-device for ARM Virt

v2:
- Fixed an issue where VMstate restore from an older version failed due to name
  collision of the memory block.
- In the ACPI table generation for CRB devices, the check for TPM 2.0 backend is
  moved to the device realize as CRB does not support TPM 1.0. It will error in
  that case.
- Dropped the patch to fix crash when PPI is enabled on TIS SysBus device since
  a separate patch submitted by Stefan Berger disables such an option.
- Fixed an issue where we default tpmEstablished=0 when it should be 1.
- In TPM CRB SysBus's ACPI entry, we accidently changed _UID from 0 to 1. This
  shouldn't be an issue but we changed it back just in case.
- Added a patch to migrate saved VMstate from an older version with the regs
  saved separately instead of as a RAM block.

Joelle van Dyne (14):
  tpm_crb: refactor common code
  tpm_crb: CTRL_RSP_ADDR is 64-bits wide
  tpm_ppi: refactor memory space initialization
  tpm_crb: use a single read-as-mem/write-as-mmio mapping
  tpm_crb: move ACPI table building to device interface
  tpm-sysbus: add plug handler for TPM on SysBus
  hw/arm/virt: connect TPM to platform bus
  hw/loongarch/virt: connect TPM to platform bus
  tpm_tis_sysbus: move DSDT AML generation to device
  tests: acpi: prepare for TPM CRB tests
  tpm_crb_sysbus: introduce TPM CRB SysBus device
  tests: acpi: implement TPM CRB tests for ARM virt
  tests: acpi: updated expected blobs for TPM CRB
  tests: add TPM-CRB sysbus tests for aarch64

 docs/specs/tpm.rst|   2 +
 hw/tpm/tpm_crb.h  |  79 ++
 hw/tpm/tpm_ppi.h  |  10 +-
 include/hw/acpi/tpm.h |   3 +-
 include/sysemu/tpm.h  |   7 +
 tests/qtest/tpm-tests.h   |   2 +
 tests/qtest/tpm-util.h|   4 +-
 hw/acpi/aml-build.c   |   7 +-
 hw/arm/virt-acpi-build.c  |  38 +--
 hw/arm/virt.c |   8 +
 hw/core/sysbus-fdt.c  |   1 +
 hw/i386/acpi-build.c  |  23 --
 hw/loongarch/acpi-build.c |  38 +--
 hw/loongarch/virt.c   |   8 +
 hw/riscv/virt.c   |   1 +
 hw/tpm/tpm-sysbus.c   |  47 
 hw/tpm/tpm_crb.c  | 302 ++
 hw/tpm/tpm_crb_common.c   | 260 +++
 hw/tpm/tpm_crb_sysbus.c   | 162 
 hw/tpm/tpm_ppi.c  |   5 +-
 hw/tpm/tpm_tis_isa.c  |   5

[PATCH v4 03/14] tpm_ppi: refactor memory space initialization

2023-10-30 Thread Joelle van Dyne
Instead of calling `memory_region_add_subregion` directly, we defer to
the caller to do it. This allows us to re-use the code for a SysBus
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_ppi.h| 10 +++---
 hw/tpm/tpm_crb.c|  4 ++--
 hw/tpm/tpm_crb_common.c |  3 +++
 hw/tpm/tpm_ppi.c|  5 +
 hw/tpm/tpm_tis_isa.c|  5 +++--
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h
index bf5d4a300f..30863c6438 100644
--- a/hw/tpm/tpm_ppi.h
+++ b/hw/tpm/tpm_ppi.h
@@ -20,17 +20,13 @@ typedef struct TPMPPI {
 } TPMPPI;
 
 /**
- * tpm_ppi_init:
+ * tpm_ppi_init_memory:
  * @tpmppi: a TPMPPI
- * @m: the address-space / MemoryRegion to use
- * @addr: the address of the PPI region
  * @obj: the owner object
  *
- * Register the TPM PPI memory region at @addr on the given address
- * space for the object @obj.
+ * Creates the TPM PPI memory region.
  **/
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj);
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj);
 
 /**
  * tpm_ppi_reset:
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 3ef4977fb5..598c3e0161 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -107,8 +107,8 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
-tpm_ppi_init(>state.ppi, get_system_memory(),
- TPM_PPI_ADDR_BASE, OBJECT(s));
+memory_region_add_subregion(get_system_memory(),
+TPM_PPI_ADDR_BASE, >state.ppi.ram);
 }
 
 if (xen_enabled()) {
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 01b35808f6..bee0b71fee 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -214,4 +214,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp)
 "tpm-crb-mmio", sizeof(s->regs));
 memory_region_init_ram(>cmdmem, obj,
 "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+if (s->ppi_enabled) {
+tpm_ppi_init_memory(>ppi, obj);
+}
 }
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 7f74e26ec6..40cab59afa 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -44,14 +44,11 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
 }
 }
 
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj)
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj)
 {
 tpmppi->buf = qemu_memalign(qemu_real_host_page_size(),
 HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
 memory_region_init_ram_device_ptr(>ram, obj, "tpm-ppi",
   TPM_PPI_ADDR_SIZE, tpmppi->buf);
 vmstate_register_ram(>ram, DEVICE(obj));
-
-memory_region_add_subregion(m, addr, >ram);
 }
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 0367401586..d596f38c0f 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -134,8 +134,9 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error 
**errp)
 TPM_TIS_ADDR_BASE, >mmio);
 
 if (s->ppi_enabled) {
-tpm_ppi_init(>ppi, isa_address_space(ISA_DEVICE(dev)),
- TPM_PPI_ADDR_BASE, OBJECT(dev));
+tpm_ppi_init_memory(>ppi, OBJECT(dev));
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
+TPM_PPI_ADDR_BASE, >ppi.ram);
 }
 }
 
-- 
2.41.0




[PATCH v4 11/14] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-10-30 Thread Joelle van Dyne
This SysBus variant of the CRB interface supports dynamically locating
the MMIO interface so that Virt machines can use it. This interface
is currently the only one supported by QEMU that works on Windows 11
ARM64 as 'tpm-tis-device' does not work with current Windows drivers.
We largely follow that device as a template.

To try out this device with Windows 11 before OVMF is updated, you
will need to modify `sysbus-fdt.c` and change the added line from:

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
```

to

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
```

This change was not included because it can confuse Linux (although
from testing, it seems like Linux is able to properly ignore the
device from the TPM TIS driver and recognize it from the ACPI device
in the TPM CRB driver). A proper fix would require OVMF to recognize
the ACPI device and not depend on the FDT node for recognizing TPM.

The command line to try out this device with SWTPM is:

```
$ qemu-system-aarch64 \
-chardev socket,id=chrtpm0,path=tpm.sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm0 \
-device tpm-crb-device,tpmdev=tpm0
```

along with SWTPM:

```
$ swtpm \
--ctrl type=unixio,path=tpm.sock,terminate \
--tpmstate backend-uri=file://tpm.data \
--tpm2
```

Signed-off-by: Joelle van Dyne 
---
 docs/specs/tpm.rst  |   1 +
 include/sysemu/tpm.h|   3 +
 hw/acpi/aml-build.c |   7 +-
 hw/arm/virt.c   |   1 +
 hw/core/sysbus-fdt.c|   1 +
 hw/loongarch/virt.c |   1 +
 hw/riscv/virt.c |   1 +
 hw/tpm/tpm_crb_sysbus.c | 162 
 hw/arm/Kconfig  |   1 +
 hw/loongarch/Kconfig|   1 +
 hw/riscv/Kconfig|   1 +
 hw/tpm/Kconfig  |   5 ++
 hw/tpm/meson.build  |   3 +
 13 files changed, 187 insertions(+), 1 deletion(-)
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index 2bc29c9804..95aeb49220 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -46,6 +46,7 @@ operating system.
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
  - ``hw/tpm/tpm_crb_common.c``
+ - ``hw/tpm/tpm_crb_sysbus.c``
 
 SPAPR interface
 ---
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index ffd300e607..bab30fa546 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -49,6 +49,7 @@ struct TPMIfClass {
 #define TYPE_TPM_TIS_ISA"tpm-tis"
 #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
 #define TYPE_TPM_CRB"tpm-crb"
+#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
 #define TYPE_TPM_SPAPR  "tpm-spapr"
 #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
 
@@ -58,6 +59,8 @@ struct TPMIfClass {
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
 #define TPM_IS_CRB(chr) \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_CRB_SYSBUS(chr)  \
+object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
 #define TPM_IS_SPAPR(chr)   \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
 #define TPM_IS_TIS_I2C(chr)  \
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index af66bde0f5..acc654382e 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -31,6 +31,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 {
 uint8_t start_method_params[12] = {};
 unsigned log_addr_offset;
-uint64_t control_area_start_address;
+uint64_t baseaddr, control_area_start_address;
 TPMIf *tpmif = tpm_find();
 uint32_t start_method;
 AcpiTable table = { .sig = "TPM2", .rev = 4,
@@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 } else if (TPM_IS_CRB(tpmif)) {
 control_area_start_address = TPM_CRB_ADDR_CTRL;
 start_method = TPM2_START_METHOD_CRB;
+} else if (TPM_IS_CRB_SYSBUS(tpmif)) {
+baseaddr = object_property_get_uint(OBJECT(tpmif), "x-baseaddr", NULL);
+control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
+start_method = TPM2_START_METHOD_CRB;
 } else {
 g_assert_not_reached();
 }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f1a161b0ea..22e147f71a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2950,6 +2950,7 @@ static void virt_machine_class_init(ObjectClass *oc, void 
*data)
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
 #ifdef CONFIG_TPM
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
 #

[PATCH v4 04/14] tpm_crb: use a single read-as-mem/write-as-mmio mapping

2023-10-30 Thread Joelle van Dyne
On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
the exception is not decoded by hardware and we cannot trap the MMIO
read. This led to the idea from @agraf to use the same mapping type as
ROM devices: namely that reads should be seen as memory type and
writes should trap as MMIO.

Once that was done, the second memory mapping of the command buffer
region was redundent and was removed.

A note about the removal of the read trap for `CRB_LOC_STATE`:
The only usage was to return the most up-to-date value for
`tpmEstablished`. However, `tpmEstablished` is only cleared when a
TPM2_HashStart operation is called which only exists for locality 4.
We do not handle locality 4. Indeed, the comment for the write handler
of `CRB_LOC_CTRL` makes the same argument for why it is not calling
the backend to reset the `tpmEstablished` bit (to 1).
As this bit is unused, we do not need to worry about updating it for
reads.

In order to maintain migration compatibility with older versions of
QEMU, we store a copy of the register data and command data which is
used only during save/restore.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.h|   5 +-
 hw/tpm/tpm_crb.c|  30 -
 hw/tpm/tpm_crb_common.c | 143 +++-
 3 files changed, 112 insertions(+), 66 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index da3a0cf256..36863e1664 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -26,9 +26,7 @@
 typedef struct TPMCRBState {
 TPMBackend *tpmbe;
 TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
 MemoryRegion mmio;
-MemoryRegion cmdmem;
 
 size_t be_buffer_size;
 
@@ -72,5 +70,8 @@ enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
 int tpm_crb_pre_save(TPMCRBState *s);
 void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
 void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void 
*saved_cmdmem);
+void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
+  const void *saved_cmdmem);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 598c3e0161..99c64dd72a 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -37,6 +37,10 @@ struct CRBState {
 DeviceState parent_obj;
 
 TPMCRBState state;
+
+/* These states are only for migration */
+uint32_t saved_regs[TPM_CRB_R_MAX];
+MemoryRegion saved_cmdmem;
 };
 typedef struct CRBState CRBState;
 
@@ -57,18 +61,36 @@ static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
 return tpm_crb_get_version(>state);
 }
 
+/**
+ * For migrating to an older version of QEMU
+ */
 static int tpm_crb_none_pre_save(void *opaque)
 {
 CRBState *s = opaque;
+void *saved_cmdmem = memory_region_get_ram_ptr(>saved_cmdmem);
 
+tpm_crb_mem_save(>state, s->saved_regs, saved_cmdmem);
 return tpm_crb_pre_save(>state);
 }
 
+/**
+ * For migrating from an older version of QEMU
+ */
+static int tpm_crb_none_post_load(void *opaque, int version_id)
+{
+CRBState *s = opaque;
+void *saved_cmdmem = memory_region_get_ram_ptr(>saved_cmdmem);
+
+tpm_crb_mem_load(>state, s->saved_regs, saved_cmdmem);
+return 0;
+}
+
 static const VMStateDescription vmstate_tpm_crb_none = {
 .name = "tpm-crb",
 .pre_save = tpm_crb_none_pre_save,
+.post_load = tpm_crb_none_post_load,
 .fields = (VMStateField[]) {
-VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),
+VMSTATE_UINT32_ARRAY(saved_regs, CRBState, TPM_CRB_R_MAX),
 VMSTATE_END_OF_LIST(),
 }
 };
@@ -101,10 +123,12 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
+/* only used for migration */
+memory_region_init_ram(>saved_cmdmem, OBJECT(s),
+"tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+
 memory_region_add_subregion(get_system_memory(),
 TPM_CRB_ADDR_BASE, >state.mmio);
-memory_region_add_subregion(get_system_memory(),
-TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
 memory_region_add_subregion(get_system_memory(),
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index bee0b71fee..605e8576e9 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -31,31 +31,12 @@
 #include "qom/object.h"
 #include "tpm_crb.h"
 
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
+static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
 {
-TPMCRBState *s = opaque;
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-switch (addr) {
-case A_CRB_LOC_STATE:
-val |= !tp

[PATCH v4 14/14] tests: add TPM-CRB sysbus tests for aarch64

2023-10-30 Thread Joelle van Dyne
- Factor out common test code from tpm-crb-test.c -> tpm-tests.c
- Store device addr in `tpm_device_base_addr` (unify with TIS tests)
- Add new tests for aarch64

Signed-off-by: Joelle van Dyne 
---
 tests/qtest/tpm-tests.h |   2 +
 tests/qtest/tpm-util.h  |   4 +-
 tests/qtest/bios-tables-test.c  |   4 +-
 tests/qtest/tpm-crb-device-swtpm-test.c |  72 ++
 tests/qtest/tpm-crb-device-test.c   |  71 ++
 tests/qtest/tpm-crb-swtpm-test.c|   2 +
 tests/qtest/tpm-crb-test.c  | 121 +---
 tests/qtest/tpm-tests.c | 121 
 tests/qtest/tpm-tis-device-swtpm-test.c |   2 +-
 tests/qtest/tpm-tis-device-test.c   |   2 +-
 tests/qtest/tpm-tis-i2c-test.c  |   3 +
 tests/qtest/tpm-tis-swtpm-test.c|   2 +-
 tests/qtest/tpm-tis-test.c  |   2 +-
 tests/qtest/tpm-util.c  |  16 ++--
 tests/qtest/meson.build |   4 +
 15 files changed, 295 insertions(+), 133 deletions(-)
 create mode 100644 tests/qtest/tpm-crb-device-swtpm-test.c
 create mode 100644 tests/qtest/tpm-crb-device-test.c

diff --git a/tests/qtest/tpm-tests.h b/tests/qtest/tpm-tests.h
index 07ba60d26e..c1bfb2f914 100644
--- a/tests/qtest/tpm-tests.h
+++ b/tests/qtest/tpm-tests.h
@@ -24,4 +24,6 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
const char *ifmodel,
const char *machine_options);
 
+void tpm_test_crb(const void *data);
+
 #endif /* TESTS_TPM_TESTS_H */
diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h
index 0cb28dd6e5..c99380684e 100644
--- a/tests/qtest/tpm-util.h
+++ b/tests/qtest/tpm-util.h
@@ -15,10 +15,10 @@
 
 #include "io/channel-socket.h"
 
-extern uint64_t tpm_tis_base_addr;
+extern uint64_t tpm_device_base_addr;
 
 #define TIS_REG(LOCTY, REG) \
-(tpm_tis_base_addr + ((LOCTY) << 12) + REG)
+(tpm_device_base_addr + ((LOCTY) << 12) + REG)
 
 typedef void (tx_func)(QTestState *s,
const unsigned char *req, size_t req_size,
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index c63bad0205..dea2a18158 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1343,7 +1343,7 @@ static void test_acpi_piix4_tcg_numamem(void)
 free_test_data();
 }
 
-uint64_t tpm_tis_base_addr;
+uint64_t tpm_device_base_addr;
 
 static test_data tcg_tpm_test_data(const char *machine)
 {
@@ -1379,7 +1379,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
 const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
 char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
 
-tpm_tis_base_addr = base;
+tpm_device_base_addr = base;
 
 module_call_init(MODULE_INIT_QOM);
 
diff --git a/tests/qtest/tpm-crb-device-swtpm-test.c 
b/tests/qtest/tpm-crb-device-swtpm-test.c
new file mode 100644
index 00..332add5ca6
--- /dev/null
+++ b/tests/qtest/tpm-crb-device-swtpm-test.c
@@ -0,0 +1,72 @@
+/*
+ * QTest testcase for TPM CRB talking to external swtpm and swtpm migration
+ *
+ * Copyright (c) 2018 IBM Corporation
+ *  with parts borrowed from migration-test.c that is:
+ * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *   Stefan Berger 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "libqtest.h"
+#include "qemu/module.h"
+#include "tpm-tests.h"
+#include "hw/acpi/tpm.h"
+
+uint64_t tpm_device_base_addr = 0xc00;
+#define MACHINE_OPTIONS "-machine virt,gic-version=max -accel tcg"
+
+typedef struct TestState {
+char *src_tpm_path;
+char *dst_tpm_path;
+char *uri;
+} TestState;
+
+static void tpm_crb_swtpm_test(const void *data)
+{
+const TestState *ts = data;
+
+tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer,
+"tpm-crb-device", MACHINE_OPTIONS);
+}
+
+static void tpm_crb_swtpm_migration_test(const void *data)
+{
+const TestState *ts = data;
+
+tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri,
+  tpm_util_crb_transfer, "tpm-crb-device",
+  MACHINE_OPTIONS);
+}
+
+int main(int argc, char **argv)
+{
+int ret;
+TestState ts = { 0 };
+
+ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XX", NULL);
+ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XX", NULL);
+ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path);
+
+module_call_in

[PATCH v4 02/14] tpm_crb: CTRL_RSP_ADDR is 64-bits wide

2023-10-30 Thread Joelle van Dyne
The register is actually 64-bits but in order to make this more clear
than the specification, we define two 32-bit registers:
CTRL_RSP_LADDR and CTRL_RSP_HADDR to match the CTRL_CMD_* naming. This
deviates from the specs but is way more clear.

Previously, the only CRB device uses a fixed system address so this
was not an issue. However, once we support SysBus CRB device, the
address can be anywhere in 64-bit space.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 include/hw/acpi/tpm.h  | 3 ++-
 hw/tpm/tpm_crb_common.c| 3 ++-
 tests/qtest/tpm-crb-test.c | 2 +-
 tests/qtest/tpm-util.c | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 579c45f5ba..f60bfe2789 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -174,7 +174,8 @@ REG32(CRB_CTRL_CMD_SIZE, 0x58)
 REG32(CRB_CTRL_CMD_LADDR, 0x5C)
 REG32(CRB_CTRL_CMD_HADDR, 0x60)
 REG32(CRB_CTRL_RSP_SIZE, 0x64)
-REG32(CRB_CTRL_RSP_ADDR, 0x68)
+REG32(CRB_CTRL_RSP_LADDR, 0x68)
+REG32(CRB_CTRL_RSP_HADDR, 0x6C)
 REG32(CRB_DATA_BUFFER, 0x80)
 
 #define TPM_CRB_ADDR_BASE   0xFED4
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index fa463f295f..01b35808f6 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -197,7 +197,8 @@ void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
 s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
 s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
 s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-s->regs[R_CRB_CTRL_RSP_ADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
 
 s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
 CRB_CTRL_CMD_SIZE);
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 396ae3f91c..9d30fe8293 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -28,7 +28,7 @@ static void tpm_crb_test(const void *data)
 uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
 uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
 uint32_t rsize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_SIZE);
-uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 uint8_t locstate = readb(TPM_CRB_ADDR_BASE + A_CRB_LOC_STATE);
 uint32_t locctrl = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL);
 uint32_t locsts = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_STS);
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index 1c0319e6e7..dd02057fc0 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -25,7 +25,7 @@ void tpm_util_crb_transfer(QTestState *s,
unsigned char *rsp, size_t rsp_size)
 {
 uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
-uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 
 qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);
 
-- 
2.41.0




[PATCH v4 09/14] tpm_tis_sysbus: move DSDT AML generation to device

2023-10-30 Thread Joelle van Dyne
This reduces redundant code in different machine types with ACPI table
generation. Additionally, this will allow us to support different TPM
interfaces with the same AML logic. Finally, this matches up with the
TPM TIS ISA implementation.

Ideally, we would be able to call `qbus_build_aml` and avoid any TPM
specific code in the ACPI table generation. However, currently we
still have to call `build_tpm2` anyways and it does not look like
most other ACPI devices support the `ACPI_DEV_AML_IF` interface.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/arm/virt-acpi-build.c  | 38 ++
 hw/loongarch/acpi-build.c | 38 ++
 hw/tpm/tpm_tis_sysbus.c   | 37 +
 3 files changed, 41 insertions(+), 72 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 9ce136cd88..3efbe6bd09 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/aml-build.h"
@@ -208,41 +209,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const 
MemMapEntry *gpio_memmap,
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 #define ID_MAPPING_ENTRY_SIZE 20
 #define SMMU_V3_ENTRY_SIZE 68
 #define ROOT_COMPLEX_ENTRY_SIZE 36
@@ -891,7 +857,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 
 acpi_dsdt_add_power_button(scope);
 #ifdef CONFIG_TPM
-acpi_dsdt_add_tpm(scope, vms);
+call_dev_aml_func(DEVICE(tpm_find()), scope);
 #endif
 
 aml_append(dsdt, scope);
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index ae292fc543..1969bfc8f9 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -14,6 +14,7 @@
 #include "target/loongarch/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "migration/vmstate.h"
@@ -328,41 +329,6 @@ static void build_flash_aml(Aml *scope, 
LoongArchMachineState *lams)
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 /* build DSDT */
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
@@ -379,7 +345,7 @@ build_dsdt(GArray *table_data, BIOSLi

[PATCH v4 12/14] tests: acpi: implement TPM CRB tests for ARM virt

2023-10-30 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 tests/qtest/bios-tables-test.c | 43 --
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 9f4bc15aab..c63bad0205 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1345,6 +1345,28 @@ static void test_acpi_piix4_tcg_numamem(void)
 
 uint64_t tpm_tis_base_addr;
 
+static test_data tcg_tpm_test_data(const char *machine)
+{
+if (g_strcmp0(machine, "virt") == 0) {
+test_data data = {
+.machine = "virt",
+.tcg_only = true,
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.cd =
+   
"tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+return data;
+} else {
+test_data data = {
+.machine = machine,
+};
+return data;
+}
+}
+
 static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
   uint64_t base, enum TPMVersion tpm_version)
 {
@@ -1352,7 +1374,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
   machine, tpm_if);
 char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL);
 TPMTestState test;
-test_data data = {};
+test_data data = tcg_tpm_test_data(machine);
 GThread *thread;
 const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
 char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
@@ -1372,13 +1394,14 @@ static void test_acpi_tcg_tpm(const char *machine, 
const char *tpm_if,
 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, );
 tpm_emu_test_wait_cond();
 
-data.machine = machine;
 data.variant = variant;
 
 args = g_strdup_printf(
+" %s"
 " -chardev socket,id=chr,path=%s"
 " -tpmdev emulator,id=dev,chardev=chr"
 " -device tpm-%s,tpmdev=dev",
+g_strcmp0(machine, "virt") == 0 ? "-cpu cortex-a57" : "",
 test.addr->u.q_unix.path, tpm_if);
 
 test_acpi_one(args, );
@@ -1404,6 +1427,16 @@ static void test_acpi_q35_tcg_tpm12_tis(void)
 test_acpi_tcg_tpm("q35", "tis", 0xFED4, TPM_VERSION_1_2);
 }
 
+static void test_acpi_q35_tcg_tpm2_crb(void)
+{
+test_acpi_tcg_tpm("q35", "crb", 0xFED4, TPM_VERSION_2_0);
+}
+
+static void test_acpi_virt_tcg_tpm2_crb(void)
+{
+test_acpi_tcg_tpm("virt", "crb-device", 0xFED4, TPM_VERSION_2_0);
+}
+
 static void test_acpi_tcg_dimm_pxm(const char *machine)
 {
 test_data data = {};
@@ -2110,6 +2143,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/tpm12-tis",
test_acpi_q35_tcg_tpm12_tis);
 }
+if (tpm_model_is_available("-machine q35", "tpm-crb")) {
+qtest_add_func("acpi/q35/tpm2-crb", 
test_acpi_q35_tcg_tpm2_crb);
+}
 qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge);
 qtest_add_func("acpi/q35/no-acpi-hotplug",
test_acpi_q35_tcg_no_acpi_hotplug);
@@ -2191,6 +2227,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/virt/viot", test_acpi_virt_viot);
 }
 }
+if (tpm_model_is_available("-machine virt", "tpm-crb")) {
+qtest_add_func("acpi/virt/tpm2-crb", test_acpi_virt_tcg_tpm2_crb);
+}
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.41.0




Re: [PATCH v3 13/14] tests: acpi: updated expected blobs for TPM CRB

2023-10-30 Thread Joelle van Dyne
I think I actually messed up and committed an older version of the
expected blobs. Since these are newly added for the new tests, they
should be passing without any additional work.

On Mon, Oct 30, 2023 at 5:35 PM Stefan Berger  wrote:
>
>
> On 10/30/23 18:42, Stefan Berger wrote:
> >
> > On 10/29/23 02:03, Joelle van Dyne wrote:
> >> Signed-off-by: Joelle van Dyne 
> >
> > I see this error here with the test cases:
> >
> >
> > | 364/377 ERROR:../tests/qtest/bios-tables-test.c:535:test_acpi_asl:
> > assertion failed: (all_tables_match) ERROR
> > 364/377 qemu:qtest+qtest-x86_64 /
> > qtest-x86_64/bios-tables-test ERROR 34.83s killed
> > by signal 6 SIGABRT
> > >>> QTEST_QEMU_BINARY=./qemu-system-x86_64 MALLOC_PERTURB_=200
> > QTEST_QEMU_IMG=./qemu-img
> > G_TEST_DBUS_DAEMON=/home/stefanb/qemu-tpm/tests/dbus-vmstate-daemon.sh
> > QTEST_QEMU_STORAGE_DAEMON_BINARY=./storage-daemon/qemu-storage-daemon
> > PYTHON=/home/stefanb/qemu-tpm/build/pyvenv/bin/python3
> > /home/stefanb/qemu-tpm/build/tests/qtest/bios-tables-test --tap -k
> > --- 8<
> > ---
> >
> > $ diff tests/data/acpi/virt/TPM2.crb-device.dsl /tmp/aml-98C6D2.dsl
> > 6c6
> > <  * Disassembly of tests/data/acpi/virt/TPM2.crb-device.tpm2, Mon Oct
> > 30 18:30:00 2023
> > ---
> > >  * Disassembly of /tmp/aml-98C6D2, Mon Oct 30 18:29:29 2023
> > 16c16
> > < [009h 0009   1] Checksum : BA
> > ---
> > > [009h 0009   1] Checksum : C2
> > 30c30
> > < [044h 0068   8]  Log Address : 43D1
> > ---
> > > [044h 0068   8]  Log Address : 43C9
> >
> > The diff is in the address of the TPM log ... Not good. I don't know
> > how we could have it ignore the address or not build the TPM2 table
> > with an address for a log. It would be good to have test cases.
> >
> >Stefan
>
>
> The log that the TPM2 ACPI table points to is needed for a BIOS, UEFI
> does not need it (but we don't typically know whether BIOS or UEFI will
> run). So we could introduce a property no-acpi-log and have the test
> cases set this to 'on' and get a NULL pointer for the 'Log Address'. You
> could use the following in a patch:
>
>
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index acc654382e..2b2de34201 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -2224,6 +2224,7 @@ void build_tpm2(GArray *table_data, BIOSLinker
> *linker, GArray *tcpalog,
>   uint32_t start_method;
>   AcpiTable table = { .sig = "TPM2", .rev = 4,
>   .oem_id = oem_id, .oem_table_id = oem_table_id };
> +bool acpi_log = true;
>
>   acpi_table_begin(, table_data);
>
> @@ -2238,6 +2239,7 @@ void build_tpm2(GArray *table_data, BIOSLinker
> *linker, GArray *tcpalog,
>   control_area_start_address = TPM_CRB_ADDR_CTRL;
>   start_method = TPM2_START_METHOD_CRB;
>   } else if (TPM_IS_CRB_SYSBUS(tpmif)) {
> +acpi_log = !object_property_get_bool(OBJECT(tpmif),
> "no-acpi-log", NULL);
>   baseaddr = object_property_get_uint(OBJECT(tpmif),
> "x-baseaddr", NULL);
>   control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
>   start_method = TPM2_START_METHOD_CRB;
> @@ -2253,20 +2255,25 @@ void build_tpm2(GArray *table_data, BIOSLinker
> *linker, GArray *tcpalog,
>   g_array_append_vals(table_data, _method_params,
>   ARRAY_SIZE(start_method_params));
>
> -/* Log Area Minimum Length */
> -build_append_int_noprefix(table_data, TPM_LOG_AREA_MINIMUM_SIZE, 4);
> +if (acpi_log) {
> +/* Log Area Minimum Length */
> +build_append_int_noprefix(table_data,
> TPM_LOG_AREA_MINIMUM_SIZE, 4);
>
> -acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
> -bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
> - false);
> +acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
> +bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE,
> tcpalog, 1,
> + false);
>
> -log_addr_offset = table_data->len;
> +log_addr_offset = table_data->len;
>
> -/* Log Area Start Address to be filled by Guest linker */
> -build_append_int_noprefix(table_data, 0, 8);
> -bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
> -

Re: [PATCH v3 11/14] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-10-30 Thread Joelle van Dyne
On Mon, Oct 30, 2023 at 2:09 PM Stefan Berger  wrote:
>
>
> On 10/29/23 02:03, Joelle van Dyne wrote:
> > This SysBus variant of the CRB interface supports dynamically locating
> > the MMIO interface so that Virt machines can use it. This interface
> > is currently the only one supported by QEMU that works on Windows 11
> > ARM64 as 'tpm-tis-device' does not work with current Windows drivers.
> > We largely follow that device as a template.
> >
> > To try out this device with Windows 11 before OVMF is updated, you
> > will need to modify `sysbud-fdt.c` and change the added line from:
>
> typo: sysbus-fdt.c
>
>
> >
> > ```c
> >  TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> > ```
> >
> > to
> >
> > ```c
> >  TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
>
>
> Would the proper fix at some point be a call to a function that has
> 'crb' in its name (add_tpm_crb_fdt_node) rather than 'tis'?
I think Linux actually doesn't support finding a CRB device through
FDT. It only finds it through ACPI tables (which we already have). The
main issue is that EDK2 does not recognize the device (on ARM) and
cannot do the required measurements.

>
> > ```
> >
> > This change was not included because it can confuse Linux (although
> > from testing, it seems like Linux is able to properly ignore the
> > device from the TPM TIS driver and recognize it from the ACPI device
> > in the TPM CRB driver). A proper fix would require OVMF to recognize
> > the ACPI device and not depend on the FDT node for recognizing TPM.
>
> What does a fix in OVMF have to do with Linux possibly getting confused?

Because of this line in EDK2:

https://github.com/tianocore/edk2/blob/master/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c#L153C26-L153C26

Only a TPM device with the name "tcg,tpm-tis-mmio" will be detected by
OVMF. However, once Linux boots, it reads the FDT and assumes it's a
TIS device. So OVMF has to be updated to support recognizing CRB
devices.

A proper fix in EDK2 would involve finding the CRB device through the
ACPI tables. A hack is to lie to EDK2 and say we have a TIS device.
The TPM driver code will then properly recognize it as CRB. However,
this lie would be seen by Linux.

>
>
> >
> > The command line to try out this device with SWTPM is:
> >
> > ```
> > $ qemu-system-aarch64 \
> >  -chardev socket,id=chrtpm0,path=tpm.sock \
> >  -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
> >  -device tpm-crb-device,tpmdev=tpm0
> > ```
> >
> > along with SWTPM:
> >
> > ```
> > $ swtpm \
> >  --ctrl type=unixio,path=tpm.sock,terminate \
> >  --tpmstate backend-uri=file://tpm.data \
> >  --tpm2
> > ```
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
> >   docs/specs/tpm.rst  |   1 +
> >   include/sysemu/tpm.h|   3 +
> >   hw/acpi/aml-build.c |   7 +-
> >   hw/arm/virt.c   |   1 +
> >   hw/core/sysbus-fdt.c|   1 +
> >   hw/loongarch/virt.c |   1 +
> >   hw/riscv/virt.c |   1 +
> >   hw/tpm/tpm_crb_sysbus.c | 161 
> >   hw/arm/Kconfig  |   1 +
> >   hw/loongarch/Kconfig|   1 +
> >   hw/riscv/Kconfig|   1 +
> >   hw/tpm/Kconfig  |   5 ++
> >   hw/tpm/meson.build  |   3 +
> >   13 files changed, 186 insertions(+), 1 deletion(-)
> >   create mode 100644 hw/tpm/tpm_crb_sysbus.c
> >
> > diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> > index 2bc29c9804..95aeb49220 100644
> > --- a/docs/specs/tpm.rst
> > +++ b/docs/specs/tpm.rst
> > @@ -46,6 +46,7 @@ operating system.
> >   QEMU files related to TPM CRB interface:
> >- ``hw/tpm/tpm_crb.c``
> >- ``hw/tpm/tpm_crb_common.c``
> > + - ``hw/tpm/tpm_crb_sysbus.c``
> >
> >   SPAPR interface
> >   ---
> > diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> > index ffd300e607..bab30fa546 100644
> > --- a/include/sysemu/tpm.h
> > +++ b/include/sysemu/tpm.h
> > @@ -49,6 +49,7 @@ struct TPMIfClass {
> >   #define TYPE_TPM_TIS_ISA"tpm-tis"
> >   #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
> >   #define TYPE_TPM_CRB"tpm-crb"
> > +#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
> >   #define TYPE_TPM_SPAPR  "tpm-spapr"
> >   #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
> >
> > @@ -58,6 +59,8 @@ struct TPMIfClass {
> >   object

Re: [PATCH v3 06/14] tpm-sysbus: add plug handler for TPM on SysBus

2023-10-30 Thread Joelle van Dyne
I was debating what to add. I couldn't find a project-wide template
for what the header should be and I couldn't copy/paste from where I
copied the code from (virt.c) because it names a specific author that
I'm not sure wrote this code... Any advice?

On Mon, Oct 30, 2023 at 9:52 AM Stefan Berger  wrote:
>
>
> On 10/29/23 02:03, Joelle van Dyne wrote:
> > TPM needs to know its own base address in order to generate its DSDT
> > device entry.
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
> >   include/sysemu/tpm.h |  4 
> >   hw/tpm/tpm-sysbus.c  | 33 +
> >   hw/tpm/meson.build   |  1 +
> >   3 files changed, 38 insertions(+)
> >   create mode 100644 hw/tpm/tpm-sysbus.c
> >
> > diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> > index 1ee568b3b6..ffd300e607 100644
> > --- a/include/sysemu/tpm.h
> > +++ b/include/sysemu/tpm.h
> > @@ -12,6 +12,8 @@
> >   #ifndef QEMU_TPM_H
> >   #define QEMU_TPM_H
> >
> > +#include "qemu/osdep.h"
> > +#include "exec/hwaddr.h"
> >   #include "qapi/qapi-types-tpm.h"
> >   #include "qom/object.h"
> >
> > @@ -78,6 +80,8 @@ static inline TPMVersion tpm_get_version(TPMIf *ti)
> >   return TPM_IF_GET_CLASS(ti)->get_version(ti);
> >   }
> >
> > +void tpm_sysbus_plug(TPMIf *tpmif, Object *pbus, hwaddr pbus_base);
> > +
> >   #else /* CONFIG_TPM */
> >
> >   #define tpm_init()  (0)
> > diff --git a/hw/tpm/tpm-sysbus.c b/hw/tpm/tpm-sysbus.c
> > new file mode 100644
> > index 00..ef0592b837
> > --- /dev/null
> > +++ b/hw/tpm/tpm-sysbus.c
> > @@ -0,0 +1,33 @@
>
> A header in this new file would be good. Otherwise LGTM.
>
>Stefan
>
> > +#include "sysemu/tpm.h"
> > +#include "hw/platform-bus.h"
> > +#include "hw/sysbus.h"
> > +#include "qapi/error.h"
>
>
>



[PATCH v3 08/14] hw/loongarch/virt: connect TPM to platform bus

2023-10-29 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
---
 hw/loongarch/virt.c  | 7 +++
 hw/loongarch/Kconfig | 1 +
 2 files changed, 8 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index 4b7dc67a2d..feed0f8bbf 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1004,6 +1004,13 @@ static void 
loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 } else if (memhp_type_supported(dev)) {
 virt_mem_plug(hotplug_dev, dev, errp);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+tpm_sysbus_plug(TPM_IF(dev), OBJECT(lams->platform_bus_dev),
+VIRT_PLATFORM_BUS_BASEADDRESS);
+}
+#endif
 }
 
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 5727efed6d..25da190ffc 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -5,6 +5,7 @@ config LOONGARCH_VIRT
 imply VIRTIO_VGA
 imply PCI_DEVICES
 imply NVDIMM
+imply TPM_TIS_SYSBUS
 select SERIAL
 select VIRTIO_PCI
 select PLATFORM_BUS
-- 
2.41.0




[PATCH v3 04/14] tpm_crb: use a single read-as-mem/write-as-mmio mapping

2023-10-29 Thread Joelle van Dyne
On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
the exception is not decoded by hardware and we cannot trap the MMIO
read. This led to the idea from @agraf to use the same mapping type as
ROM devices: namely that reads should be seen as memory type and
writes should trap as MMIO.

Once that was done, the second memory mapping of the command buffer
region was redundent and was removed.

A note about the removal of the read trap for `CRB_LOC_STATE`:
The only usage was to return the most up-to-date value for
`tpmEstablished`. However, `tpmEstablished` is only cleared when a
TPM2_HashStart operation is called which only exists for locality 4.
We do not handle locality 4. Indeed, the comment for the write handler
of `CRB_LOC_CTRL` makes the same argument for why it is not calling
the backend to reset the `tpmEstablished` bit (to 1).
As this bit is unused, we do not need to worry about updating it for
reads.

In order to maintain migration compatibility with older versions of
QEMU, we store a copy of the register data and command data which is
used only during save/restore.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.h|   5 +-
 hw/tpm/tpm_crb.c|  30 -
 hw/tpm/tpm_crb_common.c | 143 +++-
 3 files changed, 112 insertions(+), 66 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index da3a0cf256..36863e1664 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -26,9 +26,7 @@
 typedef struct TPMCRBState {
 TPMBackend *tpmbe;
 TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
 MemoryRegion mmio;
-MemoryRegion cmdmem;
 
 size_t be_buffer_size;
 
@@ -72,5 +70,8 @@ enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
 int tpm_crb_pre_save(TPMCRBState *s);
 void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
 void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void 
*saved_cmdmem);
+void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
+  const void *saved_cmdmem);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 598c3e0161..99c64dd72a 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -37,6 +37,10 @@ struct CRBState {
 DeviceState parent_obj;
 
 TPMCRBState state;
+
+/* These states are only for migration */
+uint32_t saved_regs[TPM_CRB_R_MAX];
+MemoryRegion saved_cmdmem;
 };
 typedef struct CRBState CRBState;
 
@@ -57,18 +61,36 @@ static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
 return tpm_crb_get_version(>state);
 }
 
+/**
+ * For migrating to an older version of QEMU
+ */
 static int tpm_crb_none_pre_save(void *opaque)
 {
 CRBState *s = opaque;
+void *saved_cmdmem = memory_region_get_ram_ptr(>saved_cmdmem);
 
+tpm_crb_mem_save(>state, s->saved_regs, saved_cmdmem);
 return tpm_crb_pre_save(>state);
 }
 
+/**
+ * For migrating from an older version of QEMU
+ */
+static int tpm_crb_none_post_load(void *opaque, int version_id)
+{
+CRBState *s = opaque;
+void *saved_cmdmem = memory_region_get_ram_ptr(>saved_cmdmem);
+
+tpm_crb_mem_load(>state, s->saved_regs, saved_cmdmem);
+return 0;
+}
+
 static const VMStateDescription vmstate_tpm_crb_none = {
 .name = "tpm-crb",
 .pre_save = tpm_crb_none_pre_save,
+.post_load = tpm_crb_none_post_load,
 .fields = (VMStateField[]) {
-VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),
+VMSTATE_UINT32_ARRAY(saved_regs, CRBState, TPM_CRB_R_MAX),
 VMSTATE_END_OF_LIST(),
 }
 };
@@ -101,10 +123,12 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
+/* only used for migration */
+memory_region_init_ram(>saved_cmdmem, OBJECT(s),
+"tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+
 memory_region_add_subregion(get_system_memory(),
 TPM_CRB_ADDR_BASE, >state.mmio);
-memory_region_add_subregion(get_system_memory(),
-TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
 memory_region_add_subregion(get_system_memory(),
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index bee0b71fee..605e8576e9 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -31,31 +31,12 @@
 #include "qom/object.h"
 #include "tpm_crb.h"
 
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
+static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
 {
-TPMCRBState *s = opaque;
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-switch (addr) {
-case A_CRB_LOC_STATE:
-val |= !tp

[PATCH v3 11/14] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-10-29 Thread Joelle van Dyne
This SysBus variant of the CRB interface supports dynamically locating
the MMIO interface so that Virt machines can use it. This interface
is currently the only one supported by QEMU that works on Windows 11
ARM64 as 'tpm-tis-device' does not work with current Windows drivers.
We largely follow that device as a template.

To try out this device with Windows 11 before OVMF is updated, you
will need to modify `sysbud-fdt.c` and change the added line from:

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
```

to

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
```

This change was not included because it can confuse Linux (although
from testing, it seems like Linux is able to properly ignore the
device from the TPM TIS driver and recognize it from the ACPI device
in the TPM CRB driver). A proper fix would require OVMF to recognize
the ACPI device and not depend on the FDT node for recognizing TPM.

The command line to try out this device with SWTPM is:

```
$ qemu-system-aarch64 \
-chardev socket,id=chrtpm0,path=tpm.sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm0 \
-device tpm-crb-device,tpmdev=tpm0
```

along with SWTPM:

```
$ swtpm \
--ctrl type=unixio,path=tpm.sock,terminate \
--tpmstate backend-uri=file://tpm.data \
--tpm2
```

Signed-off-by: Joelle van Dyne 
---
 docs/specs/tpm.rst  |   1 +
 include/sysemu/tpm.h|   3 +
 hw/acpi/aml-build.c |   7 +-
 hw/arm/virt.c   |   1 +
 hw/core/sysbus-fdt.c|   1 +
 hw/loongarch/virt.c |   1 +
 hw/riscv/virt.c |   1 +
 hw/tpm/tpm_crb_sysbus.c | 161 
 hw/arm/Kconfig  |   1 +
 hw/loongarch/Kconfig|   1 +
 hw/riscv/Kconfig|   1 +
 hw/tpm/Kconfig  |   5 ++
 hw/tpm/meson.build  |   3 +
 13 files changed, 186 insertions(+), 1 deletion(-)
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index 2bc29c9804..95aeb49220 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -46,6 +46,7 @@ operating system.
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
  - ``hw/tpm/tpm_crb_common.c``
+ - ``hw/tpm/tpm_crb_sysbus.c``
 
 SPAPR interface
 ---
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index ffd300e607..bab30fa546 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -49,6 +49,7 @@ struct TPMIfClass {
 #define TYPE_TPM_TIS_ISA"tpm-tis"
 #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
 #define TYPE_TPM_CRB"tpm-crb"
+#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
 #define TYPE_TPM_SPAPR  "tpm-spapr"
 #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
 
@@ -58,6 +59,8 @@ struct TPMIfClass {
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
 #define TPM_IS_CRB(chr) \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_CRB_SYSBUS(chr)  \
+object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
 #define TPM_IS_SPAPR(chr)   \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
 #define TPM_IS_TIS_I2C(chr)  \
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index af66bde0f5..acc654382e 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -31,6 +31,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 {
 uint8_t start_method_params[12] = {};
 unsigned log_addr_offset;
-uint64_t control_area_start_address;
+uint64_t baseaddr, control_area_start_address;
 TPMIf *tpmif = tpm_find();
 uint32_t start_method;
 AcpiTable table = { .sig = "TPM2", .rev = 4,
@@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 } else if (TPM_IS_CRB(tpmif)) {
 control_area_start_address = TPM_CRB_ADDR_CTRL;
 start_method = TPM2_START_METHOD_CRB;
+} else if (TPM_IS_CRB_SYSBUS(tpmif)) {
+baseaddr = object_property_get_uint(OBJECT(tpmif), "x-baseaddr", NULL);
+control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
+start_method = TPM2_START_METHOD_CRB;
 } else {
 g_assert_not_reached();
 }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index f1a161b0ea..22e147f71a 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2950,6 +2950,7 @@ static void virt_machine_class_init(ObjectClass *oc, void 
*data)
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
 #ifdef CONFIG_TPM
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
 #

[PATCH v3 14/14] tests: add TPM-CRB sysbus tests for aarch64

2023-10-29 Thread Joelle van Dyne
- Factor out common test code from tpm-crb-test.c -> tpm-tests.c
- Store device addr in `tpm_device_base_addr` (unify with TIS tests)
- Add new tests for aarch64

Signed-off-by: Joelle van Dyne 
---
 tests/qtest/tpm-tests.h |   2 +
 tests/qtest/tpm-util.h  |   4 +-
 tests/qtest/bios-tables-test.c  |   4 +-
 tests/qtest/tpm-crb-device-swtpm-test.c |  72 ++
 tests/qtest/tpm-crb-device-test.c   |  71 ++
 tests/qtest/tpm-crb-swtpm-test.c|   2 +
 tests/qtest/tpm-crb-test.c  | 121 +---
 tests/qtest/tpm-tests.c | 121 
 tests/qtest/tpm-tis-device-swtpm-test.c |   2 +-
 tests/qtest/tpm-tis-device-test.c   |   2 +-
 tests/qtest/tpm-tis-i2c-test.c  |   3 +
 tests/qtest/tpm-tis-swtpm-test.c|   2 +-
 tests/qtest/tpm-tis-test.c  |   2 +-
 tests/qtest/tpm-util.c  |  16 ++--
 tests/qtest/meson.build |   4 +
 15 files changed, 295 insertions(+), 133 deletions(-)
 create mode 100644 tests/qtest/tpm-crb-device-swtpm-test.c
 create mode 100644 tests/qtest/tpm-crb-device-test.c

diff --git a/tests/qtest/tpm-tests.h b/tests/qtest/tpm-tests.h
index 07ba60d26e..c1bfb2f914 100644
--- a/tests/qtest/tpm-tests.h
+++ b/tests/qtest/tpm-tests.h
@@ -24,4 +24,6 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
const char *ifmodel,
const char *machine_options);
 
+void tpm_test_crb(const void *data);
+
 #endif /* TESTS_TPM_TESTS_H */
diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h
index 0cb28dd6e5..c99380684e 100644
--- a/tests/qtest/tpm-util.h
+++ b/tests/qtest/tpm-util.h
@@ -15,10 +15,10 @@
 
 #include "io/channel-socket.h"
 
-extern uint64_t tpm_tis_base_addr;
+extern uint64_t tpm_device_base_addr;
 
 #define TIS_REG(LOCTY, REG) \
-(tpm_tis_base_addr + ((LOCTY) << 12) + REG)
+(tpm_device_base_addr + ((LOCTY) << 12) + REG)
 
 typedef void (tx_func)(QTestState *s,
const unsigned char *req, size_t req_size,
diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index c63bad0205..dea2a18158 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1343,7 +1343,7 @@ static void test_acpi_piix4_tcg_numamem(void)
 free_test_data();
 }
 
-uint64_t tpm_tis_base_addr;
+uint64_t tpm_device_base_addr;
 
 static test_data tcg_tpm_test_data(const char *machine)
 {
@@ -1379,7 +1379,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
 const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
 char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
 
-tpm_tis_base_addr = base;
+tpm_device_base_addr = base;
 
 module_call_init(MODULE_INIT_QOM);
 
diff --git a/tests/qtest/tpm-crb-device-swtpm-test.c 
b/tests/qtest/tpm-crb-device-swtpm-test.c
new file mode 100644
index 00..332add5ca6
--- /dev/null
+++ b/tests/qtest/tpm-crb-device-swtpm-test.c
@@ -0,0 +1,72 @@
+/*
+ * QTest testcase for TPM CRB talking to external swtpm and swtpm migration
+ *
+ * Copyright (c) 2018 IBM Corporation
+ *  with parts borrowed from migration-test.c that is:
+ * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *   Stefan Berger 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+
+#include "libqtest.h"
+#include "qemu/module.h"
+#include "tpm-tests.h"
+#include "hw/acpi/tpm.h"
+
+uint64_t tpm_device_base_addr = 0xc00;
+#define MACHINE_OPTIONS "-machine virt,gic-version=max -accel tcg"
+
+typedef struct TestState {
+char *src_tpm_path;
+char *dst_tpm_path;
+char *uri;
+} TestState;
+
+static void tpm_crb_swtpm_test(const void *data)
+{
+const TestState *ts = data;
+
+tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer,
+"tpm-crb-device", MACHINE_OPTIONS);
+}
+
+static void tpm_crb_swtpm_migration_test(const void *data)
+{
+const TestState *ts = data;
+
+tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri,
+  tpm_util_crb_transfer, "tpm-crb-device",
+  MACHINE_OPTIONS);
+}
+
+int main(int argc, char **argv)
+{
+int ret;
+TestState ts = { 0 };
+
+ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XX", NULL);
+ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-crb-swtpm-test.XX", NULL);
+ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path);
+
+module_call_in

[PATCH v3 13/14] tests: acpi: updated expected blobs for TPM CRB

2023-10-29 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
---
 tests/qtest/bios-tables-test-allowed-diff.h |   4 
 tests/data/acpi/q35/DSDT.crb.tpm2   | Bin 0 -> 8981 bytes
 tests/data/acpi/q35/TPM2.crb.tpm2   | Bin 0 -> 76 bytes
 tests/data/acpi/virt/DSDT.crb-device.tpm2   | Bin 0 -> 5276 bytes
 tests/data/acpi/virt/TPM2.crb-device.tpm2   | Bin 0 -> 76 bytes
 5 files changed, 4 deletions(-)

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index c2d1924c2f..dfb8523c8b 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1,5 +1 @@
 /* List of comma-separated changed AML files to ignore */
-"tests/data/acpi/q35/DSDT.crb.tpm2",
-"tests/data/acpi/q35/TPM2.crb.tpm2",
-"tests/data/acpi/virt/DSDT.crb.tpm2",
-"tests/data/acpi/virt/TPM2.crb.tpm2",
diff --git a/tests/data/acpi/q35/DSDT.crb.tpm2 
b/tests/data/acpi/q35/DSDT.crb.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0f04f48f0bb378f035773211b0e70ad50094f95f
 100644
GIT binary patch
literal 8981
zcmb7KO>7&-8J*>iv|28u6-D_!HeoycOW;sa;sgznmfYo^B}yxjw$soBmy+Gec7QCB
zxQJsIkQE?t3>1jXI_RYU6EH<@?V;$k26}0M9(*v607VZ4+Dm|5S`;yQu=>6kjy*$C
zK*hsyzuEWZn>VvNZ#hG+?loqQF=qTdzv7nbnfzFF1@~2D2_ckg5aGG1EU?Xwa=WpYwhs;o530*(3Q2
ztGTr@<-3)v*(z5&6X?9qGl`S)tK2jUGZ3YX}q;kcVo9MGuJyi*IkZxHl}AR
zr&;~W!q-O*egBiQ@8s^i^2LvCUAAHX%;Vd{_d-aA;96iE4!X{r%o(fPHx?#!JI
zzbwiex)KId@~JI~sH(Z%<@92_;MJ?i?#a$27EVVE7IY8X5e>Ni;-CIef8o9A?Y&=B
z_y57I_JZ#C-HTSF7lhW0n*n1eIMlghjfbgtge6_Dk=wVccKC;eqV
z>t^Sm*{#*5k64F3+{>6v9Z#R%Y;SM>UYs)LDsz_7C#Val`xEMous_;X3?oK?o6i6um}C
zcn9KOur&j!_5MHw;hGo*)33NimbP2?Ho^^x
zoUJnk^{?Z8#qUtR*6>q{Z*Qg>^80EiV?BI5%)!WGS1qo=_a8g|3JV0egOw`Y@5zYj*9}!bRBaAZvWphTalw?0N2ux?({zq;ri6~^IuWWm$2Fbfn$B@u
zCqh-Hsp|ou;l6p{jF2(>bB(oX~Y5RCQXKPD|5i={garIun}Cgr+m0>qMyPv^AZ!
zrqkASB2;xIHJwRKXHwURP}Mo9>73MbPU<=lsye4Mol~05DP1Q*Ri~rrbTplgt`niE
zb6V3mt?8WBbs|)CrZk-?O=n8iiBQ!!qv@Q{bk68H5vn@Vn$EPQGp*}HsOp^6bk1rz
zXLX$jRh@e@oqIH$dvu)$Rh_UgF=z2vX|JYpudWlJs*FbDySjpRN<3s=K3??
ze$LGIC%gTE={^aG>GiP(H0A+~c|d0(RG9}g=0S~lP-h}knTIsyA%RXChRYPif4j
zH0Dz}6QRmH%$ahIKg^kOjz27za^glvOz9*?w46t@oJaJW2t`g42AWe0v{bJkH8)cO
z=SbW)Py|RTf+zx+6b34A{3bFOv1I!UBo)xd28vKhgMkXHG*AUf1}dPB4HO|-BMnqw
z`w`_tt`0?L_Wpa`W-7^uKM_lrzad5lWpfP=V!47^ngz0~Jut
zBm+e#b;3XemNQ|X3X}{~Ksl2P6rt1!0~J`#gn=qhGEf2KOfpb}QYQ>lU^x>8szAv=
z1(Y+%KoLrvFi?TzOcu>1(q{mpbC@>R6seC3>2Z%2?G^a+#~
zP%=;f=3{*fllMEE0)CmI>Sk8ojDo`>|0p(0GP=rz^3{+q_69%e4$v_2^Gs!>^N}VuJ
zf#pmXr~)Me6;RG314Srx!axO^Vi;sdOxd?EP(-qCVW5a)-;#kMlzmGEiV$lc2U@UD*0nqQ
z$7+v$kbXKwU%B*5Wfi~wyA#)}%?;MGCVEyP{d{HBtxdpoYuV{ZEAi17o8U_cSJ^Ep
zv*I{b!fPAW6r(d#RLeHEmd4@pIk_HVPl@#x6RGRdd#ss{CfP(34#hABGt8#!Doanb
z>Wv)hQ4{>yYA!w9@+x(9ozAUIUNS`s8ia6bJl@-?*XqWtjeZ*_J(c=LfPIyU3nb
zvgdjBJldyb&!O|Sd>V}@nlwKWPB8I9HWh1K_
zdd_C_>hNYURGlarS>4cclh&)l>&8%ZqHJV!L(jpiULD>+hN=@~BdZ&_ulMNH;l*UA
zI#D*Vx}p1YuU;MAR)(q*WqNf^)fAfm1+(lI8uIotFy+yre{-|!H>wP8-uE9R7?!Rb
zif7Igmc5K$^IDnoN$xx$l>{LbwciUYC+OO@I|1tiSdZ@b&
z(AuQypU#xud?$S4%8xT|U3mM=D{rk|c$+m1*I!!fKQu|pDj8qeU)qL!73wgpW6l0c
z+p?QCzC}TfWn90oY`B%>y5ZKUXAG>oXX#KhSk!f^9#;2Lgp9iN!cqosFW1Om*}Ae^
zF+)a$c=#61@r?mANHnsqW-d$35SuIU^t9V3{vgt|IveZ*7g8^#%VXF!$W1hloqH~(
z3MB!w?mt+JWFhT@bOtYwgwUG8djHUsrNv&5uEt5$?h+Y;RiTEF^{0z_+`7AL?jXZ-
zmkVc8k?oMJhsOEOyj17B5wi245rnM$*^>QnCot}=qbLa12UBvvgM}EB?%unDr5Kj=
z&$|?y1)u%6ZUl@Y%I|IYFZbiePj=@FnuB_AM
zTOlTP->AYhwoXG1ZR^ds(c*^cLVK>Pjqc{^gu7C2*gJId=(}a8eso@VaYWyQR%Ec0
zpqB;<(aj@U*L?pax~J*sX0)q=``YZ$-Hj)pnrloaER$j3f?kKylh{~nBuEU~xOgdj
z5DyQgfmR_q&-zb1JxFvam!hqhs&+_13&
z!`Roj{Lp?JC$W9R*uVMa9=}d+)7#thHcg)h)3*Ig>}>s7Tw%Y`uH3_Z;3IM6-mABs
z!B%0vHc>|EXj=?IwGYLZezx2gbcpHpoIhx#@N{|AAvn{dJ
z+}!$3J^PXfFk%LShu7ykhTTn^%*%#edU#=IQfRE68Ua74{tiZAzH^!4RZ+!Q;
zD5W7JT{Y-e4t|lX=IP+l!7~}mY_=MLLw|P!E-)Q(%v<5rl$!fjW$jo^4d0)KnXW!~WWChF@Hs=uX_ZyMa|S^aoWx$KJA;
z|KQOE>!arklorh%Kcdm|sThqV}x>?hOeJyMS+uc%H?5F?ozkhw@;K|=E_m2P6
zF@LeA-c4YOxHlcQBHISc>XOk*@8^K=sWrmrW+7h`C1!WzpQ730h+%W
zGLnKffbRhu?apHRKcw=T)DnZCRn__Ku?}|Y9~UnejLxeBS-^cqn1!wheynFj0KR0!
zL+Tq25MX~8Jk~?LLLBJv9ovZC@w~bCuK>UfHBMNtYMMtkdCl|gO7$@(j$3=^2IriI(T7oH9(6e9=~}~m+?oXP&|4mdg)C%-
ld6XH{oT+*-2N?caVn-MrTPn!+3!*4+Y?}Y^qFTV?_CN7_gn0k}

literal 0
HcmV?d1

diff --git a/tests/data/acpi/q35/TPM2.crb.tpm2 
b/tests/data/acpi/q35/TPM2.crb.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9d89c5becc0fc4558a0556daf46e152181f2eb51
 100644
GIT binary patch
literal 76
zcmWFu@HO|?Wja`Jcf2v%^42yj*a0!E-1hz+7az=7e)KM>6hB2WNG#ec9c0JCKY
A0RR91

literal 0
HcmV?d1

diff --git a/tests/data/acpi/virt/DSDT.crb-device.tpm2 
b/tests/data/acpi/virt/DSDT.crb-device.tpm2
index 
e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d5d6d0e004ce8cf7562b17e0cbd07b81d75f3297
 100644
GIT binary patch
literal 5276
zcmZvg%WoT16o>D`lh__VVmr?JVHZlpGaB1Xla{u`9y^IkoEVSWAf=KkRYjC+Dp6IG
z3MpjKLU%M

[PATCH v3 02/14] tpm_crb: CTRL_RSP_ADDR is 64-bits wide

2023-10-29 Thread Joelle van Dyne
The register is actually 64-bits but in order to make this more clear
than the specification, we define two 32-bit registers:
CTRL_RSP_LADDR and CTRL_RSP_HADDR to match the CTRL_CMD_* naming. This
deviates from the specs but is way more clear.

Previously, the only CRB device uses a fixed system address so this
was not an issue. However, once we support SysBus CRB device, the
address can be anywhere in 64-bit space.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 include/hw/acpi/tpm.h  | 3 ++-
 hw/tpm/tpm_crb_common.c| 3 ++-
 tests/qtest/tpm-crb-test.c | 2 +-
 tests/qtest/tpm-util.c | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 579c45f5ba..f60bfe2789 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -174,7 +174,8 @@ REG32(CRB_CTRL_CMD_SIZE, 0x58)
 REG32(CRB_CTRL_CMD_LADDR, 0x5C)
 REG32(CRB_CTRL_CMD_HADDR, 0x60)
 REG32(CRB_CTRL_RSP_SIZE, 0x64)
-REG32(CRB_CTRL_RSP_ADDR, 0x68)
+REG32(CRB_CTRL_RSP_LADDR, 0x68)
+REG32(CRB_CTRL_RSP_HADDR, 0x6C)
 REG32(CRB_DATA_BUFFER, 0x80)
 
 #define TPM_CRB_ADDR_BASE   0xFED4
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index fa463f295f..01b35808f6 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -197,7 +197,8 @@ void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
 s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
 s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
 s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-s->regs[R_CRB_CTRL_RSP_ADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
 
 s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
 CRB_CTRL_CMD_SIZE);
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 396ae3f91c..9d30fe8293 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -28,7 +28,7 @@ static void tpm_crb_test(const void *data)
 uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
 uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
 uint32_t rsize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_SIZE);
-uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 uint8_t locstate = readb(TPM_CRB_ADDR_BASE + A_CRB_LOC_STATE);
 uint32_t locctrl = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL);
 uint32_t locsts = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_STS);
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index 1c0319e6e7..dd02057fc0 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -25,7 +25,7 @@ void tpm_util_crb_transfer(QTestState *s,
unsigned char *rsp, size_t rsp_size)
 {
 uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
-uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 
 qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);
 
-- 
2.41.0




[PATCH v3 00/14] tpm: introduce TPM CRB SysBus device

2023-10-29 Thread Joelle van Dyne
The impetus for this patch set is to get TPM 2.0 working on Windows 11 ARM64.
Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
VMWare's implementation). However, the current TPM CRB device uses a fixed
system bus address that is reserved for RAM in ARM64 Virt machines.

In the process of adding the TPM CRB SysBus device, we also went ahead and
cleaned up some of the existing TPM hardware code and fixed some bugs. We used
the TPM TIS devices as a template for the TPM CRB devices and refactored out
common code. We moved the ACPI DSDT generation to the device in order to handle
dynamic base address requirements as well as reduce redundent code in different
machine ACPI generation. We also changed the tpm_crb device to use the ISA bus
instead of depending on the default system bus as the device only was built for
the PC configuration.

Another change is that the TPM CRB registers are now mapped in the same way that
the pflash ROM devices are mapped. It is a memory region whose writes are
trapped as MMIO accesses. This was needed because Apple Silicon does not decode
LDP (AARCH64 load pair of registers) caused page faults. @agraf suggested that
we do this to avoid having to do AARCH64 decoding in the HVF backend's fault
handler.

Unfortunately, it seems like the LDP fault still happens on HVF but the issue
seems to be in the HVF backend which needs to be fixed in a separate patch.

One last thing that's needed to get Windows 11 to recognize the TPM 2.0 device
is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 Virt
only recognizes the TPM TIS device through a FDT entry. A workaround is to
falsely identify the TPM CRB device as a TPM TIS device in the FDT node but this
causes issues for Linux. A proper fix would involve adding an ACPI device driver
in OVMF.

This has been tested on ARM64 with `tpm-crb-device` and on x86_64 with
`tpm-crb`. Additional testing should be performed on other architectures (RISCV
and Loongarch for example) as well as migration cases.

v3:
- Support backwards and forwards migration of existing tpm-crb device
- Dropped patch which moved tpm-crb to ISA bus due to migration concerns
- Unified `tpm_sysbus_plug` handler for ARM and Loongarch
- Added ACPI table tests for tpm-crb-device
- Refactored TPM CRB tests to run on tpm-crb-device for ARM Virt

v2:
- Fixed an issue where VMstate restore from an older version failed due to name
  collision of the memory block.
- In the ACPI table generation for CRB devices, the check for TPM 2.0 backend is
  moved to the device realize as CRB does not support TPM 1.0. It will error in
  that case.
- Dropped the patch to fix crash when PPI is enabled on TIS SysBus device since
  a separate patch submitted by Stefan Berger disables such an option.
- Fixed an issue where we default tpmEstablished=0 when it should be 1.
- In TPM CRB SysBus's ACPI entry, we accidently changed _UID from 0 to 1. This
  shouldn't be an issue but we changed it back just in case.
- Added a patch to migrate saved VMstate from an older version with the regs
  saved separately instead of as a RAM block.

Joelle van Dyne (14):
  tpm_crb: refactor common code
  tpm_crb: CTRL_RSP_ADDR is 64-bits wide
  tpm_ppi: refactor memory space initialization
  tpm_crb: use a single read-as-mem/write-as-mmio mapping
  tpm_crb: move ACPI table building to device interface
  tpm-sysbus: add plug handler for TPM on SysBus
  hw/arm/virt: connect TPM to platform bus
  hw/loongarch/virt: connect TPM to platform bus
  tpm_tis_sysbus: move DSDT AML generation to device
  tests: acpi: prepare for TPM CRB tests
  tpm_crb_sysbus: introduce TPM CRB SysBus device
  tests: acpi: implement TPM CRB tests for ARM virt
  tests: acpi: updated expected blobs for TPM CRB
  tests: add TPM-CRB sysbus tests for aarch64

 docs/specs/tpm.rst|   2 +
 hw/tpm/tpm_crb.h  |  79 ++
 hw/tpm/tpm_ppi.h  |  10 +-
 include/hw/acpi/tpm.h |   3 +-
 include/sysemu/tpm.h  |   7 +
 tests/qtest/tpm-tests.h   |   2 +
 tests/qtest/tpm-util.h|   4 +-
 hw/acpi/aml-build.c   |   7 +-
 hw/arm/virt-acpi-build.c  |  38 +--
 hw/arm/virt.c |   8 +
 hw/core/sysbus-fdt.c  |   1 +
 hw/i386/acpi-build.c  |  23 --
 hw/loongarch/acpi-build.c |  38 +--
 hw/loongarch/virt.c   |   8 +
 hw/riscv/virt.c   |   1 +
 hw/tpm/tpm-sysbus.c   |  33 +++
 hw/tpm/tpm_crb.c  | 302 ++
 hw/tpm/tpm_crb_common.c   | 260 +++
 hw/tpm/tpm_crb_sysbus.c   | 161 
 hw/tpm/tpm_ppi.c  |   5 +-
 hw/tpm/tpm_tis_isa.c  |   5 +-
 hw/tpm/tpm_tis_sysbus.c

[PATCH v3 10/14] tests: acpi: prepare for TPM CRB tests

2023-10-29 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
---
 tests/qtest/bios-tables-test-allowed-diff.h | 4 
 tests/data/acpi/q35/DSDT.crb.tpm2   | 0
 tests/data/acpi/q35/TPM2.crb.tpm2   | 0
 tests/data/acpi/virt/DSDT.crb-device.tpm2   | 0
 tests/data/acpi/virt/TPM2.crb-device.tpm2   | 0
 5 files changed, 4 insertions(+)
 create mode 100644 tests/data/acpi/q35/DSDT.crb.tpm2
 create mode 100644 tests/data/acpi/q35/TPM2.crb.tpm2
 create mode 100644 tests/data/acpi/virt/DSDT.crb-device.tpm2
 create mode 100644 tests/data/acpi/virt/TPM2.crb-device.tpm2

diff --git a/tests/qtest/bios-tables-test-allowed-diff.h 
b/tests/qtest/bios-tables-test-allowed-diff.h
index dfb8523c8b..c2d1924c2f 100644
--- a/tests/qtest/bios-tables-test-allowed-diff.h
+++ b/tests/qtest/bios-tables-test-allowed-diff.h
@@ -1 +1,5 @@
 /* List of comma-separated changed AML files to ignore */
+"tests/data/acpi/q35/DSDT.crb.tpm2",
+"tests/data/acpi/q35/TPM2.crb.tpm2",
+"tests/data/acpi/virt/DSDT.crb.tpm2",
+"tests/data/acpi/virt/TPM2.crb.tpm2",
diff --git a/tests/data/acpi/q35/DSDT.crb.tpm2 
b/tests/data/acpi/q35/DSDT.crb.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/q35/TPM2.crb.tpm2 
b/tests/data/acpi/q35/TPM2.crb.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/DSDT.crb-device.tpm2 
b/tests/data/acpi/virt/DSDT.crb-device.tpm2
new file mode 100644
index 00..e69de29bb2
diff --git a/tests/data/acpi/virt/TPM2.crb-device.tpm2 
b/tests/data/acpi/virt/TPM2.crb-device.tpm2
new file mode 100644
index 00..e69de29bb2
-- 
2.41.0




[PATCH v3 09/14] tpm_tis_sysbus: move DSDT AML generation to device

2023-10-29 Thread Joelle van Dyne
This reduces redundent code in different machine types with ACPI table
generation. Additionally, this will allow us to support different TPM
interfaces with the same AML logic. Finally, this matches up with the
TPM TIS ISA implementation.

Ideally, we would be able to call `qbus_build_aml` and avoid any TPM
specific code in the ACPI table generation. However, currently we
still have to call `build_tpm2` anyways and it does not look like
most other ACPI devices support the `ACPI_DEV_AML_IF` interface.

Signed-off-by: Joelle van Dyne 
---
 hw/arm/virt-acpi-build.c  | 38 ++
 hw/loongarch/acpi-build.c | 38 ++
 hw/tpm/tpm_tis_sysbus.c   | 37 +
 3 files changed, 41 insertions(+), 72 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 9ce136cd88..3efbe6bd09 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/aml-build.h"
@@ -208,41 +209,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const 
MemMapEntry *gpio_memmap,
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 #define ID_MAPPING_ENTRY_SIZE 20
 #define SMMU_V3_ENTRY_SIZE 68
 #define ROOT_COMPLEX_ENTRY_SIZE 36
@@ -891,7 +857,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 
 acpi_dsdt_add_power_button(scope);
 #ifdef CONFIG_TPM
-acpi_dsdt_add_tpm(scope, vms);
+call_dev_aml_func(DEVICE(tpm_find()), scope);
 #endif
 
 aml_append(dsdt, scope);
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index ae292fc543..1969bfc8f9 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -14,6 +14,7 @@
 #include "target/loongarch/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "migration/vmstate.h"
@@ -328,41 +329,6 @@ static void build_flash_aml(Aml *scope, 
LoongArchMachineState *lams)
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 /* build DSDT */
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
@@ -379,7 +345,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 

[PATCH v3 01/14] tpm_crb: refactor common code

2023-10-29 Thread Joelle van Dyne
In preparation for the SysBus variant, we move common code styled
after the TPM TIS devices.

To maintain compatibility, we do not rename the existing tpm-crb
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 docs/specs/tpm.rst  |   1 +
 hw/tpm/tpm_crb.h|  76 +++
 hw/tpm/tpm_crb.c| 270 ++--
 hw/tpm/tpm_crb_common.c | 216 
 hw/tpm/meson.build  |   1 +
 hw/tpm/trace-events |   2 +-
 6 files changed, 331 insertions(+), 235 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index efe124a148..2bc29c9804 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -45,6 +45,7 @@ operating system.
 
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
+ - ``hw/tpm/tpm_crb_common.c``
 
 SPAPR interface
 ---
diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
new file mode 100644
index 00..da3a0cf256
--- /dev/null
+++ b/hw/tpm/tpm_crb.h
@@ -0,0 +1,76 @@
+/*
+ * tpm_crb.h - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Marc-André Lureau 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+#ifndef TPM_TPM_CRB_H
+#define TPM_TPM_CRB_H
+
+#include "exec/memory.h"
+#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_ppi.h"
+
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
+
+typedef struct TPMCRBState {
+TPMBackend *tpmbe;
+TPMBackendCmd cmd;
+uint32_t regs[TPM_CRB_R_MAX];
+MemoryRegion mmio;
+MemoryRegion cmdmem;
+
+size_t be_buffer_size;
+
+bool ppi_enabled;
+TPMPPI ppi;
+} TPMCRBState;
+
+#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
+#define CRB_INTF_VERSION_CRB 0b1
+#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
+#define CRB_INTF_CAP_IDLE_FAST 0b0
+#define CRB_INTF_CAP_XFER_SIZE_64 0b11
+#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
+#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
+#define CRB_INTF_IF_SELECTOR_CRB 0b1
+
+enum crb_loc_ctrl {
+CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+CRB_LOC_CTRL_RELINQUISH = BIT(1),
+CRB_LOC_CTRL_SEIZE = BIT(2),
+CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
+};
+
+enum crb_ctrl_req {
+CRB_CTRL_REQ_CMD_READY = BIT(0),
+CRB_CTRL_REQ_GO_IDLE = BIT(1),
+};
+
+enum crb_start {
+CRB_START_INVOKE = BIT(0),
+};
+
+enum crb_cancel {
+CRB_CANCEL_INVOKE = BIT(0),
+};
+
+#define TPM_CRB_NO_LOCALITY 0xff
+
+void tpm_crb_request_completed(TPMCRBState *s, int ret);
+enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
+int tpm_crb_pre_save(TPMCRBState *s);
+void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
+void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+
+#endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index ea930da545..3ef4977fb5 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -31,257 +31,62 @@
 #include "tpm_ppi.h"
 #include "trace.h"
 #include "qom/object.h"
+#include "tpm_crb.h"
 
 struct CRBState {
 DeviceState parent_obj;
 
-TPMBackend *tpmbe;
-TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
-MemoryRegion mmio;
-MemoryRegion cmdmem;
-
-size_t be_buffer_size;
-
-bool ppi_enabled;
-TPMPPI ppi;
+TPMCRBState state;
 };
 typedef struct CRBState CRBState;
 
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  TYPE_TPM_CRB)
 
-#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
-#define CRB_INTF_VERSION_CRB 0b1
-#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
-#define CRB_INTF_CAP_IDLE_FAST 0b0
-#define CRB_INTF_CAP_XFER_SIZE_64 0b11
-#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
-#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
-#define CRB_INTF_IF_SELECTOR_CRB 0b1
-
-#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
-
-enum crb_loc_ctrl {
-CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
-CRB_LOC_CTRL_RELINQUISH = BIT(1),
-CRB_LOC_CTRL_SEIZE = BIT(2),
-CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
-};
-
-enum crb_ctrl_req {
-CRB_CTRL_REQ_CMD_READY = BIT(0),
-CRB_CTRL_REQ_GO_IDLE = BIT(1),
-};
-
-enum crb_start {
-CRB_START_INVOKE = BIT(0),
-};
-
-enum crb_cancel {
-CRB_CANCEL_INVOKE = BIT(0),
-};
-
-#define TPM_CRB_NO_LOCALITY 0xff
-
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
-{
-CRBState *s = CRB(opaque);
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-s

[PATCH v3 05/14] tpm_crb: move ACPI table building to device interface

2023-10-29 Thread Joelle van Dyne
This logic is similar to TPM TIS ISA device. Since TPM CRB can only
support TPM 2.0 backends, we check for this in realize.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_crb.h|  2 ++
 hw/i386/acpi-build.c| 23 ---
 hw/tpm/tpm_crb.c| 16 
 hw/tpm/tpm_crb_common.c | 19 +++
 4 files changed, 37 insertions(+), 23 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index 36863e1664..e6a86e3fd1 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -73,5 +73,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp);
 void tpm_crb_mem_save(TPMCRBState *s, uint32_t *saved_regs, void 
*saved_cmdmem);
 void tpm_crb_mem_load(TPMCRBState *s, const uint32_t *saved_regs,
   const void *saved_cmdmem);
+void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t baseaddr, uint32_t size,
+   bool build_ppi);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 80db183b78..ce3f7b2d91 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 uint32_t nr_mem = machine->ram_slots;
 int root_bus_limit = 0xFF;
 PCIBus *bus = NULL;
-#ifdef CONFIG_TPM
-TPMIf *tpm = tpm_find();
-#endif
 bool cxl_present = false;
 int i;
 VMBusBridge *vmbus_bridge = vmbus_bridge_find();
@@ -1790,26 +1787,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 }
 
-#ifdef CONFIG_TPM
-if (TPM_IS_CRB(tpm)) {
-dev = aml_device("TPM");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR",
-  aml_string("TPM 2.0 Device")));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
-   TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-
-aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
-aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-
-tpm_build_ppi_acpi(tpm, dev);
-
-aml_append(sb_scope, dev);
-}
-#endif
-
 if (pcms->sgx_epc.size != 0) {
 uint64_t epc_base = pcms->sgx_epc.base;
 uint64_t epc_size = pcms->sgx_epc.size;
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 99c64dd72a..8d57295b15 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -19,6 +19,8 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
+#include "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
@@ -121,6 +123,11 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
+if (tpm_crb_none_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
+error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
+return;
+}
+
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
 /* only used for migration */
@@ -142,10 +149,17 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
+static void build_tpm_crb_none_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+tpm_crb_build_aml(TPM_IF(adev), scope, TPM_CRB_ADDR_BASE, 
TPM_CRB_ADDR_SIZE,
+  true);
+}
+
 static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 TPMIfClass *tc = TPM_IF_CLASS(klass);
+AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
 
 dc->realize = tpm_crb_none_realize;
 device_class_set_props(dc, tpm_crb_none_properties);
@@ -154,6 +168,7 @@ static void tpm_crb_none_class_init(ObjectClass *klass, 
void *data)
 tc->model = TPM_MODEL_TPM_CRB;
 tc->get_version = tpm_crb_none_get_version;
 tc->request_completed = tpm_crb_none_request_completed;
+adevc->build_dev_aml = build_tpm_crb_none_aml;
 
 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
@@ -166,6 +181,7 @@ static const TypeInfo tpm_crb_none_info = {
 .class_init  = tpm_crb_none_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_TPM_IF },
+{ TYPE_ACPI_DEV_AML_IF },
 { }
 }
 };
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 605e8576e9..4fff0c6b59 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -239,3 +239,22 @@ void tpm_crb_mem_load(TPMCRBState *s, const uint32_t 
*saved_regs,
 memcpy(regs, saved_regs, TPM_CRB_R_MAX);
 memcpy([R_CRB_DATA_BUFFER], saved_cmdmem, A_CRB_DATA_BUFFER);
 }
+
+void tpm_crb_build_aml(TPMIf *ti, Aml *scope, uint32_t ba

[PATCH v3 03/14] tpm_ppi: refactor memory space initialization

2023-10-29 Thread Joelle van Dyne
Instead of calling `memory_region_add_subregion` directly, we defer to
the caller to do it. This allows us to re-use the code for a SysBus
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_ppi.h| 10 +++---
 hw/tpm/tpm_crb.c|  4 ++--
 hw/tpm/tpm_crb_common.c |  3 +++
 hw/tpm/tpm_ppi.c|  5 +
 hw/tpm/tpm_tis_isa.c|  5 +++--
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h
index bf5d4a300f..30863c6438 100644
--- a/hw/tpm/tpm_ppi.h
+++ b/hw/tpm/tpm_ppi.h
@@ -20,17 +20,13 @@ typedef struct TPMPPI {
 } TPMPPI;
 
 /**
- * tpm_ppi_init:
+ * tpm_ppi_init_memory:
  * @tpmppi: a TPMPPI
- * @m: the address-space / MemoryRegion to use
- * @addr: the address of the PPI region
  * @obj: the owner object
  *
- * Register the TPM PPI memory region at @addr on the given address
- * space for the object @obj.
+ * Creates the TPM PPI memory region.
  **/
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj);
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj);
 
 /**
  * tpm_ppi_reset:
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 3ef4977fb5..598c3e0161 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -107,8 +107,8 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
-tpm_ppi_init(>state.ppi, get_system_memory(),
- TPM_PPI_ADDR_BASE, OBJECT(s));
+memory_region_add_subregion(get_system_memory(),
+TPM_PPI_ADDR_BASE, >state.ppi.ram);
 }
 
 if (xen_enabled()) {
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 01b35808f6..bee0b71fee 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -214,4 +214,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp)
 "tpm-crb-mmio", sizeof(s->regs));
 memory_region_init_ram(>cmdmem, obj,
 "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+if (s->ppi_enabled) {
+tpm_ppi_init_memory(>ppi, obj);
+}
 }
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 7f74e26ec6..40cab59afa 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -44,14 +44,11 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
 }
 }
 
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj)
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj)
 {
 tpmppi->buf = qemu_memalign(qemu_real_host_page_size(),
 HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
 memory_region_init_ram_device_ptr(>ram, obj, "tpm-ppi",
   TPM_PPI_ADDR_SIZE, tpmppi->buf);
 vmstate_register_ram(>ram, DEVICE(obj));
-
-memory_region_add_subregion(m, addr, >ram);
 }
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 0367401586..d596f38c0f 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -134,8 +134,9 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error 
**errp)
 TPM_TIS_ADDR_BASE, >mmio);
 
 if (s->ppi_enabled) {
-tpm_ppi_init(>ppi, isa_address_space(ISA_DEVICE(dev)),
- TPM_PPI_ADDR_BASE, OBJECT(dev));
+tpm_ppi_init_memory(>ppi, OBJECT(dev));
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
+TPM_PPI_ADDR_BASE, >ppi.ram);
 }
 }
 
-- 
2.41.0




[PATCH v3 06/14] tpm-sysbus: add plug handler for TPM on SysBus

2023-10-29 Thread Joelle van Dyne
TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne 
---
 include/sysemu/tpm.h |  4 
 hw/tpm/tpm-sysbus.c  | 33 +
 hw/tpm/meson.build   |  1 +
 3 files changed, 38 insertions(+)
 create mode 100644 hw/tpm/tpm-sysbus.c

diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 1ee568b3b6..ffd300e607 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -12,6 +12,8 @@
 #ifndef QEMU_TPM_H
 #define QEMU_TPM_H
 
+#include "qemu/osdep.h"
+#include "exec/hwaddr.h"
 #include "qapi/qapi-types-tpm.h"
 #include "qom/object.h"
 
@@ -78,6 +80,8 @@ static inline TPMVersion tpm_get_version(TPMIf *ti)
 return TPM_IF_GET_CLASS(ti)->get_version(ti);
 }
 
+void tpm_sysbus_plug(TPMIf *tpmif, Object *pbus, hwaddr pbus_base);
+
 #else /* CONFIG_TPM */
 
 #define tpm_init()  (0)
diff --git a/hw/tpm/tpm-sysbus.c b/hw/tpm/tpm-sysbus.c
new file mode 100644
index 00..ef0592b837
--- /dev/null
+++ b/hw/tpm/tpm-sysbus.c
@@ -0,0 +1,33 @@
+#include "sysemu/tpm.h"
+#include "hw/platform-bus.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+
+void tpm_sysbus_plug(TPMIf *tpmif, Object *pbus, hwaddr pbus_base)
+{
+PlatformBusDevice *pbusdev = PLATFORM_BUS_DEVICE(pbus);
+SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+MemoryRegion *sbdev_mr;
+hwaddr tpm_base;
+uint64_t tpm_size;
+
+/* exit early if TPM is not a sysbus device */
+if (!object_dynamic_cast(OBJECT(tpmif), TYPE_SYS_BUS_DEVICE)) {
+return;
+}
+
+assert(object_dynamic_cast(pbus, TYPE_PLATFORM_BUS_DEVICE));
+
+tpm_base = platform_bus_get_mmio_addr(pbusdev, sbdev, 0);
+assert(tpm_base != -1);
+
+tpm_base += pbus_base;
+
+sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+tpm_size = memory_region_size(sbdev_mr);
+
+object_property_set_uint(OBJECT(sbdev), "x-baseaddr",
+ tpm_base, _abort);
+object_property_set_uint(OBJECT(sbdev), "x-size",
+ tpm_size, _abort);
+}
diff --git a/hw/tpm/meson.build b/hw/tpm/meson.build
index cb8204d5bc..3060ac05e8 100644
--- a/hw/tpm/meson.build
+++ b/hw/tpm/meson.build
@@ -1,6 +1,7 @@
 system_ss.add(when: 'CONFIG_TPM_TIS', if_true: files('tpm_tis_common.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_ISA', if_true: files('tpm_tis_isa.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: 
files('tpm_tis_sysbus.c'))
+system_ss.add(when: 'CONFIG_TPM_TIS_SYSBUS', if_true: files('tpm-sysbus.c'))
 system_ss.add(when: 'CONFIG_TPM_TIS_I2C', if_true: files('tpm_tis_i2c.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb.c'))
 system_ss.add(when: 'CONFIG_TPM_CRB', if_true: files('tpm_crb_common.c'))
-- 
2.41.0




[PATCH v3 07/14] hw/arm/virt: connect TPM to platform bus

2023-10-29 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
---
 hw/arm/virt.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 529f1c089c..f1a161b0ea 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2806,6 +2806,13 @@ static void virt_machine_device_plug_cb(HotplugHandler 
*hotplug_dev,
 vms->virtio_iommu_bdf = pci_get_bdf(pdev);
 create_virtio_iommu_dt_bindings(vms);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+tpm_sysbus_plug(TPM_IF(dev), OBJECT(vms->platform_bus_dev),
+vms->memmap[VIRT_PLATFORM_BUS].base);
+}
+#endif
 }
 
 static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
-- 
2.41.0




[PATCH v3 12/14] tests: acpi: implement TPM CRB tests for ARM virt

2023-10-29 Thread Joelle van Dyne
Signed-off-by: Joelle van Dyne 
---
 tests/qtest/bios-tables-test.c | 43 --
 1 file changed, 41 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
index 9f4bc15aab..c63bad0205 100644
--- a/tests/qtest/bios-tables-test.c
+++ b/tests/qtest/bios-tables-test.c
@@ -1345,6 +1345,28 @@ static void test_acpi_piix4_tcg_numamem(void)
 
 uint64_t tpm_tis_base_addr;
 
+static test_data tcg_tpm_test_data(const char *machine)
+{
+if (g_strcmp0(machine, "virt") == 0) {
+test_data data = {
+.machine = "virt",
+.tcg_only = true,
+.uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+.uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+.cd =
+   
"tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
+.ram_start = 0x4000ULL,
+.scan_len = 128ULL * 1024 * 1024,
+};
+return data;
+} else {
+test_data data = {
+.machine = machine,
+};
+return data;
+}
+}
+
 static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
   uint64_t base, enum TPMVersion tpm_version)
 {
@@ -1352,7 +1374,7 @@ static void test_acpi_tcg_tpm(const char *machine, const 
char *tpm_if,
   machine, tpm_if);
 char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL);
 TPMTestState test;
-test_data data = {};
+test_data data = tcg_tpm_test_data(machine);
 GThread *thread;
 const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12";
 char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix);
@@ -1372,13 +1394,14 @@ static void test_acpi_tcg_tpm(const char *machine, 
const char *tpm_if,
 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, );
 tpm_emu_test_wait_cond();
 
-data.machine = machine;
 data.variant = variant;
 
 args = g_strdup_printf(
+" %s"
 " -chardev socket,id=chr,path=%s"
 " -tpmdev emulator,id=dev,chardev=chr"
 " -device tpm-%s,tpmdev=dev",
+g_strcmp0(machine, "virt") == 0 ? "-cpu cortex-a57" : "",
 test.addr->u.q_unix.path, tpm_if);
 
 test_acpi_one(args, );
@@ -1404,6 +1427,16 @@ static void test_acpi_q35_tcg_tpm12_tis(void)
 test_acpi_tcg_tpm("q35", "tis", 0xFED4, TPM_VERSION_1_2);
 }
 
+static void test_acpi_q35_tcg_tpm2_crb(void)
+{
+test_acpi_tcg_tpm("q35", "crb", 0xFED4, TPM_VERSION_2_0);
+}
+
+static void test_acpi_virt_tcg_tpm2_crb(void)
+{
+test_acpi_tcg_tpm("virt", "crb-device", 0xFED4, TPM_VERSION_2_0);
+}
+
 static void test_acpi_tcg_dimm_pxm(const char *machine)
 {
 test_data data = {};
@@ -2110,6 +2143,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/q35/tpm12-tis",
test_acpi_q35_tcg_tpm12_tis);
 }
+if (tpm_model_is_available("-machine q35", "tpm-crb")) {
+qtest_add_func("acpi/q35/tpm2-crb", 
test_acpi_q35_tcg_tpm2_crb);
+}
 qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge);
 qtest_add_func("acpi/q35/no-acpi-hotplug",
test_acpi_q35_tcg_no_acpi_hotplug);
@@ -2191,6 +2227,9 @@ int main(int argc, char *argv[])
 qtest_add_func("acpi/virt/viot", test_acpi_virt_viot);
 }
 }
+if (tpm_model_is_available("-machine virt", "tpm-crb")) {
+qtest_add_func("acpi/virt/tpm2-crb", test_acpi_virt_tcg_tpm2_crb);
+}
 }
 ret = g_test_run();
 boot_sector_cleanup(disk);
-- 
2.41.0




Re: [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-10-28 Thread Joelle van Dyne
On Mon, Jul 17, 2023 at 7:23 AM Igor Mammedov  wrote:
>
> On Fri, 14 Jul 2023 00:09:26 -0700
> Joelle van Dyne  wrote:
>
> > This SysBus variant of the CRB interface supports dynamically locating
> > the MMIO interface so that Virt machines can use it. This interface
> > is currently the only one supported by QEMU that works on Windows 11
> > ARM64. We largely follow the TPM TIS SysBus device as a template.
> >
> > To try out this device with Windows 11 before OVMF is updated, you
> > will need to modify `sysbud-fdt.c` and change the added line from:
> >
> > ```c
> > TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> > ```
> >
> > to
> >
> > ```c
> > TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
> > ```
> >
> > This change was not included because it can confuse Linux (although
> > from testing, it seems like Linux is able to properly ignore the
> > device from the TPM TIS driver and recognize it from the ACPI device
> > in the TPM CRB driver). A proper fix would require OVMF to recognize
> > the ACPI device and not depend on the FDT node for recognizing TPM.
> >
> > The command line to try out this device with SWTPM is:
> >
> > ```
> > $ qemu-system-aarch64 \
> > -chardev socket,id=chrtpm0,path=tpm.sock \
> > -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
> > -device tpm-crb-device,tpmdev=tpm0
> > ```
> >
> > along with SWTPM:
> >
> > ```
> > $ swtpm \
> > --ctrl type=unixio,path=tpm.sock,terminate \
> > --tpmstate backend-uri=file://tpm.data \
> > --tpm2
> > ```
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
> >  docs/specs/tpm.rst  |   1 +
> >  include/hw/acpi/aml-build.h |   1 +
> >  include/sysemu/tpm.h|   3 +
> >  hw/acpi/aml-build.c |   7 +-
> >  hw/arm/virt.c   |   1 +
> >  hw/core/sysbus-fdt.c|   1 +
> >  hw/loongarch/virt.c |   1 +
> >  hw/riscv/virt.c |   1 +
> >  hw/tpm/tpm_crb_sysbus.c | 170 
> >  hw/arm/Kconfig  |   1 +
> >  hw/riscv/Kconfig|   1 +
> >  hw/tpm/Kconfig  |   5 ++
> >  hw/tpm/meson.build  |   2 +
> >  13 files changed, 194 insertions(+), 1 deletion(-)
> >  create mode 100644 hw/tpm/tpm_crb_sysbus.c
> >
> > diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> > index 2bc29c9804..95aeb49220 100644
> > --- a/docs/specs/tpm.rst
> > +++ b/docs/specs/tpm.rst
> > @@ -46,6 +46,7 @@ operating system.
> >  QEMU files related to TPM CRB interface:
> >   - ``hw/tpm/tpm_crb.c``
> >   - ``hw/tpm/tpm_crb_common.c``
> > + - ``hw/tpm/tpm_crb_sysbus.c``
> >
> >  SPAPR interface
> >  ---
> > diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> > index d1fb08514b..9660e16148 100644
> > --- a/include/hw/acpi/aml-build.h
> > +++ b/include/hw/acpi/aml-build.h
> > @@ -3,6 +3,7 @@
> >
> >  #include "hw/acpi/acpi-defs.h"
> >  #include "hw/acpi/bios-linker-loader.h"
> > +#include "exec/hwaddr.h"
> >
> >  #define ACPI_BUILD_APPNAME6 "BOCHS "
> >  #define ACPI_BUILD_APPNAME8 "BXPC"
> > diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> > index 66e3b45f30..f79c8f3575 100644
> > --- a/include/sysemu/tpm.h
> > +++ b/include/sysemu/tpm.h
> > @@ -47,6 +47,7 @@ struct TPMIfClass {
> >  #define TYPE_TPM_TIS_ISA"tpm-tis"
> >  #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
> >  #define TYPE_TPM_CRB"tpm-crb"
> > +#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
> >  #define TYPE_TPM_SPAPR  "tpm-spapr"
> >  #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
> >
> > @@ -56,6 +57,8 @@ struct TPMIfClass {
> >  object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
> >  #define TPM_IS_CRB(chr) \
> >  object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
> > +#define TPM_IS_CRB_SYSBUS(chr)  \
> > +object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
> >  #define TPM_IS_SPAPR(chr)   \
> >  object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
> >  #define TPM_IS_TIS_I2C(chr)  \
> > diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> > index ea331a20d1..f809137fc9 100644
> > --- a/hw/ac

Re: [PATCH v2 06/11] tpm_crb: move ACPI table building to device interface

2023-07-31 Thread Joelle van Dyne
On Mon, Jul 17, 2023 at 6:42 AM Igor Mammedov  wrote:
>
> On Fri, 14 Jul 2023 13:21:33 -0400
> Stefan Berger  wrote:
>
> > On 7/14/23 03:09, Joelle van Dyne wrote:
> > > This logic is similar to TPM TIS ISA device. Since TPM CRB can only
> > > support TPM 2.0 backends, we check for this in realize.
> > >
> > > Signed-off-by: Joelle van Dyne 
> >
> > This patch changes the order of in which the ACPI table elements are 
> > created but doesn't matter and also doesn't seem to upset ACPI test cases 
> > from what I saw:
>
> it seems we do have tests for TIS only (which I added when I was refactoring 
> it to TYPE_ACPI_DEV_AML_IF)
> perhaps add a test for CRB before this patch a follow process described in 
> bios-tables-test.c
> for updating expected blob
I read the file and looked at the commits for TIS tests but I'm not
sure I understand how it works. At what point do I specify that the
CRB device should be created for the test?

>
> >
> > Reviewed-by: Stefan Berger 
> >
> > > ---
> > >   hw/i386/acpi-build.c | 23 ---
> > >   hw/tpm/tpm_crb.c | 29 +
> > >   2 files changed, 29 insertions(+), 23 deletions(-)
> > >
> > > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > > index 9c74fa17ad..b767df39df 100644
> > > --- a/hw/i386/acpi-build.c
> > > +++ b/hw/i386/acpi-build.c
> > > @@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> > >   uint32_t nr_mem = machine->ram_slots;
> > >   int root_bus_limit = 0xFF;
> > >   PCIBus *bus = NULL;
> > > -#ifdef CONFIG_TPM
> > > -TPMIf *tpm = tpm_find();
> > > -#endif
> > >   bool cxl_present = false;
> > >   int i;
> > >   VMBusBridge *vmbus_bridge = vmbus_bridge_find();
> > > @@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> > >   }
> > >   }
> > >
> > > -#ifdef CONFIG_TPM
> > > -if (TPM_IS_CRB(tpm)) {
> > > -dev = aml_device("TPM");
> > > -aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > > -aml_append(dev, aml_name_decl("_STR",
> > > -  aml_string("TPM 2.0 Device")));
> > > -crs = aml_resource_template();
> > > -aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> > > -   TPM_CRB_ADDR_SIZE, 
> > > AML_READ_WRITE));
> > > -aml_append(dev, aml_name_decl("_CRS", crs));
> > > -
> > > -aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
> > > -aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > > -
> > > -tpm_build_ppi_acpi(tpm, dev);
> > > -
> > > -aml_append(sb_scope, dev);
> > > -}
> > > -#endif
> > > -
> > >   if (pcms->sgx_epc.size != 0) {
> > >   uint64_t epc_base = pcms->sgx_epc.base;
> > >   uint64_t epc_size = pcms->sgx_epc.size;
> > > diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> > > index 6144081d30..594696ffb8 100644
> > > --- a/hw/tpm/tpm_crb.c
> > > +++ b/hw/tpm/tpm_crb.c
> > > @@ -19,6 +19,8 @@
> > >   #include "qemu/module.h"
> > >   #include "qapi/error.h"
> > >   #include "exec/address-spaces.h"
> > > +#include "hw/acpi/acpi_aml_interface.h"
> > > +#include "hw/acpi/tpm.h"
> > >   #include "hw/qdev-properties.h"
> > >   #include "hw/pci/pci_ids.h"
> > >   #include "hw/acpi/tpm.h"
> > > @@ -99,6 +101,11 @@ static void tpm_crb_isa_realize(DeviceState *dev, 
> > > Error **errp)
> > >   return;
> > >   }
> > >
> > > +if (tpm_crb_isa_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
> > > +error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
> > > +return;
> > > +}
> > > +
> > >   tpm_crb_init_memory(OBJECT(s), >state, errp);
> > >
> > >   memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
> > > @@ -116,10 +123,30 @@ static void tpm_crb_isa_realize(DeviceState *dev, 
> > > Error **errp)
> > >   }
> > >   }
> > >
> > > +static void bu

Re: [PATCH v2 05/11] tpm_crb: use the ISA bus

2023-07-31 Thread Joelle van Dyne
On Tue, Jul 18, 2023 at 7:16 AM Stefan Berger  wrote:
>
>
>
> On 7/17/23 09:46, Igor Mammedov wrote:
> > On Fri, 14 Jul 2023 00:09:21 -0700
> > Joelle van Dyne  wrote:
> >
> >> Since this device is gated to only build for targets with the PC
> >> configuration, we should use the ISA bus like with TPM TIS.
> >
> > does it affect migration in any way?
> >  From guest pov it looks like there a new ISA device will appear
> > and then if you do ping pong migration between old - new QEMU will really 
> > it work?
>
>
> >
> > If it will, then commit message here shall describe why it safe and why it 
> > works
> >
> I would just leave the existing device as-is. This seems safest and we know 
> thta it works.
> Stefan

Alexander, do you have any comments here? I know you wanted to move
away from the default bus. The concern is that switching from the
default bus to the ISA bus may cause issues in migration. The current
course of action is to drop this patch.



Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 12:12 PM Stefan Berger  wrote:
>
>
>
> On 7/14/23 14:49, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 11:41 AM Stefan Berger  
> > wrote:
> >>
> >>
> >>
> >> On 7/14/23 14:22, Stefan Berger wrote:
> >>> On 7/14/23 13:04, Joelle van Dyne wrote:
> >>>> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger  
> >>>> wrote:
> >>>>>
> >>>>>
> >>>>>
> >>>>> On 7/14/23 10:05, Stefan Berger wrote:
> >>>>>>
> >>>>>>
> >>>>>> On 7/14/23 03:09, Joelle van Dyne wrote:
> >>>>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
> >>>>>>> broke restoring of VMs that were saved on an older version. This
> >>>>>>> change allows those VMs to gracefully migrate to the new memory
> >>>>>>> mapping.
> >>>>>>
> >>>>>> Thanks. This has to be in 4/11 though.
> >>>>>>
> >>>>>
> >>>>> After applying the whole series and trying to resume state taken with 
> >>>>> current git
> >>>>> master I cannot restore it but it leads to this error here. I would 
> >>>>> just leave it
> >>>>> completely untouched in 4/11.
> >>>>>
> >>>>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock 
> >>>>> "tpm-crb-cmd", cannot accept migration
> >>>>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading 
> >>>>> state for instance 0x0 of device 'ram'
> >>>>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration 
> >>>>> failed: Invalid argument
> >>>>>
> >>>>>   Stefan
> >>>>
> >>>> To be clear, you are asking to back out of 4/11? That patch changes
> >>>> how the registers are mapped so it's impossible to support the old
> >>>> style register mapping. This patch attempts to fix that with a
> >>>
> >>> Why can we not keep the old style register mapping as 'secondary mapping'?
> >>
> >> I think the first goal should be for existing TPM CRB device not to change 
> >> anything, they
> >> keep their .read and .write behaivor as it.
> >>
> >> If you need different .read behavior for the sysbus device due to AARCH64 
> >> then it may want to use its own MemoryRegionOps.
> >>
> >> I am fairly sure that you could refactor the core of the existing 
> >> tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
> >> The former would be used by existing code, the latter for CRB sysbus 
> >> calling into this new function from a wrapper.
> >>
> >>  Stefan
> >
> > I agree that new QEMU should be able to read old QEMU state but vice
> > versa is not always true. There's been many changes in the past that
> > incremented the vmstate's version_id to indicate that the state format
> > has changed. Also, we are not changing the .read behavior because in
>
> Unfortunately the CRB device is being used by x86 on some distros
> and the expectation is that this existing device can also downgrade
> to a previous version of QEMU I would say. I have read people migrating
> from RHEL 9.x even to RHEL 8.x and the expectation is that this works.
But would the migration even work due to other parts of QEMU? The only
way you can, say, migrate from QEMU 8.1.0 to 8.0.0 is if every single
VMstate has its version_id unchanged. Does QEMU provide that
guarantee? I'm fine with changing it but just want to make sure
expectations are set correctly. Have you tested a downgrade and found
that no other device impeded the process?

>
> Now you are introducing a new device and I think you can leave
> the existing device with its s->regs alone and have the new device
> with its mmio regs work a little different just to preserve the QEMU
> downgrade for x86.
>
> > the old code, the only field that gets a dynamic update is
> > tpmEstablished which we found is never changed. So effectively, .read
>
> Correct and that's why you don't need a .read in the new device.
>
> > is just doing a memcpy of the `regs` state. This makes it possible to
> > map the page as memory while retaining the same behavior as before.
> > (We are changing the code but not the behavior).
> >
> > The issue with Windows's buggy tpm.sys driver

Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 11:41 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 14:22, Stefan Berger wrote:
> > On 7/14/23 13:04, Joelle van Dyne wrote:
> >> On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger  
> >> wrote:
> >>>
> >>>
> >>>
> >>> On 7/14/23 10:05, Stefan Berger wrote:
> >>>>
> >>>>
> >>>> On 7/14/23 03:09, Joelle van Dyne wrote:
> >>>>> When we moved to a single mapping and modified TPM CRB's VMState, it
> >>>>> broke restoring of VMs that were saved on an older version. This
> >>>>> change allows those VMs to gracefully migrate to the new memory
> >>>>> mapping.
> >>>>
> >>>> Thanks. This has to be in 4/11 though.
> >>>>
> >>>
> >>> After applying the whole series and trying to resume state taken with 
> >>> current git
> >>> master I cannot restore it but it leads to this error here. I would just 
> >>> leave it
> >>> completely untouched in 4/11.
> >>>
> >>> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock 
> >>> "tpm-crb-cmd", cannot accept migration
> >>> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state 
> >>> for instance 0x0 of device 'ram'
> >>> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: 
> >>> Invalid argument
> >>>
> >>>  Stefan
> >>
> >> To be clear, you are asking to back out of 4/11? That patch changes
> >> how the registers are mapped so it's impossible to support the old
> >> style register mapping. This patch attempts to fix that with a
> >
> > Why can we not keep the old style register mapping as 'secondary mapping'?
>
> I think the first goal should be for existing TPM CRB device not to change 
> anything, they
> keep their .read and .write behaivor as it.
>
> If you need different .read behavior for the sysbus device due to AARCH64 
> then it may want to use its own MemoryRegionOps.
>
> I am fairly sure that you could refactor the core of the existing 
> tpm_crb_mmio_write() and have it work on s->regs and mmio regs.
> The former would be used by existing code, the latter for CRB sysbus calling 
> into this new function from a wrapper.
>
> Stefan

I agree that new QEMU should be able to read old QEMU state but vice
versa is not always true. There's been many changes in the past that
incremented the vmstate's version_id to indicate that the state format
has changed. Also, we are not changing the .read behavior because in
the old code, the only field that gets a dynamic update is
tpmEstablished which we found is never changed. So effectively, .read
is just doing a memcpy of the `regs` state. This makes it possible to
map the page as memory while retaining the same behavior as before.
(We are changing the code but not the behavior).

The issue with Windows's buggy tpm.sys driver is that fundamentally it
cannot work with MemoryRegionOps. The way MMIO is implemented is that
a hole is left in the guest memory space so when the device registers
are accessed, the hypervisor traps it and sends it over to QEMU to
handle. QEMU looks up the address, sees its a valid MMIO mapping, and
calls into the MemoryRegionOps implementation. When tpm.sys does a LDP
instruction access to the hole, the information for QEMU to determine
if it's a valid access is not provided. Other hypervisors like Apple's
VZ.framework and VMware will read the guest PC, manually decode the
AArch64 instruction, determine the type of access, read the guest Rn
registers, does a TLB lookup to determine the physical address, then
emulate the MMIO. None of this capability currently exists in QEMU's
ARM64 backend. That's why we decided the easier path is to tell QEMU
that this mapping is RAM for read purposes and MMIO only for write
purposes (thankfully Windows does not do a STP or we'd be hosed).



Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 11:01 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 13:46, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 10:43 AM Stefan Berger  
> > wrote:
> >>
> >>
> >>
> >> On 7/14/23 13:39, Joelle van Dyne wrote:
> >>> On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger  
> >>> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 7/14/23 13:29, Joelle van Dyne wrote:
> >>>>> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger  
> >>>>> wrote:
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> I don't know whether we would want multiple devices. tpm_find() usage 
> >>>>>> is certainly not prepared for multiple devices.
> >>>>> Sorry, "multiple TPM interfaces" here does not mean "at the same
> >>>>> time". Will clarify the description.
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>> Good for the consolidation.
> >>>>>>
> >>>>>>
> >>>>>> Does moving the TIS to a different address help on aarch64?
> >>>>> That was the first thing we tried and no it doesn't help.
> >>>>
> >>>> I would remove it if we don't have a known alternative address that 
> >>>> makes it work. If we do, I think we should document it in tpm.rst.
> >>> "It" is referring to tpm-tis-device? Note that it does work fine with 
> >>> Linux VMs.
> >>
> >> yes, tpm_tis_sysbus and I know it works with Liunux but I see this 
> >> discussion here around Win 11 on aarch64. Why do we need to user another 
> >> address than the standard address if for Win 11 on aarch64 it doesn't get 
> >> it to work.
> > The standard address won't work for Linux either.
> >
> > TPM TIS on standard address on ARM64 Virt machines = collision with
> > DRAM, will not instantiate
>
> I thought that this was working with Linux on the aarch64 virt board as 
> contributed by Eric Auger.
>
> https://github.com/qemu/qemu/commit/fcaa204194e15ba24cd53087dd616aabbc29e64f
>
> Also I had tested it to some extent: 
> https://github.com/stefanberger/swtpm/issues/493#issuecomment-885221109
I think I know where the confusion is. Both your examples use
"tpm-tis-device" which indeed uses the SysBus and gets a dynamic
address. In this patch, the removed code that generates the AML gets
this address by poking into the SysBus device, getting its base, then
adding the offset from the TIS device to it. In the change, we move
that code to get the address to earlier in the Virt init sequence
(before the machine is realized) in order to tell the TIS device what
its own base address is. Then, during the AML generation phase, we can
just tell the TIS device to "generate your own AML" which is now
possible because it knows its own base address. This is also how the
TIS ISA bus device does it but that is simpler because it can just use
the default address.

Separately, there is a `build_tpm2` table function which also needs
the device base address but only for CRB devices (TIS has the field
set to 0) so it's irrelevant here.

>
>
>
> > TPM TIS on SysBus with dynamically allocated address = works on Linux,
> > cannot start on Windows
> >
> >>
> >>>
> >>>>
> >>>>
> >>>>>>
> >>>>>> Can the size really be an option? I don't see it useful and if one 
> >>>>>> gave the wrong size it may break things.
> >>>>> It was added for consistency (otherwise we have to determine the size
> >>>>> by looking at the interface everywhere). Also, it is possible for the
> >>>>> size to be larger than the constant. For example, Apple Silicon uses
> >>>>> 16KiB page sizes and we may decide to force the device to be 16KiB
> >>>>> aligned (not sure if this is needed yet while we still track down why
> >>>>> the dual mapping was not working). In that case, we would need to
> >>>>> inform the OS of the true region size to prevent any overlap issues.
> >>>>> Both baseaddr and size should be provided only by the plug handler in
> >>>>> the virt machine, otherwise things may break even if we get rid of
> >>>>> size and have just an incorrect baseaddr.
> >>>>>
> >>>>>>
> >>>>>>
> >>>>>>



Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 10:43 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 13:39, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger  
> > wrote:
> >>
> >>
> >>
> >> On 7/14/23 13:29, Joelle van Dyne wrote:
> >>> On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger  
> >>> wrote:
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> I don't know whether we would want multiple devices. tpm_find() usage is 
> >>>> certainly not prepared for multiple devices.
> >>> Sorry, "multiple TPM interfaces" here does not mean "at the same
> >>> time". Will clarify the description.
> >>>
> >>>>
> >>>>
> >>>> Good for the consolidation.
> >>>>
> >>>>
> >>>> Does moving the TIS to a different address help on aarch64?
> >>> That was the first thing we tried and no it doesn't help.
> >>
> >> I would remove it if we don't have a known alternative address that makes 
> >> it work. If we do, I think we should document it in tpm.rst.
> > "It" is referring to tpm-tis-device? Note that it does work fine with Linux 
> > VMs.
>
> yes, tpm_tis_sysbus and I know it works with Liunux but I see this discussion 
> here around Win 11 on aarch64. Why do we need to user another address than 
> the standard address if for Win 11 on aarch64 it doesn't get it to work.
The standard address won't work for Linux either.

TPM TIS on standard address on ARM64 Virt machines = collision with
DRAM, will not instantiate
TPM TIS on SysBus with dynamically allocated address = works on Linux,
cannot start on Windows

>
> >
> >>
> >>
> >>>>
> >>>> Can the size really be an option? I don't see it useful and if one gave 
> >>>> the wrong size it may break things.
> >>> It was added for consistency (otherwise we have to determine the size
> >>> by looking at the interface everywhere). Also, it is possible for the
> >>> size to be larger than the constant. For example, Apple Silicon uses
> >>> 16KiB page sizes and we may decide to force the device to be 16KiB
> >>> aligned (not sure if this is needed yet while we still track down why
> >>> the dual mapping was not working). In that case, we would need to
> >>> inform the OS of the true region size to prevent any overlap issues.
> >>> Both baseaddr and size should be provided only by the plug handler in
> >>> the virt machine, otherwise things may break even if we get rid of
> >>> size and have just an incorrect baseaddr.
> >>>
> >>>>
> >>>>
> >>>>



Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 10:37 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 13:29, Joelle van Dyne wrote:
> > On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger  wrote:
> >>
> >>
> >>
> >>
> >> I don't know whether we would want multiple devices. tpm_find() usage is 
> >> certainly not prepared for multiple devices.
> > Sorry, "multiple TPM interfaces" here does not mean "at the same
> > time". Will clarify the description.
> >
> >>
> >>
> >> Good for the consolidation.
> >>
> >>
> >> Does moving the TIS to a different address help on aarch64?
> > That was the first thing we tried and no it doesn't help.
>
> I would remove it if we don't have a known alternative address that makes it 
> work. If we do, I think we should document it in tpm.rst.
"It" is referring to tpm-tis-device? Note that it does work fine with Linux VMs.

>
>
> >>
> >> Can the size really be an option? I don't see it useful and if one gave 
> >> the wrong size it may break things.
> > It was added for consistency (otherwise we have to determine the size
> > by looking at the interface everywhere). Also, it is possible for the
> > size to be larger than the constant. For example, Apple Silicon uses
> > 16KiB page sizes and we may decide to force the device to be 16KiB
> > aligned (not sure if this is needed yet while we still track down why
> > the dual mapping was not working). In that case, we would need to
> > inform the OS of the true region size to prevent any overlap issues.
> > Both baseaddr and size should be provided only by the plug handler in
> > the virt machine, otherwise things may break even if we get rid of
> > size and have just an incorrect baseaddr.
> >
> >>
> >>
> >>



Re: [PATCH 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 4:57 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 06:05, Peter Maydell wrote:
> > On Thu, 13 Jul 2023 at 19:43, Stefan Berger  wrote:
> >>
> >>
> >>
> >> On 7/13/23 13:18, Peter Maydell wrote:
> >>> On Thu, 13 Jul 2023 at 18:16, Stefan Berger  wrote:
>  I guess the first point would be to decide whether to support an i2c bus 
>  on the virt board and then whether we can use the aspeed bus that we 
>  know that the tpm_tis_i2c device model works with but we don't know how 
>  Windows may react to it.
> 
>  It seems sysbus is already supported there so ... we may have a 'match'?
> >>>
> >>> You can use sysbus devices anywhere -- they're just
> >>
> >> 'anywhere' also includes aarch64 virt board I suppose.
> >
> > Yes. Literally any machine can have memory mapped devices.
> >
> >>> "this is a memory mapped device". The question is whether
> >>> we should, or whether an i2c controller is more like
> >>> what the real world uses (and if so, what i2c controller).
> >>>
> >>
> >>> I don't want to accept changes to the virt board that are
> >>> hard to live with in future, because changing virt in
> >>> non-backward compatible ways is painful.
> >>
> >> Once we have the CRB sysbus device we would keep it around forever and it 
> >> seems to
> >> - not require any changes to the virt board (iiuc) since sysbus is already 
> >> being used
> >> - works already with Windows and probably also Linux
> >
> > "Add a sysbus device to the virt board" is the kind of
> > change I mean -- once you do that it's hard to take it
> > out again, and if we decide in 6 months time that actually
> > i2c would be the better option then we end up with two
> > different ways to do the same thing and trying to
> > deprecate the other one is a pain.
>
>
> At least CRB is a standard interface and from this perspective we are fine. I 
> am not sure what would drive the introduction of the i2c bus in 6 months. I 
> suppose one could then still use sysbus CRB device or the i2c device. The 
> sysbus CRB device should still work then. Anyway, I think we should continue 
> with this series.
>
> Stefan
>
> >
> > -- PMM

FWIW the Windows 11 tpm.sys driver does not support the I2C interface.
The driver only recognizes ACPI devices and the case for Start Method
= 12 (FIFO Interface over I2C bus) goes to an error handler.



Re: [PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 9:19 AM Stefan Berger  wrote:
>
>
>
>
> I don't know whether we would want multiple devices. tpm_find() usage is 
> certainly not prepared for multiple devices.
Sorry, "multiple TPM interfaces" here does not mean "at the same
time". Will clarify the description.

>
>
> Good for the consolidation.
>
>
> Does moving the TIS to a different address help on aarch64?
That was the first thing we tried and no it doesn't help.
>
> Can the size really be an option? I don't see it useful and if one gave the 
> wrong size it may break things.
It was added for consistency (otherwise we have to determine the size
by looking at the interface everywhere). Also, it is possible for the
size to be larger than the constant. For example, Apple Silicon uses
16KiB page sizes and we may decide to force the device to be 16KiB
aligned (not sure if this is needed yet while we still track down why
the dual mapping was not working). In that case, we would need to
inform the OS of the true region size to prevent any overlap issues.
Both baseaddr and size should be provided only by the plug handler in
the virt machine, otherwise things may break even if we get rid of
size and have just an incorrect baseaddr.

>
>
>



Re: [PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 7:27 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 03:09, Joelle van Dyne wrote:
> > This SysBus variant of the CRB interface supports dynamically locating
> > the MMIO interface so that Virt machines can use it. This interface
> > is currently the only one supported by QEMU that works on Windows 11
> > ARM64. We largely follow the TPM TIS SysBus device as a template.
> >
> > To try out this device with Windows 11 before OVMF is updated, you
> > will need to modify `sysbud-fdt.c` and change the added line from:
> >
> > ```c
> >  TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
> > ```
> >
> > to
> >
> > ```c
> >  TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
> > ```
> >
> > This change was not included because it can confuse Linux (although
> > from testing, it seems like Linux is able to properly ignore the
> > device from the TPM TIS driver and recognize it from the ACPI device
> > in the TPM CRB driver). A proper fix would require OVMF to recognize
> > the ACPI device and not depend on the FDT node for recognizing TPM.
> >
> > The command line to try out this device with SWTPM is:
> >
> > ```
> > $ qemu-system-aarch64 \
> >  -chardev socket,id=chrtpm0,path=tpm.sock \
> >  -tpmdev emulator,id=tpm0,chardev=chrtpm0 \
> >  -device tpm-crb-device,tpmdev=tpm0
> > ```
> >
> > along with SWTPM:
> >
> > ```
> > $ swtpm \
> >  --ctrl type=unixio,path=tpm.sock,terminate \
> >  --tpmstate backend-uri=file://tpm.data \
> >  --tpm2
> > ```
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
> >   docs/specs/tpm.rst  |   1 +
> >   include/hw/acpi/aml-build.h |   1 +
> >   include/sysemu/tpm.h|   3 +
> >   hw/acpi/aml-build.c |   7 +-
> >   hw/arm/virt.c   |   1 +
> >   hw/core/sysbus-fdt.c|   1 +
> >   hw/loongarch/virt.c |   1 +
> >   hw/riscv/virt.c |   1 +
> >   hw/tpm/tpm_crb_sysbus.c | 170 
> >   hw/arm/Kconfig  |   1 +
> >   hw/riscv/Kconfig|   1 +
> >   hw/tpm/Kconfig  |   5 ++
> >   hw/tpm/meson.build  |   2 +
> >   13 files changed, 194 insertions(+), 1 deletion(-)
> >   create mode 100644 hw/tpm/tpm_crb_sysbus.c
> >
> > diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
> > index 2bc29c9804..95aeb49220 100644
> > --- a/docs/specs/tpm.rst
> > +++ b/docs/specs/tpm.rst
> > @@ -46,6 +46,7 @@ operating system.
> >   QEMU files related to TPM CRB interface:
> >- ``hw/tpm/tpm_crb.c``
> >- ``hw/tpm/tpm_crb_common.c``
> > + - ``hw/tpm/tpm_crb_sysbus.c``
> >
>
> If you added the command line to use for Windows guests to this document
> I think this would be helpful. And also mention that this must be used for 
> Windows
> since the other ones don't work.
>
>
> >   SPAPR interface
> >   ---
> > diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> > index d1fb08514b..9660e16148 100644
> > --- a/include/hw/acpi/aml-build.h
> > +++ b/include/hw/acpi/aml-build.h
> > @@ -3,6 +3,7 @@
> >
> >   #include "hw/acpi/acpi-defs.h"
> >   #include "hw/acpi/bios-linker-loader.h"
> > +#include "exec/hwaddr.h"
> >
> >   #define ACPI_BUILD_APPNAME6 "BOCHS "
> >   #define ACPI_BUILD_APPNAME8 "BXPC"
> > diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
> > index 66e3b45f30..f79c8f3575 100644
> > --- a/include/sysemu/tpm.h
> > +++ b/include/sysemu/tpm.h
> > @@ -47,6 +47,7 @@ struct TPMIfClass {
> >   #define TYPE_TPM_TIS_ISA"tpm-tis"
> >   #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
> >   #define TYPE_TPM_CRB"tpm-crb"
> > +#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
> >   #define TYPE_TPM_SPAPR  "tpm-spapr"
> >   #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
> >
> > @@ -56,6 +57,8 @@ struct TPMIfClass {
> >   object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
> >   #define TPM_IS_CRB(chr) \
> >   object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
> > +#define TPM_IS_CRB_SYSBUS(chr)  \
> > +object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
> >   #define TPM_IS_SPAPR(chr) 

Re: [PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 5:11 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 03:09, Joelle van Dyne wrote:
> > TPM needs to know its own base address in order to generate its DSDT
> > device entry.
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
> >   hw/arm/virt.c | 37 +
> >   1 file changed, 37 insertions(+)
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 7d9dbc2663..432148ef47 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler 
> > *hotplug_dev,
> >dev, _abort);
> >   }
> >
> > +#ifdef CONFIG_TPM
> > +static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
> > +{
> > +PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> > +hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
>
> +static void virt_tpm_plug(LoongArchMachineState *lams, TPMIf *tpmif)
> +{
> +PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(lams->platform_bus_dev);
> +hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
>
> These seem to be the differences between the loongarch and the arm virt 
> implementations.
> Why not have a function with this signature that both archs can call?
>
> static void virt_tpm_plug(PlatformBusDevice *pbus, hwaddr pbus_base, TPMIf 
> *tpmif)
>
> Regards,
> Stefan

That was the first intended solution, but the code that this is
replacing was copy-pasted and as I don't know anything about this arch
or know how to test it, this caused the least amount of changes to
that target architecture (no additional includes, changes to the build
scripts, etc). I don't think there is currently a common "virt" module
that all the "virt" targets use so we would have to create that. It
seemed out of scope for this TPM patchset and could be something for a
different patch set. tl;dr: the code it replaces was copy-pasted so
it's not strictly making things worse.



Re: [PATCH v2 11/11] tpm_crb: support restoring older vmstate

2023-07-14 Thread Joelle van Dyne
On Fri, Jul 14, 2023 at 7:51 AM Stefan Berger  wrote:
>
>
>
> On 7/14/23 10:05, Stefan Berger wrote:
> >
> >
> > On 7/14/23 03:09, Joelle van Dyne wrote:
> >> When we moved to a single mapping and modified TPM CRB's VMState, it
> >> broke restoring of VMs that were saved on an older version. This
> >> change allows those VMs to gracefully migrate to the new memory
> >> mapping.
> >
> > Thanks. This has to be in 4/11 though.
> >
>
> After applying the whole series and trying to resume state taken with current 
> git
> master I cannot restore it but it leads to this error here. I would just 
> leave it
> completely untouched in 4/11.
>
> 2023-07-14T14:46:34.547550Z qemu-system-x86_64: Unknown ramblock 
> "tpm-crb-cmd", cannot accept migration
> 2023-07-14T14:46:34.547799Z qemu-system-x86_64: error while loading state for 
> instance 0x0 of device 'ram'
> 2023-07-14T14:46:34.547835Z qemu-system-x86_64: load of migration failed: 
> Invalid argument
>
> Stefan

To be clear, you are asking to back out of 4/11? That patch changes
how the registers are mapped so it's impossible to support the old
style register mapping. This patch attempts to fix that with a
migration path but I realized that I missed the "tpm-crb-cmd"
ramblock. It can be added to v3 for this patch. Similar to the logic
to have `legacy_regs` we will add a `legacy_cmdmem` memory region that
is not registered with the system bus but only exists to migrate the
data. Would that work? Also open to better ideas on migrating legacy
saved state.

If we back out of 4/11 (the split mapping), then the proposed way for
working on Apple Silicon would not be available and we would have to
go down the path of emulating AArch64 instruction in HVF backend (or
decide not to support Apple Silicon).



[PATCH v2 09/11] tpm_tis_sysbus: move DSDT AML generation to device

2023-07-14 Thread Joelle van Dyne
This reduces redundent code in different machine types with ACPI table
generation. Additionally, this will allow us to support multiple TPM
interfaces. Finally, this matches up with the TPM TIS ISA
implementation.

Ideally, we would be able to call `qbus_build_aml` and avoid any TPM
specific code in the ACPI table generation. However, currently we
still have to call `build_tpm2` anyways and it does not look like
most other ACPI devices support the `ACPI_DEV_AML_IF` interface.

Signed-off-by: Joelle van Dyne 
---
 hw/arm/virt-acpi-build.c  | 38 ++
 hw/loongarch/acpi-build.c | 38 ++
 hw/tpm/tpm_tis_sysbus.c   | 35 +++
 3 files changed, 39 insertions(+), 72 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 6b674231c2..49b2f19440 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/aml-build.h"
@@ -208,41 +209,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const 
MemMapEntry *gpio_memmap,
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 #define ID_MAPPING_ENTRY_SIZE 20
 #define SMMU_V3_ENTRY_SIZE 68
 #define ROOT_COMPLEX_ENTRY_SIZE 36
@@ -891,7 +857,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 
 acpi_dsdt_add_power_button(scope);
 #ifdef CONFIG_TPM
-acpi_dsdt_add_tpm(scope, vms);
+call_dev_aml_func(DEVICE(tpm_find()), scope);
 #endif
 
 aml_append(dsdt, scope);
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 0b62c3a2f7..4291e670c8 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -14,6 +14,7 @@
 #include "target/loongarch/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "migration/vmstate.h"
@@ -328,41 +329,6 @@ static void build_flash_aml(Aml *scope, 
LoongArchMachineState *lams)
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 /* build DSDT */
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
@@ -379,7 +345,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
 build_la_ged_am

[PATCH v2 08/11] hw/loongarch/virt: add plug handler for TPM on SysBus

2023-07-14 Thread Joelle van Dyne
TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne 
---
 hw/loongarch/virt.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index e19b042ce8..9c536c52bc 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1040,6 +1040,37 @@ static void virt_mem_plug(HotplugHandler *hotplug_dev,
  dev, _abort);
 }
 
+#ifdef CONFIG_TPM
+static void virt_tpm_plug(LoongArchMachineState *lams, TPMIf *tpmif)
+{
+PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(lams->platform_bus_dev);
+hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
+SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+MemoryRegion *sbdev_mr;
+hwaddr tpm_base;
+uint64_t tpm_size;
+
+if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), TYPE_SYS_BUS_DEVICE)) {
+return;
+}
+
+tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+assert(tpm_base != -1);
+
+tpm_base += pbus_base;
+
+sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+tpm_size = memory_region_size(sbdev_mr);
+
+if (object_property_find(OBJECT(sbdev), "baseaddr")) {
+object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, NULL);
+}
+if (object_property_find(OBJECT(sbdev), "size")) {
+object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
+}
+}
+#endif
+
 static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
@@ -1054,6 +1085,12 @@ static void 
loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 } else if (memhp_type_supported(dev)) {
 virt_mem_plug(hotplug_dev, dev, errp);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+virt_tpm_plug(lams, TPM_IF(dev));
+}
+#endif
 }
 
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
-- 
2.39.2 (Apple Git-143)




[PATCH v2 07/11] hw/arm/virt: add plug handler for TPM on SysBus

2023-07-14 Thread Joelle van Dyne
TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne 
---
 hw/arm/virt.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7d9dbc2663..432148ef47 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
  dev, _abort);
 }
 
+#ifdef CONFIG_TPM
+static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
+{
+PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
+hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
+SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+MemoryRegion *sbdev_mr;
+hwaddr tpm_base;
+uint64_t tpm_size;
+
+if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), TYPE_SYS_BUS_DEVICE)) {
+return;
+}
+
+tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+assert(tpm_base != -1);
+
+tpm_base += pbus_base;
+
+sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+tpm_size = memory_region_size(sbdev_mr);
+
+if (object_property_find(OBJECT(sbdev), "baseaddr")) {
+object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, NULL);
+}
+if (object_property_find(OBJECT(sbdev), "size")) {
+object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
+}
+}
+#endif
+
 static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
@@ -2803,6 +2834,12 @@ static void virt_machine_device_plug_cb(HotplugHandler 
*hotplug_dev,
 vms->virtio_iommu_bdf = pci_get_bdf(pdev);
 create_virtio_iommu_dt_bindings(vms);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+virt_tpm_plug(vms, TPM_IF(dev));
+}
+#endif
 }
 
 static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
-- 
2.39.2 (Apple Git-143)




[PATCH v2 11/11] tpm_crb: support restoring older vmstate

2023-07-14 Thread Joelle van Dyne
When we moved to a single mapping and modified TPM CRB's VMState, it
broke restoring of VMs that were saved on an older version. This
change allows those VMs to gracefully migrate to the new memory
mapping.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.h|  1 +
 hw/tpm/tpm_crb.c| 14 ++
 hw/tpm/tpm_crb_common.c |  7 +++
 3 files changed, 22 insertions(+)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index 7cdd37335f..7d8f643e98 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -70,5 +70,6 @@ enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
 int tpm_crb_pre_save(TPMCRBState *s);
 void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
 void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+void tpm_crb_restore_regs(TPMCRBState *s, uint32_t *saved_regs);
 
 #endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 594696ffb8..be29ca8c28 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -40,6 +40,7 @@ struct CRBState {
 ISADevice parent_obj;
 
 TPMCRBState state;
+uint32_t legacy_regs[TPM_CRB_R_MAX];
 };
 typedef struct CRBState CRBState;
 
@@ -67,10 +68,23 @@ static int tpm_crb_isa_pre_save(void *opaque)
 return tpm_crb_pre_save(>state);
 }
 
+static int tpm_crb_isa_post_load(void *opaque, int version_id)
+{
+CRBState *s = opaque;
+
+if (version_id == 0) {
+tpm_crb_restore_regs(>state, s->legacy_regs);
+}
+return 0;
+}
+
 static const VMStateDescription vmstate_tpm_crb_isa = {
 .name = "tpm-crb",
+.version_id = 1,
 .pre_save = tpm_crb_isa_pre_save,
+.post_load = tpm_crb_isa_post_load,
 .fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(legacy_regs, CRBState, TPM_CRB_R_MAX),
 VMSTATE_END_OF_LIST(),
 }
 };
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 4ecf064c98..5714ac7fc4 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -224,3 +224,10 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, 
Error **errp)
 tpm_ppi_init_memory(>ppi, obj);
 }
 }
+
+void tpm_crb_restore_regs(TPMCRBState *s, uint32_t *saved_regs)
+{
+uint32_t *regs = memory_region_get_ram_ptr(>mmio);
+
+memcpy(regs, saved_regs, TPM_CRB_R_MAX);
+}
-- 
2.39.2 (Apple Git-143)




[PATCH v2 03/11] tpm_ppi: refactor memory space initialization

2023-07-14 Thread Joelle van Dyne
Instead of calling `memory_region_add_subregion` directly, we defer to
the caller to do it. This allows us to re-use the code for a SysBus
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 hw/tpm/tpm_ppi.h| 10 +++---
 hw/tpm/tpm_crb.c|  4 ++--
 hw/tpm/tpm_crb_common.c |  3 +++
 hw/tpm/tpm_ppi.c|  5 +
 hw/tpm/tpm_tis_isa.c|  5 +++--
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h
index bf5d4a300f..30863c6438 100644
--- a/hw/tpm/tpm_ppi.h
+++ b/hw/tpm/tpm_ppi.h
@@ -20,17 +20,13 @@ typedef struct TPMPPI {
 } TPMPPI;
 
 /**
- * tpm_ppi_init:
+ * tpm_ppi_init_memory:
  * @tpmppi: a TPMPPI
- * @m: the address-space / MemoryRegion to use
- * @addr: the address of the PPI region
  * @obj: the owner object
  *
- * Register the TPM PPI memory region at @addr on the given address
- * space for the object @obj.
+ * Creates the TPM PPI memory region.
  **/
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj);
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj);
 
 /**
  * tpm_ppi_reset:
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 3ef4977fb5..598c3e0161 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -107,8 +107,8 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
-tpm_ppi_init(>state.ppi, get_system_memory(),
- TPM_PPI_ADDR_BASE, OBJECT(s));
+memory_region_add_subregion(get_system_memory(),
+TPM_PPI_ADDR_BASE, >state.ppi.ram);
 }
 
 if (xen_enabled()) {
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 228e2d0faf..e56e910670 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -216,4 +216,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp)
 "tpm-crb-mmio", sizeof(s->regs));
 memory_region_init_ram(>cmdmem, obj,
 "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+if (s->ppi_enabled) {
+tpm_ppi_init_memory(>ppi, obj);
+}
 }
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 7f74e26ec6..40cab59afa 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -44,14 +44,11 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
 }
 }
 
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj)
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj)
 {
 tpmppi->buf = qemu_memalign(qemu_real_host_page_size(),
 HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
 memory_region_init_ram_device_ptr(>ram, obj, "tpm-ppi",
   TPM_PPI_ADDR_SIZE, tpmppi->buf);
 vmstate_register_ram(>ram, DEVICE(obj));
-
-memory_region_add_subregion(m, addr, >ram);
 }
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 91e3792248..7cd7415f30 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -134,8 +134,9 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error 
**errp)
 TPM_TIS_ADDR_BASE, >mmio);
 
 if (s->ppi_enabled) {
-tpm_ppi_init(>ppi, isa_address_space(ISA_DEVICE(dev)),
- TPM_PPI_ADDR_BASE, OBJECT(dev));
+tpm_ppi_init_memory(>ppi, OBJECT(dev));
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
+TPM_PPI_ADDR_BASE, >ppi.ram);
 }
 }
 
-- 
2.39.2 (Apple Git-143)




[PATCH v2 05/11] tpm_crb: use the ISA bus

2023-07-14 Thread Joelle van Dyne
Since this device is gated to only build for targets with the PC
configuration, we should use the ISA bus like with TPM TIS.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.c | 52 
 hw/tpm/Kconfig   |  2 +-
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 07c6868d8d..6144081d30 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -22,6 +22,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
+#include "hw/isa/isa.h"
 #include "migration/vmstate.h"
 #include "sysemu/tpm_backend.h"
 #include "sysemu/tpm_util.h"
@@ -34,7 +35,7 @@
 #include "tpm_crb.h"
 
 struct CRBState {
-DeviceState parent_obj;
+ISADevice parent_obj;
 
 TPMCRBState state;
 };
@@ -43,49 +44,49 @@ typedef struct CRBState CRBState;
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  TYPE_TPM_CRB)
 
-static void tpm_crb_none_request_completed(TPMIf *ti, int ret)
+static void tpm_crb_isa_request_completed(TPMIf *ti, int ret)
 {
 CRBState *s = CRB(ti);
 
 tpm_crb_request_completed(>state, ret);
 }
 
-static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
+static enum TPMVersion tpm_crb_isa_get_version(TPMIf *ti)
 {
 CRBState *s = CRB(ti);
 
 return tpm_crb_get_version(>state);
 }
 
-static int tpm_crb_none_pre_save(void *opaque)
+static int tpm_crb_isa_pre_save(void *opaque)
 {
 CRBState *s = opaque;
 
 return tpm_crb_pre_save(>state);
 }
 
-static const VMStateDescription vmstate_tpm_crb_none = {
+static const VMStateDescription vmstate_tpm_crb_isa = {
 .name = "tpm-crb",
-.pre_save = tpm_crb_none_pre_save,
+.pre_save = tpm_crb_isa_pre_save,
 .fields = (VMStateField[]) {
 VMSTATE_END_OF_LIST(),
 }
 };
 
-static Property tpm_crb_none_properties[] = {
+static Property tpm_crb_isa_properties[] = {
 DEFINE_PROP_TPMBE("tpmdev", CRBState, state.tpmbe),
 DEFINE_PROP_BOOL("ppi", CRBState, state.ppi_enabled, true),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void tpm_crb_none_reset(void *dev)
+static void tpm_crb_isa_reset(void *dev)
 {
 CRBState *s = CRB(dev);
 
 return tpm_crb_reset(>state, TPM_CRB_ADDR_BASE);
 }
 
-static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
+static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
 {
 CRBState *s = CRB(dev);
 
@@ -100,52 +101,51 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
-memory_region_add_subregion(get_system_memory(),
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
 TPM_CRB_ADDR_BASE, >state.mmio);
 
 if (s->state.ppi_enabled) {
-memory_region_add_subregion(get_system_memory(),
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
 TPM_PPI_ADDR_BASE, >state.ppi.ram);
 }
 
 if (xen_enabled()) {
-tpm_crb_none_reset(dev);
+tpm_crb_isa_reset(dev);
 } else {
-qemu_register_reset(tpm_crb_none_reset, dev);
+qemu_register_reset(tpm_crb_isa_reset, dev);
 }
 }
 
-static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
+static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 TPMIfClass *tc = TPM_IF_CLASS(klass);
 
-dc->realize = tpm_crb_none_realize;
-device_class_set_props(dc, tpm_crb_none_properties);
-dc->vmsd  = _tpm_crb_none;
+dc->realize = tpm_crb_isa_realize;
+device_class_set_props(dc, tpm_crb_isa_properties);
+dc->vmsd  = _tpm_crb_isa;
 dc->user_creatable = true;
 tc->model = TPM_MODEL_TPM_CRB;
-tc->get_version = tpm_crb_none_get_version;
-tc->request_completed = tpm_crb_none_request_completed;
+tc->get_version = tpm_crb_isa_get_version;
+tc->request_completed = tpm_crb_isa_request_completed;
 
 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
-static const TypeInfo tpm_crb_none_info = {
+static const TypeInfo tpm_crb_isa_info = {
 .name = TYPE_TPM_CRB,
-/* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
-.parent = TYPE_DEVICE,
+.parent = TYPE_ISA_DEVICE,
 .instance_size = sizeof(CRBState),
-.class_init  = tpm_crb_none_class_init,
+.class_init  = tpm_crb_isa_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_TPM_IF },
 { }
 }
 };
 
-static void tpm_crb_none_register(void)
+static void tpm_crb_isa_register(void)
 {
-type_register_static(_crb_none_info);
+type_register_static(_crb_isa_info);
 }
 
-type_init(tpm_crb_none_register)
+type_init(tpm_crb_isa_register)
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index a46663288c..1fd73fe617 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kc

[PATCH v2 10/11] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-07-14 Thread Joelle van Dyne
This SysBus variant of the CRB interface supports dynamically locating
the MMIO interface so that Virt machines can use it. This interface
is currently the only one supported by QEMU that works on Windows 11
ARM64. We largely follow the TPM TIS SysBus device as a template.

To try out this device with Windows 11 before OVMF is updated, you
will need to modify `sysbud-fdt.c` and change the added line from:

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
```

to

```c
TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, add_tpm_tis_fdt_node),
```

This change was not included because it can confuse Linux (although
from testing, it seems like Linux is able to properly ignore the
device from the TPM TIS driver and recognize it from the ACPI device
in the TPM CRB driver). A proper fix would require OVMF to recognize
the ACPI device and not depend on the FDT node for recognizing TPM.

The command line to try out this device with SWTPM is:

```
$ qemu-system-aarch64 \
-chardev socket,id=chrtpm0,path=tpm.sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm0 \
-device tpm-crb-device,tpmdev=tpm0
```

along with SWTPM:

```
$ swtpm \
--ctrl type=unixio,path=tpm.sock,terminate \
--tpmstate backend-uri=file://tpm.data \
--tpm2
```

Signed-off-by: Joelle van Dyne 
---
 docs/specs/tpm.rst  |   1 +
 include/hw/acpi/aml-build.h |   1 +
 include/sysemu/tpm.h|   3 +
 hw/acpi/aml-build.c |   7 +-
 hw/arm/virt.c   |   1 +
 hw/core/sysbus-fdt.c|   1 +
 hw/loongarch/virt.c |   1 +
 hw/riscv/virt.c |   1 +
 hw/tpm/tpm_crb_sysbus.c | 170 
 hw/arm/Kconfig  |   1 +
 hw/riscv/Kconfig|   1 +
 hw/tpm/Kconfig  |   5 ++
 hw/tpm/meson.build  |   2 +
 13 files changed, 194 insertions(+), 1 deletion(-)
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index 2bc29c9804..95aeb49220 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -46,6 +46,7 @@ operating system.
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
  - ``hw/tpm/tpm_crb_common.c``
+ - ``hw/tpm/tpm_crb_sysbus.c``
 
 SPAPR interface
 ---
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index d1fb08514b..9660e16148 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -3,6 +3,7 @@
 
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/bios-linker-loader.h"
+#include "exec/hwaddr.h"
 
 #define ACPI_BUILD_APPNAME6 "BOCHS "
 #define ACPI_BUILD_APPNAME8 "BXPC"
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 66e3b45f30..f79c8f3575 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -47,6 +47,7 @@ struct TPMIfClass {
 #define TYPE_TPM_TIS_ISA"tpm-tis"
 #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
 #define TYPE_TPM_CRB"tpm-crb"
+#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
 #define TYPE_TPM_SPAPR  "tpm-spapr"
 #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
 
@@ -56,6 +57,8 @@ struct TPMIfClass {
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
 #define TPM_IS_CRB(chr) \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_CRB_SYSBUS(chr)  \
+object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
 #define TPM_IS_SPAPR(chr)   \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
 #define TPM_IS_TIS_I2C(chr)  \
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index ea331a20d1..f809137fc9 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -31,6 +31,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 {
 uint8_t start_method_params[12] = {};
 unsigned log_addr_offset;
-uint64_t control_area_start_address;
+uint64_t baseaddr, control_area_start_address;
 TPMIf *tpmif = tpm_find();
 uint32_t start_method;
 AcpiTable table = { .sig = "TPM2", .rev = 4,
@@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 } else if (TPM_IS_CRB(tpmif)) {
 control_area_start_address = TPM_CRB_ADDR_CTRL;
 start_method = TPM2_START_METHOD_CRB;
+} else if (TPM_IS_CRB_SYSBUS(tpmif)) {
+baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
+control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
+start_method = TPM2_START_METHOD_CRB;
 } else {
 g_assert_not_reached();
 }
diff --git a/hw/ar

[PATCH v2 02/11] tpm_crb: CTRL_RSP_ADDR is 64-bits wide

2023-07-14 Thread Joelle van Dyne
The register is actually 64-bits but in order to make this more clear
than the specification, we define two 32-bit registers:
CTRL_RSP_LADDR and CTRL_RSP_HADDR to match the CTRL_CMD_* naming. This
deviates from the specs but is way more clear.

Previously, the only CRB device uses a fixed system address so this
was not an issue. However, once we support SysBus CRB device, the
address can be anywhere in 64-bit space.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 include/hw/acpi/tpm.h  | 3 ++-
 hw/tpm/tpm_crb_common.c| 3 ++-
 tests/qtest/tpm-crb-test.c | 2 +-
 tests/qtest/tpm-util.c | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 579c45f5ba..f60bfe2789 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -174,7 +174,8 @@ REG32(CRB_CTRL_CMD_SIZE, 0x58)
 REG32(CRB_CTRL_CMD_LADDR, 0x5C)
 REG32(CRB_CTRL_CMD_HADDR, 0x60)
 REG32(CRB_CTRL_RSP_SIZE, 0x64)
-REG32(CRB_CTRL_RSP_ADDR, 0x68)
+REG32(CRB_CTRL_RSP_LADDR, 0x68)
+REG32(CRB_CTRL_RSP_HADDR, 0x6C)
 REG32(CRB_DATA_BUFFER, 0x80)
 
 #define TPM_CRB_ADDR_BASE   0xFED4
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 4c173affb6..228e2d0faf 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -199,7 +199,8 @@ void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
 s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
 s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
 s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-s->regs[R_CRB_CTRL_RSP_ADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
 
 s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
 CRB_CTRL_CMD_SIZE);
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 396ae3f91c..9d30fe8293 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -28,7 +28,7 @@ static void tpm_crb_test(const void *data)
 uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
 uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
 uint32_t rsize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_SIZE);
-uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 uint8_t locstate = readb(TPM_CRB_ADDR_BASE + A_CRB_LOC_STATE);
 uint32_t locctrl = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL);
 uint32_t locsts = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_STS);
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index 1c0319e6e7..dd02057fc0 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -25,7 +25,7 @@ void tpm_util_crb_transfer(QTestState *s,
unsigned char *rsp, size_t rsp_size)
 {
 uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
-uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 
 qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);
 
-- 
2.39.2 (Apple Git-143)




[PATCH v2 06/11] tpm_crb: move ACPI table building to device interface

2023-07-14 Thread Joelle van Dyne
This logic is similar to TPM TIS ISA device. Since TPM CRB can only
support TPM 2.0 backends, we check for this in realize.

Signed-off-by: Joelle van Dyne 
---
 hw/i386/acpi-build.c | 23 ---
 hw/tpm/tpm_crb.c | 29 +
 2 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9c74fa17ad..b767df39df 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 uint32_t nr_mem = machine->ram_slots;
 int root_bus_limit = 0xFF;
 PCIBus *bus = NULL;
-#ifdef CONFIG_TPM
-TPMIf *tpm = tpm_find();
-#endif
 bool cxl_present = false;
 int i;
 VMBusBridge *vmbus_bridge = vmbus_bridge_find();
@@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 }
 
-#ifdef CONFIG_TPM
-if (TPM_IS_CRB(tpm)) {
-dev = aml_device("TPM");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR",
-  aml_string("TPM 2.0 Device")));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
-   TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-
-aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
-aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-
-tpm_build_ppi_acpi(tpm, dev);
-
-aml_append(sb_scope, dev);
-}
-#endif
-
 if (pcms->sgx_epc.size != 0) {
 uint64_t epc_base = pcms->sgx_epc.base;
 uint64_t epc_size = pcms->sgx_epc.size;
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 6144081d30..594696ffb8 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -19,6 +19,8 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
+#include "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
@@ -99,6 +101,11 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
+if (tpm_crb_isa_get_version(TPM_IF(s)) != TPM_VERSION_2_0) {
+error_setg(errp, "TPM CRB only supports TPM 2.0 backends");
+return;
+}
+
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
 memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
@@ -116,10 +123,30 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
+static void build_tpm_crb_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+Aml *dev, *crs;
+CRBState *s = CRB(adev);
+TPMIf *ti = TPM_IF(s);
+
+dev = aml_device("TPM");
+aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE,
+  AML_READ_WRITE));
+aml_append(dev, aml_name_decl("_CRS", crs));
+tpm_build_ppi_acpi(ti, dev);
+aml_append(scope, dev);
+}
+
 static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 TPMIfClass *tc = TPM_IF_CLASS(klass);
+AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
 
 dc->realize = tpm_crb_isa_realize;
 device_class_set_props(dc, tpm_crb_isa_properties);
@@ -128,6 +155,7 @@ static void tpm_crb_isa_class_init(ObjectClass *klass, void 
*data)
 tc->model = TPM_MODEL_TPM_CRB;
 tc->get_version = tpm_crb_isa_get_version;
 tc->request_completed = tpm_crb_isa_request_completed;
+adevc->build_dev_aml = build_tpm_crb_isa_aml;
 
 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
@@ -139,6 +167,7 @@ static const TypeInfo tpm_crb_isa_info = {
 .class_init  = tpm_crb_isa_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_TPM_IF },
+{ TYPE_ACPI_DEV_AML_IF },
 { }
 }
 };
-- 
2.39.2 (Apple Git-143)




[PATCH v2 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping

2023-07-14 Thread Joelle van Dyne
On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
the exception is not decoded by hardware and we cannot trap the MMIO
read. This led to the idea from @agraf to use the same mapping type as
ROM devices: namely that reads should be seen as memory type and
writes should trap as MMIO.

Once that was done, the second memory mapping of the command buffer
region was redundent and was removed.

A note about the removal of the read trap for `CRB_LOC_STATE`:
The only usage was to return the most up-to-date value for
`tpmEstablished`. However, `tpmEstablished` is only cleared when a
TPM2_HashStart operation is called which only exists for locality 4.
We do not handle locality 4. Indeed, the comment for the write handler
of `CRB_LOC_CTRL` makes the same argument for why it is not calling
the backend to reset the `tpmEstablished` bit (to 1).
As this bit is unused, we do not need to worry about updating it for
reads.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.h|   2 -
 hw/tpm/tpm_crb.c|   3 -
 hw/tpm/tpm_crb_common.c | 126 +---
 3 files changed, 65 insertions(+), 66 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index da3a0cf256..7cdd37335f 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -26,9 +26,7 @@
 typedef struct TPMCRBState {
 TPMBackend *tpmbe;
 TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
 MemoryRegion mmio;
-MemoryRegion cmdmem;
 
 size_t be_buffer_size;
 
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 598c3e0161..07c6868d8d 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -68,7 +68,6 @@ static const VMStateDescription vmstate_tpm_crb_none = {
 .name = "tpm-crb",
 .pre_save = tpm_crb_none_pre_save,
 .fields = (VMStateField[]) {
-VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),
 VMSTATE_END_OF_LIST(),
 }
 };
@@ -103,8 +102,6 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 
 memory_region_add_subregion(get_system_memory(),
 TPM_CRB_ADDR_BASE, >state.mmio);
-memory_region_add_subregion(get_system_memory(),
-TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
 memory_region_add_subregion(get_system_memory(),
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index e56e910670..4ecf064c98 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -33,31 +33,12 @@
 #include "qom/object.h"
 #include "tpm_crb.h"
 
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
+static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
 {
-TPMCRBState *s = opaque;
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-switch (addr) {
-case A_CRB_LOC_STATE:
-val |= !tpm_backend_get_tpm_established_flag(s->tpmbe);
-break;
-}
-
-trace_tpm_crb_mmio_read(addr, size, val);
-
-return val;
-}
-
-static uint8_t tpm_crb_get_active_locty(TPMCRBState *s)
-{
-if (!ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, locAssigned)) {
+if (!ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, locAssigned)) {
 return TPM_CRB_NO_LOCALITY;
 }
-return ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, activeLocality);
+return ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, activeLocality);
 }
 
 static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
@@ -65,35 +46,47 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
 {
 TPMCRBState *s = opaque;
 uint8_t locty =  addr >> 12;
+uint32_t *regs;
+void *mem;
 
 trace_tpm_crb_mmio_write(addr, size, val);
+regs = memory_region_get_ram_ptr(>mmio);
+mem = [R_CRB_DATA_BUFFER];
+assert(regs);
+
+if (addr >= A_CRB_DATA_BUFFER) {
+assert(addr + size <= TPM_CRB_ADDR_SIZE);
+assert(size <= sizeof(val));
+memcpy(mem + addr - A_CRB_DATA_BUFFER, , size);
+memory_region_set_dirty(>mmio, addr, size);
+return;
+}
 
 switch (addr) {
 case A_CRB_CTRL_REQ:
 switch (val) {
 case CRB_CTRL_REQ_CMD_READY:
-ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  tpmIdle, 0);
 break;
 case CRB_CTRL_REQ_GO_IDLE:
-ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  tpmIdle, 1);
 break;
 }
 break;
 case A_CRB_CTRL_CANCEL:
 if (val == CRB_CANCEL_INVOKE &&
-s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
+regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
 tpm_backend_cancel_cmd(s->tp

[PATCH v2 01/11] tpm_crb: refactor common code

2023-07-14 Thread Joelle van Dyne
In preparation for the SysBus variant, we move common code styled
after the TPM TIS devices.

To maintain compatibility, we do not rename the existing tpm-crb
device.

Signed-off-by: Joelle van Dyne 
Reviewed-by: Stefan Berger 
---
 docs/specs/tpm.rst  |   1 +
 hw/tpm/tpm_crb.h|  76 +++
 hw/tpm/tpm_crb.c| 270 ++--
 hw/tpm/tpm_crb_common.c | 218 
 hw/tpm/meson.build  |   1 +
 hw/tpm/trace-events |   2 +-
 6 files changed, 333 insertions(+), 235 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index efe124a148..2bc29c9804 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -45,6 +45,7 @@ operating system.
 
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
+ - ``hw/tpm/tpm_crb_common.c``
 
 SPAPR interface
 ---
diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
new file mode 100644
index 00..da3a0cf256
--- /dev/null
+++ b/hw/tpm/tpm_crb.h
@@ -0,0 +1,76 @@
+/*
+ * tpm_crb.h - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Marc-André Lureau 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+#ifndef TPM_TPM_CRB_H
+#define TPM_TPM_CRB_H
+
+#include "exec/memory.h"
+#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_ppi.h"
+
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
+
+typedef struct TPMCRBState {
+TPMBackend *tpmbe;
+TPMBackendCmd cmd;
+uint32_t regs[TPM_CRB_R_MAX];
+MemoryRegion mmio;
+MemoryRegion cmdmem;
+
+size_t be_buffer_size;
+
+bool ppi_enabled;
+TPMPPI ppi;
+} TPMCRBState;
+
+#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
+#define CRB_INTF_VERSION_CRB 0b1
+#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
+#define CRB_INTF_CAP_IDLE_FAST 0b0
+#define CRB_INTF_CAP_XFER_SIZE_64 0b11
+#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
+#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
+#define CRB_INTF_IF_SELECTOR_CRB 0b1
+
+enum crb_loc_ctrl {
+CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+CRB_LOC_CTRL_RELINQUISH = BIT(1),
+CRB_LOC_CTRL_SEIZE = BIT(2),
+CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
+};
+
+enum crb_ctrl_req {
+CRB_CTRL_REQ_CMD_READY = BIT(0),
+CRB_CTRL_REQ_GO_IDLE = BIT(1),
+};
+
+enum crb_start {
+CRB_START_INVOKE = BIT(0),
+};
+
+enum crb_cancel {
+CRB_CANCEL_INVOKE = BIT(0),
+};
+
+#define TPM_CRB_NO_LOCALITY 0xff
+
+void tpm_crb_request_completed(TPMCRBState *s, int ret);
+enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
+int tpm_crb_pre_save(TPMCRBState *s);
+void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
+void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+
+#endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index ea930da545..3ef4977fb5 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -31,257 +31,62 @@
 #include "tpm_ppi.h"
 #include "trace.h"
 #include "qom/object.h"
+#include "tpm_crb.h"
 
 struct CRBState {
 DeviceState parent_obj;
 
-TPMBackend *tpmbe;
-TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
-MemoryRegion mmio;
-MemoryRegion cmdmem;
-
-size_t be_buffer_size;
-
-bool ppi_enabled;
-TPMPPI ppi;
+TPMCRBState state;
 };
 typedef struct CRBState CRBState;
 
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  TYPE_TPM_CRB)
 
-#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
-#define CRB_INTF_VERSION_CRB 0b1
-#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
-#define CRB_INTF_CAP_IDLE_FAST 0b0
-#define CRB_INTF_CAP_XFER_SIZE_64 0b11
-#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
-#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
-#define CRB_INTF_IF_SELECTOR_CRB 0b1
-
-#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
-
-enum crb_loc_ctrl {
-CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
-CRB_LOC_CTRL_RELINQUISH = BIT(1),
-CRB_LOC_CTRL_SEIZE = BIT(2),
-CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
-};
-
-enum crb_ctrl_req {
-CRB_CTRL_REQ_CMD_READY = BIT(0),
-CRB_CTRL_REQ_GO_IDLE = BIT(1),
-};
-
-enum crb_start {
-CRB_START_INVOKE = BIT(0),
-};
-
-enum crb_cancel {
-CRB_CANCEL_INVOKE = BIT(0),
-};
-
-#define TPM_CRB_NO_LOCALITY 0xff
-
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
-{
-CRBState *s = CRB(opaque);
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-s

[PATCH v2 00/11] tpm: introduce TPM CRB SysBus device

2023-07-14 Thread Joelle van Dyne
The impetus for this patch set is to get TPM 2.0 working on Windows 11 ARM64.
Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
VMWare's implementation). However, the current TPM CRB device uses a fixed
system bus address that is reserved for RAM in ARM64 Virt machines.

In the process of adding the TPM CRB SysBus device, we also went ahead and
cleaned up some of the existing TPM hardware code and fixed some bugs. We used
the TPM TIS devices as a template for the TPM CRB devices and refactored out
common code. We moved the ACPI DSDT generation to the device in order to handle
dynamic base address requirements as well as reduce redundent code in different
machine ACPI generation. We also changed the tpm_crb device to use the ISA bus
instead of depending on the default system bus as the device only was built for
the PC configuration.

Another change is that the TPM CRB registers are now mapped in the same way that
the pflash ROM devices are mapped. It is a memory region whose writes are
trapped as MMIO accesses. This was needed because Apple Silicon does not decode
LDP (AARCH64 load pair of registers) caused page faults. @agraf suggested that
we do this to avoid having to do AARCH64 decoding in the HVF backend's fault
handler.

Unfortunately, it seems like the LDP fault still happens on HVF but the issue
seems to be in the HVF backend which needs to be fixed in a separate patch.

One last thing that's needed to get Windows 11 to recognize the TPM 2.0 device
is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 Virt
only recognizes the TPM TIS device through a FDT entry. A workaround is to
falsely identify the TPM CRB device as a TPM TIS device in the FDT node but this
causes issues for Linux. A proper fix would involve adding an ACPI device driver
in OVMF.

v2:
- Fixed an issue where VMstate restore from an older version failed due to name
  collision of the memory block.
- In the ACPI table generation for CRB devices, the check for TPM 2.0 backend is
  moved to the device realize as CRB does not support TPM 1.0. It will error in
  that case.
- Dropped the patch to fix crash when PPI is enabled on TIS SysBus device since
  a separate patch submitted by Stefan Berger disables such an option.
- Fixed an issue where we default tpmEstablished=0 when it should be 1.
- In TPM CRB SysBus's ACPI entry, we accidently changed _UID from 0 to 1. This
  shouldn't be an issue but we changed it back just in case.
- Added a patch to migrate saved VMstate from an older version with the regs
  saved separately instead of as a RAM block.

Joelle van Dyne (11):
  tpm_crb: refactor common code
  tpm_crb: CTRL_RSP_ADDR is 64-bits wide
  tpm_ppi: refactor memory space initialization
  tpm_crb: use a single read-as-mem/write-as-mmio mapping
  tpm_crb: use the ISA bus
  tpm_crb: move ACPI table building to device interface
  hw/arm/virt: add plug handler for TPM on SysBus
  hw/loongarch/virt: add plug handler for TPM on SysBus
  tpm_tis_sysbus: move DSDT AML generation to device
  tpm_crb_sysbus: introduce TPM CRB SysBus device
  tpm_crb: support restoring older vmstate

 docs/specs/tpm.rst  |   2 +
 hw/tpm/tpm_crb.h|  75 +
 hw/tpm/tpm_ppi.h|  10 +-
 include/hw/acpi/aml-build.h |   1 +
 include/hw/acpi/tpm.h   |   3 +-
 include/sysemu/tpm.h|   3 +
 hw/acpi/aml-build.c |   7 +-
 hw/arm/virt-acpi-build.c|  38 +
 hw/arm/virt.c   |  38 +
 hw/core/sysbus-fdt.c|   1 +
 hw/i386/acpi-build.c|  23 ---
 hw/loongarch/acpi-build.c   |  38 +
 hw/loongarch/virt.c |  38 +
 hw/riscv/virt.c |   1 +
 hw/tpm/tpm_crb.c| 314 +---
 hw/tpm/tpm_crb_common.c | 233 ++
 hw/tpm/tpm_crb_sysbus.c | 170 +++
 hw/tpm/tpm_ppi.c|   5 +-
 hw/tpm/tpm_tis_isa.c|   5 +-
 hw/tpm/tpm_tis_sysbus.c |  35 
 tests/qtest/tpm-crb-test.c  |   2 +-
 tests/qtest/tpm-util.c  |   2 +-
 hw/arm/Kconfig  |   1 +
 hw/riscv/Kconfig|   1 +
 hw/tpm/Kconfig  |   7 +-
 hw/tpm/meson.build  |   3 +
 hw/tpm/trace-events |   2 +-
 27 files changed, 708 insertions(+), 350 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

-- 
2.39.2 (Apple Git-143)




Re: [PATCH] hw/tpm: TIS on sysbus: Remove unsupport ppi command line option

2023-07-14 Thread Joelle van Dyne
On Thu, Jul 13, 2023 at 11:07 PM Joelle van Dyne  wrote:
>
> On Thu, Jul 13, 2023 at 10:20 AM Stefan Berger  wrote:
> >
> > The ppi command line option for the TIS device on sysbus never worked
> > and caused an immediate segfault. Remove support for it since it also
> > needs support in the firmware and needs testing inside the VM.
> >
> > Reproducer with the ppi=on option passed:
> >
> > qemu-system-aarch64 \
> >-machine virt,gic-version=3 \
> >-m 4G  \
> >-nographic -no-acpi \
> >-chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
> >-tpmdev emulator,id=tpm0,chardev=chrtpm \
> >-device tpm-tis-device,tpmdev=tpm0,ppi=on
> > [...]
> > Segmentation fault (core dumped)
> >
> > Signed-off-by: Stefan Berger 
>
> Do you need to add a VMSTATE_UNUSED_TEST in case a future QEMU version
> introduces a new field in the same position which will cause an issue
> when restoring from an older version?

Actually, ignore that last message. I misread the patch thinking it's
on the VMState.



Re: [PATCH] hw/tpm: TIS on sysbus: Remove unsupport ppi command line option

2023-07-14 Thread Joelle van Dyne
On Thu, Jul 13, 2023 at 10:20 AM Stefan Berger  wrote:
>
> The ppi command line option for the TIS device on sysbus never worked
> and caused an immediate segfault. Remove support for it since it also
> needs support in the firmware and needs testing inside the VM.
>
> Reproducer with the ppi=on option passed:
>
> qemu-system-aarch64 \
>-machine virt,gic-version=3 \
>-m 4G  \
>-nographic -no-acpi \
>-chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
>-tpmdev emulator,id=tpm0,chardev=chrtpm \
>-device tpm-tis-device,tpmdev=tpm0,ppi=on
> [...]
> Segmentation fault (core dumped)
>
> Signed-off-by: Stefan Berger 

Do you need to add a VMSTATE_UNUSED_TEST in case a future QEMU version
introduces a new field in the same position which will cause an issue
when restoring from an older version?



Re: [PATCH 09/11] tpm_tis_sysbus: fix crash when PPI is enabled

2023-07-13 Thread Joelle van Dyne
On Thu, Jul 13, 2023 at 9:49 AM Stefan Berger  wrote:
>
>
> The tpm-tis-device doesn't work for x86_64 but for aarch64.
>
>
> We have this here in this file:
>
>  DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, false),
>
> I don't know whether ppi would work on aarch64. It needs firmware support 
> like in edk2.
> I think the best solution is to remove this DEFINE_PROP_BOOL() and if someone 
> wants
> to enable it they would have to add firmware support and test it before 
> re-enabling it.
>
> Stefan
>
> >   static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data)

Yeah, I'm not sure if PPI works with AARCH64 since I didn't bother to
change it to not use hard coded addresses. However, isn't that "ppi"
overridable from the command line? If so, should we add a check in
"realize" to error if PPI=true? Otherwise, it will just crash.



Re: [PATCH 06/11] tpm_crb: move ACPI table building to device interface

2023-07-13 Thread Joelle van Dyne
In that case, do you think we should have a check in "realize" to make
sure the backend is 2.0?

On Thu, Jul 13, 2023 at 9:08 AM Stefan Berger  wrote:
>
>
>
> On 7/12/23 23:51, Joelle van Dyne wrote:
> > This logic is similar to TPM TIS ISA device.
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
> >   hw/i386/acpi-build.c | 23 ---
> >   hw/tpm/tpm_crb.c | 28 
> >   2 files changed, 28 insertions(+), 23 deletions(-)
> >
> > diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> > index 9c74fa17ad..b767df39df 100644
> > --- a/hw/i386/acpi-build.c
> > +++ b/hw/i386/acpi-build.c
> > @@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >   uint32_t nr_mem = machine->ram_slots;
> >   int root_bus_limit = 0xFF;
> >   PCIBus *bus = NULL;
> > -#ifdef CONFIG_TPM
> > -TPMIf *tpm = tpm_find();
> > -#endif
> >   bool cxl_present = false;
> >   int i;
> >   VMBusBridge *vmbus_bridge = vmbus_bridge_find();
> > @@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
> >   }
> >   }
> >
> > -#ifdef CONFIG_TPM
> > -if (TPM_IS_CRB(tpm)) {
> > -dev = aml_device("TPM");
> > -aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > -aml_append(dev, aml_name_decl("_STR",
> > -  aml_string("TPM 2.0 Device")));
> > -crs = aml_resource_template();
> > -aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
> > -   TPM_CRB_ADDR_SIZE, 
> > AML_READ_WRITE));
> > -aml_append(dev, aml_name_decl("_CRS", crs));
> > -
> > -aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
> > -aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > -
> > -tpm_build_ppi_acpi(tpm, dev);
> > -
> > -aml_append(sb_scope, dev);
> > -}
> > -#endif
> > -
> >   if (pcms->sgx_epc.size != 0) {
> >   uint64_t epc_base = pcms->sgx_epc.base;
> >   uint64_t epc_size = pcms->sgx_epc.size;
> > diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
> > index 6144081d30..14feb9857f 100644
> > --- a/hw/tpm/tpm_crb.c
> > +++ b/hw/tpm/tpm_crb.c
> > @@ -19,6 +19,8 @@
> >   #include "qemu/module.h"
> >   #include "qapi/error.h"
> >   #include "exec/address-spaces.h"
> > +#include "hw/acpi/acpi_aml_interface.h"
> > +#include "hw/acpi/tpm.h"
> >   #include "hw/qdev-properties.h"
> >   #include "hw/pci/pci_ids.h"
> >   #include "hw/acpi/tpm.h"
> > @@ -116,10 +118,34 @@ static void tpm_crb_isa_realize(DeviceState *dev, 
> > Error **errp)
> >   }
> >   }
> >
> > +static void build_tpm_crb_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
> > +{
> > +Aml *dev, *crs;
> > +CRBState *s = CRB(adev);
> > +TPMIf *ti = TPM_IF(s);
> > +
> > +dev = aml_device("TPM");
> > +if (tpm_crb_isa_get_version(ti) == TPM_VERSION_2_0) {
> > +aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
> > +aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 
> > Device")));
> > +} else {
> > +aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
> > +}
>
> CRB only exists for TPM 2.0 and that's why we didn't have a different case 
> here before.
>
> CRB only has MSFT0101: 
> https://elixir.bootlin.com/linux/latest/source/drivers/char/tpm/tpm_crb.c#L820
> TIS has PNP0C31: 
> https://elixir.bootlin.com/linux/latest/source/drivers/char/tpm/tpm_tis.c
>
> You should remove the check for TPM_VERSION_2_0.
>
> Stefan
> > +aml_append(dev, aml_name_decl("_UID", aml_int(1)));
> > +aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
> > +crs = aml_resource_template();
> > +aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, 
> > TPM_CRB_ADDR_SIZE,
> > +  AML_READ_WRITE));
> > +aml_append(dev, aml_name_decl("_CRS", crs));
> > +tpm_build_ppi_acpi(ti, dev);
> > +aml_append(scope, dev);
> > +}
> > +
> >   static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
> >   {
> >   DeviceClass *dc = DEVICE_CLASS(klass);
> >   TPMIfClass *tc = TPM_IF_CLASS(klass);
> > +AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
> >
> >   dc->realize = tpm_crb_isa_realize;
> >   device_class_set_props(dc, tpm_crb_isa_properties);
> > @@ -128,6 +154,7 @@ static void tpm_crb_isa_class_init(ObjectClass *klass, 
> > void *data)
> >   tc->model = TPM_MODEL_TPM_CRB;
> >   tc->get_version = tpm_crb_isa_get_version;
> >   tc->request_completed = tpm_crb_isa_request_completed;
> > +adevc->build_dev_aml = build_tpm_crb_isa_aml;
> >
> >   set_bit(DEVICE_CATEGORY_MISC, dc->categories);
> >   }
> > @@ -139,6 +166,7 @@ static const TypeInfo tpm_crb_isa_info = {
> >   .class_init  = tpm_crb_isa_class_init,
> >   .interfaces = (InterfaceInfo[]) {
> >   { TYPE_TPM_IF },
> > +{ TYPE_ACPI_DEV_AML_IF },
> >   { }
> >   }
> >   };



Re: [PATCH 07/11] hw/arm/virt: add plug handler for TPM on SysBus

2023-07-13 Thread Joelle van Dyne
On Thu, Jul 13, 2023 at 8:31 AM Peter Maydell  wrote:
>
> On Thu, 13 Jul 2023 at 04:52, Joelle van Dyne  wrote:
> >
> > TPM needs to know its own base address in order to generate its DSDT
> > device entry.
> >
> > Signed-off-by: Joelle van Dyne 
> > ---
> >  hw/arm/virt.c | 37 +
> >  1 file changed, 37 insertions(+)
> >
> > diff --git a/hw/arm/virt.c b/hw/arm/virt.c
> > index 7d9dbc2663..432148ef47 100644
> > --- a/hw/arm/virt.c
> > +++ b/hw/arm/virt.c
> > @@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler 
> > *hotplug_dev,
> >   dev, _abort);
> >  }
> >
> > +#ifdef CONFIG_TPM
> > +static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
> > +{
> > +PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
> > +hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
> > +SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
> > +MemoryRegion *sbdev_mr;
> > +hwaddr tpm_base;
> > +uint64_t tpm_size;
> > +
> > +if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), 
> > TYPE_SYS_BUS_DEVICE)) {
> > +return;
> > +}
> > +
> > +tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
> > +assert(tpm_base != -1);
> > +
> > +tpm_base += pbus_base;
> > +
> > +sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
> > +tpm_size = memory_region_size(sbdev_mr);
> > +
> > +if (object_property_find(OBJECT(sbdev), "baseaddr")) {
> > +object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, 
> > NULL);
> > +}
> > +if (object_property_find(OBJECT(sbdev), "size")) {
> > +object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
> > +}
> > +}
> > +#endif
>
> I do not like the "platform bus" at all -- it is a nasty hack.
> If the virt board needs a memory mapped TPM device it should probably
> just create one, the same way we create our other memory mapped
> devices. But...
>
> How are TPM devices typically set up/visible to the guest on
> real Arm server hardware ? Should this be a sysbus device at all?

+Alexander Graf who may answer this better.

My understanding is that we need to do this for the device to know its
own address which it needs to return in a register. On ISA devices, it
is always mapped to the same physical address so there's no issues but
for Virt machines, device addresses are dynamically allocated by the
PlatformBusDevice so only at this late stage can we tell the device
what its own address is.

>
> thanks
> -- PMM

Also to Stefan's question on consolidating code: that is ideal but
currently, it seems like much platform setup code is duplicated
amongst the various architecture's Virt machines. There would have to
be a larger effort in de-duplicating a lot of that code. Indeed, we
try to do this already with some of the ACPI stuff in the other
patches. For this specifically, we would need to know the platform
bus' base address which is done differently in ARM64's Virt and in
Loongarch's Virt. All we did was delete some existing duplicated code
and replace it with a different duplicated code :)



Re: [PATCH 00/11] tpm: introduce TPM CRB SysBus device

2023-07-13 Thread Joelle van Dyne
On Thu, Jul 13, 2023 at 6:07 AM Stefan Berger  wrote:
>
>
>
> On 7/12/23 23:51, Joelle van Dyne wrote:
> > The impetus for this patch set is to get TPM 2.0 working on Windows 11 
> > ARM64.
> > Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
> > VMWare's implementation). However, the current TPM CRB device uses a fixed
> > system bus address that is reserved for RAM in ARM64 Virt machines.
>
> Thanks a lot for this work. The last sentence seems to hint at the current 
> issue
> with TPM CRB on ARM64 and seems to be the only way forward there. You may want
> to reformulate it a bit because it's not clear how the 'however' related to
> CRB relates to TIS.
>
> >
> > In the process of adding the TPM CRB SysBus device, we also went ahead and
> > cleaned up some of the existing TPM hardware code and fixed some bugs. We 
> > used
>
> Please reorder bugs to the beginning of the series or submit in an extra 
> patch set
> so we can backport them. Ideal would be description(s) for how to trigger the 
> bug(s).
>
> > the TPM TIS devices as a template for the TPM CRB devices and refactored out
> > common code. We moved the ACPI DSDT generation to the device in order to 
> > handle
> > dynamic base address requirements as well as reduce redundent code in 
> > different
> s/redundent/redundant
>
>
> > machine ACPI generation. We also changed the tpm_crb device to use the ISA 
> > bus
> > instead of depending on the default system bus as the device only was built 
> > for
> > the PC configuration.
> >
> > Another change is that the TPM CRB registers are now mapped in the same way 
> > that
> > the pflash ROM devices are mapped. It is a memory region whose writes are
> > trapped as MMIO accesses. This was needed because Apple Silicon does not 
> > decode
> > LDP caused page faults. @agraf suggested that we do this to avoid having to
>
> Afaik, LDP is an ARM assembly instruction that loads two 32bit or 64bit 
> registers from
> consecutive addresses. May be worth mentioning for those wondering about it...
>
> > do AARCH64 decoding in the HVF fault handler.
>
> What is HVF?

Sorry, HVF is the QEMU backend for Apple's Hypervisor.framework which
runs on macOS including on Apple Silicon.

>
> Regards,
> Stefan
> >
> > Unfortunately, it seems like the LDP fault still happens on HVF but the 
> > issue
> > seems to be in the HVF backend which needs to be fixed in a separate patch.
> >
> > One last thing that's needed to get Windows 11 to recognize the TPM 2.0 
> > device
> > is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 
> > Virt
> > only recognizes the TPM TIS device through a FDT entry. A workaround is to
> > falsely identify the TPM CRB device as a TPM TIS device in the FDT node but 
> > this
> > causes issues for Linux. A proper fix would involve adding an ACPI device 
> > driver
> > in OVMF.
> >
> > Joelle van Dyne (11):
> >tpm_crb: refactor common code
> >tpm_crb: CTRL_RSP_ADDR is 64-bits wide
> >tpm_ppi: refactor memory space initialization
> >tpm_crb: use a single read-as-mem/write-as-mmio mapping
> >tpm_crb: use the ISA bus
> >tpm_crb: move ACPI table building to device interface
> >hw/arm/virt: add plug handler for TPM on SysBus
> >hw/loongarch/virt: add plug handler for TPM on SysBus
> >tpm_tis_sysbus: fix crash when PPI is enabled
> >tpm_tis_sysbus: move DSDT AML generation to device
> >tpm_crb_sysbus: introduce TPM CRB SysBus device
> >
> >   docs/specs/tpm.rst  |   2 +
> >   hw/tpm/tpm_crb.h|  74 +
> >   hw/tpm/tpm_ppi.h|  10 +-
> >   include/hw/acpi/aml-build.h |   1 +
> >   include/hw/acpi/tpm.h   |   3 +-
> >   include/sysemu/tpm.h|   3 +
> >   hw/acpi/aml-build.c |   7 +-
> >   hw/arm/virt-acpi-build.c|  38 +
> >   hw/arm/virt.c   |  38 +
> >   hw/core/sysbus-fdt.c|   1 +
> >   hw/i386/acpi-build.c|  23 ---
> >   hw/loongarch/acpi-build.c   |  38 +
> >   hw/loongarch/virt.c |  38 +
> >   hw/riscv/virt.c |   1 +
> >   hw/tpm/tpm_crb.c| 307 
> >   hw/tpm/tpm_crb_common.c | 224 ++
> >   hw/tpm/tpm_crb_sysbus.c | 178 +
> >   hw/tpm/tpm_ppi.c|   5 +-
> >   hw/tpm/tpm_tis_isa.c|   5 +-
> >   hw/tpm/tpm_tis_sysbus.c |  43 +
> >   tests/qtest/tpm-crb-test.c  |   2 +-
> >   tests/qtest/tpm-util.c  |   2 +-
> >   hw/arm/Kconfig  |   1 +
> >   hw/riscv/Kconfig|   1 +
> >   hw/tpm/Kconfig  |   7 +-
> >   hw/tpm/meson.build  |   3 +
> >   hw/tpm/trace-events |   2 +-
> >   27 files changed, 703 insertions(+), 354 deletions(-)
> >   create mode 100644 hw/tpm/tpm_crb.h
> >   create mode 100644 hw/tpm/tpm_crb_common.c
> >   create mode 100644 hw/tpm/tpm_crb_sysbus.c
> >



[PATCH 01/11] tpm_crb: refactor common code

2023-07-12 Thread Joelle van Dyne
In preparation for the SysBus variant, we move common code styled
after the TPM TIS devices.

To maintain compatibility, we do not rename the existing tpm-crb
device.

Signed-off-by: Joelle van Dyne 
---
 docs/specs/tpm.rst  |   1 +
 hw/tpm/tpm_crb.h|  76 +++
 hw/tpm/tpm_crb.c| 270 ++--
 hw/tpm/tpm_crb_common.c | 218 
 hw/tpm/meson.build  |   1 +
 hw/tpm/trace-events |   2 +-
 6 files changed, 333 insertions(+), 235 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index efe124a148..2bc29c9804 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -45,6 +45,7 @@ operating system.
 
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
+ - ``hw/tpm/tpm_crb_common.c``
 
 SPAPR interface
 ---
diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
new file mode 100644
index 00..da3a0cf256
--- /dev/null
+++ b/hw/tpm/tpm_crb.h
@@ -0,0 +1,76 @@
+/*
+ * tpm_crb.h - QEMU's TPM CRB interface emulator
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * Authors:
+ *   Marc-André Lureau 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * tpm_crb is a device for TPM 2.0 Command Response Buffer (CRB) Interface
+ * as defined in TCG PC Client Platform TPM Profile (PTP) Specification
+ * Family “2.0” Level 00 Revision 01.03 v22
+ */
+#ifndef TPM_TPM_CRB_H
+#define TPM_TPM_CRB_H
+
+#include "exec/memory.h"
+#include "hw/acpi/tpm.h"
+#include "sysemu/tpm_backend.h"
+#include "tpm_ppi.h"
+
+#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
+
+typedef struct TPMCRBState {
+TPMBackend *tpmbe;
+TPMBackendCmd cmd;
+uint32_t regs[TPM_CRB_R_MAX];
+MemoryRegion mmio;
+MemoryRegion cmdmem;
+
+size_t be_buffer_size;
+
+bool ppi_enabled;
+TPMPPI ppi;
+} TPMCRBState;
+
+#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
+#define CRB_INTF_VERSION_CRB 0b1
+#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
+#define CRB_INTF_CAP_IDLE_FAST 0b0
+#define CRB_INTF_CAP_XFER_SIZE_64 0b11
+#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
+#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
+#define CRB_INTF_IF_SELECTOR_CRB 0b1
+
+enum crb_loc_ctrl {
+CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
+CRB_LOC_CTRL_RELINQUISH = BIT(1),
+CRB_LOC_CTRL_SEIZE = BIT(2),
+CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
+};
+
+enum crb_ctrl_req {
+CRB_CTRL_REQ_CMD_READY = BIT(0),
+CRB_CTRL_REQ_GO_IDLE = BIT(1),
+};
+
+enum crb_start {
+CRB_START_INVOKE = BIT(0),
+};
+
+enum crb_cancel {
+CRB_CANCEL_INVOKE = BIT(0),
+};
+
+#define TPM_CRB_NO_LOCALITY 0xff
+
+void tpm_crb_request_completed(TPMCRBState *s, int ret);
+enum TPMVersion tpm_crb_get_version(TPMCRBState *s);
+int tpm_crb_pre_save(TPMCRBState *s);
+void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr);
+void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error **errp);
+
+#endif /* TPM_TPM_CRB_H */
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index ea930da545..3ef4977fb5 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -31,257 +31,62 @@
 #include "tpm_ppi.h"
 #include "trace.h"
 #include "qom/object.h"
+#include "tpm_crb.h"
 
 struct CRBState {
 DeviceState parent_obj;
 
-TPMBackend *tpmbe;
-TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
-MemoryRegion mmio;
-MemoryRegion cmdmem;
-
-size_t be_buffer_size;
-
-bool ppi_enabled;
-TPMPPI ppi;
+TPMCRBState state;
 };
 typedef struct CRBState CRBState;
 
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  TYPE_TPM_CRB)
 
-#define CRB_INTF_TYPE_CRB_ACTIVE 0b1
-#define CRB_INTF_VERSION_CRB 0b1
-#define CRB_INTF_CAP_LOCALITY_0_ONLY 0b0
-#define CRB_INTF_CAP_IDLE_FAST 0b0
-#define CRB_INTF_CAP_XFER_SIZE_64 0b11
-#define CRB_INTF_CAP_FIFO_NOT_SUPPORTED 0b0
-#define CRB_INTF_CAP_CRB_SUPPORTED 0b1
-#define CRB_INTF_IF_SELECTOR_CRB 0b1
-
-#define CRB_CTRL_CMD_SIZE (TPM_CRB_ADDR_SIZE - A_CRB_DATA_BUFFER)
-
-enum crb_loc_ctrl {
-CRB_LOC_CTRL_REQUEST_ACCESS = BIT(0),
-CRB_LOC_CTRL_RELINQUISH = BIT(1),
-CRB_LOC_CTRL_SEIZE = BIT(2),
-CRB_LOC_CTRL_RESET_ESTABLISHMENT_BIT = BIT(3),
-};
-
-enum crb_ctrl_req {
-CRB_CTRL_REQ_CMD_READY = BIT(0),
-CRB_CTRL_REQ_GO_IDLE = BIT(1),
-};
-
-enum crb_start {
-CRB_START_INVOKE = BIT(0),
-};
-
-enum crb_cancel {
-CRB_CANCEL_INVOKE = BIT(0),
-};
-
-#define TPM_CRB_NO_LOCALITY 0xff
-
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
-{
-CRBState *s = CRB(opaque);
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-switch (addr) {
-case

[PATCH 11/11] tpm_crb_sysbus: introduce TPM CRB SysBus device

2023-07-12 Thread Joelle van Dyne
This SysBus variant of the CRB interface supports dynamically locating
the MMIO interface so that Virt machines can use it. This interface
is currently the only one supported by QEMU that works on Windows 11
ARM64. We largely follow the TPM TIS SysBus device as a template.

Signed-off-by: Joelle van Dyne 
---
 docs/specs/tpm.rst  |   1 +
 include/hw/acpi/aml-build.h |   1 +
 include/sysemu/tpm.h|   3 +
 hw/acpi/aml-build.c |   7 +-
 hw/arm/virt.c   |   1 +
 hw/core/sysbus-fdt.c|   1 +
 hw/loongarch/virt.c |   1 +
 hw/riscv/virt.c |   1 +
 hw/tpm/tpm_crb_sysbus.c | 178 
 hw/arm/Kconfig  |   1 +
 hw/riscv/Kconfig|   1 +
 hw/tpm/Kconfig  |   5 +
 hw/tpm/meson.build  |   2 +
 13 files changed, 202 insertions(+), 1 deletion(-)
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index 2bc29c9804..95aeb49220 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -46,6 +46,7 @@ operating system.
 QEMU files related to TPM CRB interface:
  - ``hw/tpm/tpm_crb.c``
  - ``hw/tpm/tpm_crb_common.c``
+ - ``hw/tpm/tpm_crb_sysbus.c``
 
 SPAPR interface
 ---
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index d1fb08514b..9660e16148 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -3,6 +3,7 @@
 
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/bios-linker-loader.h"
+#include "exec/hwaddr.h"
 
 #define ACPI_BUILD_APPNAME6 "BOCHS "
 #define ACPI_BUILD_APPNAME8 "BXPC"
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 66e3b45f30..f79c8f3575 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -47,6 +47,7 @@ struct TPMIfClass {
 #define TYPE_TPM_TIS_ISA"tpm-tis"
 #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device"
 #define TYPE_TPM_CRB"tpm-crb"
+#define TYPE_TPM_CRB_SYSBUS "tpm-crb-device"
 #define TYPE_TPM_SPAPR  "tpm-spapr"
 #define TYPE_TPM_TIS_I2C"tpm-tis-i2c"
 
@@ -56,6 +57,8 @@ struct TPMIfClass {
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_SYSBUS)
 #define TPM_IS_CRB(chr) \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_CRB_SYSBUS(chr)  \
+object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB_SYSBUS)
 #define TPM_IS_SPAPR(chr)   \
 object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
 #define TPM_IS_TIS_I2C(chr)  \
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index ea331a20d1..f809137fc9 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -31,6 +31,7 @@
 #include "hw/pci/pci_bus.h"
 #include "hw/pci/pci_bridge.h"
 #include "qemu/cutils.h"
+#include "qom/object.h"
 
 static GArray *build_alloc_array(void)
 {
@@ -2218,7 +2219,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 {
 uint8_t start_method_params[12] = {};
 unsigned log_addr_offset;
-uint64_t control_area_start_address;
+uint64_t baseaddr, control_area_start_address;
 TPMIf *tpmif = tpm_find();
 uint32_t start_method;
 AcpiTable table = { .sig = "TPM2", .rev = 4,
@@ -2236,6 +2237,10 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, 
GArray *tcpalog,
 } else if (TPM_IS_CRB(tpmif)) {
 control_area_start_address = TPM_CRB_ADDR_CTRL;
 start_method = TPM2_START_METHOD_CRB;
+} else if (TPM_IS_CRB_SYSBUS(tpmif)) {
+baseaddr = object_property_get_uint(OBJECT(tpmif), "baseaddr", NULL);
+control_area_start_address = baseaddr + A_CRB_CTRL_REQ;
+start_method = TPM2_START_METHOD_CRB;
 } else {
 g_assert_not_reached();
 }
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 432148ef47..88e8b16103 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2977,6 +2977,7 @@ static void virt_machine_class_init(ObjectClass *oc, void 
*data)
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
 #ifdef CONFIG_TPM
 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
+machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_CRB_SYSBUS);
 #endif
 mc->block_default_type = IF_VIRTIO;
 mc->no_cdrom = 1;
diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
index eebcd28f9a..9c783f88eb 100644
--- a/hw/core/sysbus-fdt.c
+++ b/hw/core/sysbus-fdt.c
@@ -493,6 +493,7 @@ static const BindingEntry bindings[] = {
 #endif
 #ifdef CONFIG_TPM
 TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
+TYPE_BINDING(TYPE_TPM_CRB_SYSBUS, no_fdt_node),
 #endif
 TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
 TYPE_BINDING("", NULL), /* last element */
diff --git 

[PATCH 07/11] hw/arm/virt: add plug handler for TPM on SysBus

2023-07-12 Thread Joelle van Dyne
TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne 
---
 hw/arm/virt.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7d9dbc2663..432148ef47 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2732,6 +2732,37 @@ static void virt_memory_plug(HotplugHandler *hotplug_dev,
  dev, _abort);
 }
 
+#ifdef CONFIG_TPM
+static void virt_tpm_plug(VirtMachineState *vms, TPMIf *tpmif)
+{
+PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
+hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
+SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+MemoryRegion *sbdev_mr;
+hwaddr tpm_base;
+uint64_t tpm_size;
+
+if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), TYPE_SYS_BUS_DEVICE)) {
+return;
+}
+
+tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+assert(tpm_base != -1);
+
+tpm_base += pbus_base;
+
+sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+tpm_size = memory_region_size(sbdev_mr);
+
+if (object_property_find(OBJECT(sbdev), "baseaddr")) {
+object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, NULL);
+}
+if (object_property_find(OBJECT(sbdev), "size")) {
+object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
+}
+}
+#endif
+
 static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
@@ -2803,6 +2834,12 @@ static void virt_machine_device_plug_cb(HotplugHandler 
*hotplug_dev,
 vms->virtio_iommu_bdf = pci_get_bdf(pdev);
 create_virtio_iommu_dt_bindings(vms);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+virt_tpm_plug(vms, TPM_IF(dev));
+}
+#endif
 }
 
 static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
-- 
2.39.2 (Apple Git-143)




[PATCH 10/11] tpm_tis_sysbus: move DSDT AML generation to device

2023-07-12 Thread Joelle van Dyne
This reduces redundent code in different machine types with ACPI table
generation. Additionally, this will allow us to support multiple TPM
interfaces. Finally, this matches up with the TPM TIS ISA
implementation.

Ideally, we would be able to call `qbus_build_aml` and avoid any TPM
specific code in the ACPI table generation. However, currently we
still have to call `build_tpm2` anyways and it does not look like
most other ACPI devices support the `ACPI_DEV_AML_IF` interface.

Signed-off-by: Joelle van Dyne 
---
 hw/arm/virt-acpi-build.c  | 38 ++
 hw/loongarch/acpi-build.c | 38 ++
 hw/tpm/tpm_tis_sysbus.c   | 39 +++
 3 files changed, 43 insertions(+), 72 deletions(-)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 6b674231c2..49b2f19440 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -35,6 +35,7 @@
 #include "target/arm/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "hw/acpi/aml-build.h"
@@ -208,41 +209,6 @@ static void acpi_dsdt_add_gpio(Aml *scope, const 
MemMapEntry *gpio_memmap,
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 #define ID_MAPPING_ENTRY_SIZE 20
 #define SMMU_V3_ENTRY_SIZE 68
 #define ROOT_COMPLEX_ENTRY_SIZE 36
@@ -891,7 +857,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
VirtMachineState *vms)
 
 acpi_dsdt_add_power_button(scope);
 #ifdef CONFIG_TPM
-acpi_dsdt_add_tpm(scope, vms);
+call_dev_aml_func(DEVICE(tpm_find()), scope);
 #endif
 
 aml_append(dsdt, scope);
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
index 0b62c3a2f7..4291e670c8 100644
--- a/hw/loongarch/acpi-build.c
+++ b/hw/loongarch/acpi-build.c
@@ -14,6 +14,7 @@
 #include "target/loongarch/cpu.h"
 #include "hw/acpi/acpi-defs.h"
 #include "hw/acpi/acpi.h"
+#include "hw/acpi/acpi_aml_interface.h"
 #include "hw/nvram/fw_cfg.h"
 #include "hw/acpi/bios-linker-loader.h"
 #include "migration/vmstate.h"
@@ -328,41 +329,6 @@ static void build_flash_aml(Aml *scope, 
LoongArchMachineState *lams)
 aml_append(scope, dev);
 }
 
-#ifdef CONFIG_TPM
-static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms)
-{
-PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev);
-hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
-SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find());
-MemoryRegion *sbdev_mr;
-hwaddr tpm_base;
-
-if (!sbdev) {
-return;
-}
-
-tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
-assert(tpm_base != -1);
-
-tpm_base += pbus_base;
-
-sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
-
-Aml *dev = aml_device("TPM0");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
-aml_append(dev, aml_name_decl("_UID", aml_int(0)));
-
-Aml *crs = aml_resource_template();
-aml_append(crs,
-   aml_memory32_fixed(tpm_base,
-  (uint32_t)memory_region_size(sbdev_mr),
-  AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-aml_append(scope, dev);
-}
-#endif
-
 /* build DSDT */
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
@@ -379,7 +345,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 
MachineState *machine)
   

[PATCH 04/11] tpm_crb: use a single read-as-mem/write-as-mmio mapping

2023-07-12 Thread Joelle van Dyne
On Apple Silicon, when Windows performs a LDP on the CRB MMIO space,
the exception is not decoded by hardware and we cannot trap the MMIO
read. This led to the idea from @agraf to use the same mapping type as
ROM devices: namely that reads should be seen as memory type and
writes should trap as MMIO.

Once that was done, the second memory mapping of the command buffer
region was redundent and was removed.

A note about the removal of the read trap for `CRB_LOC_STATE`:
The only usage was to return the most up-to-date value for
`tpmEstablished`. However, `tpmEstablished` is only set when a
TPM2_HashStart operation is called which only exists for locality 4.
Indeed, the comment for the write handler of `CRB_LOC_CTRL` makes the
same argument for why it is not calling the backend to reset the
`tpmEstablished` bit. As this bit is unused, we do not need to worry
about updating it for reads.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.h|   2 -
 hw/tpm/tpm_crb.c|   3 -
 hw/tpm/tpm_crb_common.c | 124 
 3 files changed, 63 insertions(+), 66 deletions(-)

diff --git a/hw/tpm/tpm_crb.h b/hw/tpm/tpm_crb.h
index da3a0cf256..7cdd37335f 100644
--- a/hw/tpm/tpm_crb.h
+++ b/hw/tpm/tpm_crb.h
@@ -26,9 +26,7 @@
 typedef struct TPMCRBState {
 TPMBackend *tpmbe;
 TPMBackendCmd cmd;
-uint32_t regs[TPM_CRB_R_MAX];
 MemoryRegion mmio;
-MemoryRegion cmdmem;
 
 size_t be_buffer_size;
 
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 598c3e0161..07c6868d8d 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -68,7 +68,6 @@ static const VMStateDescription vmstate_tpm_crb_none = {
 .name = "tpm-crb",
 .pre_save = tpm_crb_none_pre_save,
 .fields = (VMStateField[]) {
-VMSTATE_UINT32_ARRAY(state.regs, CRBState, TPM_CRB_R_MAX),
 VMSTATE_END_OF_LIST(),
 }
 };
@@ -103,8 +102,6 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 
 memory_region_add_subregion(get_system_memory(),
 TPM_CRB_ADDR_BASE, >state.mmio);
-memory_region_add_subregion(get_system_memory(),
-TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
 memory_region_add_subregion(get_system_memory(),
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index e56e910670..f3e40095e3 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -33,31 +33,12 @@
 #include "qom/object.h"
 #include "tpm_crb.h"
 
-static uint64_t tpm_crb_mmio_read(void *opaque, hwaddr addr,
-  unsigned size)
+static uint8_t tpm_crb_get_active_locty(TPMCRBState *s, uint32_t *regs)
 {
-TPMCRBState *s = opaque;
-void *regs = (void *)>regs + (addr & ~3);
-unsigned offset = addr & 3;
-uint32_t val = *(uint32_t *)regs >> (8 * offset);
-
-switch (addr) {
-case A_CRB_LOC_STATE:
-val |= !tpm_backend_get_tpm_established_flag(s->tpmbe);
-break;
-}
-
-trace_tpm_crb_mmio_read(addr, size, val);
-
-return val;
-}
-
-static uint8_t tpm_crb_get_active_locty(TPMCRBState *s)
-{
-if (!ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, locAssigned)) {
+if (!ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, locAssigned)) {
 return TPM_CRB_NO_LOCALITY;
 }
-return ARRAY_FIELD_EX32(s->regs, CRB_LOC_STATE, activeLocality);
+return ARRAY_FIELD_EX32(regs, CRB_LOC_STATE, activeLocality);
 }
 
 static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
@@ -65,35 +46,47 @@ static void tpm_crb_mmio_write(void *opaque, hwaddr addr,
 {
 TPMCRBState *s = opaque;
 uint8_t locty =  addr >> 12;
+uint32_t *regs;
+void *mem;
 
 trace_tpm_crb_mmio_write(addr, size, val);
+regs = memory_region_get_ram_ptr(>mmio);
+mem = [R_CRB_DATA_BUFFER];
+assert(regs);
+
+if (addr >= A_CRB_DATA_BUFFER) {
+assert(addr + size <= TPM_CRB_ADDR_SIZE);
+assert(size <= sizeof(val));
+memcpy(mem + addr - A_CRB_DATA_BUFFER, , size);
+memory_region_set_dirty(>mmio, addr, size);
+return;
+}
 
 switch (addr) {
 case A_CRB_CTRL_REQ:
 switch (val) {
 case CRB_CTRL_REQ_CMD_READY:
-ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  tpmIdle, 0);
 break;
 case CRB_CTRL_REQ_GO_IDLE:
-ARRAY_FIELD_DP32(s->regs, CRB_CTRL_STS,
+ARRAY_FIELD_DP32(regs, CRB_CTRL_STS,
  tpmIdle, 1);
 break;
 }
 break;
 case A_CRB_CTRL_CANCEL:
 if (val == CRB_CANCEL_INVOKE &&
-s->regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
+regs[R_CRB_CTRL_START] & CRB_START_INVOKE) {
 tpm_backend_cancel_cmd(s->tpmbe);
 }
  

[PATCH 03/11] tpm_ppi: refactor memory space initialization

2023-07-12 Thread Joelle van Dyne
Instead of calling `memory_region_add_subregion` directly, we defer to
the caller to do it. This allows us to re-use the code for a SysBus
device.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_ppi.h| 10 +++---
 hw/tpm/tpm_crb.c|  4 ++--
 hw/tpm/tpm_crb_common.c |  3 +++
 hw/tpm/tpm_ppi.c|  5 +
 hw/tpm/tpm_tis_isa.c|  5 +++--
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/hw/tpm/tpm_ppi.h b/hw/tpm/tpm_ppi.h
index bf5d4a300f..30863c6438 100644
--- a/hw/tpm/tpm_ppi.h
+++ b/hw/tpm/tpm_ppi.h
@@ -20,17 +20,13 @@ typedef struct TPMPPI {
 } TPMPPI;
 
 /**
- * tpm_ppi_init:
+ * tpm_ppi_init_memory:
  * @tpmppi: a TPMPPI
- * @m: the address-space / MemoryRegion to use
- * @addr: the address of the PPI region
  * @obj: the owner object
  *
- * Register the TPM PPI memory region at @addr on the given address
- * space for the object @obj.
+ * Creates the TPM PPI memory region.
  **/
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj);
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj);
 
 /**
  * tpm_ppi_reset:
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 3ef4977fb5..598c3e0161 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -107,8 +107,8 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 TPM_CRB_ADDR_BASE + sizeof(s->state.regs), >state.cmdmem);
 
 if (s->state.ppi_enabled) {
-tpm_ppi_init(>state.ppi, get_system_memory(),
- TPM_PPI_ADDR_BASE, OBJECT(s));
+memory_region_add_subregion(get_system_memory(),
+TPM_PPI_ADDR_BASE, >state.ppi.ram);
 }
 
 if (xen_enabled()) {
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 228e2d0faf..e56e910670 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -216,4 +216,7 @@ void tpm_crb_init_memory(Object *obj, TPMCRBState *s, Error 
**errp)
 "tpm-crb-mmio", sizeof(s->regs));
 memory_region_init_ram(>cmdmem, obj,
 "tpm-crb-cmd", CRB_CTRL_CMD_SIZE, errp);
+if (s->ppi_enabled) {
+tpm_ppi_init_memory(>ppi, obj);
+}
 }
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index 7f74e26ec6..40cab59afa 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -44,14 +44,11 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
 }
 }
 
-void tpm_ppi_init(TPMPPI *tpmppi, MemoryRegion *m,
-  hwaddr addr, Object *obj)
+void tpm_ppi_init_memory(TPMPPI *tpmppi, Object *obj)
 {
 tpmppi->buf = qemu_memalign(qemu_real_host_page_size(),
 HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
 memory_region_init_ram_device_ptr(>ram, obj, "tpm-ppi",
   TPM_PPI_ADDR_SIZE, tpmppi->buf);
 vmstate_register_ram(>ram, DEVICE(obj));
-
-memory_region_add_subregion(m, addr, >ram);
 }
diff --git a/hw/tpm/tpm_tis_isa.c b/hw/tpm/tpm_tis_isa.c
index 91e3792248..7cd7415f30 100644
--- a/hw/tpm/tpm_tis_isa.c
+++ b/hw/tpm/tpm_tis_isa.c
@@ -134,8 +134,9 @@ static void tpm_tis_isa_realizefn(DeviceState *dev, Error 
**errp)
 TPM_TIS_ADDR_BASE, >mmio);
 
 if (s->ppi_enabled) {
-tpm_ppi_init(>ppi, isa_address_space(ISA_DEVICE(dev)),
- TPM_PPI_ADDR_BASE, OBJECT(dev));
+tpm_ppi_init_memory(>ppi, OBJECT(dev));
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
+TPM_PPI_ADDR_BASE, >ppi.ram);
 }
 }
 
-- 
2.39.2 (Apple Git-143)




[PATCH 08/11] hw/loongarch/virt: add plug handler for TPM on SysBus

2023-07-12 Thread Joelle van Dyne
TPM needs to know its own base address in order to generate its DSDT
device entry.

Signed-off-by: Joelle van Dyne 
---
 hw/loongarch/virt.c | 37 +
 1 file changed, 37 insertions(+)

diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
index e19b042ce8..9c536c52bc 100644
--- a/hw/loongarch/virt.c
+++ b/hw/loongarch/virt.c
@@ -1040,6 +1040,37 @@ static void virt_mem_plug(HotplugHandler *hotplug_dev,
  dev, _abort);
 }
 
+#ifdef CONFIG_TPM
+static void virt_tpm_plug(LoongArchMachineState *lams, TPMIf *tpmif)
+{
+PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(lams->platform_bus_dev);
+hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS;
+SysBusDevice *sbdev = SYS_BUS_DEVICE(tpmif);
+MemoryRegion *sbdev_mr;
+hwaddr tpm_base;
+uint64_t tpm_size;
+
+if (!sbdev || !object_dynamic_cast(OBJECT(sbdev), TYPE_SYS_BUS_DEVICE)) {
+return;
+}
+
+tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+assert(tpm_base != -1);
+
+tpm_base += pbus_base;
+
+sbdev_mr = sysbus_mmio_get_region(sbdev, 0);
+tpm_size = memory_region_size(sbdev_mr);
+
+if (object_property_find(OBJECT(sbdev), "baseaddr")) {
+object_property_set_uint(OBJECT(sbdev), "baseaddr", tpm_base, NULL);
+}
+if (object_property_find(OBJECT(sbdev), "size")) {
+object_property_set_uint(OBJECT(sbdev), "size", tpm_size, NULL);
+}
+}
+#endif
+
 static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 DeviceState *dev, Error **errp)
 {
@@ -1054,6 +1085,12 @@ static void 
loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
 } else if (memhp_type_supported(dev)) {
 virt_mem_plug(hotplug_dev, dev, errp);
 }
+
+#ifdef CONFIG_TPM
+if (object_dynamic_cast(OBJECT(dev), TYPE_TPM_IF)) {
+virt_tpm_plug(lams, TPM_IF(dev));
+}
+#endif
 }
 
 static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
-- 
2.39.2 (Apple Git-143)




[PATCH 06/11] tpm_crb: move ACPI table building to device interface

2023-07-12 Thread Joelle van Dyne
This logic is similar to TPM TIS ISA device.

Signed-off-by: Joelle van Dyne 
---
 hw/i386/acpi-build.c | 23 ---
 hw/tpm/tpm_crb.c | 28 
 2 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 9c74fa17ad..b767df39df 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1441,9 +1441,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 uint32_t nr_mem = machine->ram_slots;
 int root_bus_limit = 0xFF;
 PCIBus *bus = NULL;
-#ifdef CONFIG_TPM
-TPMIf *tpm = tpm_find();
-#endif
 bool cxl_present = false;
 int i;
 VMBusBridge *vmbus_bridge = vmbus_bridge_find();
@@ -1793,26 +1790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 }
 }
 
-#ifdef CONFIG_TPM
-if (TPM_IS_CRB(tpm)) {
-dev = aml_device("TPM");
-aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
-aml_append(dev, aml_name_decl("_STR",
-  aml_string("TPM 2.0 Device")));
-crs = aml_resource_template();
-aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE,
-   TPM_CRB_ADDR_SIZE, AML_READ_WRITE));
-aml_append(dev, aml_name_decl("_CRS", crs));
-
-aml_append(dev, aml_name_decl("_STA", aml_int(0xf)));
-aml_append(dev, aml_name_decl("_UID", aml_int(1)));
-
-tpm_build_ppi_acpi(tpm, dev);
-
-aml_append(sb_scope, dev);
-}
-#endif
-
 if (pcms->sgx_epc.size != 0) {
 uint64_t epc_base = pcms->sgx_epc.base;
 uint64_t epc_size = pcms->sgx_epc.size;
diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 6144081d30..14feb9857f 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -19,6 +19,8 @@
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "exec/address-spaces.h"
+#include "hw/acpi/acpi_aml_interface.h"
+#include "hw/acpi/tpm.h"
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
@@ -116,10 +118,34 @@ static void tpm_crb_isa_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
+static void build_tpm_crb_isa_aml(AcpiDevAmlIf *adev, Aml *scope)
+{
+Aml *dev, *crs;
+CRBState *s = CRB(adev);
+TPMIf *ti = TPM_IF(s);
+
+dev = aml_device("TPM");
+if (tpm_crb_isa_get_version(ti) == TPM_VERSION_2_0) {
+aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
+aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
+} else {
+aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
+}
+aml_append(dev, aml_name_decl("_UID", aml_int(1)));
+aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
+crs = aml_resource_template();
+aml_append(crs, aml_memory32_fixed(TPM_CRB_ADDR_BASE, TPM_CRB_ADDR_SIZE,
+  AML_READ_WRITE));
+aml_append(dev, aml_name_decl("_CRS", crs));
+tpm_build_ppi_acpi(ti, dev);
+aml_append(scope, dev);
+}
+
 static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 TPMIfClass *tc = TPM_IF_CLASS(klass);
+AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
 
 dc->realize = tpm_crb_isa_realize;
 device_class_set_props(dc, tpm_crb_isa_properties);
@@ -128,6 +154,7 @@ static void tpm_crb_isa_class_init(ObjectClass *klass, void 
*data)
 tc->model = TPM_MODEL_TPM_CRB;
 tc->get_version = tpm_crb_isa_get_version;
 tc->request_completed = tpm_crb_isa_request_completed;
+adevc->build_dev_aml = build_tpm_crb_isa_aml;
 
 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
@@ -139,6 +166,7 @@ static const TypeInfo tpm_crb_isa_info = {
 .class_init  = tpm_crb_isa_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_TPM_IF },
+{ TYPE_ACPI_DEV_AML_IF },
 { }
 }
 };
-- 
2.39.2 (Apple Git-143)




[PATCH 02/11] tpm_crb: CTRL_RSP_ADDR is 64-bits wide

2023-07-12 Thread Joelle van Dyne
The register is actually 64-bits but in order to make this more clear
than the specification, we define two 32-bit registers:
CTRL_RSP_LADDR and CTRL_RSP_HADDR to match the CTRL_CMD_* naming. This
deviates from the specs but is way more clear.

Previously, the only CRB device uses a fixed system address so this
was not an issue. However, once we support SysBus CRB device, the
address can be anywhere in 64-bit space.

Signed-off-by: Joelle van Dyne 
---
 include/hw/acpi/tpm.h  | 3 ++-
 hw/tpm/tpm_crb_common.c| 3 ++-
 tests/qtest/tpm-crb-test.c | 2 +-
 tests/qtest/tpm-util.c | 2 +-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/hw/acpi/tpm.h b/include/hw/acpi/tpm.h
index 579c45f5ba..f60bfe2789 100644
--- a/include/hw/acpi/tpm.h
+++ b/include/hw/acpi/tpm.h
@@ -174,7 +174,8 @@ REG32(CRB_CTRL_CMD_SIZE, 0x58)
 REG32(CRB_CTRL_CMD_LADDR, 0x5C)
 REG32(CRB_CTRL_CMD_HADDR, 0x60)
 REG32(CRB_CTRL_RSP_SIZE, 0x64)
-REG32(CRB_CTRL_RSP_ADDR, 0x68)
+REG32(CRB_CTRL_RSP_LADDR, 0x68)
+REG32(CRB_CTRL_RSP_HADDR, 0x6C)
 REG32(CRB_DATA_BUFFER, 0x80)
 
 #define TPM_CRB_ADDR_BASE   0xFED4
diff --git a/hw/tpm/tpm_crb_common.c b/hw/tpm/tpm_crb_common.c
index 4c173affb6..228e2d0faf 100644
--- a/hw/tpm/tpm_crb_common.c
+++ b/hw/tpm/tpm_crb_common.c
@@ -199,7 +199,8 @@ void tpm_crb_reset(TPMCRBState *s, uint64_t baseaddr)
 s->regs[R_CRB_CTRL_CMD_LADDR] = (uint32_t)baseaddr;
 s->regs[R_CRB_CTRL_CMD_HADDR] = (uint32_t)(baseaddr >> 32);
 s->regs[R_CRB_CTRL_RSP_SIZE] = CRB_CTRL_CMD_SIZE;
-s->regs[R_CRB_CTRL_RSP_ADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_LADDR] = (uint32_t)baseaddr;
+s->regs[R_CRB_CTRL_RSP_HADDR] = (uint32_t)(baseaddr >> 32);
 
 s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->tpmbe),
 CRB_CTRL_CMD_SIZE);
diff --git a/tests/qtest/tpm-crb-test.c b/tests/qtest/tpm-crb-test.c
index 396ae3f91c..9d30fe8293 100644
--- a/tests/qtest/tpm-crb-test.c
+++ b/tests/qtest/tpm-crb-test.c
@@ -28,7 +28,7 @@ static void tpm_crb_test(const void *data)
 uint32_t csize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_SIZE);
 uint64_t caddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
 uint32_t rsize = readl(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_SIZE);
-uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = readq(TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 uint8_t locstate = readb(TPM_CRB_ADDR_BASE + A_CRB_LOC_STATE);
 uint32_t locctrl = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL);
 uint32_t locsts = readl(TPM_CRB_ADDR_BASE + A_CRB_LOC_STS);
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index 1c0319e6e7..dd02057fc0 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -25,7 +25,7 @@ void tpm_util_crb_transfer(QTestState *s,
unsigned char *rsp, size_t rsp_size)
 {
 uint64_t caddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_CMD_LADDR);
-uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_ADDR);
+uint64_t raddr = qtest_readq(s, TPM_CRB_ADDR_BASE + A_CRB_CTRL_RSP_LADDR);
 
 qtest_writeb(s, TPM_CRB_ADDR_BASE + A_CRB_LOC_CTRL, 1);
 
-- 
2.39.2 (Apple Git-143)




[PATCH 05/11] tpm_crb: use the ISA bus

2023-07-12 Thread Joelle van Dyne
Since this device is gated to only build for targets with the PC
configuration, we should use the ISA bus like with TPM TIS.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_crb.c | 52 
 hw/tpm/Kconfig   |  2 +-
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c
index 07c6868d8d..6144081d30 100644
--- a/hw/tpm/tpm_crb.c
+++ b/hw/tpm/tpm_crb.c
@@ -22,6 +22,7 @@
 #include "hw/qdev-properties.h"
 #include "hw/pci/pci_ids.h"
 #include "hw/acpi/tpm.h"
+#include "hw/isa/isa.h"
 #include "migration/vmstate.h"
 #include "sysemu/tpm_backend.h"
 #include "sysemu/tpm_util.h"
@@ -34,7 +35,7 @@
 #include "tpm_crb.h"
 
 struct CRBState {
-DeviceState parent_obj;
+ISADevice parent_obj;
 
 TPMCRBState state;
 };
@@ -43,49 +44,49 @@ typedef struct CRBState CRBState;
 DECLARE_INSTANCE_CHECKER(CRBState, CRB,
  TYPE_TPM_CRB)
 
-static void tpm_crb_none_request_completed(TPMIf *ti, int ret)
+static void tpm_crb_isa_request_completed(TPMIf *ti, int ret)
 {
 CRBState *s = CRB(ti);
 
 tpm_crb_request_completed(>state, ret);
 }
 
-static enum TPMVersion tpm_crb_none_get_version(TPMIf *ti)
+static enum TPMVersion tpm_crb_isa_get_version(TPMIf *ti)
 {
 CRBState *s = CRB(ti);
 
 return tpm_crb_get_version(>state);
 }
 
-static int tpm_crb_none_pre_save(void *opaque)
+static int tpm_crb_isa_pre_save(void *opaque)
 {
 CRBState *s = opaque;
 
 return tpm_crb_pre_save(>state);
 }
 
-static const VMStateDescription vmstate_tpm_crb_none = {
+static const VMStateDescription vmstate_tpm_crb_isa = {
 .name = "tpm-crb",
-.pre_save = tpm_crb_none_pre_save,
+.pre_save = tpm_crb_isa_pre_save,
 .fields = (VMStateField[]) {
 VMSTATE_END_OF_LIST(),
 }
 };
 
-static Property tpm_crb_none_properties[] = {
+static Property tpm_crb_isa_properties[] = {
 DEFINE_PROP_TPMBE("tpmdev", CRBState, state.tpmbe),
 DEFINE_PROP_BOOL("ppi", CRBState, state.ppi_enabled, true),
 DEFINE_PROP_END_OF_LIST(),
 };
 
-static void tpm_crb_none_reset(void *dev)
+static void tpm_crb_isa_reset(void *dev)
 {
 CRBState *s = CRB(dev);
 
 return tpm_crb_reset(>state, TPM_CRB_ADDR_BASE);
 }
 
-static void tpm_crb_none_realize(DeviceState *dev, Error **errp)
+static void tpm_crb_isa_realize(DeviceState *dev, Error **errp)
 {
 CRBState *s = CRB(dev);
 
@@ -100,52 +101,51 @@ static void tpm_crb_none_realize(DeviceState *dev, Error 
**errp)
 
 tpm_crb_init_memory(OBJECT(s), >state, errp);
 
-memory_region_add_subregion(get_system_memory(),
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
 TPM_CRB_ADDR_BASE, >state.mmio);
 
 if (s->state.ppi_enabled) {
-memory_region_add_subregion(get_system_memory(),
+memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
 TPM_PPI_ADDR_BASE, >state.ppi.ram);
 }
 
 if (xen_enabled()) {
-tpm_crb_none_reset(dev);
+tpm_crb_isa_reset(dev);
 } else {
-qemu_register_reset(tpm_crb_none_reset, dev);
+qemu_register_reset(tpm_crb_isa_reset, dev);
 }
 }
 
-static void tpm_crb_none_class_init(ObjectClass *klass, void *data)
+static void tpm_crb_isa_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 TPMIfClass *tc = TPM_IF_CLASS(klass);
 
-dc->realize = tpm_crb_none_realize;
-device_class_set_props(dc, tpm_crb_none_properties);
-dc->vmsd  = _tpm_crb_none;
+dc->realize = tpm_crb_isa_realize;
+device_class_set_props(dc, tpm_crb_isa_properties);
+dc->vmsd  = _tpm_crb_isa;
 dc->user_creatable = true;
 tc->model = TPM_MODEL_TPM_CRB;
-tc->get_version = tpm_crb_none_get_version;
-tc->request_completed = tpm_crb_none_request_completed;
+tc->get_version = tpm_crb_isa_get_version;
+tc->request_completed = tpm_crb_isa_request_completed;
 
 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 }
 
-static const TypeInfo tpm_crb_none_info = {
+static const TypeInfo tpm_crb_isa_info = {
 .name = TYPE_TPM_CRB,
-/* could be TYPE_SYS_BUS_DEVICE (or LPC etc) */
-.parent = TYPE_DEVICE,
+.parent = TYPE_ISA_DEVICE,
 .instance_size = sizeof(CRBState),
-.class_init  = tpm_crb_none_class_init,
+.class_init  = tpm_crb_isa_class_init,
 .interfaces = (InterfaceInfo[]) {
 { TYPE_TPM_IF },
 { }
 }
 };
 
-static void tpm_crb_none_register(void)
+static void tpm_crb_isa_register(void)
 {
-type_register_static(_crb_none_info);
+type_register_static(_crb_isa_info);
 }
 
-type_init(tpm_crb_none_register)
+type_init(tpm_crb_isa_register)
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index a46663288c..1fd73fe617 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kc

[PATCH 09/11] tpm_tis_sysbus: fix crash when PPI is enabled

2023-07-12 Thread Joelle van Dyne
If 'ppi' property is set, then `tpm_ppi_reset` is called on reset
which SEGFAULTs because `tpmppi->buf` is not allocated.

Signed-off-by: Joelle van Dyne 
---
 hw/tpm/tpm_tis_sysbus.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c
index 45e63efd63..1014d5d993 100644
--- a/hw/tpm/tpm_tis_sysbus.c
+++ b/hw/tpm/tpm_tis_sysbus.c
@@ -124,6 +124,10 @@ static void tpm_tis_sysbus_realizefn(DeviceState *dev, 
Error **errp)
 error_setg(errp, "'tpmdev' property is required");
 return;
 }
+
+if (s->ppi_enabled) {
+sysbus_init_mmio(SYS_BUS_DEVICE(dev), >ppi.ram);
+}
 }
 
 static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data)
-- 
2.39.2 (Apple Git-143)




[PATCH 00/11] tpm: introduce TPM CRB SysBus device

2023-07-12 Thread Joelle van Dyne
The impetus for this patch set is to get TPM 2.0 working on Windows 11 ARM64.
Windows' tpm.sys does not seem to work on a TPM TIS device (as verified with
VMWare's implementation). However, the current TPM CRB device uses a fixed
system bus address that is reserved for RAM in ARM64 Virt machines.

In the process of adding the TPM CRB SysBus device, we also went ahead and
cleaned up some of the existing TPM hardware code and fixed some bugs. We used
the TPM TIS devices as a template for the TPM CRB devices and refactored out
common code. We moved the ACPI DSDT generation to the device in order to handle
dynamic base address requirements as well as reduce redundent code in different
machine ACPI generation. We also changed the tpm_crb device to use the ISA bus
instead of depending on the default system bus as the device only was built for
the PC configuration.

Another change is that the TPM CRB registers are now mapped in the same way that
the pflash ROM devices are mapped. It is a memory region whose writes are
trapped as MMIO accesses. This was needed because Apple Silicon does not decode
LDP caused page faults. @agraf suggested that we do this to avoid having to
do AARCH64 decoding in the HVF fault handler.

Unfortunately, it seems like the LDP fault still happens on HVF but the issue
seems to be in the HVF backend which needs to be fixed in a separate patch.

One last thing that's needed to get Windows 11 to recognize the TPM 2.0 device
is for the OVMF firmware to setup the TPM device. Currently, OVMF for ARM64 Virt
only recognizes the TPM TIS device through a FDT entry. A workaround is to
falsely identify the TPM CRB device as a TPM TIS device in the FDT node but this
causes issues for Linux. A proper fix would involve adding an ACPI device driver
in OVMF.

Joelle van Dyne (11):
  tpm_crb: refactor common code
  tpm_crb: CTRL_RSP_ADDR is 64-bits wide
  tpm_ppi: refactor memory space initialization
  tpm_crb: use a single read-as-mem/write-as-mmio mapping
  tpm_crb: use the ISA bus
  tpm_crb: move ACPI table building to device interface
  hw/arm/virt: add plug handler for TPM on SysBus
  hw/loongarch/virt: add plug handler for TPM on SysBus
  tpm_tis_sysbus: fix crash when PPI is enabled
  tpm_tis_sysbus: move DSDT AML generation to device
  tpm_crb_sysbus: introduce TPM CRB SysBus device

 docs/specs/tpm.rst  |   2 +
 hw/tpm/tpm_crb.h|  74 +
 hw/tpm/tpm_ppi.h|  10 +-
 include/hw/acpi/aml-build.h |   1 +
 include/hw/acpi/tpm.h   |   3 +-
 include/sysemu/tpm.h|   3 +
 hw/acpi/aml-build.c |   7 +-
 hw/arm/virt-acpi-build.c|  38 +
 hw/arm/virt.c   |  38 +
 hw/core/sysbus-fdt.c|   1 +
 hw/i386/acpi-build.c|  23 ---
 hw/loongarch/acpi-build.c   |  38 +
 hw/loongarch/virt.c |  38 +
 hw/riscv/virt.c |   1 +
 hw/tpm/tpm_crb.c| 307 
 hw/tpm/tpm_crb_common.c | 224 ++
 hw/tpm/tpm_crb_sysbus.c | 178 +
 hw/tpm/tpm_ppi.c|   5 +-
 hw/tpm/tpm_tis_isa.c|   5 +-
 hw/tpm/tpm_tis_sysbus.c |  43 +
 tests/qtest/tpm-crb-test.c  |   2 +-
 tests/qtest/tpm-util.c  |   2 +-
 hw/arm/Kconfig  |   1 +
 hw/riscv/Kconfig|   1 +
 hw/tpm/Kconfig  |   7 +-
 hw/tpm/meson.build  |   3 +
 hw/tpm/trace-events |   2 +-
 27 files changed, 703 insertions(+), 354 deletions(-)
 create mode 100644 hw/tpm/tpm_crb.h
 create mode 100644 hw/tpm/tpm_crb_common.c
 create mode 100644 hw/tpm/tpm_crb_sysbus.c

-- 
2.39.2 (Apple Git-143)




Re: [PATCH 1/2] hw/intc/arm_gicv3: Make ITT entry size configurable

2023-03-09 Thread Joelle van Dyne
On Fri, Dec 23, 2022 at 12:50 AM Alexander Graf  wrote:
>
> An ITT entry is opaque to the OS. The only thing it does get told by HW is
> its size. In theory, that size can be any byte aligned number, in practice
> HW will always use power of 2s to simplify offset calculation. We currently
> expose the size as 12, which is not a power of 2.
>
> To prepare for a future where we expose power of 2 sized entry sizes, let's
> make the size itself configurable. We only need to watch out that we don't
> have an entry be smaller than the fields we want to access inside. Bigger
> is always fine.
>
> Signed-off-by: Alexander Graf 
> ---

Tested-by: Joelle van Dyne 



Re: [PATCH] hvf: arm: Add support for GICv3

2023-03-09 Thread Joelle van Dyne
On Mon, Dec 19, 2022 at 2:08 PM Alexander Graf  wrote:
>
> We currently only support GICv2 emulation. To also support GICv3, we will
> need to pass a few system registers into their respective handler functions.
>
> This patch adds support for HVF to call into the TCG callbacks for GICv3
> system register handlers. This is safe because the GICv3 TCG code is generic
> as long as we limit ourselves to EL0 and EL1 - which are the only modes
> supported by HVF.
>
> To make sure nobody trips over that, we also annotate callbacks that don't
> work in HVF mode, such as EL state change hooks.
>
> With GICv3 support in place, we can run with more than 8 vCPUs.
>
> Signed-off-by: Alexander Graf 
> ---

Tested-by: Joelle van Dyne 



  1   2   3   4   >