qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

Merge remote-tracking branch 'remotes/stefanberger/tags/pull-tpm-2020-03-04-2' into staging

Merge tpm 2020/03/04 v2

# gpg: Signature made Thu 05 Mar 2020 17:21:05 GMT
# gpg: using RSA key B818B9CADF9089C2D5CEC66B75AD65802A0B4211
# gpg: Good signature from "Stefan Berger <stefanb@linux.vnet.ibm.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: B818 B9CA DF90 89C2 D5CE C66B 75AD 6580 2A0B 4211

* remotes/stefanberger/tags/pull-tpm-2020-03-04-2:
test: tpm-tis: Add Sysbus TPM-TIS device test
test: tpm-tis: Get prepared to share tests between ISA and sysbus devices
test: tpm: pass optional machine options to swtpm test functions
docs/specs/tpm: Document TPM_TIS sysbus device for ARM
hw/arm/virt: vTPM support
tpm: Add the SysBus TPM TIS device
tpm: Separate TPM_TIS and TPM_TIS_ISA configs
tpm: Separate tpm_tis common functions from isa code
tpm: Use TPMState as a common struct
tpm: rename TPM_TIS into TPM_TIS_ISA

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

+1207 -609
+1 -1
default-configs/i386-softmmu.mak
··· 20 20 #CONFIG_SGA=n 21 21 #CONFIG_TEST_DEVICES=n 22 22 #CONFIG_TPM_CRB=n 23 - #CONFIG_TPM_TIS=n 23 + #CONFIG_TPM_TIS_ISA=n 24 24 #CONFIG_VTD=n 25 25 26 26 # Boards:
+24 -1
docs/specs/tpm.rst
··· 18 18 0xfed40000-0xfed44fff available to the guest operating system. 19 19 20 20 QEMU files related to TPM TIS interface: 21 - - ``hw/tpm/tpm_tis.c`` 21 + - ``hw/tpm/tpm_tis_common.c`` 22 + - ``hw/tpm/tpm_tis_isa.c`` 23 + - ``hw/tpm/tpm_tis_sysbus.c`` 22 24 - ``hw/tpm/tpm_tis.h`` 25 + 26 + Both an ISA device and a sysbus device are available. The former is 27 + used with pc/q35 machine while the latter can be instantiated in the 28 + ARM virt machine. 23 29 24 30 CRB interface 25 31 ------------- ··· 324 330 -device spapr-vscsi,id=scsi0,reg=0x00002000 \ 325 331 -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x3,drive=drive-virtio-disk0,id=virtio-disk0 \ 326 332 -drive file=test.img,format=raw,if=none,id=drive-virtio-disk0 333 + 334 + In case an ARM virt machine is emulated, use the following command line: 335 + 336 + .. code-block:: console 337 + 338 + qemu-system-aarch64 -machine virt,gic-version=3,accel=kvm \ 339 + -cpu host -m 4G \ 340 + -nographic -no-acpi \ 341 + -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ 342 + -tpmdev emulator,id=tpm0,chardev=chrtpm \ 343 + -device tpm-tis-device,tpmdev=tpm0 \ 344 + -device virtio-blk-pci,drive=drv0 \ 345 + -drive format=qcow2,file=hda.qcow2,if=none,id=drv0 \ 346 + -drive if=pflash,format=raw,file=flash0.img,readonly \ 347 + -drive if=pflash,format=raw,file=flash1.img 348 + 349 + On ARM, ACPI boot with TPM is not yet supported. 327 350 328 351 In case SeaBIOS is used as firmware, it should show the TPM menu item 329 352 after entering the menu with 'ESC'.
+1
hw/arm/Kconfig
··· 5 5 imply VFIO_AMD_XGBE 6 6 imply VFIO_PLATFORM 7 7 imply VFIO_XGMAC 8 + imply TPM_TIS_SYSBUS 8 9 select A15MPCORE 9 10 select ACPI 10 11 select ARM_SMMUV3
+33
hw/arm/sysbus-fdt.c
··· 30 30 #include "hw/arm/sysbus-fdt.h" 31 31 #include "qemu/error-report.h" 32 32 #include "sysemu/device_tree.h" 33 + #include "sysemu/tpm.h" 33 34 #include "hw/platform-bus.h" 34 35 #include "hw/vfio/vfio-platform.h" 35 36 #include "hw/vfio/vfio-calxeda-xgmac.h" ··· 436 437 437 438 #endif /* CONFIG_LINUX */ 438 439 440 + /* 441 + * add_tpm_tis_fdt_node: Create a DT node for TPM TIS 442 + * 443 + * See kernel documentation: 444 + * Documentation/devicetree/bindings/security/tpm/tpm_tis_mmio.txt 445 + * Optional interrupt for command completion is not exposed 446 + */ 447 + static int add_tpm_tis_fdt_node(SysBusDevice *sbdev, void *opaque) 448 + { 449 + PlatformBusFDTData *data = opaque; 450 + PlatformBusDevice *pbus = data->pbus; 451 + void *fdt = data->fdt; 452 + const char *parent_node = data->pbus_node_name; 453 + char *nodename; 454 + uint32_t reg_attr[2]; 455 + uint64_t mmio_base; 456 + 457 + mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); 458 + nodename = g_strdup_printf("%s/tpm_tis@%" PRIx64, parent_node, mmio_base); 459 + qemu_fdt_add_subnode(fdt, nodename); 460 + 461 + qemu_fdt_setprop_string(fdt, nodename, "compatible", "tcg,tpm-tis-mmio"); 462 + 463 + reg_attr[0] = cpu_to_be32(mmio_base); 464 + reg_attr[1] = cpu_to_be32(0x5000); 465 + qemu_fdt_setprop(fdt, nodename, "reg", reg_attr, 2 * sizeof(uint32_t)); 466 + 467 + g_free(nodename); 468 + return 0; 469 + } 470 + 439 471 static int no_fdt_node(SysBusDevice *sbdev, void *opaque) 440 472 { 441 473 return 0; ··· 456 488 TYPE_BINDING(TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node), 457 489 VFIO_PLATFORM_BINDING("amd,xgbe-seattle-v1a", add_amd_xgbe_fdt_node), 458 490 #endif 491 + TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node), 459 492 TYPE_BINDING(TYPE_RAMFB_DEVICE, no_fdt_node), 460 493 TYPE_BINDING("", NULL), /* last element */ 461 494 };
+7
hw/arm/virt.c
··· 48 48 #include "sysemu/numa.h" 49 49 #include "sysemu/runstate.h" 50 50 #include "sysemu/sysemu.h" 51 + #include "sysemu/tpm.h" 51 52 #include "sysemu/kvm.h" 52 53 #include "hw/loader.h" 53 54 #include "exec/address-spaces.h" ··· 2083 2084 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE); 2084 2085 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); 2085 2086 machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM); 2087 + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS); 2086 2088 mc->block_default_type = IF_VIRTIO; 2087 2089 mc->no_cdrom = 1; 2088 2090 mc->pci_allow_0_address = true; ··· 2196 2198 2197 2199 static void virt_machine_5_0_options(MachineClass *mc) 2198 2200 { 2201 + static GlobalProperty compat[] = { 2202 + { TYPE_TPM_TIS_SYSBUS, "ppi", "false" }, 2203 + }; 2204 + 2205 + compat_props_add(mc->compat_props, compat, G_N_ELEMENTS(compat)); 2199 2206 } 2200 2207 DEFINE_VIRT_MACHINE_AS_LATEST(5, 0) 2201 2208
+1 -1
hw/i386/Kconfig
··· 20 20 imply SGA 21 21 imply TEST_DEVICES 22 22 imply TPM_CRB 23 - imply TPM_TIS 23 + imply TPM_TIS_ISA 24 24 imply VGA_PCI 25 25 imply VIRTIO_VGA 26 26 select FDC
+3 -3
hw/i386/acpi-build.c
··· 2026 2026 } 2027 2027 } 2028 2028 2029 - if (TPM_IS_TIS(tpm_find())) { 2029 + if (TPM_IS_TIS_ISA(tpm_find())) { 2030 2030 aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE, 2031 2031 TPM_TIS_ADDR_SIZE, AML_READ_WRITE)); 2032 2032 } ··· 2197 2197 /* Scan all PCI buses. Generate tables to support hotplug. */ 2198 2198 build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en); 2199 2199 2200 - if (TPM_IS_TIS(tpm)) { 2200 + if (TPM_IS_TIS_ISA(tpm)) { 2201 2201 if (misc->tpm_version == TPM_VERSION_2_0) { 2202 2202 dev = aml_device("TPM"); 2203 2203 aml_append(dev, aml_name_decl("_HID", ··· 2304 2304 (char *)&tpm2_ptr->log_area_start_address - table_data->data; 2305 2305 2306 2306 tpm2_ptr->platform_class = cpu_to_le16(TPM2_ACPI_CLASS_CLIENT); 2307 - if (TPM_IS_TIS(tpm_find())) { 2307 + if (TPM_IS_TIS_ISA(tpm_find())) { 2308 2308 tpm2_ptr->control_area_address = cpu_to_le64(0); 2309 2309 tpm2_ptr->start_method = cpu_to_le32(TPM2_START_METHOD_MMIO); 2310 2310 } else if (TPM_IS_CRB(tpm_find())) {
+11 -1
hw/tpm/Kconfig
··· 2 2 bool 3 3 depends on TPM 4 4 5 - config TPM_TIS 5 + config TPM_TIS_ISA 6 6 bool 7 7 depends on TPM && ISA_BUS 8 + select TPM_TIS 9 + 10 + config TPM_TIS_SYSBUS 11 + bool 12 + depends on TPM 13 + select TPM_TIS 14 + 15 + config TPM_TIS 16 + bool 17 + depends on TPM 8 18 select TPMDEV 9 19 10 20 config TPM_CRB
+3 -1
hw/tpm/Makefile.objs
··· 1 1 common-obj-$(CONFIG_TPM) += tpm_util.o 2 2 obj-$(call lor,$(CONFIG_TPM_TIS),$(CONFIG_TPM_CRB)) += tpm_ppi.o 3 - common-obj-$(CONFIG_TPM_TIS) += tpm_tis.o 3 + common-obj-$(CONFIG_TPM_TIS_ISA) += tpm_tis_isa.o 4 + common-obj-$(CONFIG_TPM_TIS_SYSBUS) += tpm_tis_sysbus.o 5 + common-obj-$(CONFIG_TPM_TIS) += tpm_tis_common.o 4 6 common-obj-$(CONFIG_TPM_CRB) += tpm_crb.o 5 7 common-obj-$(CONFIG_TPM_PASSTHROUGH) += tpm_passthrough.o 6 8 common-obj-$(CONFIG_TPM_EMULATOR) += tpm_emulator.o
+13 -168
hw/tpm/tpm_tis.c hw/tpm/tpm_tis_common.c
··· 1 1 /* 2 - * tpm_tis.c - QEMU's TPM TIS interface emulator 2 + * tpm_tis_common.c - QEMU's TPM TIS interface emulator 3 + * device agnostic functions 3 4 * 4 5 * Copyright (C) 2006,2010-2013 IBM Corporation 5 6 * ··· 21 22 * TPM TIS for TPM 2 implementation following TCG PC Client Platform 22 23 * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 23 24 */ 24 - 25 25 #include "qemu/osdep.h" 26 26 #include "hw/irq.h" 27 27 #include "hw/isa/isa.h" ··· 38 38 #include "tpm_ppi.h" 39 39 #include "trace.h" 40 40 41 - #define TPM_TIS_NUM_LOCALITIES 5 /* per spec */ 42 - #define TPM_TIS_LOCALITY_SHIFT 12 43 - #define TPM_TIS_NO_LOCALITY 0xff 44 - 45 - #define TPM_TIS_IS_VALID_LOCTY(x) ((x) < TPM_TIS_NUM_LOCALITIES) 46 - 47 - #define TPM_TIS_BUFFER_MAX 4096 48 - 49 - typedef enum { 50 - TPM_TIS_STATE_IDLE = 0, 51 - TPM_TIS_STATE_READY, 52 - TPM_TIS_STATE_COMPLETION, 53 - TPM_TIS_STATE_EXECUTION, 54 - TPM_TIS_STATE_RECEPTION, 55 - } TPMTISState; 56 - 57 - /* locality data -- all fields are persisted */ 58 - typedef struct TPMLocality { 59 - TPMTISState state; 60 - uint8_t access; 61 - uint32_t sts; 62 - uint32_t iface_id; 63 - uint32_t inte; 64 - uint32_t ints; 65 - } TPMLocality; 66 - 67 - typedef struct TPMState { 68 - ISADevice busdev; 69 - MemoryRegion mmio; 70 - 71 - unsigned char buffer[TPM_TIS_BUFFER_MAX]; 72 - uint16_t rw_offset; 73 - 74 - uint8_t active_locty; 75 - uint8_t aborting_locty; 76 - uint8_t next_locty; 77 - 78 - TPMLocality loc[TPM_TIS_NUM_LOCALITIES]; 79 - 80 - qemu_irq irq; 81 - uint32_t irq_num; 82 - 83 - TPMBackendCmd cmd; 84 - 85 - TPMBackend *be_driver; 86 - TPMVersion be_tpm_version; 87 - 88 - size_t be_buffer_size; 89 - 90 - bool ppi_enabled; 91 - TPMPPI ppi; 92 - } TPMState; 93 - 94 - #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) 41 + #include "tpm_tis.h" 95 42 96 43 #define DEBUG_TIS 0 97 44 ··· 281 228 /* 282 229 * Callback from the TPM to indicate that the response was received. 283 230 */ 284 - static void tpm_tis_request_completed(TPMIf *ti, int ret) 231 + void tpm_tis_request_completed(TPMState *s, int ret) 285 232 { 286 - TPMState *s = TPM(ti); 287 233 uint8_t locty = s->cmd.locty; 288 234 uint8_t l; 289 235 ··· 338 284 } 339 285 340 286 #ifdef DEBUG_TIS 341 - static void tpm_tis_dump_state(void *opaque, hwaddr addr) 287 + static void tpm_tis_dump_state(TPMState *s, hwaddr addr) 342 288 { 343 289 static const unsigned regs[] = { 344 290 TPM_TIS_REG_ACCESS, ··· 353 299 int idx; 354 300 uint8_t locty = tpm_tis_locality_from_addr(addr); 355 301 hwaddr base = addr & ~0xfff; 356 - TPMState *s = opaque; 357 302 358 303 printf("tpm_tis: active locality : %d\n" 359 304 "tpm_tis: state of locality %d : %d\n" ··· 363 308 364 309 for (idx = 0; regs[idx] != 0xfff; idx++) { 365 310 printf("tpm_tis: 0x%04x : 0x%08x\n", regs[idx], 366 - (int)tpm_tis_mmio_read(opaque, base + regs[idx], 4)); 311 + (int)tpm_tis_mmio_read(s, base + regs[idx], 4)); 367 312 } 368 313 369 314 printf("tpm_tis: r/w offset : %d\n" ··· 488 433 break; 489 434 #ifdef DEBUG_TIS 490 435 case TPM_TIS_REG_DEBUG: 491 - tpm_tis_dump_state(opaque, addr); 436 + tpm_tis_dump_state(s, addr); 492 437 break; 493 438 #endif 494 439 } ··· 822 767 } 823 768 } 824 769 825 - static const MemoryRegionOps tpm_tis_memory_ops = { 770 + const MemoryRegionOps tpm_tis_memory_ops = { 826 771 .read = tpm_tis_mmio_read, 827 772 .write = tpm_tis_mmio_write, 828 773 .endianness = DEVICE_LITTLE_ENDIAN, ··· 835 780 /* 836 781 * Get the TPMVersion of the backend device being used 837 782 */ 838 - static enum TPMVersion tpm_tis_get_tpm_version(TPMIf *ti) 783 + enum TPMVersion tpm_tis_get_tpm_version(TPMState *s) 839 784 { 840 - TPMState *s = TPM(ti); 841 - 842 785 if (tpm_backend_had_startup_error(s->be_driver)) { 843 786 return TPM_VERSION_UNSPEC; 844 787 } ··· 850 793 * This function is called when the machine starts, resets or due to 851 794 * S3 resume. 852 795 */ 853 - static void tpm_tis_reset(DeviceState *dev) 796 + void tpm_tis_reset(TPMState *s) 854 797 { 855 - TPMState *s = TPM(dev); 856 798 int c; 857 799 858 800 s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); ··· 896 838 897 839 /* persistent state handling */ 898 840 899 - static int tpm_tis_pre_save(void *opaque) 841 + int tpm_tis_pre_save(TPMState *s) 900 842 { 901 - TPMState *s = opaque; 902 843 uint8_t locty = s->active_locty; 903 844 904 845 trace_tpm_tis_pre_save(locty, s->rw_offset); 905 846 906 847 if (DEBUG_TIS) { 907 - tpm_tis_dump_state(opaque, 0); 848 + tpm_tis_dump_state(s, 0); 908 849 } 909 850 910 851 /* ··· 915 856 return 0; 916 857 } 917 858 918 - static const VMStateDescription vmstate_locty = { 859 + const VMStateDescription vmstate_locty = { 919 860 .name = "tpm-tis/locty", 920 861 .version_id = 0, 921 862 .fields = (VMStateField[]) { ··· 929 870 } 930 871 }; 931 872 932 - static const VMStateDescription vmstate_tpm_tis = { 933 - .name = "tpm-tis", 934 - .version_id = 0, 935 - .pre_save = tpm_tis_pre_save, 936 - .fields = (VMStateField[]) { 937 - VMSTATE_BUFFER(buffer, TPMState), 938 - VMSTATE_UINT16(rw_offset, TPMState), 939 - VMSTATE_UINT8(active_locty, TPMState), 940 - VMSTATE_UINT8(aborting_locty, TPMState), 941 - VMSTATE_UINT8(next_locty, TPMState), 942 - 943 - VMSTATE_STRUCT_ARRAY(loc, TPMState, TPM_TIS_NUM_LOCALITIES, 0, 944 - vmstate_locty, TPMLocality), 945 - 946 - VMSTATE_END_OF_LIST() 947 - } 948 - }; 949 - 950 - static Property tpm_tis_properties[] = { 951 - DEFINE_PROP_UINT32("irq", TPMState, irq_num, TPM_TIS_IRQ), 952 - DEFINE_PROP_TPMBE("tpmdev", TPMState, be_driver), 953 - DEFINE_PROP_BOOL("ppi", TPMState, ppi_enabled, true), 954 - DEFINE_PROP_END_OF_LIST(), 955 - }; 956 - 957 - static void tpm_tis_realizefn(DeviceState *dev, Error **errp) 958 - { 959 - TPMState *s = TPM(dev); 960 - 961 - if (!tpm_find()) { 962 - error_setg(errp, "at most one TPM device is permitted"); 963 - return; 964 - } 965 - 966 - if (!s->be_driver) { 967 - error_setg(errp, "'tpmdev' property is required"); 968 - return; 969 - } 970 - if (s->irq_num > 15) { 971 - error_setg(errp, "IRQ %d is outside valid range of 0 to 15", 972 - s->irq_num); 973 - return; 974 - } 975 - 976 - isa_init_irq(&s->busdev, &s->irq, s->irq_num); 977 - 978 - memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)), 979 - TPM_TIS_ADDR_BASE, &s->mmio); 980 - 981 - if (s->ppi_enabled) { 982 - tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)), 983 - TPM_PPI_ADDR_BASE, OBJECT(s)); 984 - } 985 - } 986 - 987 - static void tpm_tis_initfn(Object *obj) 988 - { 989 - TPMState *s = TPM(obj); 990 - 991 - memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, 992 - s, "tpm-tis-mmio", 993 - TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); 994 - } 995 - 996 - static void tpm_tis_class_init(ObjectClass *klass, void *data) 997 - { 998 - DeviceClass *dc = DEVICE_CLASS(klass); 999 - TPMIfClass *tc = TPM_IF_CLASS(klass); 1000 - 1001 - dc->realize = tpm_tis_realizefn; 1002 - device_class_set_props(dc, tpm_tis_properties); 1003 - dc->reset = tpm_tis_reset; 1004 - dc->vmsd = &vmstate_tpm_tis; 1005 - tc->model = TPM_MODEL_TPM_TIS; 1006 - tc->get_version = tpm_tis_get_tpm_version; 1007 - tc->request_completed = tpm_tis_request_completed; 1008 - } 1009 - 1010 - static const TypeInfo tpm_tis_info = { 1011 - .name = TYPE_TPM_TIS, 1012 - .parent = TYPE_ISA_DEVICE, 1013 - .instance_size = sizeof(TPMState), 1014 - .instance_init = tpm_tis_initfn, 1015 - .class_init = tpm_tis_class_init, 1016 - .interfaces = (InterfaceInfo[]) { 1017 - { TYPE_TPM_IF }, 1018 - { } 1019 - } 1020 - }; 1021 - 1022 - static void tpm_tis_register(void) 1023 - { 1024 - type_register_static(&tpm_tis_info); 1025 - } 1026 - 1027 - type_init(tpm_tis_register)
+91
hw/tpm/tpm_tis.h
··· 1 + /* 2 + * tpm_tis.h - QEMU's TPM TIS common header 3 + * 4 + * Copyright (C) 2006,2010-2013 IBM Corporation 5 + * 6 + * Authors: 7 + * Stefan Berger <stefanb@us.ibm.com> 8 + * David Safford <safford@us.ibm.com> 9 + * 10 + * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at> 11 + * 12 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 13 + * See the COPYING file in the top-level directory. 14 + * 15 + * Implementation of the TIS interface according to specs found at 16 + * http://www.trustedcomputinggroup.org. This implementation currently 17 + * supports version 1.3, 21 March 2013 18 + * In the developers menu choose the PC Client section then find the TIS 19 + * specification. 20 + * 21 + * TPM TIS for TPM 2 implementation following TCG PC Client Platform 22 + * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 23 + */ 24 + #ifndef TPM_TPM_TIS_H 25 + #define TPM_TPM_TIS_H 26 + 27 + #include "qemu/osdep.h" 28 + #include "sysemu/tpm_backend.h" 29 + #include "tpm_ppi.h" 30 + 31 + #define TPM_TIS_NUM_LOCALITIES 5 /* per spec */ 32 + #define TPM_TIS_LOCALITY_SHIFT 12 33 + #define TPM_TIS_NO_LOCALITY 0xff 34 + 35 + #define TPM_TIS_IS_VALID_LOCTY(x) ((x) < TPM_TIS_NUM_LOCALITIES) 36 + 37 + #define TPM_TIS_BUFFER_MAX 4096 38 + 39 + typedef enum { 40 + TPM_TIS_STATE_IDLE = 0, 41 + TPM_TIS_STATE_READY, 42 + TPM_TIS_STATE_COMPLETION, 43 + TPM_TIS_STATE_EXECUTION, 44 + TPM_TIS_STATE_RECEPTION, 45 + } TPMTISState; 46 + 47 + /* locality data -- all fields are persisted */ 48 + typedef struct TPMLocality { 49 + TPMTISState state; 50 + uint8_t access; 51 + uint32_t sts; 52 + uint32_t iface_id; 53 + uint32_t inte; 54 + uint32_t ints; 55 + } TPMLocality; 56 + 57 + typedef struct TPMState { 58 + MemoryRegion mmio; 59 + 60 + unsigned char buffer[TPM_TIS_BUFFER_MAX]; 61 + uint16_t rw_offset; 62 + 63 + uint8_t active_locty; 64 + uint8_t aborting_locty; 65 + uint8_t next_locty; 66 + 67 + TPMLocality loc[TPM_TIS_NUM_LOCALITIES]; 68 + 69 + qemu_irq irq; 70 + uint32_t irq_num; 71 + 72 + TPMBackendCmd cmd; 73 + 74 + TPMBackend *be_driver; 75 + TPMVersion be_tpm_version; 76 + 77 + size_t be_buffer_size; 78 + 79 + bool ppi_enabled; 80 + TPMPPI ppi; 81 + } TPMState; 82 + 83 + extern const VMStateDescription vmstate_locty; 84 + extern const MemoryRegionOps tpm_tis_memory_ops; 85 + 86 + int tpm_tis_pre_save(TPMState *s); 87 + void tpm_tis_reset(TPMState *s); 88 + enum TPMVersion tpm_tis_get_tpm_version(TPMState *s); 89 + void tpm_tis_request_completed(TPMState *s, int ret); 90 + 91 + #endif /* TPM_TPM_TIS_H */
+170
hw/tpm/tpm_tis_isa.c
··· 1 + /* 2 + * tpm_tis_isa.c - QEMU's TPM TIS ISA Device 3 + * 4 + * Copyright (C) 2006,2010-2013 IBM Corporation 5 + * 6 + * Authors: 7 + * Stefan Berger <stefanb@us.ibm.com> 8 + * David Safford <safford@us.ibm.com> 9 + * 10 + * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at> 11 + * 12 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 13 + * See the COPYING file in the top-level directory. 14 + * 15 + * Implementation of the TIS interface according to specs found at 16 + * http://www.trustedcomputinggroup.org. This implementation currently 17 + * supports version 1.3, 21 March 2013 18 + * In the developers menu choose the PC Client section then find the TIS 19 + * specification. 20 + * 21 + * TPM TIS for TPM 2 implementation following TCG PC Client Platform 22 + * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 23 + */ 24 + 25 + #include "qemu/osdep.h" 26 + #include "hw/isa/isa.h" 27 + #include "hw/qdev-properties.h" 28 + #include "migration/vmstate.h" 29 + #include "tpm_util.h" 30 + #include "tpm_tis.h" 31 + 32 + typedef struct TPMStateISA { 33 + /*< private >*/ 34 + ISADevice parent_obj; 35 + 36 + /*< public >*/ 37 + TPMState state; /* not a QOM object */ 38 + } TPMStateISA; 39 + 40 + #define TPM_TIS_ISA(obj) OBJECT_CHECK(TPMStateISA, (obj), TYPE_TPM_TIS_ISA) 41 + 42 + static int tpm_tis_pre_save_isa(void *opaque) 43 + { 44 + TPMStateISA *isadev = opaque; 45 + 46 + return tpm_tis_pre_save(&isadev->state); 47 + } 48 + 49 + static const VMStateDescription vmstate_tpm_tis_isa = { 50 + .name = "tpm-tis", 51 + .version_id = 0, 52 + .pre_save = tpm_tis_pre_save_isa, 53 + .fields = (VMStateField[]) { 54 + VMSTATE_BUFFER(state.buffer, TPMStateISA), 55 + VMSTATE_UINT16(state.rw_offset, TPMStateISA), 56 + VMSTATE_UINT8(state.active_locty, TPMStateISA), 57 + VMSTATE_UINT8(state.aborting_locty, TPMStateISA), 58 + VMSTATE_UINT8(state.next_locty, TPMStateISA), 59 + 60 + VMSTATE_STRUCT_ARRAY(state.loc, TPMStateISA, TPM_TIS_NUM_LOCALITIES, 0, 61 + vmstate_locty, TPMLocality), 62 + 63 + VMSTATE_END_OF_LIST() 64 + } 65 + }; 66 + 67 + static void tpm_tis_isa_request_completed(TPMIf *ti, int ret) 68 + { 69 + TPMStateISA *isadev = TPM_TIS_ISA(ti); 70 + TPMState *s = &isadev->state; 71 + 72 + tpm_tis_request_completed(s, ret); 73 + } 74 + 75 + static enum TPMVersion tpm_tis_isa_get_tpm_version(TPMIf *ti) 76 + { 77 + TPMStateISA *isadev = TPM_TIS_ISA(ti); 78 + TPMState *s = &isadev->state; 79 + 80 + return tpm_tis_get_tpm_version(s); 81 + } 82 + 83 + static void tpm_tis_isa_reset(DeviceState *dev) 84 + { 85 + TPMStateISA *isadev = TPM_TIS_ISA(dev); 86 + TPMState *s = &isadev->state; 87 + 88 + return tpm_tis_reset(s); 89 + } 90 + 91 + static Property tpm_tis_isa_properties[] = { 92 + DEFINE_PROP_UINT32("irq", TPMStateISA, state.irq_num, TPM_TIS_IRQ), 93 + DEFINE_PROP_TPMBE("tpmdev", TPMStateISA, state.be_driver), 94 + DEFINE_PROP_BOOL("ppi", TPMStateISA, state.ppi_enabled, true), 95 + DEFINE_PROP_END_OF_LIST(), 96 + }; 97 + 98 + static void tpm_tis_isa_initfn(Object *obj) 99 + { 100 + TPMStateISA *isadev = TPM_TIS_ISA(obj); 101 + TPMState *s = &isadev->state; 102 + 103 + memory_region_init_io(&s->mmio, obj, &tpm_tis_memory_ops, 104 + s, "tpm-tis-mmio", 105 + TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); 106 + } 107 + 108 + static void tpm_tis_isa_realizefn(DeviceState *dev, Error **errp) 109 + { 110 + TPMStateISA *isadev = TPM_TIS_ISA(dev); 111 + TPMState *s = &isadev->state; 112 + 113 + if (!tpm_find()) { 114 + error_setg(errp, "at most one TPM device is permitted"); 115 + return; 116 + } 117 + 118 + if (!s->be_driver) { 119 + error_setg(errp, "'tpmdev' property is required"); 120 + return; 121 + } 122 + if (s->irq_num > 15) { 123 + error_setg(errp, "IRQ %d is outside valid range of 0 to 15", 124 + s->irq_num); 125 + return; 126 + } 127 + 128 + isa_init_irq(ISA_DEVICE(dev), &s->irq, s->irq_num); 129 + 130 + memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)), 131 + TPM_TIS_ADDR_BASE, &s->mmio); 132 + 133 + if (s->ppi_enabled) { 134 + tpm_ppi_init(&s->ppi, isa_address_space(ISA_DEVICE(dev)), 135 + TPM_PPI_ADDR_BASE, OBJECT(dev)); 136 + } 137 + } 138 + 139 + static void tpm_tis_isa_class_init(ObjectClass *klass, void *data) 140 + { 141 + DeviceClass *dc = DEVICE_CLASS(klass); 142 + TPMIfClass *tc = TPM_IF_CLASS(klass); 143 + 144 + device_class_set_props(dc, tpm_tis_isa_properties); 145 + dc->vmsd = &vmstate_tpm_tis_isa; 146 + tc->model = TPM_MODEL_TPM_TIS; 147 + dc->realize = tpm_tis_isa_realizefn; 148 + dc->reset = tpm_tis_isa_reset; 149 + tc->request_completed = tpm_tis_isa_request_completed; 150 + tc->get_version = tpm_tis_isa_get_tpm_version; 151 + } 152 + 153 + static const TypeInfo tpm_tis_isa_info = { 154 + .name = TYPE_TPM_TIS_ISA, 155 + .parent = TYPE_ISA_DEVICE, 156 + .instance_size = sizeof(TPMStateISA), 157 + .instance_init = tpm_tis_isa_initfn, 158 + .class_init = tpm_tis_isa_class_init, 159 + .interfaces = (InterfaceInfo[]) { 160 + { TYPE_TPM_IF }, 161 + { } 162 + } 163 + }; 164 + 165 + static void tpm_tis_isa_register(void) 166 + { 167 + type_register_static(&tpm_tis_isa_info); 168 + } 169 + 170 + type_init(tpm_tis_isa_register)
+159
hw/tpm/tpm_tis_sysbus.c
··· 1 + /* 2 + * tpm_tis_sysbus.c - QEMU's TPM TIS SYSBUS Device 3 + * 4 + * Copyright (C) 2006,2010-2013 IBM Corporation 5 + * 6 + * Authors: 7 + * Stefan Berger <stefanb@us.ibm.com> 8 + * David Safford <safford@us.ibm.com> 9 + * 10 + * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at> 11 + * 12 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 13 + * See the COPYING file in the top-level directory. 14 + * 15 + * Implementation of the TIS interface according to specs found at 16 + * http://www.trustedcomputinggroup.org. This implementation currently 17 + * supports version 1.3, 21 March 2013 18 + * In the developers menu choose the PC Client section then find the TIS 19 + * specification. 20 + * 21 + * TPM TIS for TPM 2 implementation following TCG PC Client Platform 22 + * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 23 + */ 24 + 25 + #include "qemu/osdep.h" 26 + #include "hw/qdev-properties.h" 27 + #include "migration/vmstate.h" 28 + #include "tpm_util.h" 29 + #include "hw/sysbus.h" 30 + #include "tpm_tis.h" 31 + 32 + typedef struct TPMStateSysBus { 33 + /*< private >*/ 34 + SysBusDevice parent_obj; 35 + 36 + /*< public >*/ 37 + TPMState state; /* not a QOM object */ 38 + } TPMStateSysBus; 39 + 40 + #define TPM_TIS_SYSBUS(obj) OBJECT_CHECK(TPMStateSysBus, (obj), TYPE_TPM_TIS_SYSBUS) 41 + 42 + static int tpm_tis_pre_save_sysbus(void *opaque) 43 + { 44 + TPMStateSysBus *sbdev = opaque; 45 + 46 + return tpm_tis_pre_save(&sbdev->state); 47 + } 48 + 49 + static const VMStateDescription vmstate_tpm_tis_sysbus = { 50 + .name = "tpm-tis", 51 + .version_id = 0, 52 + .pre_save = tpm_tis_pre_save_sysbus, 53 + .fields = (VMStateField[]) { 54 + VMSTATE_BUFFER(state.buffer, TPMStateSysBus), 55 + VMSTATE_UINT16(state.rw_offset, TPMStateSysBus), 56 + VMSTATE_UINT8(state.active_locty, TPMStateSysBus), 57 + VMSTATE_UINT8(state.aborting_locty, TPMStateSysBus), 58 + VMSTATE_UINT8(state.next_locty, TPMStateSysBus), 59 + 60 + VMSTATE_STRUCT_ARRAY(state.loc, TPMStateSysBus, TPM_TIS_NUM_LOCALITIES, 61 + 0, vmstate_locty, TPMLocality), 62 + 63 + VMSTATE_END_OF_LIST() 64 + } 65 + }; 66 + 67 + static void tpm_tis_sysbus_request_completed(TPMIf *ti, int ret) 68 + { 69 + TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(ti); 70 + TPMState *s = &sbdev->state; 71 + 72 + tpm_tis_request_completed(s, ret); 73 + } 74 + 75 + static enum TPMVersion tpm_tis_sysbus_get_tpm_version(TPMIf *ti) 76 + { 77 + TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(ti); 78 + TPMState *s = &sbdev->state; 79 + 80 + return tpm_tis_get_tpm_version(s); 81 + } 82 + 83 + static void tpm_tis_sysbus_reset(DeviceState *dev) 84 + { 85 + TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev); 86 + TPMState *s = &sbdev->state; 87 + 88 + return tpm_tis_reset(s); 89 + } 90 + 91 + static Property tpm_tis_sysbus_properties[] = { 92 + DEFINE_PROP_UINT32("irq", TPMStateSysBus, state.irq_num, TPM_TIS_IRQ), 93 + DEFINE_PROP_TPMBE("tpmdev", TPMStateSysBus, state.be_driver), 94 + DEFINE_PROP_BOOL("ppi", TPMStateSysBus, state.ppi_enabled, true), 95 + DEFINE_PROP_END_OF_LIST(), 96 + }; 97 + 98 + static void tpm_tis_sysbus_initfn(Object *obj) 99 + { 100 + TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(obj); 101 + TPMState *s = &sbdev->state; 102 + 103 + memory_region_init_io(&s->mmio, obj, &tpm_tis_memory_ops, 104 + s, "tpm-tis-mmio", 105 + TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); 106 + 107 + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); 108 + sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq); 109 + } 110 + 111 + static void tpm_tis_sysbus_realizefn(DeviceState *dev, Error **errp) 112 + { 113 + TPMStateSysBus *sbdev = TPM_TIS_SYSBUS(dev); 114 + TPMState *s = &sbdev->state; 115 + 116 + if (!tpm_find()) { 117 + error_setg(errp, "at most one TPM device is permitted"); 118 + return; 119 + } 120 + 121 + if (!s->be_driver) { 122 + error_setg(errp, "'tpmdev' property is required"); 123 + return; 124 + } 125 + } 126 + 127 + static void tpm_tis_sysbus_class_init(ObjectClass *klass, void *data) 128 + { 129 + DeviceClass *dc = DEVICE_CLASS(klass); 130 + TPMIfClass *tc = TPM_IF_CLASS(klass); 131 + 132 + device_class_set_props(dc, tpm_tis_sysbus_properties); 133 + dc->vmsd = &vmstate_tpm_tis_sysbus; 134 + tc->model = TPM_MODEL_TPM_TIS; 135 + dc->realize = tpm_tis_sysbus_realizefn; 136 + dc->user_creatable = true; 137 + dc->reset = tpm_tis_sysbus_reset; 138 + tc->request_completed = tpm_tis_sysbus_request_completed; 139 + tc->get_version = tpm_tis_sysbus_get_tpm_version; 140 + } 141 + 142 + static const TypeInfo tpm_tis_sysbus_info = { 143 + .name = TYPE_TPM_TIS_SYSBUS, 144 + .parent = TYPE_SYS_BUS_DEVICE, 145 + .instance_size = sizeof(TPMStateSysBus), 146 + .instance_init = tpm_tis_sysbus_initfn, 147 + .class_init = tpm_tis_sysbus_class_init, 148 + .interfaces = (InterfaceInfo[]) { 149 + { TYPE_TPM_IF }, 150 + { } 151 + } 152 + }; 153 + 154 + static void tpm_tis_sysbus_register(void) 155 + { 156 + type_register_static(&tpm_tis_sysbus_info); 157 + } 158 + 159 + type_init(tpm_tis_sysbus_register)
+4 -3
include/sysemu/tpm.h
··· 43 43 enum TPMVersion (*get_version)(TPMIf *obj); 44 44 } TPMIfClass; 45 45 46 - #define TYPE_TPM_TIS "tpm-tis" 46 + #define TYPE_TPM_TIS_ISA "tpm-tis" 47 + #define TYPE_TPM_TIS_SYSBUS "tpm-tis-device" 47 48 #define TYPE_TPM_CRB "tpm-crb" 48 49 #define TYPE_TPM_SPAPR "tpm-spapr" 49 50 50 - #define TPM_IS_TIS(chr) \ 51 - object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS) 51 + #define TPM_IS_TIS_ISA(chr) \ 52 + object_dynamic_cast(OBJECT(chr), TYPE_TPM_TIS_ISA) 52 53 #define TPM_IS_CRB(chr) \ 53 54 object_dynamic_cast(OBJECT(chr), TYPE_TPM_CRB) 54 55 #define TPM_IS_SPAPR(chr) \
+8 -3
tests/qtest/Makefile.include
··· 54 54 check-qtest-i386-y += vmgenid-test 55 55 check-qtest-i386-$(CONFIG_TPM_CRB) += tpm-crb-swtpm-test 56 56 check-qtest-i386-$(CONFIG_TPM_CRB) += tpm-crb-test 57 - check-qtest-i386-$(CONFIG_TPM_TIS) += tpm-tis-swtpm-test 58 - check-qtest-i386-$(CONFIG_TPM_TIS) += tpm-tis-test 57 + check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tpm-tis-swtpm-test 58 + check-qtest-i386-$(CONFIG_TPM_TIS_ISA) += tpm-tis-test 59 59 check-qtest-i386-$(CONFIG_SLIRP) += test-netfilter 60 60 check-qtest-i386-$(CONFIG_POSIX) += test-filter-mirror 61 61 check-qtest-i386-$(CONFIG_RTL8139_PCI) += test-filter-redirector ··· 130 130 check-qtest-arm-$(CONFIG_PFLASH_CFI02) += pflash-cfi02-test 131 131 132 132 check-qtest-aarch64-y += arm-cpu-features 133 + check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-test 134 + check-qtest-aarch64-$(CONFIG_TPM_TIS_SYSBUS) += tpm-tis-device-swtpm-test 133 135 check-qtest-aarch64-y += numa-test 134 136 check-qtest-aarch64-y += boot-serial-test 135 137 check-qtest-aarch64-y += migration-test ··· 302 304 tests/qtest/tpm-crb-test$(EXESUF): tests/qtest/tpm-crb-test.o tests/qtest/tpm-emu.o $(test-io-obj-y) 303 305 tests/qtest/tpm-tis-swtpm-test$(EXESUF): tests/qtest/tpm-tis-swtpm-test.o tests/qtest/tpm-emu.o \ 304 306 tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) 305 - tests/qtest/tpm-tis-test$(EXESUF): tests/qtest/tpm-tis-test.o tests/qtest/tpm-emu.o $(test-io-obj-y) 307 + tests/qtest/tpm-tis-device-swtpm-test$(EXESUF): tests/qtest/tpm-tis-device-swtpm-test.o tests/qtest/tpm-emu.o \ 308 + tests/qtest/tpm-util.o tests/qtest/tpm-tests.o $(test-io-obj-y) 309 + tests/qtest/tpm-tis-test$(EXESUF): tests/qtest/tpm-tis-test.o tests/qtest/tpm-tis-util.o tests/qtest/tpm-emu.o $(test-io-obj-y) 310 + tests/qtest/tpm-tis-device-test$(EXESUF): tests/qtest/tpm-tis-device-test.o tests/qtest/tpm-tis-util.o tests/qtest/tpm-emu.o $(test-io-obj-y) 306 311 307 312 # QTest rules 308 313
+7 -2
tests/qtest/tpm-crb-swtpm-test.c
··· 18 18 #include "libqtest.h" 19 19 #include "qemu/module.h" 20 20 #include "tpm-tests.h" 21 + #include "hw/acpi/tpm.h" 22 + 23 + /* Not used but needed for linking */ 24 + uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; 21 25 22 26 typedef struct TestState { 23 27 char *src_tpm_path; ··· 29 33 { 30 34 const TestState *ts = data; 31 35 32 - tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer, "tpm-crb"); 36 + tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_transfer, 37 + "tpm-crb", NULL); 33 38 } 34 39 35 40 static void tpm_crb_swtpm_migration_test(const void *data) ··· 37 42 const TestState *ts = data; 38 43 39 44 tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, 40 - tpm_util_crb_transfer, "tpm-crb"); 45 + tpm_util_crb_transfer, "tpm-crb", NULL); 41 46 } 42 47 43 48 int main(int argc, char **argv)
+3
tests/qtest/tpm-crb-test.c
··· 19 19 #include "qemu/module.h" 20 20 #include "tpm-emu.h" 21 21 22 + /* Not used but needed for linking */ 23 + uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; 24 + 22 25 #define TPM_CMD "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00" 23 26 24 27 static void tpm_crb_test(const void *data)
+6 -4
tests/qtest/tpm-tests.c
··· 30 30 } 31 31 32 32 void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, 33 - const char *ifmodel) 33 + const char *ifmodel, const char *machine_options) 34 34 { 35 35 char *args = NULL; 36 36 QTestState *s; ··· 47 47 g_assert_true(succ); 48 48 49 49 args = g_strdup_printf( 50 + "%s " 50 51 "-chardev socket,id=chr,path=%s " 51 52 "-tpmdev emulator,id=dev,chardev=chr " 52 53 "-device %s,tpmdev=dev", 53 - addr->u.q_unix.path, ifmodel); 54 + machine_options ? : "", addr->u.q_unix.path, ifmodel); 54 55 55 56 s = qtest_start(args); 56 57 g_free(args); ··· 78 79 void tpm_test_swtpm_migration_test(const char *src_tpm_path, 79 80 const char *dst_tpm_path, 80 81 const char *uri, tx_func *tx, 81 - const char *ifmodel) 82 + const char *ifmodel, 83 + const char *machine_options) 82 84 { 83 85 gboolean succ; 84 86 GPid src_tpm_pid, dst_tpm_pid; ··· 100 102 101 103 tpm_util_migration_start_qemu(&src_qemu, &dst_qemu, 102 104 src_tpm_addr, dst_tpm_addr, uri, 103 - ifmodel); 105 + ifmodel, machine_options); 104 106 105 107 tpm_util_startup(src_qemu, tx); 106 108 tpm_util_pcrextend(src_qemu, tx);
+3 -2
tests/qtest/tpm-tests.h
··· 16 16 #include "tpm-util.h" 17 17 18 18 void tpm_test_swtpm_test(const char *src_tpm_path, tx_func *tx, 19 - const char *ifmodel); 19 + const char *ifmodel, const char *machine_options); 20 20 21 21 void tpm_test_swtpm_migration_test(const char *src_tpm_path, 22 22 const char *dst_tpm_path, 23 23 const char *uri, tx_func *tx, 24 - const char *ifmodel); 24 + const char *ifmodel, 25 + const char *machine_options); 25 26 26 27 #endif /* TESTS_TPM_TESTS_H */
+76
tests/qtest/tpm-tis-device-swtpm-test.c
··· 1 + /* 2 + * QTest testcase for Sysbus TPM TIS talking to external swtpm and swtpm 3 + * migration 4 + * 5 + * Copyright (c) 2018 IBM Corporation 6 + * with parts borrowed from migration-test.c that is: 7 + * Copyright (c) 2016-2018 Red Hat, Inc. and/or its affiliates 8 + * 9 + * Authors: 10 + * Stefan Berger <stefanb@linux.vnet.ibm.com> 11 + * 12 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 13 + * See the COPYING file in the top-level directory. 14 + */ 15 + 16 + #include "qemu/osdep.h" 17 + #include <glib/gstdio.h> 18 + 19 + #include "libqtest.h" 20 + #include "qemu/module.h" 21 + #include "tpm-tests.h" 22 + #include "hw/acpi/tpm.h" 23 + 24 + uint64_t tpm_tis_base_addr = 0xc000000; 25 + #define MACHINE_OPTIONS "-machine virt,gic-version=max -accel tcg" 26 + 27 + typedef struct TestState { 28 + char *src_tpm_path; 29 + char *dst_tpm_path; 30 + char *uri; 31 + } TestState; 32 + 33 + static void tpm_tis_swtpm_test(const void *data) 34 + { 35 + const TestState *ts = data; 36 + 37 + tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, 38 + "tpm-tis-device", MACHINE_OPTIONS); 39 + } 40 + 41 + static void tpm_tis_swtpm_migration_test(const void *data) 42 + { 43 + const TestState *ts = data; 44 + 45 + tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, 46 + tpm_util_tis_transfer, "tpm-tis-device", 47 + MACHINE_OPTIONS); 48 + } 49 + 50 + int main(int argc, char **argv) 51 + { 52 + int ret; 53 + TestState ts = { 0 }; 54 + 55 + ts.src_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX", 56 + NULL); 57 + ts.dst_tpm_path = g_dir_make_tmp("qemu-tpm-tis-device-swtpm-test.XXXXXX", 58 + NULL); 59 + ts.uri = g_strdup_printf("unix:%s/migsocket", ts.src_tpm_path); 60 + 61 + module_call_init(MODULE_INIT_QOM); 62 + g_test_init(&argc, &argv, NULL); 63 + 64 + qtest_add_data_func("/tpm/tis-swtpm/test", &ts, tpm_tis_swtpm_test); 65 + qtest_add_data_func("/tpm/tis-swtpm-migration/test", &ts, 66 + tpm_tis_swtpm_migration_test); 67 + ret = g_test_run(); 68 + 69 + g_rmdir(ts.dst_tpm_path); 70 + g_free(ts.dst_tpm_path); 71 + g_rmdir(ts.src_tpm_path); 72 + g_free(ts.src_tpm_path); 73 + g_free(ts.uri); 74 + 75 + return ret; 76 + }
+87
tests/qtest/tpm-tis-device-test.c
··· 1 + /* 2 + * QTest testcase for SYSBUS TPM TIS 3 + * 4 + * Copyright (c) 2018 Red Hat, Inc. 5 + * Copyright (c) 2018 IBM Corporation 6 + * 7 + * Authors: 8 + * Marc-André Lureau <marcandre.lureau@redhat.com> 9 + * Stefan Berger <stefanb@linux.vnet.ibm.com> 10 + * 11 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 12 + * See the COPYING file in the top-level directory. 13 + */ 14 + 15 + #include "qemu/osdep.h" 16 + #include <glib/gstdio.h> 17 + 18 + #include "io/channel-socket.h" 19 + #include "libqtest-single.h" 20 + #include "qemu/module.h" 21 + #include "tpm-emu.h" 22 + #include "tpm-util.h" 23 + #include "tpm-tis-util.h" 24 + 25 + /* 26 + * As the Sysbus tpm-tis-device is instantiated on the ARM virt 27 + * platform bus and it is the only sysbus device dynamically 28 + * instantiated, it gets plugged at its base address 29 + */ 30 + uint64_t tpm_tis_base_addr = 0xc000000; 31 + 32 + int main(int argc, char **argv) 33 + { 34 + char *tmp_path = g_dir_make_tmp("qemu-tpm-tis-device-test.XXXXXX", NULL); 35 + GThread *thread; 36 + TestState test; 37 + char *args; 38 + int ret; 39 + 40 + module_call_init(MODULE_INIT_QOM); 41 + g_test_init(&argc, &argv, NULL); 42 + 43 + test.addr = g_new0(SocketAddress, 1); 44 + test.addr->type = SOCKET_ADDRESS_TYPE_UNIX; 45 + test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL); 46 + g_mutex_init(&test.data_mutex); 47 + g_cond_init(&test.data_cond); 48 + test.data_cond_signal = false; 49 + 50 + thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); 51 + tpm_emu_test_wait_cond(&test); 52 + 53 + args = g_strdup_printf( 54 + "-machine virt,gic-version=max -accel tcg " 55 + "-chardev socket,id=chr,path=%s " 56 + "-tpmdev emulator,id=dev,chardev=chr " 57 + "-device tpm-tis-device,tpmdev=dev", 58 + test.addr->u.q_unix.path); 59 + qtest_start(args); 60 + 61 + qtest_add_data_func("/tpm-tis/test_check_localities", &test, 62 + tpm_tis_test_check_localities); 63 + 64 + qtest_add_data_func("/tpm-tis/test_check_access_reg", &test, 65 + tpm_tis_test_check_access_reg); 66 + 67 + qtest_add_data_func("/tpm-tis/test_check_access_reg_seize", &test, 68 + tpm_tis_test_check_access_reg_seize); 69 + 70 + qtest_add_data_func("/tpm-tis/test_check_access_reg_release", &test, 71 + tpm_tis_test_check_access_reg_release); 72 + 73 + qtest_add_data_func("/tpm-tis/test_check_transmit", &test, 74 + tpm_tis_test_check_transmit); 75 + 76 + ret = g_test_run(); 77 + 78 + qtest_end(); 79 + 80 + g_thread_join(thread); 81 + g_unlink(test.addr->u.q_unix.path); 82 + qapi_free_SocketAddress(test.addr); 83 + g_rmdir(tmp_path); 84 + g_free(tmp_path); 85 + g_free(args); 86 + return ret; 87 + }
+6 -2
tests/qtest/tpm-tis-swtpm-test.c
··· 18 18 #include "libqtest.h" 19 19 #include "qemu/module.h" 20 20 #include "tpm-tests.h" 21 + #include "hw/acpi/tpm.h" 22 + 23 + uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; 21 24 22 25 typedef struct TestState { 23 26 char *src_tpm_path; ··· 29 32 { 30 33 const TestState *ts = data; 31 34 32 - tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, "tpm-tis"); 35 + tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_tis_transfer, 36 + "tpm-tis", NULL); 33 37 } 34 38 35 39 static void tpm_tis_swtpm_migration_test(const void *data) ··· 37 41 const TestState *ts = data; 38 42 39 43 tpm_test_swtpm_migration_test(ts->src_tpm_path, ts->dst_tpm_path, ts->uri, 40 - tpm_util_tis_transfer, "tpm-tis"); 44 + tpm_util_tis_transfer, "tpm-tis", NULL); 41 45 } 42 46 43 47 int main(int argc, char **argv)
+3 -411
tests/qtest/tpm-tis-test.c
··· 1 1 /* 2 - * QTest testcase for TPM TIS 2 + * QTest testcase for ISA TPM TIS 3 3 * 4 4 * Copyright (c) 2018 Red Hat, Inc. 5 5 * Copyright (c) 2018 IBM Corporation ··· 20 20 #include "libqtest-single.h" 21 21 #include "qemu/module.h" 22 22 #include "tpm-emu.h" 23 - 24 - #define TIS_REG(LOCTY, REG) \ 25 - (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) 26 - 27 - #define DEBUG_TIS_TEST 0 28 - 29 - #define DPRINTF(fmt, ...) do { \ 30 - if (DEBUG_TIS_TEST) { \ 31 - printf(fmt, ## __VA_ARGS__); \ 32 - } \ 33 - } while (0) 34 - 35 - #define DPRINTF_ACCESS \ 36 - DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ 37 - __func__, __LINE__, locty, l, access, pending_request_flag) 38 - 39 - #define DPRINTF_STS \ 40 - DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) 41 - 42 - static const uint8_t TPM_CMD[12] = 43 - "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; 44 - 45 - static void tpm_tis_test_check_localities(const void *data) 46 - { 47 - uint8_t locty; 48 - uint8_t access; 49 - uint32_t ifaceid; 50 - uint32_t capability; 51 - uint32_t didvid; 52 - uint32_t rid; 53 - 54 - for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { 55 - access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 56 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 57 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 58 - 59 - capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY)); 60 - g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0); 61 - 62 - ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID)); 63 - g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0); 64 - 65 - didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID)); 66 - g_assert_cmpint(didvid, !=, 0); 67 - g_assert_cmpint(didvid, !=, 0xffffffff); 68 - 69 - rid = readl(TIS_REG(locty, TPM_TIS_REG_RID)); 70 - g_assert_cmpint(rid, !=, 0); 71 - g_assert_cmpint(rid, !=, 0xffffffff); 72 - } 73 - } 74 - 75 - static void tpm_tis_test_check_access_reg(const void *data) 76 - { 77 - uint8_t locty; 78 - uint8_t access; 79 - 80 - /* do not test locality 4 (hw only) */ 81 - for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { 82 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 83 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 84 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 85 - 86 - /* request use of locality */ 87 - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 88 - 89 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 90 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 91 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 92 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 93 - 94 - /* release access */ 95 - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), 96 - TPM_TIS_ACCESS_ACTIVE_LOCALITY); 97 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 98 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 99 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 100 - } 101 - } 102 - 103 - /* 104 - * Test case for seizing access by a higher number locality 105 - */ 106 - static void tpm_tis_test_check_access_reg_seize(const void *data) 107 - { 108 - int locty, l; 109 - uint8_t access; 110 - uint8_t pending_request_flag; 111 - 112 - /* do not test locality 4 (hw only) */ 113 - for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { 114 - pending_request_flag = 0; 115 - 116 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 117 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 118 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 119 - 120 - /* request use of locality */ 121 - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 122 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 123 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 124 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 125 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 126 - 127 - /* lower localities cannot seize access */ 128 - for (l = 0; l < locty; l++) { 129 - /* lower locality is not active */ 130 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 131 - DPRINTF_ACCESS; 132 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 133 - pending_request_flag | 134 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 135 - 136 - /* try to request use from 'l' */ 137 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 138 - 139 - /* requesting use from 'l' was not possible; 140 - we must see REQUEST_USE and possibly PENDING_REQUEST */ 141 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 142 - DPRINTF_ACCESS; 143 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 144 - TPM_TIS_ACCESS_REQUEST_USE | 145 - pending_request_flag | 146 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 147 - 148 - /* locality 'locty' must be unchanged; 149 - we must see PENDING_REQUEST */ 150 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 151 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 152 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 153 - TPM_TIS_ACCESS_PENDING_REQUEST | 154 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 155 - 156 - /* try to seize from 'l' */ 157 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); 158 - /* seize from 'l' was not possible */ 159 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 160 - DPRINTF_ACCESS; 161 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 162 - TPM_TIS_ACCESS_REQUEST_USE | 163 - pending_request_flag | 164 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 165 - 166 - /* locality 'locty' must be unchanged */ 167 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 168 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 169 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 170 - TPM_TIS_ACCESS_PENDING_REQUEST | 171 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 172 - 173 - /* on the next loop we will have a PENDING_REQUEST flag 174 - set for locality 'l' */ 175 - pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; 176 - } 177 - 178 - /* higher localities can 'seize' access but not 'request use'; 179 - note: this will activate first l+1, then l+2 etc. */ 180 - for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 181 - /* try to 'request use' from 'l' */ 182 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 183 - 184 - /* requesting use from 'l' was not possible; we should see 185 - REQUEST_USE and may see PENDING_REQUEST */ 186 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 187 - DPRINTF_ACCESS; 188 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 189 - TPM_TIS_ACCESS_REQUEST_USE | 190 - pending_request_flag | 191 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 192 - 193 - /* locality 'l-1' must be unchanged; we should always 194 - see PENDING_REQUEST from 'l' requesting access */ 195 - access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 196 - DPRINTF_ACCESS; 197 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 198 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 199 - TPM_TIS_ACCESS_PENDING_REQUEST | 200 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 201 - 202 - /* try to seize from 'l' */ 203 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); 204 - 205 - /* seize from 'l' was possible */ 206 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 207 - DPRINTF_ACCESS; 208 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 209 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 210 - pending_request_flag | 211 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 212 - 213 - /* l - 1 should show that it has BEEN_SEIZED */ 214 - access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 215 - DPRINTF_ACCESS; 216 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 217 - TPM_TIS_ACCESS_BEEN_SEIZED | 218 - pending_request_flag | 219 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 220 - 221 - /* clear the BEEN_SEIZED flag and make sure it's gone */ 222 - writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS), 223 - TPM_TIS_ACCESS_BEEN_SEIZED); 224 - 225 - access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 226 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 227 - pending_request_flag | 228 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 229 - } 230 - 231 - /* PENDING_REQUEST will not be set if locty = 0 since all localities 232 - were active; in case of locty = 1, locality 0 will be active 233 - but no PENDING_REQUEST anywhere */ 234 - if (locty <= 1) { 235 - pending_request_flag = 0; 236 - } 237 - 238 - /* release access from l - 1; this activates locty - 1 */ 239 - l--; 240 - 241 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 242 - DPRINTF_ACCESS; 243 - 244 - DPRINTF("%s: %d: relinquishing control on l = %d\n", 245 - __func__, __LINE__, l); 246 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 247 - TPM_TIS_ACCESS_ACTIVE_LOCALITY); 248 - 249 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 250 - DPRINTF_ACCESS; 251 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 252 - pending_request_flag | 253 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 254 - 255 - for (l = locty - 1; l >= 0; l--) { 256 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 257 - DPRINTF_ACCESS; 258 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 259 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 260 - pending_request_flag | 261 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 262 - 263 - /* release this locality */ 264 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 265 - TPM_TIS_ACCESS_ACTIVE_LOCALITY); 266 - 267 - if (l == 1) { 268 - pending_request_flag = 0; 269 - } 270 - } 271 - 272 - /* no locality may be active now */ 273 - for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 274 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 275 - DPRINTF_ACCESS; 276 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 277 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 278 - } 279 - } 280 - } 281 - 282 - /* 283 - * Test case for getting access when higher number locality relinquishes access 284 - */ 285 - static void tpm_tis_test_check_access_reg_release(const void *data) 286 - { 287 - int locty, l; 288 - uint8_t access; 289 - uint8_t pending_request_flag; 290 - 291 - /* do not test locality 4 (hw only) */ 292 - for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { 293 - pending_request_flag = 0; 294 - 295 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 296 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 297 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 298 - 299 - /* request use of locality */ 300 - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 301 - access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 302 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 303 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 304 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 23 + #include "tpm-tis-util.h" 305 24 306 - /* request use of all other localities */ 307 - for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 308 - if (l == locty) { 309 - continue; 310 - } 311 - /* request use of locality 'l' -- we MUST see REQUEST USE and 312 - may see PENDING_REQUEST */ 313 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 314 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 315 - DPRINTF_ACCESS; 316 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 317 - TPM_TIS_ACCESS_REQUEST_USE | 318 - pending_request_flag | 319 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 320 - pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; 321 - } 322 - /* release locality 'locty' */ 323 - writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), 324 - TPM_TIS_ACCESS_ACTIVE_LOCALITY); 325 - /* highest locality should now be active; release it and make sure the 326 - next higest locality is active afterwards */ 327 - for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { 328 - if (l == locty) { 329 - continue; 330 - } 331 - /* 'l' should be active now */ 332 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 333 - DPRINTF_ACCESS; 334 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 335 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 336 - pending_request_flag | 337 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 338 - /* 'l' relinquishes access */ 339 - writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 340 - TPM_TIS_ACCESS_ACTIVE_LOCALITY); 341 - access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 342 - DPRINTF_ACCESS; 343 - if (l == 1 || (locty <= 1 && l == 2)) { 344 - pending_request_flag = 0; 345 - } 346 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 347 - pending_request_flag | 348 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 349 - } 350 - } 351 - } 352 - 353 - /* 354 - * Test case for transmitting packets 355 - */ 356 - static void tpm_tis_test_check_transmit(const void *data) 357 - { 358 - const TestState *s = data; 359 - uint8_t access; 360 - uint32_t sts; 361 - uint16_t bcount; 362 - size_t i; 363 - 364 - /* request use of locality 0 */ 365 - writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 366 - access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 367 - g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 368 - TPM_TIS_ACCESS_ACTIVE_LOCALITY | 369 - TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 370 - 371 - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 372 - DPRINTF_STS; 373 - 374 - g_assert_cmpint(sts & 0xff, ==, 0); 375 - g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==, 376 - TPM_TIS_STS_TPM_FAMILY2_0); 377 - 378 - bcount = (sts >> 8) & 0xffff; 379 - g_assert_cmpint(bcount, >=, 128); 380 - 381 - writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); 382 - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 383 - DPRINTF_STS; 384 - g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); 385 - 386 - /* transmit command */ 387 - for (i = 0; i < sizeof(TPM_CMD); i++) { 388 - writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]); 389 - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 390 - DPRINTF_STS; 391 - if (i < sizeof(TPM_CMD) - 1) { 392 - g_assert_cmpint(sts & 0xff, ==, 393 - TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); 394 - } else { 395 - g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); 396 - } 397 - g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); 398 - } 399 - /* start processing */ 400 - writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); 401 - 402 - uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; 403 - do { 404 - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 405 - if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { 406 - break; 407 - } 408 - } while (g_get_monotonic_time() < end_time); 409 - 410 - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 411 - DPRINTF_STS; 412 - g_assert_cmpint(sts & 0xff, == , 413 - TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); 414 - bcount = (sts >> 8) & 0xffff; 415 - 416 - /* read response */ 417 - uint8_t tpm_msg[sizeof(struct tpm_hdr)]; 418 - g_assert_cmpint(sizeof(tpm_msg), ==, bcount); 419 - 420 - for (i = 0; i < sizeof(tpm_msg); i++) { 421 - tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); 422 - sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 423 - DPRINTF_STS; 424 - if (sts & TPM_TIS_STS_DATA_AVAILABLE) { 425 - g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); 426 - } 427 - } 428 - g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); 429 - 430 - /* relinquish use of locality 0 */ 431 - writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); 432 - access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 433 - } 25 + uint64_t tpm_tis_base_addr = TPM_TIS_ADDR_BASE; 434 26 435 27 int main(int argc, char **argv) 436 28 {
+451
tests/qtest/tpm-tis-util.c
··· 1 + /* 2 + * QTest testcase for TPM TIS: common test functions used for both 3 + * the ISA and SYSBUS devices 4 + * 5 + * Copyright (c) 2018 Red Hat, Inc. 6 + * Copyright (c) 2018 IBM Corporation 7 + * 8 + * Authors: 9 + * Marc-André Lureau <marcandre.lureau@redhat.com> 10 + * Stefan Berger <stefanb@linux.vnet.ibm.com> 11 + * 12 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 13 + * See the COPYING file in the top-level directory. 14 + */ 15 + 16 + #include "qemu/osdep.h" 17 + #include <glib/gstdio.h> 18 + 19 + #include "hw/acpi/tpm.h" 20 + #include "io/channel-socket.h" 21 + #include "libqtest-single.h" 22 + #include "qemu/module.h" 23 + #include "tpm-emu.h" 24 + #include "tpm-util.h" 25 + #include "tpm-tis-util.h" 26 + 27 + #define DEBUG_TIS_TEST 0 28 + 29 + #define DPRINTF(fmt, ...) do { \ 30 + if (DEBUG_TIS_TEST) { \ 31 + printf(fmt, ## __VA_ARGS__); \ 32 + } \ 33 + } while (0) 34 + 35 + #define DPRINTF_ACCESS \ 36 + DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ 37 + __func__, __LINE__, locty, l, access, pending_request_flag) 38 + 39 + #define DPRINTF_STS \ 40 + DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) 41 + 42 + static const uint8_t TPM_CMD[12] = 43 + "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; 44 + 45 + void tpm_tis_test_check_localities(const void *data) 46 + { 47 + uint8_t locty; 48 + uint8_t access; 49 + uint32_t ifaceid; 50 + uint32_t capability; 51 + uint32_t didvid; 52 + uint32_t rid; 53 + 54 + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { 55 + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 56 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 57 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 58 + 59 + capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY)); 60 + g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0); 61 + 62 + ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID)); 63 + g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0); 64 + 65 + didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID)); 66 + g_assert_cmpint(didvid, !=, 0); 67 + g_assert_cmpint(didvid, !=, 0xffffffff); 68 + 69 + rid = readl(TIS_REG(locty, TPM_TIS_REG_RID)); 70 + g_assert_cmpint(rid, !=, 0); 71 + g_assert_cmpint(rid, !=, 0xffffffff); 72 + } 73 + } 74 + 75 + void tpm_tis_test_check_access_reg(const void *data) 76 + { 77 + uint8_t locty; 78 + uint8_t access; 79 + 80 + /* do not test locality 4 (hw only) */ 81 + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { 82 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 83 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 84 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 85 + 86 + /* request use of locality */ 87 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 88 + 89 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 90 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 91 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 92 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 93 + 94 + /* release access */ 95 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), 96 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 97 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 98 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 99 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 100 + } 101 + } 102 + 103 + /* 104 + * Test case for seizing access by a higher number locality 105 + */ 106 + void tpm_tis_test_check_access_reg_seize(const void *data) 107 + { 108 + int locty, l; 109 + uint8_t access; 110 + uint8_t pending_request_flag; 111 + 112 + /* do not test locality 4 (hw only) */ 113 + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { 114 + pending_request_flag = 0; 115 + 116 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 117 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 118 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 119 + 120 + /* request use of locality */ 121 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 122 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 123 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 124 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 125 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 126 + 127 + /* lower localities cannot seize access */ 128 + for (l = 0; l < locty; l++) { 129 + /* lower locality is not active */ 130 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 131 + DPRINTF_ACCESS; 132 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 133 + pending_request_flag | 134 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 135 + 136 + /* try to request use from 'l' */ 137 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 138 + 139 + /* 140 + * requesting use from 'l' was not possible; 141 + * we must see REQUEST_USE and possibly PENDING_REQUEST 142 + */ 143 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 144 + DPRINTF_ACCESS; 145 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 146 + TPM_TIS_ACCESS_REQUEST_USE | 147 + pending_request_flag | 148 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 149 + 150 + /* 151 + * locality 'locty' must be unchanged; 152 + * we must see PENDING_REQUEST 153 + */ 154 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 155 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 156 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 157 + TPM_TIS_ACCESS_PENDING_REQUEST | 158 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 159 + 160 + /* try to seize from 'l' */ 161 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); 162 + /* seize from 'l' was not possible */ 163 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 164 + DPRINTF_ACCESS; 165 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 166 + TPM_TIS_ACCESS_REQUEST_USE | 167 + pending_request_flag | 168 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 169 + 170 + /* locality 'locty' must be unchanged */ 171 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 172 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 173 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 174 + TPM_TIS_ACCESS_PENDING_REQUEST | 175 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 176 + 177 + /* 178 + * on the next loop we will have a PENDING_REQUEST flag 179 + * set for locality 'l' 180 + */ 181 + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; 182 + } 183 + 184 + /* 185 + * higher localities can 'seize' access but not 'request use'; 186 + * note: this will activate first l+1, then l+2 etc. 187 + */ 188 + for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 189 + /* try to 'request use' from 'l' */ 190 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 191 + 192 + /* 193 + * requesting use from 'l' was not possible; we should see 194 + * REQUEST_USE and may see PENDING_REQUEST 195 + */ 196 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 197 + DPRINTF_ACCESS; 198 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 199 + TPM_TIS_ACCESS_REQUEST_USE | 200 + pending_request_flag | 201 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 202 + 203 + /* 204 + * locality 'l-1' must be unchanged; we should always 205 + * see PENDING_REQUEST from 'l' requesting access 206 + */ 207 + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 208 + DPRINTF_ACCESS; 209 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 210 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 211 + TPM_TIS_ACCESS_PENDING_REQUEST | 212 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 213 + 214 + /* try to seize from 'l' */ 215 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); 216 + 217 + /* seize from 'l' was possible */ 218 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 219 + DPRINTF_ACCESS; 220 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 221 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 222 + pending_request_flag | 223 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 224 + 225 + /* l - 1 should show that it has BEEN_SEIZED */ 226 + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 227 + DPRINTF_ACCESS; 228 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 229 + TPM_TIS_ACCESS_BEEN_SEIZED | 230 + pending_request_flag | 231 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 232 + 233 + /* clear the BEEN_SEIZED flag and make sure it's gone */ 234 + writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS), 235 + TPM_TIS_ACCESS_BEEN_SEIZED); 236 + 237 + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 238 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 239 + pending_request_flag | 240 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 241 + } 242 + 243 + /* 244 + * PENDING_REQUEST will not be set if locty = 0 since all localities 245 + * were active; in case of locty = 1, locality 0 will be active 246 + * but no PENDING_REQUEST anywhere 247 + */ 248 + if (locty <= 1) { 249 + pending_request_flag = 0; 250 + } 251 + 252 + /* release access from l - 1; this activates locty - 1 */ 253 + l--; 254 + 255 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 256 + DPRINTF_ACCESS; 257 + 258 + DPRINTF("%s: %d: relinquishing control on l = %d\n", 259 + __func__, __LINE__, l); 260 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 261 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 262 + 263 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 264 + DPRINTF_ACCESS; 265 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 266 + pending_request_flag | 267 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 268 + 269 + for (l = locty - 1; l >= 0; l--) { 270 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 271 + DPRINTF_ACCESS; 272 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 273 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 274 + pending_request_flag | 275 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 276 + 277 + /* release this locality */ 278 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 279 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 280 + 281 + if (l == 1) { 282 + pending_request_flag = 0; 283 + } 284 + } 285 + 286 + /* no locality may be active now */ 287 + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 288 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 289 + DPRINTF_ACCESS; 290 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 291 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 292 + } 293 + } 294 + } 295 + 296 + /* 297 + * Test case for getting access when higher number locality relinquishes access 298 + */ 299 + void tpm_tis_test_check_access_reg_release(const void *data) 300 + { 301 + int locty, l; 302 + uint8_t access; 303 + uint8_t pending_request_flag; 304 + 305 + /* do not test locality 4 (hw only) */ 306 + for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { 307 + pending_request_flag = 0; 308 + 309 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 310 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 311 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 312 + 313 + /* request use of locality */ 314 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 315 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 316 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 317 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 318 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 319 + 320 + /* request use of all other localities */ 321 + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 322 + if (l == locty) { 323 + continue; 324 + } 325 + /* 326 + * request use of locality 'l' -- we MUST see REQUEST USE and 327 + * may see PENDING_REQUEST 328 + */ 329 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 330 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 331 + DPRINTF_ACCESS; 332 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 333 + TPM_TIS_ACCESS_REQUEST_USE | 334 + pending_request_flag | 335 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 336 + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; 337 + } 338 + /* release locality 'locty' */ 339 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), 340 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 341 + /* 342 + * highest locality should now be active; release it and make sure the 343 + * next higest locality is active afterwards 344 + */ 345 + for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { 346 + if (l == locty) { 347 + continue; 348 + } 349 + /* 'l' should be active now */ 350 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 351 + DPRINTF_ACCESS; 352 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 353 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 354 + pending_request_flag | 355 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 356 + /* 'l' relinquishes access */ 357 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 358 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 359 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 360 + DPRINTF_ACCESS; 361 + if (l == 1 || (locty <= 1 && l == 2)) { 362 + pending_request_flag = 0; 363 + } 364 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 365 + pending_request_flag | 366 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 367 + } 368 + } 369 + } 370 + 371 + /* 372 + * Test case for transmitting packets 373 + */ 374 + void tpm_tis_test_check_transmit(const void *data) 375 + { 376 + const TestState *s = data; 377 + uint8_t access; 378 + uint32_t sts; 379 + uint16_t bcount; 380 + size_t i; 381 + 382 + /* request use of locality 0 */ 383 + writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 384 + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 385 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 386 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 387 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 388 + 389 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 390 + DPRINTF_STS; 391 + 392 + g_assert_cmpint(sts & 0xff, ==, 0); 393 + g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==, 394 + TPM_TIS_STS_TPM_FAMILY2_0); 395 + 396 + bcount = (sts >> 8) & 0xffff; 397 + g_assert_cmpint(bcount, >=, 128); 398 + 399 + writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); 400 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 401 + DPRINTF_STS; 402 + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); 403 + 404 + /* transmit command */ 405 + for (i = 0; i < sizeof(TPM_CMD); i++) { 406 + writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]); 407 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 408 + DPRINTF_STS; 409 + if (i < sizeof(TPM_CMD) - 1) { 410 + g_assert_cmpint(sts & 0xff, ==, 411 + TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); 412 + } else { 413 + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); 414 + } 415 + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); 416 + } 417 + /* start processing */ 418 + writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); 419 + 420 + uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; 421 + do { 422 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 423 + if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { 424 + break; 425 + } 426 + } while (g_get_monotonic_time() < end_time); 427 + 428 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 429 + DPRINTF_STS; 430 + g_assert_cmpint(sts & 0xff, == , 431 + TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); 432 + bcount = (sts >> 8) & 0xffff; 433 + 434 + /* read response */ 435 + uint8_t tpm_msg[sizeof(struct tpm_hdr)]; 436 + g_assert_cmpint(sizeof(tpm_msg), ==, bcount); 437 + 438 + for (i = 0; i < sizeof(tpm_msg); i++) { 439 + tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); 440 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 441 + DPRINTF_STS; 442 + if (sts & TPM_TIS_STS_DATA_AVAILABLE) { 443 + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); 444 + } 445 + } 446 + g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); 447 + 448 + /* relinquish use of locality 0 */ 449 + writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); 450 + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 451 + }
+23
tests/qtest/tpm-tis-util.h
··· 1 + /* 2 + * QTest TPM TIS: Common test functions used for both the 3 + * ISA and SYSBUS devices 4 + * 5 + * Copyright (c) 2018 IBM Corporation 6 + * 7 + * Authors: 8 + * Stefan Berger <stefanb@linux.vnet.ibm.com> 9 + * 10 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 11 + * See the COPYING file in the top-level directory. 12 + */ 13 + 14 + #ifndef TESTS_TPM_TIS_UTIL_H 15 + #define TESTS_TPM_TIS_UTIL_H 16 + 17 + void tpm_tis_test_check_localities(const void *data); 18 + void tpm_tis_test_check_access_reg(const void *data); 19 + void tpm_tis_test_check_access_reg_seize(const void *data); 20 + void tpm_tis_test_check_access_reg_release(const void *data); 21 + void tpm_tis_test_check_transmit(const void *data); 22 + 23 + #endif /* TESTS_TPM_TIS_UTIL_H */
+6 -5
tests/qtest/tpm-util.c
··· 19 19 #include "tpm-util.h" 20 20 #include "qapi/qmp/qdict.h" 21 21 22 - #define TIS_REG(LOCTY, REG) \ 23 - (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) 24 - 25 22 void tpm_util_crb_transfer(QTestState *s, 26 23 const unsigned char *req, size_t req_size, 27 24 unsigned char *rsp, size_t rsp_size) ··· 258 255 SocketAddress *src_tpm_addr, 259 256 SocketAddress *dst_tpm_addr, 260 257 const char *miguri, 261 - const char *ifmodel) 258 + const char *ifmodel, 259 + const char *machine_options) 262 260 { 263 261 char *src_qemu_args, *dst_qemu_args; 264 262 265 263 src_qemu_args = g_strdup_printf( 264 + "%s " 266 265 "-chardev socket,id=chr,path=%s " 267 266 "-tpmdev emulator,id=dev,chardev=chr " 268 267 "-device %s,tpmdev=dev ", 269 - src_tpm_addr->u.q_unix.path, ifmodel); 268 + machine_options ? : "", src_tpm_addr->u.q_unix.path, ifmodel); 270 269 271 270 *src_qemu = qtest_init(src_qemu_args); 272 271 273 272 dst_qemu_args = g_strdup_printf( 273 + "%s " 274 274 "-chardev socket,id=chr,path=%s " 275 275 "-tpmdev emulator,id=dev,chardev=chr " 276 276 "-device %s,tpmdev=dev " 277 277 "-incoming %s", 278 + machine_options ? : "", 278 279 dst_tpm_addr->u.q_unix.path, 279 280 ifmodel, miguri); 280 281
+7 -1
tests/qtest/tpm-util.h
··· 15 15 16 16 #include "io/channel-socket.h" 17 17 18 + extern uint64_t tpm_tis_base_addr; 19 + 20 + #define TIS_REG(LOCTY, REG) \ 21 + (tpm_tis_base_addr + ((LOCTY) << 12) + REG) 22 + 18 23 typedef void (tx_func)(QTestState *s, 19 24 const unsigned char *req, size_t req_size, 20 25 unsigned char *rsp, size_t rsp_size); ··· 44 49 SocketAddress *src_tpm_addr, 45 50 SocketAddress *dst_tpm_addr, 46 51 const char *miguri, 47 - const char *ifmodel); 52 + const char *ifmodel, 53 + const char *machine_options); 48 54 49 55 void tpm_util_wait_for_migration_complete(QTestState *who); 50 56