 63d211993b
			
		
	
	
		63d211993b
		
	
	
	
	
		
			
			Fixes, cleanups in ACPI, PCI, virtio. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAl70SM8PHG1zdEByZWRo YXQuY29tAAoJECgfDbjSjVRpmlYIAMX7h46FSx8jXJPLMVHYjlOnzwSCZdFXnNt+ qj6GZfIrLSDsnz+X7hRA5QlX23NBjhwDvcQC3ucvGwzFMmQRjGwCK8tJJSfFWYTB oL1/YpTU6qHxOtR8UynuZak/Rq822Ug6PSAazQDG39HbS2v5srHXC1aVNSbhiMIi 7SdE8wBWae3R7Y7sVfIU4pMc3GeztPiqgXewAyOskVqrTQzuwuBhwQiK7kd6Md2Y fdTP+pZrXl7czMjnb9dM6Wq1griFrGDQVesSiggfGGI3rQ3W8Z24k5k+u81DKi+1 fVXwXsebRokCpEYgWgmyK9D2SajNjmDWBdyCHvO64FClpAzZWlc= =J1qe -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging virtio,acpi,pci: fixes, cleanups. Fixes, cleanups in ACPI, PCI, virtio. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Thu 25 Jun 2020 07:48:47 BST # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * remotes/mst/tags/for_upstream: Rename use_acpi_pci_hotplug to more appropriate use_acpi_hotplug_bridge Stop vhost-user sending uninitialized mmap_offsets docs/specs/tpm: ACPI boot now supported for TPM/ARM arm/acpi: Add the TPM2.0 device under the DSDT acpi: Some build_tpm2() code reshape tests/acpi: update expected data files acpi: q35: drop _SB.PCI0.ISA.LPCD opregion. acpi: drop build_piix4_pm() acpi: drop serial/parallel enable bits from dsdt acpi: simplify build_isa_devices_aml() acpi: factor out fw_cfg_add_acpi_dsdt() acpi: move aml builder code for i8042 (kbd+mouse) device floppy: move cmos_get_fd_drive_type() from pc floppy: make isa_fdc_get_drive_max_chs static acpi: move aml builder code for floppy device acpi: bios-tables-test: show more context on asl diffs qtest: allow DSDT acpi table changes Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
		
			
				
	
	
		
			525 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			525 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| ===============
 | |
| 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_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
 | |
| -------------
 | |
| 
 | |
| 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.h``
 | |
|  - ``include/sysemu/tpm_backend.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:
 | |
|  - ``backends/tpm/tpm_passthrough.c``
 | |
|  - ``backends/tpm/tpm_util.c``
 | |
|  - ``include/sysemu/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:
 | |
|  - ``backends/tpm/tpm_emulator.c``
 | |
|  - ``backends/tpm/tpm_util.c``
 | |
|  - ``include/sysemu/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 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
 | |
| 
 | |
| 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
 |