!77 Aarch64 support vtpm

Merge pull request !77 from JackJF/master
This commit is contained in:
openeuler-ci-bot 2020-08-17 18:30:49 +08:00 committed by Gitee
commit d95a35c2e0
20 changed files with 5677 additions and 1 deletions

View File

@ -0,0 +1,26 @@
From 3020ae141ef40f06b17eb0f16d2a3c6d5872ff89 Mon Sep 17 00:00:00 2001
From: jiangfangjie <jiangfangjie@huawei.com>
Date: Wed, 29 Jul 2020 08:45:50 +0000
Subject: [PATCH 05/19] delete the in tpm.txt
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
docs/specs/tpm.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt
index 5d8c26b1..9c8cca04 100644
--- a/docs/specs/tpm.txt
+++ b/docs/specs/tpm.txt
@@ -89,7 +89,7 @@ TPM upon reboot. The PPI specification defines the operation requests and the
actions the firmware has to take. The system administrator passes the operation
request number to the firmware through an ACPI interface which writes this
number to a memory location that the firmware knows. Upon reboot, the firmware
-finds the number and sends commands to the the TPM. The firmware writes the TPM
+finds the number and sends commands to the TPM. The firmware writes the TPM
result code and the operation request number to a memory location that ACPI can
read from and pass the result on to the administrator.
--
2.23.0

View File

@ -0,0 +1,66 @@
From dd7f6cc3bcd71681920e3530f2c53041c812c5d3 Mon Sep 17 00:00:00 2001
From: Eric Auger <eric.auger@redhat.com>
Date: Thu, 5 Mar 2020 17:51:46 +0100
Subject: [PATCH 16/19] docs/specs/tpm: Document TPM_TIS sysbus device for ARM
Update the documentation with recent changes related to the
sysbus TPM_TIS device addition and add the command line
to be used with arm VIRT.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Message-id: 20200305165149.618-8-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
docs/specs/tpm.rst | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
index 2bdf637f..da9eb39c 100644
--- a/docs/specs/tpm.rst
+++ b/docs/specs/tpm.rst
@@ -18,9 +18,15 @@ The TIS interface makes a memory mapped IO region in the area
0xfed40000-0xfed44fff available to the guest operating system.
QEMU files related to TPM TIS interface:
- - ``hw/tpm/tpm_tis.c``
+ - ``hw/tpm/tpm_tis_common.c``
+ - ``hw/tpm/tpm_tis_isa.c``
+ - ``hw/tpm/tpm_tis_sysbus.c``
- ``hw/tpm/tpm_tis.h``
+Both an ISA device and a sysbus device are available. The former is
+used with pc/q35 machine while the latter can be instantiated in the
+ARM virt machine.
+
CRB interface
-------------
@@ -325,6 +331,23 @@ In case a pSeries machine is emulated, use the following command line:
-device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \
-drive file=test.img,format=raw,if=none,id=drive-virtio-disk0
+In case an ARM virt machine is emulated, use the following command line:
+
+.. code-block:: console
+
+ qemu-system-aarch64 -machine virt,gic-version=3,accel=kvm \
+ -cpu host -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 \
+ -device virtio-blk-pci,drive=drv0 \
+ -drive format=qcow2,file=hda.qcow2,if=none,id=drv0 \
+ -drive if=pflash,format=raw,file=flash0.img,readonly \
+ -drive if=pflash,format=raw,file=flash1.img
+
+ On ARM, ACPI boot with TPM is not yet supported.
+
In case SeaBIOS is used as firmware, it should show the TPM menu item
after entering the menu with 'ESC'.
--
2.23.0

View File

@ -0,0 +1,993 @@
From 5d1865496ca39f08142a0c1eb2c9b14ec1ec9140 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Tue, 21 Jan 2020 10:29:35 -0500
Subject: [PATCH 09/19] docs/specs/tpm: reST-ify TPM documentation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Message-Id: <20200121152935.649898-7-stefanb@linux.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
docs/specs/index.rst | 1 +
docs/specs/tpm.rst | 503 +++++++++++++++++++++++++++++++++++++++++++
docs/specs/tpm.txt | 445 --------------------------------------
3 files changed, 504 insertions(+), 445 deletions(-)
create mode 100644 docs/specs/tpm.rst
delete mode 100644 docs/specs/tpm.txt
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
index 984ba440..de46a8b5 100644
--- a/docs/specs/index.rst
+++ b/docs/specs/index.rst
@@ -13,3 +13,4 @@ Contents:
ppc-xive
ppc-spapr-xive
acpi_hw_reduced_hotplug
+ tpm
diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst
new file mode 100644
index 00000000..2bdf637f
--- /dev/null
+++ b/docs/specs/tpm.rst
@@ -0,0 +1,503 @@
+===============
+QEMU TPM Device
+===============
+
+Guest-side hardware interface
+=============================
+
+TIS interface
+-------------
+
+The QEMU TPM emulation implements a TPM TIS hardware interface
+following the Trusted Computing Group's specification "TCG PC Client
+Specific TPM Interface Specification (TIS)", Specification Version
+1.3, 21 March 2013. (see the `TIS specification`_, or a later version
+of it).
+
+The TIS interface makes a memory mapped IO region in the area
+0xfed40000-0xfed44fff available to the guest operating system.
+
+QEMU files related to TPM TIS interface:
+ - ``hw/tpm/tpm_tis.c``
+ - ``hw/tpm/tpm_tis.h``
+
+CRB interface
+-------------
+
+QEMU also implements a TPM CRB interface following the Trusted
+Computing Group's specification "TCG PC Client Platform TPM Profile
+(PTP) Specification", Family "2.0", Level 00 Revision 01.03 v22, May
+22, 2017. (see the `CRB specification`_, or a later version of it)
+
+The CRB interface makes a memory mapped IO region in the area
+0xfed40000-0xfed40fff (1 locality) available to the guest
+operating system.
+
+QEMU files related to TPM CRB interface:
+ - ``hw/tpm/tpm_crb.c``
+
+SPAPR interface
+---------------
+
+pSeries (ppc64) machines offer a tpm-spapr device model.
+
+QEMU files related to the SPAPR interface:
+ - ``hw/tpm/tpm_spapr.c``
+
+fw_cfg interface
+================
+
+The bios/firmware may read the ``"etc/tpm/config"`` fw_cfg entry for
+configuring the guest appropriately.
+
+The entry of 6 bytes has the following content, in little-endian:
+
+.. code-block:: c
+
+ #define TPM_VERSION_UNSPEC 0
+ #define TPM_VERSION_1_2 1
+ #define TPM_VERSION_2_0 2
+
+ #define TPM_PPI_VERSION_NONE 0
+ #define TPM_PPI_VERSION_1_30 1
+
+ struct FwCfgTPMConfig {
+ uint32_t tpmppi_address; /* PPI memory location */
+ uint8_t tpm_version; /* TPM version */
+ uint8_t tpmppi_version; /* PPI version */
+ };
+
+ACPI interface
+==============
+
+The TPM device is defined with ACPI ID "PNP0C31". QEMU builds a SSDT
+and passes it into the guest through the fw_cfg device. The device
+description contains the base address of the TIS interface 0xfed40000
+and the size of the MMIO area (0x5000). In case a TPM2 is used by
+QEMU, a TPM2 ACPI table is also provided. The device is described to
+be used in polling mode rather than interrupt mode primarily because
+no unused IRQ could be found.
+
+To support measurement logs to be written by the firmware,
+e.g. SeaBIOS, a TCPA table is implemented. This table provides a 64kb
+buffer where the firmware can write its log into. For TPM 2 only a
+more recent version of the TPM2 table provides support for
+measurements logs and a TCPA table does not need to be created.
+
+The TCPA and TPM2 ACPI tables follow the Trusted Computing Group
+specification "TCG ACPI Specification" Family "1.2" and "2.0", Level
+00 Revision 00.37. (see the `ACPI specification`_, or a later version
+of it)
+
+ACPI PPI Interface
+------------------
+
+QEMU supports the Physical Presence Interface (PPI) for TPM 1.2 and
+TPM 2. This interface requires ACPI and firmware support. (see the
+`PPI specification`_)
+
+PPI enables a system administrator (root) to request a modification to
+the TPM upon reboot. The PPI specification defines the operation
+requests and the actions the firmware has to take. The system
+administrator passes the operation request number to the firmware
+through an ACPI interface which writes this number to a memory
+location that the firmware knows. Upon reboot, the firmware finds the
+number and sends commands to the TPM. The firmware writes the TPM
+result code and the operation request number to a memory location that
+ACPI can read from and pass the result on to the administrator.
+
+The PPI specification defines a set of mandatory and optional
+operations for the firmware to implement. The ACPI interface also
+allows an administrator to list the supported operations. In QEMU the
+ACPI code is generated by QEMU, yet the firmware needs to implement
+support on a per-operations basis, and different firmwares may support
+a different subset. Therefore, QEMU introduces the virtual memory
+device for PPI where the firmware can indicate which operations it
+supports and ACPI can enable the ones that are supported and disable
+all others. This interface lies in main memory and has the following
+layout:
+
+ +-------------+--------+--------+-------------------------------------------+
+ | Field | Length | Offset | Description |
+ +=============+========+========+===========================================+
+ | ``func`` | 0x100 | 0x000 | Firmware sets values for each supported |
+ | | | | operation. See defined values below. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``ppin`` | 0x1 | 0x100 | SMI interrupt to use. Set by firmware. |
+ | | | | Not supported. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``ppip`` | 0x4 | 0x101 | ACPI function index to pass to SMM code. |
+ | | | | Set by ACPI. Not supported. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``pprp`` | 0x4 | 0x105 | Result of last executed operation. Set by |
+ | | | | firmware. See function index 5 for values.|
+ +-------------+--------+--------+-------------------------------------------+
+ | ``pprq`` | 0x4 | 0x109 | Operation request number to execute. See |
+ | | | | 'Physical Presence Interface Operation |
+ | | | | Summary' tables in specs. Set by ACPI. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``pprm`` | 0x4 | 0x10d | Operation request optional parameter. |
+ | | | | Values depend on operation. Set by ACPI. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``lppr`` | 0x4 | 0x111 | Last executed operation request number. |
+ | | | | Copied from pprq field by firmware. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``fret`` | 0x4 | 0x115 | Result code from SMM function. |
+ | | | | Not supported. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``res1`` | 0x40 | 0x119 | Reserved for future use |
+ +-------------+--------+--------+-------------------------------------------+
+ |``next_step``| 0x1 | 0x159 | Operation to execute after reboot by |
+ | | | | firmware. Used by firmware. |
+ +-------------+--------+--------+-------------------------------------------+
+ | ``movv`` | 0x1 | 0x15a | Memory overwrite variable |
+ +-------------+--------+--------+-------------------------------------------+
+
+The following values are supported for the ``func`` field. They
+correspond to the values used by ACPI function index 8.
+
+ +----------+-------------------------------------------------------------+
+ | Value | Description |
+ +==========+=============================================================+
+ | 0 | Operation is not implemented. |
+ +----------+-------------------------------------------------------------+
+ | 1 | Operation is only accessible through firmware. |
+ +----------+-------------------------------------------------------------+
+ | 2 | Operation is blocked for OS by firmware configuration. |
+ +----------+-------------------------------------------------------------+
+ | 3 | Operation is allowed and physically present user required. |
+ +----------+-------------------------------------------------------------+
+ | 4 | Operation is allowed and physically present user is not |
+ | | required. |
+ +----------+-------------------------------------------------------------+
+
+The location of the table is given by the fw_cfg ``tpmppi_address``
+field. The PPI memory region size is 0x400 (``TPM_PPI_ADDR_SIZE``) to
+leave enough room for future updates.
+
+QEMU files related to TPM ACPI tables:
+ - ``hw/i386/acpi-build.c``
+ - ``include/hw/acpi/tpm.h``
+
+TPM backend devices
+===================
+
+The TPM implementation is split into two parts, frontend and
+backend. The frontend part is the hardware interface, such as the TPM
+TIS interface described earlier, and the other part is the TPM backend
+interface. The backend interfaces implement the interaction with a TPM
+device, which may be a physical or an emulated device. The split
+between the front- and backend devices allows a frontend to be
+connected with any available backend. This enables the TIS interface
+to be used with the passthrough backend or the swtpm backend.
+
+QEMU files related to TPM backends:
+ - ``backends/tpm.c``
+ - ``include/sysemu/tpm_backend.h``
+ - ``include/sysemu/tpm_backend_int.h``
+
+The QEMU TPM passthrough device
+-------------------------------
+
+In case QEMU is run on Linux as the host operating system it is
+possible to make the hardware TPM device available to a single QEMU
+guest. In this case the user must make sure that no other program is
+using the device, e.g., /dev/tpm0, before trying to start QEMU with
+it.
+
+The passthrough driver uses the host's TPM device for sending TPM
+commands and receiving responses from. Besides that it accesses the
+TPM device's sysfs entry for support of command cancellation. Since
+none of the state of a hardware TPM can be migrated between hosts,
+virtual machine migration is disabled when the TPM passthrough driver
+is used.
+
+Since the host's TPM device will already be initialized by the host's
+firmware, certain commands, e.g. ``TPM_Startup()``, sent by the
+virtual firmware for device initialization, will fail. In this case
+the firmware should not use the TPM.
+
+Sharing the device with the host is generally not a recommended usage
+scenario for a TPM device. The primary reason for this is that two
+operating systems can then access the device's single set of
+resources, such as platform configuration registers
+(PCRs). Applications or kernel security subsystems, such as the Linux
+Integrity Measurement Architecture (IMA), are not expecting to share
+PCRs.
+
+QEMU files related to the TPM passthrough device:
+ - ``hw/tpm/tpm_passthrough.c``
+ - ``hw/tpm/tpm_util.c``
+ - ``hw/tpm/tpm_util.h``
+
+
+Command line to start QEMU with the TPM passthrough device using the host's
+hardware TPM ``/dev/tpm0``:
+
+.. code-block:: console
+
+ qemu-system-x86_64 -display sdl -accel kvm \
+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
+ -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \
+ -device tpm-tis,tpmdev=tpm0 test.img
+
+
+The following commands should result in similar output inside the VM
+with a Linux kernel that either has the TPM TIS driver built-in or
+available as a module:
+
+.. code-block:: console
+
+ # dmesg | grep -i tpm
+ [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1)
+
+ # dmesg | grep TCPA
+ [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \
+ BXPCTCPA 0000001 BXPC 00000001)
+
+ # ls -l /dev/tpm*
+ crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0
+
+ # find /sys/devices/ | grep pcrs$ | xargs cat
+ PCR-00: 35 4E 3B CE 23 9F 38 59 ...
+ ...
+ PCR-23: 00 00 00 00 00 00 00 00 ...
+
+The QEMU TPM emulator device
+----------------------------
+
+The TPM emulator device uses an external TPM emulator called 'swtpm'
+for sending TPM commands to and receiving responses from. The swtpm
+program must have been started before trying to access it through the
+TPM emulator with QEMU.
+
+The TPM emulator implements a command channel for transferring TPM
+commands and responses as well as a control channel over which control
+commands can be sent. (see the `SWTPM protocol`_ specification)
+
+The control channel serves the purpose of resetting, initializing, and
+migrating the TPM state, among other things.
+
+The swtpm program behaves like a hardware TPM and therefore needs to
+be initialized by the firmware running inside the QEMU virtual
+machine. One necessary step for initializing the device is to send
+the TPM_Startup command to it. SeaBIOS, for example, has been
+instrumented to initialize a TPM 1.2 or TPM 2 device using this
+command.
+
+QEMU files related to the TPM emulator device:
+ - ``hw/tpm/tpm_emulator.c``
+ - ``hw/tpm/tpm_util.c``
+ - ``hw/tpm/tpm_util.h``
+
+The following commands start the swtpm with a UnixIO control channel over
+a socket interface. They do not need to be run as root.
+
+.. code-block:: console
+
+ mkdir /tmp/mytpm1
+ swtpm socket --tpmstate dir=/tmp/mytpm1 \
+ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
+ --log level=20
+
+Command line to start QEMU with the TPM emulator device communicating
+with the swtpm (x86):
+
+.. code-block:: console
+
+ qemu-system-x86_64 -display sdl -accel kvm \
+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
+ -tpmdev emulator,id=tpm0,chardev=chrtpm \
+ -device tpm-tis,tpmdev=tpm0 test.img
+
+In case a pSeries machine is emulated, use the following command line:
+
+.. code-block:: console
+
+ qemu-system-ppc64 -display sdl -machine pseries,accel=kvm \
+ -m 1024 -bios slof.bin -boot menu=on \
+ -nodefaults -device VGA -device pci-ohci -device usb-kbd \
+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
+ -tpmdev emulator,id=tpm0,chardev=chrtpm \
+ -device tpm-spapr,tpmdev=tpm0 \
+ -device spapr-vscsi,id=scsi0,reg=0x00002000 \
+ -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \
+ -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0
+
+In case SeaBIOS is used as firmware, it should show the TPM menu item
+after entering the menu with 'ESC'.
+
+.. code-block:: console
+
+ Select boot device:
+ 1. DVD/CD [ata1-0: QEMU DVD-ROM ATAPI-4 DVD/CD]
+ [...]
+ 5. Legacy option rom
+
+ t. TPM Configuration
+
+The following commands should result in similar output inside the VM
+with a Linux kernel that either has the TPM TIS driver built-in or
+available as a module:
+
+.. code-block:: console
+
+ # dmesg | grep -i tpm
+ [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1)
+
+ # dmesg | grep TCPA
+ [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \
+ BXPCTCPA 0000001 BXPC 00000001)
+
+ # ls -l /dev/tpm*
+ crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0
+
+ # find /sys/devices/ | grep pcrs$ | xargs cat
+ PCR-00: 35 4E 3B CE 23 9F 38 59 ...
+ ...
+ PCR-23: 00 00 00 00 00 00 00 00 ...
+
+Migration with the TPM emulator
+===============================
+
+The TPM emulator supports the following types of virtual machine
+migration:
+
+- VM save / restore (migration into a file)
+- Network migration
+- Snapshotting (migration into storage like QoW2 or QED)
+
+The following command sequences can be used to test VM save / restore.
+
+In a 1st terminal start an instance of a swtpm using the following command:
+
+.. code-block:: console
+
+ mkdir /tmp/mytpm1
+ swtpm socket --tpmstate dir=/tmp/mytpm1 \
+ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
+ --log level=20 --tpm2
+
+In a 2nd terminal start the VM:
+
+.. code-block:: console
+
+ qemu-system-x86_64 -display sdl -accel kvm \
+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
+ -tpmdev emulator,id=tpm0,chardev=chrtpm \
+ -device tpm-tis,tpmdev=tpm0 \
+ -monitor stdio \
+ test.img
+
+Verify that the attached TPM is working as expected using applications
+inside the VM.
+
+To store the state of the VM use the following command in the QEMU
+monitor in the 2nd terminal:
+
+.. code-block:: console
+
+ (qemu) migrate "exec:cat > testvm.bin"
+ (qemu) quit
+
+At this point a file called ``testvm.bin`` should exists and the swtpm
+and QEMU processes should have ended.
+
+To test 'VM restore' you have to start the swtpm with the same
+parameters as before. If previously a TPM 2 [--tpm2] was saved, --tpm2
+must now be passed again on the command line.
+
+In the 1st terminal restart the swtpm with the same command line as
+before:
+
+.. code-block:: console
+
+ swtpm socket --tpmstate dir=/tmp/mytpm1 \
+ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
+ --log level=20 --tpm2
+
+In the 2nd terminal restore the state of the VM using the additional
+'-incoming' option.
+
+.. code-block:: console
+
+ qemu-system-x86_64 -display sdl -accel kvm \
+ -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
+ -tpmdev emulator,id=tpm0,chardev=chrtpm \
+ -device tpm-tis,tpmdev=tpm0 \
+ -incoming "exec:cat < testvm.bin" \
+ test.img
+
+Troubleshooting migration
+-------------------------
+
+There are several reasons why migration may fail. In case of problems,
+please ensure that the command lines adhere to the following rules
+and, if possible, that identical versions of QEMU and swtpm are used
+at all times.
+
+VM save and restore:
+
+ - QEMU command line parameters should be identical apart from the
+ '-incoming' option on VM restore
+
+ - swtpm command line parameters should be identical
+
+VM migration to 'localhost':
+
+ - QEMU command line parameters should be identical apart from the
+ '-incoming' option on the destination side
+
+ - swtpm command line parameters should point to two different
+ directories on the source and destination swtpm (--tpmstate dir=...)
+ (especially if different versions of libtpms were to be used on the
+ same machine).
+
+VM migration across the network:
+
+ - QEMU command line parameters should be identical apart from the
+ '-incoming' option on the destination side
+
+ - swtpm command line parameters should be identical
+
+VM Snapshotting:
+ - QEMU command line parameters should be identical
+
+ - swtpm command line parameters should be identical
+
+
+Besides that, migration failure reasons on the swtpm level may include
+the following:
+
+ - the versions of the swtpm on the source and destination sides are
+ incompatible
+
+ - downgrading of TPM state may not be supported
+
+ - the source and destination libtpms were compiled with different
+ compile-time options and the destination side refuses to accept the
+ state
+
+ - different migration keys are used on the source and destination side
+ and the destination side cannot decrypt the migrated state
+ (swtpm ... --migration-key ... )
+
+
+.. _TIS specification:
+ https://trustedcomputinggroup.org/pc-client-work-group-pc-client-specific-tpm-interface-specification-tis/
+
+.. _CRB specification:
+ https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
+
+
+.. _ACPI specification:
+ https://trustedcomputinggroup.org/tcg-acpi-specification/
+
+.. _PPI specification:
+ https://trustedcomputinggroup.org/resource/tcg-physical-presence-interface-specification/
+
+.. _SWTPM protocol:
+ https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod
diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt
deleted file mode 100644
index 9c3e67d8..00000000
--- a/docs/specs/tpm.txt
+++ /dev/null
@@ -1,445 +0,0 @@
-QEMU TPM Device
-===============
-
-= Guest-side Hardware Interface =
-
-The QEMU TPM emulation implements a TPM TIS hardware interface following the
-Trusted Computing Group's specification "TCG PC Client Specific TPM Interface
-Specification (TIS)", Specification Version 1.3, 21 March 2013. This
-specification, or a later version of it, can be accessed from the following
-URL:
-
-https://trustedcomputinggroup.org/pc-client-work-group-pc-client-specific-tpm-interface-specification-tis/
-
-The TIS interface makes a memory mapped IO region in the area 0xfed40000 -
-0xfed44fff available to the guest operating system.
-
-
-QEMU files related to TPM TIS interface:
- - hw/tpm/tpm_tis.c
- - hw/tpm/tpm_tis.h
-
-
-QEMU also implements a TPM CRB interface following the Trusted Computing
-Group's specification "TCG PC Client Platform TPM Profile (PTP)
-Specification", Family "2.0", Level 00 Revision 01.03 v22, May 22, 2017.
-This specification, or a later version of it, can be accessed from the
-following URL:
-
-https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
-
-The CRB interface makes a memory mapped IO region in the area 0xfed40000 -
-0xfed40fff (1 locality) available to the guest operating system.
-
-QEMU files related to TPM CRB interface:
- - hw/tpm/tpm_crb.c
-
-
-pSeries (ppc64) machines offer a tpm-spapr device model.
-
-QEMU files related to the SPAPR interface:
- - hw/tpm/tpm_spapr.c
-
-= fw_cfg interface =
-
-The bios/firmware may read the "etc/tpm/config" fw_cfg entry for
-configuring the guest appropriately.
-
-The entry of 6 bytes has the following content, in little-endian:
-
- #define TPM_VERSION_UNSPEC 0
- #define TPM_VERSION_1_2 1
- #define TPM_VERSION_2_0 2
-
- #define TPM_PPI_VERSION_NONE 0
- #define TPM_PPI_VERSION_1_30 1
-
- struct FwCfgTPMConfig {
- uint32_t tpmppi_address; /* PPI memory location */
- uint8_t tpm_version; /* TPM version */
- uint8_t tpmppi_version; /* PPI version */
- };
-
-= ACPI Interface =
-
-The TPM device is defined with ACPI ID "PNP0C31". QEMU builds a SSDT and passes
-it into the guest through the fw_cfg device. The device description contains
-the base address of the TIS interface 0xfed40000 and the size of the MMIO area
-(0x5000). In case a TPM2 is used by QEMU, a TPM2 ACPI table is also provided.
-The device is described to be used in polling mode rather than interrupt mode
-primarily because no unused IRQ could be found.
-
-To support measurement logs to be written by the firmware, e.g. SeaBIOS, a TCPA
-table is implemented. This table provides a 64kb buffer where the firmware can
-write its log into. For TPM 2 only a more recent version of the TPM2 table
-provides support for measurements logs and a TCPA table does not need to be
-created.
-
-The TCPA and TPM2 ACPI tables follow the Trusted Computing Group specification
-"TCG ACPI Specification" Family "1.2" and "2.0", Level 00 Revision 00.37. This
-specification, or a later version of it, can be accessed from the following
-URL:
-
-https://trustedcomputinggroup.org/tcg-acpi-specification/
-
-== ACPI PPI Interface ==
-
-QEMU supports the Physical Presence Interface (PPI) for TPM 1.2 and TPM 2. This
-interface requires ACPI and firmware support. The specification can be found at
-the following URL:
-
-https://trustedcomputinggroup.org/resource/tcg-physical-presence-interface-specification/
-
-PPI enables a system administrator (root) to request a modification to the
-TPM upon reboot. The PPI specification defines the operation requests and the
-actions the firmware has to take. The system administrator passes the operation
-request number to the firmware through an ACPI interface which writes this
-number to a memory location that the firmware knows. Upon reboot, the firmware
-finds the number and sends commands to the TPM. The firmware writes the TPM
-result code and the operation request number to a memory location that ACPI can
-read from and pass the result on to the administrator.
-
-The PPI specification defines a set of mandatory and optional operations for
-the firmware to implement. The ACPI interface also allows an administrator to
-list the supported operations. In QEMU the ACPI code is generated by QEMU, yet
-the firmware needs to implement support on a per-operations basis, and
-different firmwares may support a different subset. Therefore, QEMU introduces
-the virtual memory device for PPI where the firmware can indicate which
-operations it supports and ACPI can enable the ones that are supported and
-disable all others. This interface lies in main memory and has the following
-layout:
-
- +----------+--------+--------+-------------------------------------------+
- | Field | Length | Offset | Description |
- +----------+--------+--------+-------------------------------------------+
- | func | 0x100 | 0x000 | Firmware sets values for each supported |
- | | | | operation. See defined values below. |
- +----------+--------+--------+-------------------------------------------+
- | ppin | 0x1 | 0x100 | SMI interrupt to use. Set by firmware. |
- | | | | Not supported. |
- +----------+--------+--------+-------------------------------------------+
- | ppip | 0x4 | 0x101 | ACPI function index to pass to SMM code. |
- | | | | Set by ACPI. Not supported. |
- +----------+--------+--------+-------------------------------------------+
- | pprp | 0x4 | 0x105 | Result of last executed operation. Set by |
- | | | | firmware. See function index 5 for values.|
- +----------+--------+--------+-------------------------------------------+
- | pprq | 0x4 | 0x109 | Operation request number to execute. See |
- | | | | 'Physical Presence Interface Operation |
- | | | | Summary' tables in specs. Set by ACPI. |
- +----------+--------+--------+-------------------------------------------+
- | pprm | 0x4 | 0x10d | Operation request optional parameter. |
- | | | | Values depend on operation. Set by ACPI. |
- +----------+--------+--------+-------------------------------------------+
- | lppr | 0x4 | 0x111 | Last executed operation request number. |
- | | | | Copied from pprq field by firmware. |
- +----------+--------+--------+-------------------------------------------+
- | fret | 0x4 | 0x115 | Result code from SMM function. |
- | | | | Not supported. |
- +----------+--------+--------+-------------------------------------------+
- | res1 | 0x40 | 0x119 | Reserved for future use |
- +----------+--------+--------+-------------------------------------------+
- | next_step| 0x1 | 0x159 | Operation to execute after reboot by |
- | | | | firmware. Used by firmware. |
- +----------+--------+--------+-------------------------------------------+
- | movv | 0x1 | 0x15a | Memory overwrite variable |
- +----------+--------+--------+-------------------------------------------+
-
- The following values are supported for the 'func' field. They correspond
- to the values used by ACPI function index 8.
-
- +----------+-------------------------------------------------------------+
- | value | Description |
- +----------+-------------------------------------------------------------+
- | 0 | Operation is not implemented. |
- +----------+-------------------------------------------------------------+
- | 1 | Operation is only accessible through firmware. |
- +----------+-------------------------------------------------------------+
- | 2 | Operation is blocked for OS by firmware configuration. |
- +----------+-------------------------------------------------------------+
- | 3 | Operation is allowed and physically present user required. |
- +----------+-------------------------------------------------------------+
- | 4 | Operation is allowed and physically present user is not |
- | | required. |
- +----------+-------------------------------------------------------------+
-
-The location of the table is given by the fw_cfg tpmppi_address field.
-The PPI memory region size is 0x400 (TPM_PPI_ADDR_SIZE) to leave
-enough room for future updates.
-
-
-QEMU files related to TPM ACPI tables:
- - hw/i386/acpi-build.c
- - include/hw/acpi/tpm.h
-
-
-= TPM backend devices =
-
-The TPM implementation is split into two parts, frontend and backend. The
-frontend part is the hardware interface, such as the TPM TIS interface
-described earlier, and the other part is the TPM backend interface. The backend
-interfaces implement the interaction with a TPM device, which may be a physical
-or an emulated device. The split between the front- and backend devices allows
-a frontend to be connected with any available backend. This enables the TIS
-interface to be used with the passthrough backend or the (future) swtpm backend.
-
-
-QEMU files related to TPM backends:
- - backends/tpm.c
- - include/sysemu/tpm_backend.h
- - include/sysemu/tpm_backend_int.h
-
-
-== The QEMU TPM passthrough device ==
-
-In case QEMU is run on Linux as the host operating system it is possible to
-make the hardware TPM device available to a single QEMU guest. In this case the
-user must make sure that no other program is using the device, e.g., /dev/tpm0,
-before trying to start QEMU with it.
-
-The passthrough driver uses the host's TPM device for sending TPM commands
-and receiving responses from. Besides that it accesses the TPM device's sysfs
-entry for support of command cancellation. Since none of the state of a
-hardware TPM can be migrated between hosts, virtual machine migration is
-disabled when the TPM passthrough driver is used.
-
-Since the host's TPM device will already be initialized by the host's firmware,
-certain commands, e.g. TPM_Startup(), sent by the virtual firmware for device
-initialization, will fail. In this case the firmware should not use the TPM.
-
-Sharing the device with the host is generally not a recommended usage scenario
-for a TPM device. The primary reason for this is that two operating systems can
-then access the device's single set of resources, such as platform configuration
-registers (PCRs). Applications or kernel security subsystems, such as the
-Linux Integrity Measurement Architecture (IMA), are not expecting to share PCRs.
-
-
-QEMU files related to the TPM passthrough device:
- - hw/tpm/tpm_passthrough.c
- - hw/tpm/tpm_util.c
- - hw/tpm/tpm_util.h
-
-
-Command line to start QEMU with the TPM passthrough device using the host's
-hardware TPM /dev/tpm0:
-
-qemu-system-x86_64 -display sdl -accel kvm \
- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
- -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \
- -device tpm-tis,tpmdev=tpm0 test.img
-
-The following commands should result in similar output inside the VM with a
-Linux kernel that either has the TPM TIS driver built-in or available as a
-module:
-
-#> dmesg | grep -i tpm
-[ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1)
-
-#> dmesg | grep TCPA
-[ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \
- BXPCTCPA 0000001 BXPC 00000001)
-
-#> ls -l /dev/tpm*
-crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0
-
-#> find /sys/devices/ | grep pcrs$ | xargs cat
-PCR-00: 35 4E 3B CE 23 9F 38 59 ...
-...
-PCR-23: 00 00 00 00 00 00 00 00 ...
-
-
-== The QEMU TPM emulator device ==
-
-The TPM emulator device uses an external TPM emulator called 'swtpm' for
-sending TPM commands to and receiving responses from. The swtpm program
-must have been started before trying to access it through the TPM emulator
-with QEMU.
-
-The TPM emulator implements a command channel for transferring TPM commands
-and responses as well as a control channel over which control commands can
-be sent. The specification for the control channel can be found here:
-
-https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod
-
-
-The control channel serves the purpose of resetting, initializing, and
-migrating the TPM state, among other things.
-
-The swtpm program behaves like a hardware TPM and therefore needs to be
-initialized by the firmware running inside the QEMU virtual machine.
-One necessary step for initializing the device is to send the TPM_Startup
-command to it. SeaBIOS, for example, has been instrumented to initialize
-a TPM 1.2 or TPM 2 device using this command.
-
-
-QEMU files related to the TPM emulator device:
- - hw/tpm/tpm_emulator.c
- - hw/tpm/tpm_util.c
- - hw/tpm/tpm_util.h
-
-
-The following commands start the swtpm with a UnixIO control channel over
-a socket interface. They do not need to be run as root.
-
-mkdir /tmp/mytpm1
-swtpm socket --tpmstate dir=/tmp/mytpm1 \
- --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
- --log level=20
-
-Command line to start QEMU with the TPM emulator device communicating with
-the swtpm (x86):
-
-qemu-system-x86_64 -display sdl -accel kvm \
- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
- -tpmdev emulator,id=tpm0,chardev=chrtpm \
- -device tpm-tis,tpmdev=tpm0 test.img
-
-In case a pSeries machine is emulated, use the following command line:
-
-qemu-system-ppc64 -display sdl -machine pseries,accel=kvm \
- -m 1024 -bios slof.bin -boot menu=on \
- -nodefaults -device VGA -device pci-ohci -device usb-kbd \
- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
- -tpmdev emulator,id=tpm0,chardev=chrtpm \
- -device tpm-spapr,tpmdev=tpm0 \
- -device spapr-vscsi,id=scsi0,reg=0x00002000 \
- -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \
- -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0
-
-
-In case SeaBIOS is used as firmware, it should show the TPM menu item
-after entering the menu with 'ESC'.
-
-Select boot device:
-1. DVD/CD [ata1-0: QEMU DVD-ROM ATAPI-4 DVD/CD]
-[...]
-5. Legacy option rom
-
-t. TPM Configuration
-
-
-The following commands should result in similar output inside the VM with a
-Linux kernel that either has the TPM TIS driver built-in or available as a
-module:
-
-#> dmesg | grep -i tpm
-[ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1)
-
-#> dmesg | grep TCPA
-[ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \
- BXPCTCPA 0000001 BXPC 00000001)
-
-#> ls -l /dev/tpm*
-crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0
-
-#> find /sys/devices/ | grep pcrs$ | xargs cat
-PCR-00: 35 4E 3B CE 23 9F 38 59 ...
-...
-PCR-23: 00 00 00 00 00 00 00 00 ...
-
-
-=== Migration with the TPM emulator ===
-
-The TPM emulator supports the following types of virtual machine migration:
-
-- VM save / restore (migration into a file)
-- Network migration
-- Snapshotting (migration into storage like QoW2 or QED)
-
-The following command sequences can be used to test VM save / restore.
-
-
-In a 1st terminal start an instance of a swtpm using the following command:
-
-mkdir /tmp/mytpm1
-swtpm socket --tpmstate dir=/tmp/mytpm1 \
- --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
- --log level=20 --tpm2
-
-In a 2nd terminal start the VM:
-
-qemu-system-x86_64 -display sdl -accel kvm \
- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
- -tpmdev emulator,id=tpm0,chardev=chrtpm \
- -device tpm-tis,tpmdev=tpm0 \
- -monitor stdio \
- test.img
-
-Verify that the attached TPM is working as expected using applications inside
-the VM.
-
-To store the state of the VM use the following command in the QEMU monitor in
-the 2nd terminal:
-
-(qemu) migrate "exec:cat > testvm.bin"
-(qemu) quit
-
-At this point a file called 'testvm.bin' should exists and the swtpm and QEMU
-processes should have ended.
-
-To test 'VM restore' you have to start the swtpm with the same parameters
-as before. If previously a TPM 2 [--tpm2] was saved, --tpm2 must now be
-passed again on the command line.
-
-In the 1st terminal restart the swtpm with the same command line as before:
-
-swtpm socket --tpmstate dir=/tmp/mytpm1 \
- --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \
- --log level=20 --tpm2
-
-In the 2nd terminal restore the state of the VM using the additional
-'-incoming' option.
-
-qemu-system-x86_64 -display sdl -accel kvm \
- -m 1024 -boot d -bios bios-256k.bin -boot menu=on \
- -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
- -tpmdev emulator,id=tpm0,chardev=chrtpm \
- -device tpm-tis,tpmdev=tpm0 \
- -incoming "exec:cat < testvm.bin" \
- test.img
-
-
-Troubleshooting migration:
-
-There are several reasons why migration may fail. In case of problems,
-please ensure that the command lines adhere to the following rules and,
-if possible, that identical versions of QEMU and swtpm are used at all
-times.
-
-VM save and restore:
- - QEMU command line parameters should be identical apart from the
- '-incoming' option on VM restore
- - swtpm command line parameters should be identical
-
-VM migration to 'localhost':
- - QEMU command line parameters should be identical apart from the
- '-incoming' option on the destination side
- - swtpm command line parameters should point to two different
- directories on the source and destination swtpm (--tpmstate dir=...)
- (especially if different versions of libtpms were to be used on the
- same machine).
-
-VM migration across the network:
- - QEMU command line parameters should be identical apart from the
- '-incoming' option on the destination side
- - swtpm command line parameters should be identical
-
-VM Snapshotting:
- - QEMU command line parameters should be identical
- - swtpm command line parameters should be identical
-
-
-Besides that, migration failure reasons on the swtpm level may include
-the following:
-
- - the versions of the swtpm on the source and destination sides are
- incompatible
- - downgrading of TPM state may not be supported
- - the source and destination libtpms were compiled with different
- compile-time options and the destination side refuses to accept the
- state
- - different migration keys are used on the source and destination side
- and the destination side cannot decrypt the migrated state
- (swtpm ... --migration-key ... )
--
2.23.0

View File

@ -0,0 +1,141 @@
From 443ebab9c299b04f020a6873454facb078723141 Mon Sep 17 00:00:00 2001
From: jiangfangjie <jiangfangjie@huawei.com>
Date: Thu, 13 Aug 2020 20:01:10 +0800
Subject: [PATCH 15/19] hw/arm/virt: vTPM support
Let the TPM TIS SYSBUS device be dynamically instantiable
in ARM virt. A device tree node is dynamically created
(TPM via MMIO).
The TPM Physical Presence interface (PPI) is not supported.
To run with the swtmp TPM emulator, the qemu command line must
be augmented with:
-chardev socket,id=chrtpm,path=swtpm-sock
-tpmdev emulator,id=tpm0,chardev=chrtpm
-device tpm-tis-device,tpmdev=tpm0
swtpm/libtpms command line example:
swtpm socket --tpm2 -t -d --tpmstate dir=/tmp/tpm
--ctrl type=unixio,path=swtpm-sock
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Message-id: 20200305165149.618-7-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/arm/Kconfig | 1 +
hw/arm/sysbus-fdt.c | 33 +++++++++++++++++++++++++++++++++
hw/arm/virt.c | 7 +++++++
3 files changed, 41 insertions(+)
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 15e18b0a..06e49f26 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -5,6 +5,7 @@ config ARM_VIRT
imply VFIO_AMD_XGBE
imply VFIO_PLATFORM
imply VFIO_XGMAC
+ imply TPM_TIS_SYSBUS
select A15MPCORE
select ACPI
select ARM_SMMUV3
diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
index 57f94e65..c725d325 100644
--- a/hw/arm/sysbus-fdt.c
+++ b/hw/arm/sysbus-fdt.c
@@ -30,6 +30,7 @@
#include "hw/arm/sysbus-fdt.h"
#include "qemu/error-report.h"
#include "sysemu/device_tree.h"
+#include "sysemu/tpm.h"
#include "hw/platform-bus.h"
#include "sysemu/sysemu.h"
#include "hw/vfio/vfio-platform.h"
@@ -437,6 +438,37 @@ static bool vfio_platform_match(SysBusDevice *sbdev,
#endif /* CONFIG_LINUX */
+/*
+ * add_tpm_tis_fdt_node: Create a DT node for TPM TIS
+ *
+ * See kernel documentation:
+ * Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt
+ * Optional interrupt for command completion is not exposed
+ */
+static int add_tpm_tis_fdt_node(SysBusDevice *sbdev, void *opaque)
+{
+ PlatformBusFDTData *data = opaque;
+ PlatformBusDevice *pbus = data->pbus;
+ void *fdt = data->fdt;
+ const char *parent_node = data->pbus_node_name;
+ char *nodename;
+ uint32_t reg_attr[2];
+ uint64_t mmio_base;
+
+ mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+ nodename = g_strdup_printf("%s/tpm_tis@%" PRIx64, parent_node, mmio_base);
+ qemu_fdt_add_subnode(fdt, nodename);
+
+ qemu_fdt_setprop_string(fdt, nodename, "compatible", "tcg,tpm-tis-mmio");
+
+ reg_attr[0] = cpu_to_be32(mmio_base);
+ reg_attr[1] = cpu_to_be32(0x5000);
+ qemu_fdt_setprop(fdt, nodename, "reg", reg_attr, 2 * sizeof(uint32_t));
+
+ g_free(nodename);
+ return 0;
+}
+
static int no_fdt_node(SysBusDevice *sbdev, void *opaque)
{
return 0;
@@ -457,6 +489,7 @@ static const BindingEntry bindings[] = {
TYPE_BINDING(TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node),
VFIO_PLATFORM_BINDING("amd,xgbe-seattle-v1a", add_amd_xgbe_fdt_node),
#endif
+ TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node),
TYPE_BINDING("", NULL), /* last element */
};
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 133d36a4..7afc6c5e 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -47,6 +47,7 @@
#include "sysemu/numa.h"
#include "sysemu/cpus.h"
#include "sysemu/sysemu.h"
+#include "sysemu/tpm.h"
#include "sysemu/kvm.h"
#include "sysemu/cpus.h"
#include "sysemu/hw_accel.h"
@@ -2368,6 +2369,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
+ machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
mc->block_default_type = IF_VIRTIO;
mc->no_cdrom = 1;
mc->pci_allow_0_address = true;
@@ -2481,6 +2483,11 @@ type_init(machvirt_machine_init);
static void virt_machine_4_1_options(MachineClass *mc)
{
+ static GlobalProperty compat[] = {
+ { TYPE_TPM_TIS_SYSBUS, "ppi", "false" },
+ };
+
+ compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat));
}
DEFINE_VIRT_MACHINE_AS_LATEST(4, 1)
--
2.23.0

View File

@ -0,0 +1,36 @@
From 95cbe18c649a20f98562a993537a67e0ad78bf36 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Tue, 21 Jan 2020 10:29:34 -0500
Subject: [PATCH 08/19] hw/ppc/Kconfig: Enable TPM_SPAPR as part of PSERIES
config
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200121152935.649898-6-stefanb@linux.ibm.com>
[dwg: Use default in Kconfig rather than select to avoid breaking
Windows host build]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/tpm/Kconfig | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index 4d4ab085..9e67d990 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -25,6 +25,6 @@ config TPM_EMULATOR
config TPM_SPAPR
bool
- default n
+ default y
depends on TPM && PSERIES
select TPMDEV
--
2.23.0

View File

@ -0,0 +1,58 @@
From f2dceb3cde537210896a2cadb8958cfd310113a3 Mon Sep 17 00:00:00 2001
From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Date: Thu, 5 Dec 2019 20:46:30 +0300
Subject: [PATCH 01/19] hw/tpm: rename Error ** parameter to more common errp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Message-Id: <20191205174635.18758-17-vsementsov@virtuozzo.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/tpm/tpm_emulator.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c
index fc0b512f..38bf5fd6 100644
--- a/hw/tpm/tpm_emulator.c
+++ b/hw/tpm/tpm_emulator.c
@@ -155,7 +155,7 @@ static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
const uint8_t *in, uint32_t in_len,
uint8_t *out, uint32_t out_len,
bool *selftest_done,
- Error **err)
+ Error **errp)
{
ssize_t ret;
bool is_selftest = false;
@@ -165,20 +165,20 @@ static int tpm_emulator_unix_tx_bufs(TPMEmulator *tpm_emu,
is_selftest = tpm_util_is_selftest(in, in_len);
}
- ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, err);
+ ret = qio_channel_write_all(tpm_emu->data_ioc, (char *)in, in_len, errp);
if (ret != 0) {
return -1;
}
ret = qio_channel_read_all(tpm_emu->data_ioc, (char *)out,
- sizeof(struct tpm_resp_hdr), err);
+ sizeof(struct tpm_resp_hdr), errp);
if (ret != 0) {
return -1;
}
ret = qio_channel_read_all(tpm_emu->data_ioc,
(char *)out + sizeof(struct tpm_resp_hdr),
- tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), err);
+ tpm_cmd_get_size(out) - sizeof(struct tpm_resp_hdr), errp);
if (ret != 0) {
return -1;
}
--
2.23.0

View File

@ -1,6 +1,6 @@
Name: qemu Name: qemu
Version: 4.1.0 Version: 4.1.0
Release: 17 Release: 18
Epoch: 2 Epoch: 2
Summary: QEMU is a generic and open source machine emulator and virtualizer Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY License: GPLv2 and BSD and MIT and CC-BY
@ -184,6 +184,25 @@ Patch0171: megasas-avoid-NULL-pointer-dereference.patch
Patch0172: megasas-use-unsigned-type-for-positive-numeric-field.patch Patch0172: megasas-use-unsigned-type-for-positive-numeric-field.patch
Patch0173: hw-scsi-megasas-Fix-possible-out-of-bounds-array-acc.patch Patch0173: hw-scsi-megasas-Fix-possible-out-of-bounds-array-acc.patch
Patch0174: hw-arm-acpi-enable-SHPC-native-hot-plug.patch Patch0174: hw-arm-acpi-enable-SHPC-native-hot-plug.patch
Patch0175: hw-tpm-rename-Error-parameter-to-more-common-errp.patch
Patch0176: tpm-ppi-page-align-PPI-RAM.patch
Patch0177: tpm-Move-tpm_tis_show_buffer-to-tpm_util.c.patch
Patch0178: spapr-Implement-get_dt_compatible-callback.patch
Patch0179: delete-the-in-tpm.txt.patch
Patch0180: tpm_spapr-Support-TPM-for-ppc64-using-CRQ-based-inte.patch
Patch0181: tpm_spapr-Support-suspend-and-resume.patch
Patch0182: hw-ppc-Kconfig-Enable-TPM_SPAPR-as-part-of-PSERIES-c.patch
Patch0183: docs-specs-tpm-reST-ify-TPM-documentation.patch
Patch0184: tpm-rename-TPM_TIS-into-TPM_TIS_ISA.patch
Patch0185: tpm-Use-TPMState-as-a-common-struct.patch
Patch0186: tpm-Separate-tpm_tis-common-functions-from-isa-code.patch
Patch0187: tpm-Separate-TPM_TIS-and-TPM_TIS_ISA-configs.patch
Patch0188: tpm-Add-the-SysBus-TPM-TIS-device.patch
Patch0189: hw-arm-virt-vTPM-support.patch
Patch0190: docs-specs-tpm-Document-TPM_TIS-sysbus-device-for-AR.patch
Patch0191: test-tpm-pass-optional-machine-options-to-swtpm-test.patch
Patch0192: test-tpm-tis-Get-prepared-to-share-tests-between-ISA.patch
Patch0193: test-tpm-tis-Add-Sysbus-TPM-TIS-device-test.patch
BuildRequires: flex BuildRequires: flex
BuildRequires: bison BuildRequires: bison
@ -326,6 +345,7 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id"
--enable-linux-aio \ --enable-linux-aio \
--enable-cap-ng \ --enable-cap-ng \
--enable-vhost-user \ --enable-vhost-user \
--enable-tpm \
%ifarch aarch64 %ifarch aarch64
--enable-fdt \ --enable-fdt \
--enable-virglrenderer \ --enable-virglrenderer \
@ -529,6 +549,9 @@ getent passwd qemu >/dev/null || \
%endif %endif
%changelog %changelog
* Wed Aug 13 2020 Huawei Technologies Co., Ltd <jiangfangjie@huawei.com>
-target/arm: Aarch64 support vtpm
* Wed Aug 12 2020 Huawei Technologies Co., Ltd <jinzeyu@huawei.com> * Wed Aug 12 2020 Huawei Technologies Co., Ltd <jinzeyu@huawei.com>
- backport upstream patch to support SHPCHotplug in arm - backport upstream patch to support SHPCHotplug in arm

View File

@ -0,0 +1,68 @@
From c520d8e823431be94268daa2a911e224cab81521 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Tue, 21 Jan 2020 10:29:31 -0500
Subject: [PATCH 04/19] spapr: Implement get_dt_compatible() callback
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
For devices that cannot be statically initialized, implement a
get_dt_compatible() callback that allows us to ask the device for
the 'compatible' value.
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200121152935.649898-3-stefanb@linux.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/ppc/spapr_vio.c | 11 +++++++++--
include/hw/ppc/spapr_vio.h | 1 +
2 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c
index 583c13de..4e50916f 100644
--- a/hw/ppc/spapr_vio.c
+++ b/hw/ppc/spapr_vio.c
@@ -89,6 +89,7 @@ static int vio_make_devnode(SpaprVioDevice *dev,
SpaprVioDeviceClass *pc = VIO_SPAPR_DEVICE_GET_CLASS(dev);
int vdevice_off, node_off, ret;
char *dt_name;
+ const char *dt_compatible;
vdevice_off = fdt_path_offset(fdt, "/vdevice");
if (vdevice_off < 0) {
@@ -115,9 +116,15 @@ static int vio_make_devnode(SpaprVioDevice *dev,
}
}
- if (pc->dt_compatible) {
+ if (pc->get_dt_compatible) {
+ dt_compatible = pc->get_dt_compatible(dev);
+ } else {
+ dt_compatible = pc->dt_compatible;
+ }
+
+ if (dt_compatible) {
ret = fdt_setprop_string(fdt, node_off, "compatible",
- pc->dt_compatible);
+ dt_compatible);
if (ret < 0) {
return ret;
}
diff --git a/include/hw/ppc/spapr_vio.h b/include/hw/ppc/spapr_vio.h
index 04609f21..97951fc6 100644
--- a/include/hw/ppc/spapr_vio.h
+++ b/include/hw/ppc/spapr_vio.h
@@ -56,6 +56,7 @@ typedef struct SpaprVioDeviceClass {
void (*realize)(SpaprVioDevice *dev, Error **errp);
void (*reset)(SpaprVioDevice *dev);
int (*devnode)(SpaprVioDevice *dev, void *fdt, int node_off);
+ const char *(*get_dt_compatible)(SpaprVioDevice *dev);
} SpaprVioDeviceClass;
struct SpaprVioDevice {
--
2.23.0

View File

@ -0,0 +1,187 @@
From c06a3ceacc1793bc1cfe5c2a6ed510c9aea8253d Mon Sep 17 00:00:00 2001
From: jiangfangjie <jiangfangjie@huawei.com>
Date: Thu, 13 Aug 2020 20:28:25 +0800
Subject: [PATCH 17/19] test: tpm: pass optional machine options to swtpm test
functions
We plan to use swtpm test functions on ARM for testing the
sysbus TPM-TIS device. However on ARM there is no default machine
type. So we need to explictly pass some machine options on startup.
Let's allow this by adding a new parameter to both swtpm test
functions and update all call sites.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Message-id: 20200305165149.618-9-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
tests/tpm-crb-swtpm-test.c | 5 +++--
tests/tpm-tests.c | 10 ++++++----
tests/tpm-tests.h | 5 +++--
tests/tpm-tis-swtpm-test.c | 5 +++--
tests/tpm-util.c | 8 ++++++--
tests/tpm-util.h | 3 ++-
6 files changed, 23 insertions(+), 13 deletions(-)
diff --git a/tests/tpm-crb-swtpm-test.c b/tests/tpm-crb-swtpm-test.c
index 2c4fb8ae..5228cb7a 100644
--- a/tests/tpm-crb-swtpm-test.c
+++ b/tests/tpm-crb-swtpm-test.c
@@ -29,7 +29,8 @@ 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");
+ tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer,
+ "tpm-crb", NULL);
}
static void tpm_crb_swtpm_migration_test(const void *data)
@@ -37,7 +38,7 @@ 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");
+ tpm_util_crb_transfer, "tpm-crb", NULL);
}
int main(int argc, char **argv)
diff --git a/tests/tpm-tests.c b/tests/tpm-tests.c
index e640777a..d823bda8 100644
--- a/tests/tpm-tests.c
+++ b/tests/tpm-tests.c
@@ -30,7 +30,7 @@ tpm_test_swtpm_skip(void)
}
void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx,
- const char *ifmodel)
+ const char *ifmodel, const char *machine_options)
{
char *args = NULL;
QTestState *s;
@@ -47,10 +47,11 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx,
g_assert_true(succ);
args = g_strdup_printf(
+ "%s "
"-chardev socket,id=chr,path=%s "
"-tpmdev emulator,id=dev,chardev=chr "
"-device %s,tpmdev=dev",
- addr->u.q_unix.path, ifmodel);
+ machine_options ? : "", addr->u.q_unix.path, ifmodel);
s = qtest_start(args);
g_free(args);
@@ -78,7 +79,8 @@ void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx,
void tpm_test_swtpm_migration_test(const char *src_tpm_path,
const char *dst_tpm_path,
const char *uri, tx_func *tx,
- const char *ifmodel)
+ const char *ifmodel,
+ const char *machine_options)
{
gboolean succ;
GPid src_tpm_pid, dst_tpm_pid;
@@ -100,7 +102,7 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
tpm_util_migration_start_qemu(&src_qemu, &dst_qemu,
src_tpm_addr, dst_tpm_addr, uri,
- ifmodel);
+ ifmodel, machine_options);
tpm_util_startup(src_qemu, tx);
tpm_util_pcrextend(src_qemu, tx);
diff --git a/tests/tpm-tests.h b/tests/tpm-tests.h
index b97688fe..a5df35ab 100644
--- a/tests/tpm-tests.h
+++ b/tests/tpm-tests.h
@@ -16,11 +16,12 @@
#include "tpm-util.h"
void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx,
- const char *ifmodel);
+ const char *ifmodel, const char *machine_options);
void tpm_test_swtpm_migration_test(const char *src_tpm_path,
const char *dst_tpm_path,
const char *uri, tx_func *tx,
- const char *ifmodel);
+ const char *ifmodel,
+ const char *machine_options);
#endif /* TESTS_TPM_TESTS_H */
diff --git a/tests/tpm-tis-swtpm-test.c b/tests/tpm-tis-swtpm-test.c
index 9f58a3a9..9470f157 100644
--- a/tests/tpm-tis-swtpm-test.c
+++ b/tests/tpm-tis-swtpm-test.c
@@ -29,7 +29,8 @@ static void tpm_tis_swtpm_test(const void *data)
{
const TestState *ts = data;
- tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, "tpm-tis");
+ tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer,
+ "tpm-tis", NULL);
}
static void tpm_tis_swtpm_migration_test(const void *data)
@@ -37,7 +38,7 @@ static void tpm_tis_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_tis_transfer, "tpm-tis");
+ tpm_util_tis_transfer, "tpm-tis", NULL);
}
int main(int argc, char **argv)
diff --git a/tests/tpm-util.c b/tests/tpm-util.c
index e08b1376..7ecdae2f 100644
--- a/tests/tpm-util.c
+++ b/tests/tpm-util.c
@@ -258,23 +258,27 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu,
SocketAddress *src_tpm_addr,
SocketAddress *dst_tpm_addr,
const char *miguri,
- const char *ifmodel)
+ const char *ifmodel,
+ const char *machine_options)
{
char *src_qemu_args, *dst_qemu_args;
src_qemu_args = g_strdup_printf(
+ "%s "
"-chardev socket,id=chr,path=%s "
"-tpmdev emulator,id=dev,chardev=chr "
"-device %s,tpmdev=dev ",
- src_tpm_addr->u.q_unix.path, ifmodel);
+ machine_options ? : "", src_tpm_addr->u.q_unix.path, ifmodel);
*src_qemu = qtest_init(src_qemu_args);
dst_qemu_args = g_strdup_printf(
+ "%s "
"-chardev socket,id=chr,path=%s "
"-tpmdev emulator,id=dev,chardev=chr "
"-device %s,tpmdev=dev "
"-incoming %s",
+ machine_options ? : "",
dst_tpm_addr->u.q_unix.path,
ifmodel, miguri);
diff --git a/tests/tpm-util.h b/tests/tpm-util.h
index 5755698a..15e39249 100644
--- a/tests/tpm-util.h
+++ b/tests/tpm-util.h
@@ -44,7 +44,8 @@ void tpm_util_migration_start_qemu(QTestState **src_qemu,
SocketAddress *src_tpm_addr,
SocketAddress *dst_tpm_addr,
const char *miguri,
- const char *ifmodel);
+ const char *ifmodel,
+ const char *machine_options);
void tpm_util_wait_for_migration_complete(QTestState *who);
--
2.23.0

View File

@ -0,0 +1,226 @@
From 2d28c0edddeaee5e4aa6e8c6b109776cddc1c4e4 Mon Sep 17 00:00:00 2001
From: jiangfangjie <jiangfangjie@huawei.com>
Date: Thu, 13 Aug 2020 21:37:23 +0800
Subject: [PATCH 19/19] test: tpm-tis: Add Sysbus TPM-TIS device test
The tests themselves are the same as the ISA device ones.
Only the main() changes as the tpm-tis-device device gets
instantiated. Also the base address of the device is not
0xFED40000 anymore but matches the base address of the
ARM virt platform bus.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Message-id: 20200305165149.618-11-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
tests/Makefile.include | 5 ++
tests/tpm-tis-device-swtpm-test.c | 76 +++++++++++++++++++++++++++
tests/tpm-tis-device-test.c | 87 +++++++++++++++++++++++++++++++
3 files changed, 168 insertions(+)
create mode 100644 tests/tpm-tis-device-swtpm-test.c
create mode 100644 tests/tpm-tis-device-test.c
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 950b32a2..d6de4e10 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -263,6 +263,8 @@ check-qtest-arm-y += tests/boot-serial-test$(EXESUF)
check-qtest-arm-y += tests/hexloader-test$(EXESUF)
check-qtest-arm-$(CONFIG_PFLASH_CFI02) += tests/pflash-cfi02-test$(EXESUF)
+check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-test
+check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-swtpm-test
check-qtest-aarch64-y = tests/numa-test$(EXESUF)
check-qtest-aarch64-y += tests/boot-serial-test$(EXESUF)
check-qtest-aarch64-y += tests/migration-test$(EXESUF)
@@ -667,7 +669,10 @@ tests/tpm-crb-swtpm-test$(EXESUF): tests/tpm-crb-swtpm-test.o tests/tpm-emu.o \
tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o tests/tpm-emu.o $(test-io-obj-y)
tests/tpm-tis-swtpm-test$(EXESUF): tests/tpm-tis-swtpm-test.o tests/tpm-emu.o \
tests/tpm-util.o tests/tpm-tests.o $(test-io-obj-y)
+tests/tpm-tis-device-swtpm-test$(EXESUF): tests/tpm-tis-device-swtpm-test.o tests/tpm-emu.o \
+ tests/tpm-util.o tests/tpm-tests.o $(test-io-obj-y)
tests/tpm-tis-test$(EXESUF): tests/tpm-tis-test.o tests/tpm-tis-util.o tests/tpm-emu.o $(test-io-obj-y)
+tests/tpm-tis-device-test$(EXESUF): tests/tpm-tis-device-test.o tests/tpm-tis-util.o tests/tpm-emu.o $(test-io-obj-y)
tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \
tests/io-channel-helpers.o $(test-io-obj-y)
tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \
diff --git a/tests/tpm-tis-device-swtpm-test.c b/tests/tpm-tis-device-swtpm-test.c
new file mode 100644
index 00000000..7b200351
--- /dev/null
+++ b/tests/tpm-tis-device-swtpm-test.c
@@ -0,0 +1,76 @@
+/*
+ * QTest testcase for Sysbus TPM TIS 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 <stefanb@linux.vnet.ibm.com>
+ *
+ * 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 <glib/gstdio.h>
+
+#include "libqtest.h"
+#include "qemu/module.h"
+#include "tpm-tests.h"
+#include "hw/acpi/tpm.h"
+
+uint64_t tpm_tis_base_addr = 0xc000000;
+#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_tis_swtpm_test(const void *data)
+{
+ const TestState *ts = data;
+
+ tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer,
+ "tpm-tis-device", MACHINE_OPTIONS);
+}
+
+static void tpm_tis_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_tis_transfer, "tpm-tis-device",
+ MACHINE_OPTIONS);
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+ TestState ts = { 0 };
+
+ ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX",
+ NULL);
+ ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX",
+ NULL);
+ ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path);
+
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+
+ qtest_add_data_func("/tpm/tis-swtpm/test", &ts, tpm_tis_swtpm_test);
+ qtest_add_data_func("/tpm/tis-swtpm-migration/test", &ts,
+ tpm_tis_swtpm_migration_test);
+ ret = g_test_run();
+
+ g_rmdir(ts.dst_tpm_path);
+ g_free(ts.dst_tpm_path);
+ g_rmdir(ts.src_tpm_path);
+ g_free(ts.src_tpm_path);
+ g_free(ts.uri);
+
+ return ret;
+}
diff --git a/tests/tpm-tis-device-test.c b/tests/tpm-tis-device-test.c
new file mode 100644
index 00000000..63ed3644
--- /dev/null
+++ b/tests/tpm-tis-device-test.c
@@ -0,0 +1,87 @@
+/*
+ * QTest testcase for SYSBUS TPM TIS
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ * Copyright (c) 2018 IBM Corporation
+ *
+ * Authors:
+ * Marc-André Lureau <marcandre.lureau@redhat.com>
+ * Stefan Berger <stefanb@linux.vnet.ibm.com>
+ *
+ * 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 <glib/gstdio.h>
+
+#include "io/channel-socket.h"
+#include "libqtest-single.h"
+#include "qemu/module.h"
+#include "tpm-emu.h"
+#include "tpm-util.h"
+#include "tpm-tis-util.h"
+
+/*
+ * As the Sysbus tpm-tis-device is instantiated on the ARM virt
+ * platform bus and it is the only sysbus device dynamically
+ * instantiated, it gets plugged at its base address
+ */
+uint64_t tpm_tis_base_addr = 0xc000000;
+
+int main(int argc, char **argv)
+{
+ char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-device-test.XXXXXX", NULL);
+ GThread *thread;
+ TestState test;
+ char *args;
+ int ret;
+
+ module_call_init(MODULE_INIT_QOM);
+ g_test_init(&argc, &argv, NULL);
+
+ test.addr = g_new0(SocketAddress, 1);
+ test.addr->type = SOCKET_ADDRESS_TYPE_UNIX;
+ test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL);
+ g_mutex_init(&test.data_mutex);
+ g_cond_init(&test.data_cond);
+ test.data_cond_signal = false;
+
+ thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
+ tpm_emu_test_wait_cond(&test);
+
+ args = g_strdup_printf(
+ "-machine virt,gic-version=max -accel tcg "
+ "-chardev socket,id=chr,path=%s "
+ "-tpmdev emulator,id=dev,chardev=chr "
+ "-device tpm-tis-device,tpmdev=dev",
+ test.addr->u.q_unix.path);
+ qtest_start(args);
+
+ qtest_add_data_func("/tpm-tis/test_check_localities", &test,
+ tpm_tis_test_check_localities);
+
+ qtest_add_data_func("/tpm-tis/test_check_access_reg", &test,
+ tpm_tis_test_check_access_reg);
+
+ qtest_add_data_func("/tpm-tis/test_check_access_reg_seize", &test,
+ tpm_tis_test_check_access_reg_seize);
+
+ qtest_add_data_func("/tpm-tis/test_check_access_reg_release", &test,
+ tpm_tis_test_check_access_reg_release);
+
+ qtest_add_data_func("/tpm-tis/test_check_transmit", &test,
+ tpm_tis_test_check_transmit);
+
+ ret = g_test_run();
+
+ qtest_end();
+
+ g_thread_join(thread);
+ g_unlink(test.addr->u.q_unix.path);
+ qapi_free_SocketAddress(test.addr);
+ g_rmdir(tmp_path);
+ g_free(tmp_path);
+ g_free(args);
+ return ret;
+}
--
2.23.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,231 @@
From 4fe655326eeae322b621dcc25c53af722d2e1afa Mon Sep 17 00:00:00 2001
From: jiangfangjie <jiangfangjie@huawei.com>
Date: Tue, 11 Aug 2020 11:23:34 +0800
Subject: [PATCH 14/19] tpm: Add the SysBus TPM TIS device
Introduce the tpm-tis-device which is a sysbus device
and is bound to be used on ARM.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Message-id: 20200305165149.618-6-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/tpm/Kconfig | 5 ++
hw/tpm/Makefile.objs | 1 +
hw/tpm/tpm_tis_sysbus.c | 159 ++++++++++++++++++++++++++++++++++++++++
include/sysemu/tpm.h | 1 +
4 files changed, 166 insertions(+)
create mode 100644 hw/tpm/tpm_tis_sysbus.c
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index 686f8206..4794e7fe 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -7,6 +7,11 @@ config TPM_TIS_ISA
depends on TPM && ISA_BUS
select TPM_TIS
+config TPM_TIS_SYSBUS
+ bool
+ depends on TPM
+ select TPM_TIS
+
config TPM_TIS
bool
depends on TPM
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index 3ef2036c..f1ec4beb 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -1,6 +1,7 @@
common-obj-$(CONFIG_TPM) += tpm_util.o
obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o
common-obj-$(CONFIG_TPM_TIS_ISA) += tpm_tis_isa.o
+common-obj-$(CONFIG_TPM_TIS_SYSBUS) += tpm_tis_sysbus.o
common-obj-$(CONFIG_TPM_TIS) += tpm_tis_common.o
common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
diff --git a/hw/tpm/tpm_tis_sysbus.c b/hw/tpm/tpm_tis_sysbus.c
new file mode 100644
index 00000000..18c02aed
--- /dev/null
+++ b/hw/tpm/tpm_tis_sysbus.c
@@ -0,0 +1,159 @@
+/*
+ * tpm_tis_sysbus.c - QEMU's TPM TIS SYSBUS Device
+ *
+ * Copyright (C) 2006,2010-2013 IBM Corporation
+ *
+ * Authors:
+ * Stefan Berger <stefanb@us.ibm.com>
+ * David Safford <safford@us.ibm.com>
+ *
+ * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Implementation of the TIS interface according to specs found at
+ * http://www.trustedcomputinggroup.org. This implementation currently
+ * supports version 1.3, 21 March 2013
+ * In the developers menu choose the PC Client section then find the TIS
+ * specification.
+ *
+ * TPM TIS for TPM 2 implementation following TCG PC Client Platform
+ * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43
+ */
+
+#include "qemu/osdep.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+#include "tpm_util.h"
+#include "hw/sysbus.h"
+#include "tpm_tis.h"
+
+typedef struct TPMStateSysBus {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ TPMState state; /* not a QOM object */
+} TPMStateSysBus;
+
+#define TPM_TIS_SYSBUS(obj) OBJECT_CHECK(TPMStateSysBus, (obj), TYPE_TPM_TIS_SYSBUS)
+
+static int tpm_tis_pre_save_sysbus(void *opaque)
+{
+ TPMStateSysBus *sbdev = opaque;
+
+ return tpm_tis_pre_save(&sbdev->state);
+}
+
+static const VMStateDescription vmstate_tpm_tis_sysbus = {
+ .name = "tpm-tis",
+ .version_id = 0,
+ .pre_save = tpm_tis_pre_save_sysbus,
+ .fields = (VMStateField[]) {
+ VMSTATE_BUFFER(state.buffer, TPMStateSysBus),
+ VMSTATE_UINT16(state.rw_offset, TPMStateSysBus),
+ VMSTATE_UINT8(state.active_locty, TPMStateSysBus),
+ VMSTATE_UINT8(state.aborting_locty, TPMStateSysBus),
+ VMSTATE_UINT8(state.next_locty, TPMStateSysBus),
+
+ VMSTATE_STRUCT_ARRAY(state.loc, TPMStateSysBus, TPM_TIS_NUM_LOCALITIES,
+ 0, vmstate_locty, TPMLocality),
+
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void tpm_tis_sysbus_request_completed(TPMIf *ti, int ret)
+{
+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(ti);
+ TPMState *s = &sbdev->state;
+
+ tpm_tis_request_completed(s, ret);
+}
+
+static enum TPMVersion tpm_tis_sysbus_get_tpm_version(TPMIf *ti)
+{
+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(ti);
+ TPMState *s = &sbdev->state;
+
+ return tpm_tis_get_tpm_version(s);
+}
+
+static void tpm_tis_sysbus_reset(DeviceState *dev)
+{
+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev);
+ TPMState *s = &sbdev->state;
+
+ return tpm_tis_reset(s);
+}
+
+static Property tpm_tis_sysbus_properties[] = {
+ DEFINE_PROP_UINT32("irq", TPMStateSysBus, state.irq_num, TPM_TIS_IRQ),
+ DEFINE_PROP_TPMBE("tpmdev", TPMStateSysBus, state.be_driver),
+ DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, true),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tpm_tis_sysbus_initfn(Object *obj)
+{
+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(obj);
+ TPMState *s = &sbdev->state;
+
+ memory_region_init_io(&s->mmio, obj, &tpm_tis_memory_ops,
+ s, "tpm-tis-mmio",
+ TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
+
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+}
+
+static void tpm_tis_sysbus_realizefn(DeviceState *dev, Error **errp)
+{
+ TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev);
+ TPMState *s = &sbdev->state;
+
+ if (!tpm_find()) {
+ error_setg(errp, "at most one TPM device is permitted");
+ return;
+ }
+
+ if (!s->be_driver) {
+ error_setg(errp, "'tpmdev' property is required");
+ return;
+ }
+}
+
+static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ TPMIfClass *tc = TPM_IF_CLASS(klass);
+
+ dc->props = tpm_tis_sysbus_properties;
+ dc->vmsd = &vmstate_tpm_tis_sysbus;
+ tc->model = TPM_MODEL_TPM_TIS;
+ dc->realize = tpm_tis_sysbus_realizefn;
+ dc->user_creatable = true;
+ dc->reset = tpm_tis_sysbus_reset;
+ tc->request_completed = tpm_tis_sysbus_request_completed;
+ tc->get_version = tpm_tis_sysbus_get_tpm_version;
+}
+
+static const TypeInfo tpm_tis_sysbus_info = {
+ .name = TYPE_TPM_TIS_SYSBUS,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(TPMStateSysBus),
+ .instance_init = tpm_tis_sysbus_initfn,
+ .class_init = tpm_tis_sysbus_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_TPM_IF },
+ { }
+ }
+};
+
+static void tpm_tis_sysbus_register(void)
+{
+ type_register_static(&tpm_tis_sysbus_info);
+}
+
+type_init(tpm_tis_sysbus_register)
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 1691b92c..f37851b1 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -44,6 +44,7 @@ typedef struct TPMIfClass {
} 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_SPAPR "tpm-spapr"
--
2.23.0

View File

@ -0,0 +1,146 @@
From c6cf45f38cb6e28cf4db42296fedcd5f26ca610b Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Tue, 21 Jan 2020 10:29:30 -0500
Subject: [PATCH 03/19] tpm: Move tpm_tis_show_buffer to tpm_util.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200121152935.649898-2-stefanb@linux.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/tpm/tpm_tis.c | 32 ++++----------------------------
hw/tpm/tpm_util.c | 25 +++++++++++++++++++++++++
hw/tpm/tpm_util.h | 3 +++
hw/tpm/trace-events | 2 +-
4 files changed, 33 insertions(+), 29 deletions(-)
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index d6b32128..96a9ac48 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -104,30 +104,6 @@ static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7);
}
-static void tpm_tis_show_buffer(const unsigned char *buffer,
- size_t buffer_size, const char *string)
-{
- size_t len, i;
- char *line_buffer, *p;
-
- len = MIN(tpm_cmd_get_size(buffer), buffer_size);
-
- /*
- * allocate enough room for 3 chars per buffer entry plus a
- * newline after every 16 chars and a final null terminator.
- */
- line_buffer = g_malloc(len * 3 + (len / 16) + 1);
-
- for (i = 0, p = line_buffer; i < len; i++) {
- if (i && !(i % 16)) {
- p += sprintf(p, "\n");
- }
- p += sprintf(p, "%.2X ", buffer[i]);
- }
- trace_tpm_tis_show_buffer(string, len, line_buffer);
-
- g_free(line_buffer);
-}
/*
* Set the given flags in the STS register by clearing the register but
@@ -153,8 +129,8 @@ static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
*/
static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
{
- if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) {
- tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
+ if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) {
+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
}
/*
@@ -322,8 +298,8 @@ static void tpm_tis_request_completed(TPMIf *ti, int ret)
s->loc[locty].state = TPM_TIS_STATE_COMPLETION;
s->rw_offset = 0;
- if (trace_event_get_state_backends(TRACE_TPM_TIS_SHOW_BUFFER)) {
- tpm_tis_show_buffer(s->buffer, s->be_buffer_size, "From TPM");
+ if (trace_event_get_state_backends(TRACE_TPM_UTIL_SHOW_BUFFER)) {
+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "From TPM");
}
if (TPM_TIS_IS_VALID_LOCTY(s->next_locty)) {
diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c
index ee41757e..8643eb50 100644
--- a/hw/tpm/tpm_util.c
+++ b/hw/tpm/tpm_util.c
@@ -350,3 +350,28 @@ void tpm_sized_buffer_reset(TPMSizedBuffer *tsb)
tsb->buffer = NULL;
tsb->size = 0;
}
+
+void tpm_util_show_buffer(const unsigned char *buffer,
+ size_t buffer_size, const char *string)
+{
+ size_t len, i;
+ char *line_buffer, *p;
+
+ len = MIN(tpm_cmd_get_size(buffer), buffer_size);
+
+ /*
+ * allocate enough room for 3 chars per buffer entry plus a
+ * newline after every 16 chars and a final null terminator.
+ */
+ line_buffer = g_malloc(len * 3 + (len / 16) + 1);
+
+ for (i = 0, p = line_buffer; i < len; i++) {
+ if (i && !(i % 16)) {
+ p += sprintf(p, "\n");
+ }
+ p += sprintf(p, "%.2X ", buffer[i]);
+ }
+ trace_tpm_util_show_buffer(string, len, line_buffer);
+
+ g_free(line_buffer);
+}
diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h
index f397ac21..7889081f 100644
--- a/hw/tpm/tpm_util.h
+++ b/hw/tpm/tpm_util.h
@@ -79,4 +79,7 @@ typedef struct TPMSizedBuffer {
void tpm_sized_buffer_reset(TPMSizedBuffer *tsb);
+void tpm_util_show_buffer(const unsigned char *buffer,
+ size_t buffer_size, const char *string);
+
#endif /* TPM_TPM_UTIL_H */
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index 0b94aa15..82c45ee5 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -14,6 +14,7 @@ tpm_util_get_buffer_size_len(uint32_t len, size_t expected) "tpm_resp->len = %u,
tpm_util_get_buffer_size_hdr_len2(uint32_t len, size_t expected) "tpm2_resp->hdr.len = %u, expected = %zu"
tpm_util_get_buffer_size_len2(uint32_t len, size_t expected) "tpm2_resp->len = %u, expected = %zu"
tpm_util_get_buffer_size(size_t len) "buffersize of device: %zu"
+tpm_util_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s"
# tpm_emulator.c
tpm_emulator_set_locality(uint8_t locty) "setting locality to %d"
@@ -36,7 +37,6 @@ tpm_emulator_pre_save(void) ""
tpm_emulator_inst_init(void) ""
# tpm_tis.c
-tpm_tis_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\nbuf: %s"
tpm_tis_raise_irq(uint32_t irqmask) "Raising IRQ for flag 0x%08x"
tpm_tis_new_active_locality(uint8_t locty) "Active locality is now %d"
tpm_tis_abort(uint8_t locty) "New active locality is %d"
--
2.23.0

View File

@ -0,0 +1,108 @@
From 1eca7dbacabbc8ccc737f320839e7800fef5dfa1 Mon Sep 17 00:00:00 2001
From: jiangfangjie <jiangfangjie@huawei.com>
Date: Tue, 11 Aug 2020 12:42:31 +0800
Subject: [PATCH 13/19] tpm: Separate TPM_TIS and TPM_TIS_ISA configs
MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Let's separate the compilation of tpm_tis_common.c from
the compilation of tpm_tis_isa.c
The common part will be also compiled along with the
tpm_tis_sysbus device.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Message-id: 20200305165149.618-5-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
default-configs/i386-softmmu.mak | 2 +-
hw/i386/Kconfig | 2 +-
hw/tpm/Kconfig | 7 ++++++-
hw/tpm/Makefile.objs | 3 ++-
tests/Makefile.include | 4 ++--
5 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index cd5ea391..bdeef670 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -17,7 +17,7 @@
#CONFIG_SGA=n
#CONFIG_TEST_DEVICES=n
#CONFIG_TPM_CRB=n
-#CONFIG_TPM_TIS=n
+#CONFIG_TPM_TIS_ISA=n
#CONFIG_VTD=n
# Boards:
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index 63504380..60334504 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -17,7 +17,7 @@ config PC
imply SGA
imply TEST_DEVICES
imply TPM_CRB
- imply TPM_TIS
+ imply TPM_TIS_ISA
imply VGA_PCI
imply VIRTIO_VGA
select FDC
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index 9e67d990..686f8206 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -2,9 +2,14 @@ config TPMDEV
bool
depends on TPM
-config TPM_TIS
+config TPM_TIS_ISA
bool
depends on TPM && ISA_BUS
+ select TPM_TIS
+
+config TPM_TIS
+ bool
+ depends on TPM
select TPMDEV
config TPM_CRB
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index fcc4c2f2..3ef2036c 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -1,6 +1,7 @@
common-obj-$(CONFIG_TPM) += tpm_util.o
obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o
-common-obj-$(CONFIG_TPM_TIS) += tpm_tis_isa.o tpm_tis_common.o
+common-obj-$(CONFIG_TPM_TIS_ISA) += tpm_tis_isa.o
+common-obj-$(CONFIG_TPM_TIS) += tpm_tis_common.o
common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
diff --git a/tests/Makefile.include b/tests/Makefile.include
index f3273ad3..c151de64 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -190,8 +190,8 @@ check-qtest-i386-y += tests/q35-test$(EXESUF)
check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-swtpm-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-test$(EXESUF)
-check-qtest-i386-$(CONFIG_TPM_TIS) += tests/tpm-tis-swtpm-test$(EXESUF)
-check-qtest-i386-$(CONFIG_TPM_TIS) += tests/tpm-tis-test$(EXESUF)
+check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tests/tpm-tis-swtpm-test$(EXESUF)
+check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tests/tpm-tis-test$(EXESUF)
check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF)
check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF)
check-qtest-i386-$(CONFIG_RTL8139_PCI) += tests/test-filter-redirector$(EXESUF)
--
2.23.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
From c57e57c86f9d3c13b33746436bc1f09db88d4d42 Mon Sep 17 00:00:00 2001
From: jiangfangjie <jiangfangjie@huawei.com>
Date: Tue, 11 Aug 2020 02:52:12 +0000
Subject: [PATCH 11/19] tpm: Use TPMState as a common struct
As we plan to introduce a SysBus TPM TIS device, let's
make the TPMState a common struct usable by both the
ISADevice and the SysBusDevice. TPMStateISA embeds the
struct and inherits from the ISADevice.
The prototype of functions bound to be used by both
the ISA and SysBus devices is changed to take TPMState
handle.
A bunch of structs also are renamed to be specialized
for the ISA device. Besides those transformations, no
functional change is expected.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Message-id: 20200305165149.618-3-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/tpm/tpm_tis.c | 147 +++++++++++++++++++++++++++++------------------
1 file changed, 92 insertions(+), 55 deletions(-)
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index 49d44652..735a528f 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -62,7 +62,6 @@ typedef struct TPMLocality {
} TPMLocality;
typedef struct TPMState {
- ISADevice busdev;
MemoryRegion mmio;
unsigned char buffer[TPM_TIS_BUFFER_MAX];
@@ -88,7 +87,15 @@ typedef struct TPMState {
TPMPPI ppi;
} TPMState;
-#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS_ISA)
+typedef struct TPMStateISA {
+ /*< private >*/
+ ISADevice parent_obj;
+
+ /*< public >*/
+ TPMState state; /* not a QOM object */
+} TPMStateISA;
+
+#define TPM_TIS_ISA(obj) OBJECT_CHECK(TPMStateISA, (obj), TYPE_TPM_TIS_ISA)
#define DEBUG_TIS 0
@@ -278,9 +285,8 @@ static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
/*
* Callback from the TPM to indicate that the response was received.
*/
-static void tpm_tis_request_completed(TPMIf *ti, int ret)
+static void tpm_tis_request_completed(TPMState *s, int ret)
{
- TPMState *s = TPM(ti);
uint8_t locty = s->cmd.locty;
uint8_t l;
@@ -335,7 +341,7 @@ static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
}
#ifdef DEBUG_TIS
-static void tpm_tis_dump_state(void *opaque, hwaddr addr)
+static void tpm_tis_dump_state(TPMState *s, hwaddr addr)
{
static const unsigned regs[] = {
TPM_TIS_REG_ACCESS,
@@ -350,7 +356,6 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr)
int idx;
uint8_t locty = tpm_tis_locality_from_addr(addr);
hwaddr base = addr & ~0xfff;
- TPMState *s = opaque;
printf("tpm_tis: active locality : %d\n"
"tpm_tis: state of locality %d : %d\n"
@@ -360,7 +365,7 @@ static void tpm_tis_dump_state(void *opaque, hwaddr addr)
for (idx = 0; regs[idx] != 0xfff; idx++) {
printf("tpm_tis: 0x%04x : 0x%08x\n", regs[idx],
- (int)tpm_tis_mmio_read(opaque, base + regs[idx], 4));
+ (int)tpm_tis_mmio_read(s, base + regs[idx], 4));
}
printf("tpm_tis: r/w offset : %d\n"
@@ -485,7 +490,7 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
break;
#ifdef DEBUG_TIS
case TPM_TIS_REG_DEBUG:
- tpm_tis_dump_state(opaque, addr);
+ tpm_tis_dump_state(s, addr);
break;
#endif
}
@@ -832,10 +837,8 @@ static const MemoryRegionOps tpm_tis_memory_ops = {
/*
* Get the TPMVersion of the backend device being used
*/
-static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti)
+static enum TPMVersion tpm_tis_get_tpm_version(TPMState *s)
{
- TPMState *s = TPM(ti);
-
if (tpm_backend_had_startup_error(s->be_driver)) {
return TPM_VERSION_UNSPEC;
}
@@ -847,9 +850,8 @@ static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti)
* This function is called when the machine starts, resets or due to
* S3 resume.
*/
-static void tpm_tis_reset(DeviceState *dev)
+static void tpm_tis_reset(TPMState *s)
{
- TPMState *s = TPM(dev);
int c;
s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
@@ -893,15 +895,14 @@ static void tpm_tis_reset(DeviceState *dev)
/* persistent state handling */
-static int tpm_tis_pre_save(void *opaque)
+static int tpm_tis_pre_save(TPMState *s)
{
- TPMState *s = opaque;
uint8_t locty = s->active_locty;
trace_tpm_tis_pre_save(locty, s->rw_offset);
if (DEBUG_TIS) {
- tpm_tis_dump_state(opaque, 0);
+ tpm_tis_dump_state(s, 0);
}
/*
@@ -926,34 +927,78 @@ static const VMStateDescription vmstate_locty = {
}
};
-static const VMStateDescription vmstate_tpm_tis = {
+/* ISA */
+
+static int tpm_tis_pre_save_isa(void *opaque)
+{
+ TPMStateISA *isadev = opaque;
+
+ return tpm_tis_pre_save(&isadev->state);
+}
+
+static const VMStateDescription vmstate_tpm_tis_isa = {
.name = "tpm-tis",
.version_id = 0,
- .pre_save = tpm_tis_pre_save,
+ .pre_save = tpm_tis_pre_save_isa,
.fields = (VMStateField[]) {
- VMSTATE_BUFFER(buffer, TPMState),
- VMSTATE_UINT16(rw_offset, TPMState),
- VMSTATE_UINT8(active_locty, TPMState),
- VMSTATE_UINT8(aborting_locty, TPMState),
- VMSTATE_UINT8(next_locty, TPMState),
+ VMSTATE_BUFFER(state.buffer, TPMStateISA),
+ VMSTATE_UINT16(state.rw_offset, TPMStateISA),
+ VMSTATE_UINT8(state.active_locty, TPMStateISA),
+ VMSTATE_UINT8(state.aborting_locty, TPMStateISA),
+ VMSTATE_UINT8(state.next_locty, TPMStateISA),
- VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 0,
+ VMSTATE_STRUCT_ARRAY(state.loc, TPMStateISA, TPM_TIS_NUM_LOCALITIES, 0,
vmstate_locty, TPMLocality),
VMSTATE_END_OF_LIST()
}
};
-static Property tpm_tis_properties[] = {
- DEFINE_PROP_UINT32("irq", TPMState, irq_num, TPM_TIS_IRQ),
- DEFINE_PROP_TPMBE("tpmdev", TPMState, be_driver),
- DEFINE_PROP_BOOL("ppi", TPMState, ppi_enabled, true),
+static void tpm_tis_isa_request_completed(TPMIf *ti, int ret)
+{
+ TPMStateISA *isadev = TPM_TIS_ISA(ti);
+ TPMState *s = &isadev->state;
+
+ tpm_tis_request_completed(s, ret);
+}
+
+static enum TPMVersion tpm_tis_isa_get_tpm_version(TPMIf *ti)
+{
+ TPMStateISA *isadev = TPM_TIS_ISA(ti);
+ TPMState *s = &isadev->state;
+
+ return tpm_tis_get_tpm_version(s);
+}
+
+static void tpm_tis_isa_reset(DeviceState *dev)
+{
+ TPMStateISA *isadev = TPM_TIS_ISA(dev);
+ TPMState *s = &isadev->state;
+
+ return tpm_tis_reset(s);
+}
+
+static Property tpm_tis_isa_properties[] = {
+ DEFINE_PROP_UINT32("irq", TPMStateISA, state.irq_num, TPM_TIS_IRQ),
+ DEFINE_PROP_TPMBE("tpmdev", TPMStateISA, state.be_driver),
+ DEFINE_PROP_BOOL("ppi", TPMStateISA, state.ppi_enabled, true),
DEFINE_PROP_END_OF_LIST(),
};
-static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
+static void tpm_tis_isa_initfn(Object *obj)
{
- TPMState *s = TPM(dev);
+ TPMStateISA *isadev = TPM_TIS_ISA(obj);
+ TPMState *s = &isadev->state;
+
+ memory_region_init_io(&s->mmio, obj, &tpm_tis_memory_ops,
+ s, "tpm-tis-mmio",
+ TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
+}
+
+static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp)
+{
+ TPMStateISA *isadev = TPM_TIS_ISA(dev);
+ TPMState *s = &isadev->state;
if (!tpm_find()) {
error_setg(errp, "at most one TPM device is permitted");
@@ -970,55 +1015,47 @@ static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
return;
}
- isa_init_irq(&s->busdev, &s->irq, s->irq_num);
+ isa_init_irq(ISA_DEVICE(dev), &s->irq, s->irq_num);
memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
TPM_TIS_ADDR_BASE, &s->mmio);
if (s->ppi_enabled) {
tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)),
- TPM_PPI_ADDR_BASE, OBJECT(s));
+ TPM_PPI_ADDR_BASE, OBJECT(dev));
}
}
-static void tpm_tis_initfn(Object *obj)
-{
- TPMState *s = TPM(obj);
-
- memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops,
- s, "tpm-tis-mmio",
- TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
-}
-
-static void tpm_tis_class_init(ObjectClass *klass, void *data)
+static void tpm_tis_isa_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
TPMIfClass *tc = TPM_IF_CLASS(klass);
- dc->realize = tpm_tis_realizefn;
- dc->props = tpm_tis_properties;
- dc->reset = tpm_tis_reset;
- dc->vmsd = &vmstate_tpm_tis;
+ dc->props = tpm_tis_isa_properties;
+ dc->vmsd = &vmstate_tpm_tis_isa;
tc->model = TPM_MODEL_TPM_TIS;
- tc->get_version = tpm_tis_get_tpm_version;
- tc->request_completed = tpm_tis_request_completed;
+ dc->realize = tpm_tis_isa_realizefn;
+ dc->reset = tpm_tis_isa_reset;
+ tc->request_completed = tpm_tis_isa_request_completed;
+ tc->get_version = tpm_tis_isa_get_tpm_version;
+
}
-static const TypeInfo tpm_tis_info = {
+static const TypeInfo tpm_tis_isa_info = {
.name = TYPE_TPM_TIS_ISA,
.parent = TYPE_ISA_DEVICE,
- .instance_size = sizeof(TPMState),
- .instance_init = tpm_tis_initfn,
- .class_init = tpm_tis_class_init,
+ .instance_size = sizeof(TPMStateISA),
+ .instance_init = tpm_tis_isa_initfn,
+ .class_init = tpm_tis_isa_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_TPM_IF },
{ }
}
};
-static void tpm_tis_register(void)
+static void tpm_tis_isa_register(void)
{
- type_register_static(&tpm_tis_info);
+ type_register_static(&tpm_tis_isa_info);
}
-type_init(tpm_tis_register)
+type_init(tpm_tis_isa_register)
--
2.23.0

View File

@ -0,0 +1,43 @@
From 26b54c545f253049faa633ff886132602ff47241 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= <marcandre.lureau@redhat.com>
Date: Fri, 3 Jan 2020 11:39:59 +0400
Subject: [PATCH 02/19] tpm-ppi: page-align PPI RAM
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
post-copy migration fails on destination with error such as:
2019-12-26T10:22:44.714644Z qemu-kvm: ram_block_discard_range:
Unaligned start address: 0x559d2afae9a0
Use qemu_memalign() to constrain the PPI RAM memory alignment.
Cc: qemu-stable@nongnu.org
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Message-id: 20200103074000.1006389-3-marcandre.lureau@redhat.com
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/tpm/tpm_ppi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/tpm/tpm_ppi.c b/hw/tpm/tpm_ppi.c
index cd8205f2..6509ffd4 100644
--- a/hw/tpm/tpm_ppi.c
+++ b/hw/tpm/tpm_ppi.c
@@ -44,7 +44,8 @@ void tpm_ppi_reset(TPMPPI *tpmppi)
void tpm_ppi_init(TPMPPI *tpmppi, struct MemoryRegion *m,
hwaddr addr, Object *obj)
{
- tpmppi->buf = g_malloc0(HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
+ tpmppi->buf = qemu_memalign(qemu_real_host_page_size,
+ HOST_PAGE_ALIGN(TPM_PPI_ADDR_SIZE));
memory_region_init_ram_device_ptr(&tpmppi->ram, obj, "tpm-ppi",
TPM_PPI_ADDR_SIZE, tpmppi->buf);
vmstate_register_ram(&tpmppi->ram, DEVICE(obj));
--
2.23.0

View File

@ -0,0 +1,101 @@
From 7974f8ffd75171be106a1ce2705878abbb6c4477 Mon Sep 17 00:00:00 2001
From: Eric Auger <eric.auger@redhat.com>
Date: Thu, 5 Mar 2020 17:51:40 +0100
Subject: [PATCH 10/19] tpm: rename TPM_TIS into TPM_TIS_ISA
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
As we plan to introduce a sysbus TPM_TIS, let's rename
TPM_TIS into TPM_TIS_ISA.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Message-id: 20200305165149.618-2-eric.auger@redhat.com
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/i386/acpi-build.c | 6 +++---
hw/tpm/tpm_tis.c | 4 ++--
include/sysemu/tpm.h | 6 +++---
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index c97731ec..093f7d93 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2007,7 +2007,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
}
}
- if (TPM_IS_TIS(tpm_find())) {
+ if (TPM_IS_TIS_ISA(tpm_find())) {
aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
TPM_TIS_ADDR_SIZE, AML_READ_WRITE));
}
@@ -2178,7 +2178,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
/* Scan all PCI buses. Generate tables to support hotplug. */
build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
- if (TPM_IS_TIS(tpm)) {
+ if (TPM_IS_TIS_ISA(tpm)) {
if (misc->tpm_version == TPM_VERSION_2_0) {
dev = aml_device("TPM");
aml_append(dev, aml_name_decl("_HID",
@@ -2285,7 +2285,7 @@ build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog)
(char *)&tpm2_ptr->log_area_start_address - table_data->data;
tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT);
- if (TPM_IS_TIS(tpm_find())) {
+ if (TPM_IS_TIS_ISA(tpm_find())) {
tpm2_ptr->control_area_address = cpu_to_le64(0);
tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO);
} else if (TPM_IS_CRB(tpm_find())) {
diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c
index 96a9ac48..49d44652 100644
--- a/hw/tpm/tpm_tis.c
+++ b/hw/tpm/tpm_tis.c
@@ -88,7 +88,7 @@ typedef struct TPMState {
TPMPPI ppi;
} TPMState;
-#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS)
+#define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS_ISA)
#define DEBUG_TIS 0
@@ -1005,7 +1005,7 @@ static void tpm_tis_class_init(ObjectClass *klass, void *data)
}
static const TypeInfo tpm_tis_info = {
- .name = TYPE_TPM_TIS,
+ .name = TYPE_TPM_TIS_ISA,
.parent = TYPE_ISA_DEVICE,
.instance_size = sizeof(TPMState),
.instance_init = tpm_tis_initfn,
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 15979a36..1691b92c 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -43,12 +43,12 @@ typedef struct TPMIfClass {
enum TPMVersion (*get_version)(TPMIf *obj);
} TPMIfClass;
-#define TYPE_TPM_TIS "tpm-tis"
+#define TYPE_TPM_TIS_ISA "tpm-tis"
#define TYPE_TPM_CRB "tpm-crb"
#define TYPE_TPM_SPAPR "tpm-spapr"
-#define TPM_IS_TIS(chr) \
- object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
+#define TPM_IS_TIS_ISA(chr) \
+ object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_ISA)
#define TPM_IS_CRB(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
#define TPM_IS_SPAPR(chr) \
--
2.23.0

View File

@ -0,0 +1,552 @@
From 14402a8ca57fb722eb324d141fafb41ef06f4c2b Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Tue, 21 Jan 2020 10:29:32 -0500
Subject: [PATCH 06/19] tpm_spapr: Support TPM for ppc64 using CRQ based
interface
Implement support for TPM on ppc64 by implementing the vTPM CRQ interface
as a frontend. It can use the tpm_emulator driver backend with the external
swtpm.
The Linux vTPM driver for ppc64 works with this emulation.
This TPM emulator also handles the TPM 2 case.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Message-Id: <20200121152935.649898-4-stefanb@linux.ibm.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
docs/specs/tpm.txt | 20 ++-
hw/tpm/Kconfig | 6 +
hw/tpm/Makefile.objs | 1 +
hw/tpm/tpm_spapr.c | 379 +++++++++++++++++++++++++++++++++++++++++++
hw/tpm/trace-events | 12 ++
include/sysemu/tpm.h | 3 +
qapi/tpm.json | 6 +-
7 files changed, 423 insertions(+), 4 deletions(-)
create mode 100644 hw/tpm/tpm_spapr.c
diff --git a/docs/specs/tpm.txt b/docs/specs/tpm.txt
index 9c8cca04..9c3e67d8 100644
--- a/docs/specs/tpm.txt
+++ b/docs/specs/tpm.txt
@@ -34,6 +34,12 @@ The CRB interface makes a memory mapped IO region in the area 0xfed40000 -
QEMU files related to TPM CRB interface:
- hw/tpm/tpm_crb.c
+
+pSeries (ppc64) machines offer a tpm-spapr device model.
+
+QEMU files related to the SPAPR interface:
+ - hw/tpm/tpm_spapr.c
+
= fw_cfg interface =
The bios/firmware may read the "etc/tpm/config" fw_cfg entry for
@@ -281,7 +287,7 @@ swtpm socket --tpmstate dir=/tmp/mytpm1 \
--log level=20
Command line to start QEMU with the TPM emulator device communicating with
-the swtpm:
+the swtpm (x86):
qemu-system-x86_64 -display sdl -accel kvm \
-m 1024 -boot d -bios bios-256k.bin -boot menu=on \
@@ -289,6 +295,18 @@ qemu-system-x86_64 -display sdl -accel kvm \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0 test.img
+In case a pSeries machine is emulated, use the following command line:
+
+qemu-system-ppc64 -display sdl -machine pseries,accel=kvm \
+ -m 1024 -bios slof.bin -boot menu=on \
+ -nodefaults -device VGA -device pci-ohci -device usb-kbd \
+ -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \
+ -tpmdev emulator,id=tpm0,chardev=chrtpm \
+ -device tpm-spapr,tpmdev=tpm0 \
+ -device spapr-vscsi,id=scsi0,reg=0x00002000 \
+ -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \
+ -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0
+
In case SeaBIOS is used as firmware, it should show the TPM menu item
after entering the menu with 'ESC'.
diff --git a/hw/tpm/Kconfig b/hw/tpm/Kconfig
index 4c8ee87d..4d4ab085 100644
--- a/hw/tpm/Kconfig
+++ b/hw/tpm/Kconfig
@@ -22,3 +22,9 @@ config TPM_EMULATOR
bool
default y
depends on TPMDEV
+
+config TPM_SPAPR
+ bool
+ default n
+ depends on TPM && PSERIES
+ select TPMDEV
diff --git a/hw/tpm/Makefile.objs b/hw/tpm/Makefile.objs
index de0b85d0..85eb99ae 100644
--- a/hw/tpm/Makefile.objs
+++ b/hw/tpm/Makefile.objs
@@ -4,3 +4,4 @@ common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o
common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o
common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o
common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
+obj-$(CONFIG_TPM_SPAPR) += tpm_spapr.o
diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c
new file mode 100644
index 00000000..1db9696a
--- /dev/null
+++ b/hw/tpm/tpm_spapr.c
@@ -0,0 +1,379 @@
+/*
+ * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
+ *
+ * PAPR Virtual TPM
+ *
+ * Copyright (c) 2015, 2017, 2019 IBM Corporation.
+ *
+ * Authors:
+ * Stefan Berger <stefanb@linux.vnet.ibm.com>
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "hw/qdev-properties.h"
+#include "migration/vmstate.h"
+
+#include "sysemu/tpm_backend.h"
+#include "tpm_int.h"
+#include "tpm_util.h"
+
+#include "hw/ppc/spapr.h"
+#include "hw/ppc/spapr_vio.h"
+#include "trace.h"
+
+#define DEBUG_SPAPR 0
+
+#define VIO_SPAPR_VTPM(obj) \
+ OBJECT_CHECK(SpaprTpmState, (obj), TYPE_TPM_SPAPR)
+
+typedef struct TpmCrq {
+ uint8_t valid; /* 0x80: cmd; 0xc0: init crq */
+ /* 0x81-0x83: CRQ message response */
+ uint8_t msg; /* see below */
+ uint16_t len; /* len of TPM request; len of TPM response */
+ uint32_t data; /* rtce_dma_handle when sending TPM request */
+ uint64_t reserved;
+} TpmCrq;
+
+#define SPAPR_VTPM_VALID_INIT_CRQ_COMMAND 0xC0
+#define SPAPR_VTPM_VALID_COMMAND 0x80
+#define SPAPR_VTPM_MSG_RESULT 0x80
+
+/* msg types for valid = SPAPR_VTPM_VALID_INIT_CRQ */
+#define SPAPR_VTPM_INIT_CRQ_RESULT 0x1
+#define SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT 0x2
+
+/* msg types for valid = SPAPR_VTPM_VALID_CMD */
+#define SPAPR_VTPM_GET_VERSION 0x1
+#define SPAPR_VTPM_TPM_COMMAND 0x2
+#define SPAPR_VTPM_GET_RTCE_BUFFER_SIZE 0x3
+#define SPAPR_VTPM_PREPARE_TO_SUSPEND 0x4
+
+/* response error messages */
+#define SPAPR_VTPM_VTPM_ERROR 0xff
+
+/* error codes */
+#define SPAPR_VTPM_ERR_COPY_IN_FAILED 0x3
+#define SPAPR_VTPM_ERR_COPY_OUT_FAILED 0x4
+
+#define TPM_SPAPR_BUFFER_MAX 4096
+
+typedef struct {
+ SpaprVioDevice vdev;
+
+ TpmCrq crq; /* track single TPM command */
+
+ uint8_t state;
+#define SPAPR_VTPM_STATE_NONE 0
+#define SPAPR_VTPM_STATE_EXECUTION 1
+#define SPAPR_VTPM_STATE_COMPLETION 2
+
+ unsigned char *buffer;
+
+ TPMBackendCmd cmd;
+
+ TPMBackend *be_driver;
+ TPMVersion be_tpm_version;
+
+ size_t be_buffer_size;
+} SpaprTpmState;
+
+/*
+ * Send a request to the TPM.
+ */
+static void tpm_spapr_tpm_send(SpaprTpmState *s)
+{
+ if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) {
+ tpm_util_show_buffer(s->buffer, s->be_buffer_size, "To TPM");
+ }
+
+ s->state = SPAPR_VTPM_STATE_EXECUTION;
+ s->cmd = (TPMBackendCmd) {
+ .locty = 0,
+ .in = s->buffer,
+ .in_len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size),
+ .out = s->buffer,
+ .out_len = s->be_buffer_size,
+ };
+
+ tpm_backend_deliver_request(s->be_driver, &s->cmd);
+}
+
+static int tpm_spapr_process_cmd(SpaprTpmState *s, uint64_t dataptr)
+{
+ long rc;
+
+ /* a max. of be_buffer_size bytes can be transported */
+ rc = spapr_vio_dma_read(&s->vdev, dataptr,
+ s->buffer, s->be_buffer_size);
+ if (rc) {
+ error_report("tpm_spapr_got_payload: DMA read failure");
+ }
+ /* let vTPM handle any malformed request */
+ tpm_spapr_tpm_send(s);
+
+ return rc;
+}
+
+static inline int spapr_tpm_send_crq(struct SpaprVioDevice *dev, TpmCrq *crq)
+{
+ return spapr_vio_send_crq(dev, (uint8_t *)crq);
+}
+
+static int tpm_spapr_do_crq(struct SpaprVioDevice *dev, uint8_t *crq_data)
+{
+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
+ TpmCrq local_crq;
+ TpmCrq *crq = &s->crq; /* requests only */
+ int rc;
+ uint8_t valid = crq_data[0];
+ uint8_t msg = crq_data[1];
+
+ trace_tpm_spapr_do_crq(valid, msg);
+
+ switch (valid) {
+ case SPAPR_VTPM_VALID_INIT_CRQ_COMMAND: /* Init command/response */
+
+ /* Respond to initialization request */
+ switch (msg) {
+ case SPAPR_VTPM_INIT_CRQ_RESULT:
+ trace_tpm_spapr_do_crq_crq_result();
+ memset(&local_crq, 0, sizeof(local_crq));
+ local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND;
+ local_crq.msg = SPAPR_VTPM_INIT_CRQ_RESULT;
+ spapr_tpm_send_crq(dev, &local_crq);
+ break;
+
+ case SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT:
+ trace_tpm_spapr_do_crq_crq_complete_result();
+ memset(&local_crq, 0, sizeof(local_crq));
+ local_crq.valid = SPAPR_VTPM_VALID_INIT_CRQ_COMMAND;
+ local_crq.msg = SPAPR_VTPM_INIT_CRQ_COMPLETE_RESULT;
+ spapr_tpm_send_crq(dev, &local_crq);
+ break;
+ }
+
+ break;
+ case SPAPR_VTPM_VALID_COMMAND: /* Payloads */
+ switch (msg) {
+ case SPAPR_VTPM_TPM_COMMAND:
+ trace_tpm_spapr_do_crq_tpm_command();
+ if (s->state == SPAPR_VTPM_STATE_EXECUTION) {
+ return H_BUSY;
+ }
+ memcpy(crq, crq_data, sizeof(*crq));
+
+ rc = tpm_spapr_process_cmd(s, be32_to_cpu(crq->data));
+
+ if (rc == H_SUCCESS) {
+ crq->valid = be16_to_cpu(0);
+ } else {
+ local_crq.valid = SPAPR_VTPM_MSG_RESULT;
+ local_crq.msg = SPAPR_VTPM_VTPM_ERROR;
+ local_crq.len = cpu_to_be16(0);
+ local_crq.data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_IN_FAILED);
+ spapr_tpm_send_crq(dev, &local_crq);
+ }
+ break;
+
+ case SPAPR_VTPM_GET_RTCE_BUFFER_SIZE:
+ trace_tpm_spapr_do_crq_tpm_get_rtce_buffer_size(s->be_buffer_size);
+ local_crq.valid = SPAPR_VTPM_VALID_COMMAND;
+ local_crq.msg = SPAPR_VTPM_GET_RTCE_BUFFER_SIZE |
+ SPAPR_VTPM_MSG_RESULT;
+ local_crq.len = cpu_to_be16(s->be_buffer_size);
+ spapr_tpm_send_crq(dev, &local_crq);
+ break;
+
+ case SPAPR_VTPM_GET_VERSION:
+ local_crq.valid = SPAPR_VTPM_VALID_COMMAND;
+ local_crq.msg = SPAPR_VTPM_GET_VERSION | SPAPR_VTPM_MSG_RESULT;
+ local_crq.len = cpu_to_be16(0);
+ switch (s->be_tpm_version) {
+ case TPM_VERSION_1_2:
+ local_crq.data = cpu_to_be32(1);
+ break;
+ case TPM_VERSION_2_0:
+ local_crq.data = cpu_to_be32(2);
+ break;
+ default:
+ g_assert_not_reached();
+ break;
+ }
+ trace_tpm_spapr_do_crq_get_version(be32_to_cpu(local_crq.data));
+ spapr_tpm_send_crq(dev, &local_crq);
+ break;
+
+ case SPAPR_VTPM_PREPARE_TO_SUSPEND:
+ trace_tpm_spapr_do_crq_prepare_to_suspend();
+ local_crq.valid = SPAPR_VTPM_VALID_COMMAND;
+ local_crq.msg = SPAPR_VTPM_PREPARE_TO_SUSPEND |
+ SPAPR_VTPM_MSG_RESULT;
+ spapr_tpm_send_crq(dev, &local_crq);
+ break;
+
+ default:
+ trace_tpm_spapr_do_crq_unknown_msg_type(crq->msg);
+ }
+ break;
+ default:
+ trace_tpm_spapr_do_crq_unknown_crq(valid, msg);
+ };
+
+ return H_SUCCESS;
+}
+
+static void tpm_spapr_request_completed(TPMIf *ti, int ret)
+{
+ SpaprTpmState *s = VIO_SPAPR_VTPM(ti);
+ TpmCrq *crq = &s->crq;
+ uint32_t len;
+ int rc;
+
+ s->state = SPAPR_VTPM_STATE_COMPLETION;
+
+ /* a max. of be_buffer_size bytes can be transported */
+ len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);
+ rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->data),
+ s->buffer, len);
+
+ if (trace_event_get_state_backends(TRACE_TPM_SPAPR_SHOW_BUFFER)) {
+ tpm_util_show_buffer(s->buffer, len, "From TPM");
+ }
+
+ crq->valid = SPAPR_VTPM_MSG_RESULT;
+ if (rc == H_SUCCESS) {
+ crq->msg = SPAPR_VTPM_TPM_COMMAND | SPAPR_VTPM_MSG_RESULT;
+ crq->len = cpu_to_be16(len);
+ } else {
+ error_report("%s: DMA write failure", __func__);
+ crq->msg = SPAPR_VTPM_VTPM_ERROR;
+ crq->len = cpu_to_be16(0);
+ crq->data = cpu_to_be32(SPAPR_VTPM_ERR_COPY_OUT_FAILED);
+ }
+
+ rc = spapr_tpm_send_crq(&s->vdev, crq);
+ if (rc) {
+ error_report("%s: Error sending response", __func__);
+ }
+}
+
+static int tpm_spapr_do_startup_tpm(SpaprTpmState *s, size_t buffersize)
+{
+ return tpm_backend_startup_tpm(s->be_driver, buffersize);
+}
+
+static const char *tpm_spapr_get_dt_compatible(SpaprVioDevice *dev)
+{
+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
+
+ switch (s->be_tpm_version) {
+ case TPM_VERSION_1_2:
+ return "IBM,vtpm";
+ case TPM_VERSION_2_0:
+ return "IBM,vtpm20";
+ default:
+ g_assert_not_reached();
+ }
+}
+
+static void tpm_spapr_reset(SpaprVioDevice *dev)
+{
+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
+
+ s->state = SPAPR_VTPM_STATE_NONE;
+
+ s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
+
+ s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver),
+ TPM_SPAPR_BUFFER_MAX);
+
+ tpm_backend_reset(s->be_driver);
+ tpm_spapr_do_startup_tpm(s, s->be_buffer_size);
+}
+
+static enum TPMVersion tpm_spapr_get_version(TPMIf *ti)
+{
+ SpaprTpmState *s = VIO_SPAPR_VTPM(ti);
+
+ if (tpm_backend_had_startup_error(s->be_driver)) {
+ return TPM_VERSION_UNSPEC;
+ }
+
+ return tpm_backend_get_tpm_version(s->be_driver);
+}
+
+static const VMStateDescription vmstate_spapr_vtpm = {
+ .name = "tpm-spapr",
+ .unmigratable = 1,
+};
+
+static Property tpm_spapr_properties[] = {
+ DEFINE_SPAPR_PROPERTIES(SpaprTpmState, vdev),
+ DEFINE_PROP_TPMBE("tpmdev", SpaprTpmState, be_driver),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void tpm_spapr_realizefn(SpaprVioDevice *dev, Error **errp)
+{
+ SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
+
+ if (!tpm_find()) {
+ error_setg(errp, "at most one TPM device is permitted");
+ return;
+ }
+
+ dev->crq.SendFunc = tpm_spapr_do_crq;
+
+ if (!s->be_driver) {
+ error_setg(errp, "'tpmdev' property is required");
+ return;
+ }
+ s->buffer = g_malloc(TPM_SPAPR_BUFFER_MAX);
+}
+
+static void tpm_spapr_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SpaprVioDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+ TPMIfClass *tc = TPM_IF_CLASS(klass);
+
+ k->realize = tpm_spapr_realizefn;
+ k->reset = tpm_spapr_reset;
+ k->dt_name = "vtpm";
+ k->dt_type = "IBM,vtpm";
+ k->get_dt_compatible = tpm_spapr_get_dt_compatible;
+ k->signal_mask = 0x00000001;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->props = tpm_spapr_properties;
+ k->rtce_window_size = 0x10000000;
+ dc->vmsd = &vmstate_spapr_vtpm;
+
+ tc->model = TPM_MODEL_TPM_SPAPR;
+ tc->get_version = tpm_spapr_get_version;
+ tc->request_completed = tpm_spapr_request_completed;
+}
+
+static const TypeInfo tpm_spapr_info = {
+ .name = TYPE_TPM_SPAPR,
+ .parent = TYPE_VIO_SPAPR_DEVICE,
+ .instance_size = sizeof(SpaprTpmState),
+ .class_init = tpm_spapr_class_init,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_TPM_IF },
+ { }
+ }
+};
+
+static void tpm_spapr_register_types(void)
+{
+ type_register_static(&tpm_spapr_info);
+}
+
+type_init(tpm_spapr_register_types)
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index 82c45ee5..edbe1bd7 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -55,3 +55,15 @@ tpm_tis_pre_save(uint8_t locty, uint32_t rw_offset) "locty: %d, rw_offset = %u"
# tpm_ppi.c
tpm_ppi_memset(uint8_t *ptr, size_t size) "memset: %p %zu"
+
+# hw/tpm/tpm_spapr.c
+tpm_spapr_show_buffer(const char *direction, size_t len, const char *buf) "direction: %s len: %zu\n%s"
+tpm_spapr_do_crq(uint8_t raw1, uint8_t raw2) "1st 2 bytes in CRQ: 0x%02x 0x%02x"
+tpm_spapr_do_crq_crq_result(void) "SPAPR_VTPM_INIT_CRQ_RESULT"
+tpm_spapr_do_crq_crq_complete_result(void) "SPAPR_VTPM_INIT_CRQ_COMP_RESULT"
+tpm_spapr_do_crq_tpm_command(void) "got TPM command payload"
+tpm_spapr_do_crq_tpm_get_rtce_buffer_size(size_t buffersize) "response: buffer size is %zu"
+tpm_spapr_do_crq_get_version(uint32_t version) "response: version %u"
+tpm_spapr_do_crq_prepare_to_suspend(void) "response: preparing to suspend"
+tpm_spapr_do_crq_unknown_msg_type(uint8_t type) "Unknown message type 0x%02x"
+tpm_spapr_do_crq_unknown_crq(uint8_t raw1, uint8_t raw2) "unknown CRQ 0x%02x 0x%02x ..."
diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h
index 5b541a71..15979a36 100644
--- a/include/sysemu/tpm.h
+++ b/include/sysemu/tpm.h
@@ -45,11 +45,14 @@ typedef struct TPMIfClass {
#define TYPE_TPM_TIS "tpm-tis"
#define TYPE_TPM_CRB "tpm-crb"
+#define TYPE_TPM_SPAPR "tpm-spapr"
#define TPM_IS_TIS(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS)
#define TPM_IS_CRB(chr) \
object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB)
+#define TPM_IS_SPAPR(chr) \
+ object_dynamic_cast(OBJECT(chr), TYPE_TPM_SPAPR)
/* returns NULL unless there is exactly one TPM device */
static inline TPMIf *tpm_find(void)
diff --git a/qapi/tpm.json b/qapi/tpm.json
index b30323bb..63878aa0 100644
--- a/qapi/tpm.json
+++ b/qapi/tpm.json
@@ -12,11 +12,11 @@
#
# @tpm-tis: TPM TIS model
# @tpm-crb: TPM CRB model (since 2.12)
+# @tpm-spapr: TPM SPAPR model (since 5.0)
#
# Since: 1.5
##
-{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb' ] }
-
+{ 'enum': 'TpmModel', 'data': [ 'tpm-tis', 'tpm-crb', 'tpm-spapr' ] }
##
# @query-tpm-models:
#
@@ -29,7 +29,7 @@
# Example:
#
# -> { "execute": "query-tpm-models" }
-# <- { "return": [ "tpm-tis", "tpm-crb" ] }
+# <- { "return": [ "tpm-tis", "tpm-crb", "tpm-spapr" ] }
#
##
{ 'command': 'query-tpm-models', 'returns': ['TpmModel'] }
--
2.23.0

View File

@ -0,0 +1,119 @@
From 2948d9712a7058bcdca6732101874beb1a6e00a9 Mon Sep 17 00:00:00 2001
From: Stefan Berger <stefanb@linux.vnet.ibm.com>
Date: Tue, 21 Jan 2020 10:29:33 -0500
Subject: [PATCH 07/19] tpm_spapr: Support suspend and resume
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Extend the tpm_spapr frontend with VM suspend and resume support.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Message-Id: <20200121152935.649898-5-stefanb@linux.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: jiangfangjie <jiangfangjie@huawei.com>
---
hw/tpm/tpm_spapr.c | 52 ++++++++++++++++++++++++++++++++++++++++++++-
hw/tpm/trace-events | 2 ++
2 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c
index 1db9696a..8ba561f4 100644
--- a/hw/tpm/tpm_spapr.c
+++ b/hw/tpm/tpm_spapr.c
@@ -76,6 +76,8 @@ typedef struct {
unsigned char *buffer;
+ uint32_t numbytes; /* number of bytes to deliver on resume */
+
TPMBackendCmd cmd;
TPMBackend *be_driver;
@@ -240,6 +242,14 @@ static void tpm_spapr_request_completed(TPMIf *ti, int ret)
/* a max. of be_buffer_size bytes can be transported */
len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size);
+
+ if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
+ trace_tpm_spapr_caught_response(len);
+ /* defer delivery of response until .post_load */
+ s->numbytes = len;
+ return;
+ }
+
rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->data),
s->buffer, len);
@@ -288,6 +298,7 @@ static void tpm_spapr_reset(SpaprVioDevice *dev)
SpaprTpmState *s = VIO_SPAPR_VTPM(dev);
s->state = SPAPR_VTPM_STATE_NONE;
+ s->numbytes = 0;
s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver);
@@ -309,9 +320,48 @@ static enum TPMVersion tpm_spapr_get_version(TPMIf *ti)
return tpm_backend_get_tpm_version(s->be_driver);
}
+/* persistent state handling */
+
+static int tpm_spapr_pre_save(void *opaque)
+{
+ SpaprTpmState *s = opaque;
+
+ tpm_backend_finish_sync(s->be_driver);
+ /*
+ * we cannot deliver the results to the VM since DMA would touch VM memory
+ */
+
+ return 0;
+}
+
+static int tpm_spapr_post_load(void *opaque, int version_id)
+{
+ SpaprTpmState *s = opaque;
+
+ if (s->numbytes) {
+ trace_tpm_spapr_post_load();
+ /* deliver the results to the VM via DMA */
+ tpm_spapr_request_completed(TPM_IF(s), 0);
+ s->numbytes = 0;
+ }
+
+ return 0;
+}
+
static const VMStateDescription vmstate_spapr_vtpm = {
.name = "tpm-spapr",
- .unmigratable = 1,
+ .pre_save = tpm_spapr_pre_save,
+ .post_load = tpm_spapr_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_SPAPR_VIO(vdev, SpaprTpmState),
+
+ VMSTATE_UINT8(state, SpaprTpmState),
+ VMSTATE_UINT32(numbytes, SpaprTpmState),
+ VMSTATE_VBUFFER_UINT32(buffer, SpaprTpmState, 0, NULL, numbytes),
+ /* remember DMA address */
+ VMSTATE_UINT32(crq.data, SpaprTpmState),
+ VMSTATE_END_OF_LIST(),
+ }
};
static Property tpm_spapr_properties[] = {
diff --git a/hw/tpm/trace-events b/hw/tpm/trace-events
index edbe1bd7..b97eea24 100644
--- a/hw/tpm/trace-events
+++ b/hw/tpm/trace-events
@@ -67,3 +67,5 @@ tpm_spapr_do_crq_get_version(uint32_t version) "response: version %u"
tpm_spapr_do_crq_prepare_to_suspend(void) "response: preparing to suspend"
tpm_spapr_do_crq_unknown_msg_type(uint8_t type) "Unknown message type 0x%02x"
tpm_spapr_do_crq_unknown_crq(uint8_t raw1, uint8_t raw2) "unknown CRQ 0x%02x 0x%02x ..."
+tpm_spapr_post_load(void) "Delivering TPM response after resume"
+tpm_spapr_caught_response(uint32_t v) "Caught response to deliver after resume: %u bytes"
--
2.23.0