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

Merge remote-tracking branch 'remotes/stefanberger/tags/pull-tpm-2018-02-21-2' into staging

Merge tpm 2018/02/21 v2

# gpg: Signature made Tue 27 Feb 2018 13:50:28 GMT
# gpg: using RSA key 75AD65802A0B4211
# gpg: Good signature from "Stefan Berger <stefanb@linux.vnet.ibm.com>"
# 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-2018-02-21-2:
tests: add test for TPM TIS device
tests: Move common TPM test code into tpm-emu.c

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

+810 -273
+1
MAINTAINERS
··· 1639 1639 F: include/sysemu/tpm* 1640 1640 F: qapi/tpm.json 1641 1641 F: backends/tpm.c 1642 + F: tests/*tpm* 1642 1643 T: git git://github.com/stefanberger/qemu-tpm.git tpm-next 1643 1644 1644 1645 Checkpatch
-101
hw/tpm/tpm_tis.c
··· 92 92 } \ 93 93 } while (0) 94 94 95 - /* tis registers */ 96 - #define TPM_TIS_REG_ACCESS 0x00 97 - #define TPM_TIS_REG_INT_ENABLE 0x08 98 - #define TPM_TIS_REG_INT_VECTOR 0x0c 99 - #define TPM_TIS_REG_INT_STATUS 0x10 100 - #define TPM_TIS_REG_INTF_CAPABILITY 0x14 101 - #define TPM_TIS_REG_STS 0x18 102 - #define TPM_TIS_REG_DATA_FIFO 0x24 103 - #define TPM_TIS_REG_INTERFACE_ID 0x30 104 - #define TPM_TIS_REG_DATA_XFIFO 0x80 105 - #define TPM_TIS_REG_DATA_XFIFO_END 0xbc 106 - #define TPM_TIS_REG_DID_VID 0xf00 107 - #define TPM_TIS_REG_RID 0xf04 108 - 109 - /* vendor-specific registers */ 110 - #define TPM_TIS_REG_DEBUG 0xf90 111 - 112 - #define TPM_TIS_STS_TPM_FAMILY_MASK (0x3 << 26)/* TPM 2.0 */ 113 - #define TPM_TIS_STS_TPM_FAMILY1_2 (0 << 26) /* TPM 2.0 */ 114 - #define TPM_TIS_STS_TPM_FAMILY2_0 (1 << 26) /* TPM 2.0 */ 115 - #define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25) /* TPM 2.0 */ 116 - #define TPM_TIS_STS_COMMAND_CANCEL (1 << 24) /* TPM 2.0 */ 117 - 118 - #define TPM_TIS_STS_VALID (1 << 7) 119 - #define TPM_TIS_STS_COMMAND_READY (1 << 6) 120 - #define TPM_TIS_STS_TPM_GO (1 << 5) 121 - #define TPM_TIS_STS_DATA_AVAILABLE (1 << 4) 122 - #define TPM_TIS_STS_EXPECT (1 << 3) 123 - #define TPM_TIS_STS_SELFTEST_DONE (1 << 2) 124 - #define TPM_TIS_STS_RESPONSE_RETRY (1 << 1) 125 - 126 - #define TPM_TIS_BURST_COUNT_SHIFT 8 127 - #define TPM_TIS_BURST_COUNT(X) \ 128 - ((X) << TPM_TIS_BURST_COUNT_SHIFT) 129 - 130 - #define TPM_TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) 131 - #define TPM_TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) 132 - #define TPM_TIS_ACCESS_BEEN_SEIZED (1 << 4) 133 - #define TPM_TIS_ACCESS_SEIZE (1 << 3) 134 - #define TPM_TIS_ACCESS_PENDING_REQUEST (1 << 2) 135 - #define TPM_TIS_ACCESS_REQUEST_USE (1 << 1) 136 - #define TPM_TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) 137 - 138 - #define TPM_TIS_INT_ENABLED (1 << 31) 139 - #define TPM_TIS_INT_DATA_AVAILABLE (1 << 0) 140 - #define TPM_TIS_INT_STS_VALID (1 << 1) 141 - #define TPM_TIS_INT_LOCALITY_CHANGED (1 << 2) 142 - #define TPM_TIS_INT_COMMAND_READY (1 << 7) 143 - 144 - #define TPM_TIS_INT_POLARITY_MASK (3 << 3) 145 - #define TPM_TIS_INT_POLARITY_LOW_LEVEL (1 << 3) 146 - 147 - #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \ 148 - TPM_TIS_INT_DATA_AVAILABLE | \ 149 - TPM_TIS_INT_STS_VALID | \ 150 - TPM_TIS_INT_COMMAND_READY) 151 - 152 - #define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28) 153 - #define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28) 154 - #define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9) 155 - #define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9) 156 - #define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8) 157 - #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ 158 - #define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \ 159 - (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ 160 - TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ 161 - TPM_TIS_CAP_DATA_TRANSFER_64B | \ 162 - TPM_TIS_CAP_INTERFACE_VERSION1_3 | \ 163 - TPM_TIS_INTERRUPTS_SUPPORTED) 164 - 165 - #define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \ 166 - (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ 167 - TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ 168 - TPM_TIS_CAP_DATA_TRANSFER_64B | \ 169 - TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \ 170 - TPM_TIS_INTERRUPTS_SUPPORTED) 171 - 172 - #define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 (0xf) /* TPM 2.0 */ 173 - #define TPM_TIS_IFACE_ID_INTERFACE_FIFO (0x0) /* TPM 2.0 */ 174 - #define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4) /* TPM 2.0 */ 175 - #define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES (1 << 8) /* TPM 2.0 */ 176 - #define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED (1 << 13) /* TPM 2.0 */ 177 - #define TPM_TIS_IFACE_ID_INT_SEL_LOCK (1 << 19) /* TPM 2.0 */ 178 - 179 - #define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \ 180 - (TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \ 181 - (~0u << 4)/* all of it is don't care */) 182 - 183 - /* if backend was a TPM 2.0: */ 184 - #define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \ 185 - (TPM_TIS_IFACE_ID_INTERFACE_FIFO | \ 186 - TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \ 187 - TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \ 188 - TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED) 189 - 190 - #define TPM_TIS_TPM_DID 0x0001 191 - #define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM 192 - #define TPM_TIS_TPM_RID 0x0001 193 - 194 - #define TPM_TIS_NO_DATA_BYTE 0xff 195 - 196 95 /* local prototypes */ 197 96 198 97 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
+105
include/hw/acpi/tpm.h
··· 23 23 24 24 #define TPM_TIS_IRQ 5 25 25 26 + #define TPM_TIS_NUM_LOCALITIES 5 /* per spec */ 27 + #define TPM_TIS_LOCALITY_SHIFT 12 28 + 29 + /* tis registers */ 30 + #define TPM_TIS_REG_ACCESS 0x00 31 + #define TPM_TIS_REG_INT_ENABLE 0x08 32 + #define TPM_TIS_REG_INT_VECTOR 0x0c 33 + #define TPM_TIS_REG_INT_STATUS 0x10 34 + #define TPM_TIS_REG_INTF_CAPABILITY 0x14 35 + #define TPM_TIS_REG_STS 0x18 36 + #define TPM_TIS_REG_DATA_FIFO 0x24 37 + #define TPM_TIS_REG_INTERFACE_ID 0x30 38 + #define TPM_TIS_REG_DATA_XFIFO 0x80 39 + #define TPM_TIS_REG_DATA_XFIFO_END 0xbc 40 + #define TPM_TIS_REG_DID_VID 0xf00 41 + #define TPM_TIS_REG_RID 0xf04 42 + 43 + /* vendor-specific registers */ 44 + #define TPM_TIS_REG_DEBUG 0xf90 45 + 46 + #define TPM_TIS_STS_TPM_FAMILY_MASK (0x3 << 26)/* TPM 2.0 */ 47 + #define TPM_TIS_STS_TPM_FAMILY1_2 (0 << 26) /* TPM 2.0 */ 48 + #define TPM_TIS_STS_TPM_FAMILY2_0 (1 << 26) /* TPM 2.0 */ 49 + #define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25) /* TPM 2.0 */ 50 + #define TPM_TIS_STS_COMMAND_CANCEL (1 << 24) /* TPM 2.0 */ 51 + 52 + #define TPM_TIS_STS_VALID (1 << 7) 53 + #define TPM_TIS_STS_COMMAND_READY (1 << 6) 54 + #define TPM_TIS_STS_TPM_GO (1 << 5) 55 + #define TPM_TIS_STS_DATA_AVAILABLE (1 << 4) 56 + #define TPM_TIS_STS_EXPECT (1 << 3) 57 + #define TPM_TIS_STS_SELFTEST_DONE (1 << 2) 58 + #define TPM_TIS_STS_RESPONSE_RETRY (1 << 1) 59 + 60 + #define TPM_TIS_BURST_COUNT_SHIFT 8 61 + #define TPM_TIS_BURST_COUNT(X) \ 62 + ((X) << TPM_TIS_BURST_COUNT_SHIFT) 63 + 64 + #define TPM_TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) 65 + #define TPM_TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) 66 + #define TPM_TIS_ACCESS_BEEN_SEIZED (1 << 4) 67 + #define TPM_TIS_ACCESS_SEIZE (1 << 3) 68 + #define TPM_TIS_ACCESS_PENDING_REQUEST (1 << 2) 69 + #define TPM_TIS_ACCESS_REQUEST_USE (1 << 1) 70 + #define TPM_TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) 71 + 72 + #define TPM_TIS_INT_ENABLED (1 << 31) 73 + #define TPM_TIS_INT_DATA_AVAILABLE (1 << 0) 74 + #define TPM_TIS_INT_STS_VALID (1 << 1) 75 + #define TPM_TIS_INT_LOCALITY_CHANGED (1 << 2) 76 + #define TPM_TIS_INT_COMMAND_READY (1 << 7) 77 + 78 + #define TPM_TIS_INT_POLARITY_MASK (3 << 3) 79 + #define TPM_TIS_INT_POLARITY_LOW_LEVEL (1 << 3) 80 + 81 + #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \ 82 + TPM_TIS_INT_DATA_AVAILABLE | \ 83 + TPM_TIS_INT_STS_VALID | \ 84 + TPM_TIS_INT_COMMAND_READY) 85 + 86 + #define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28) 87 + #define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28) 88 + #define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9) 89 + #define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9) 90 + #define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8) 91 + #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ 92 + #define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \ 93 + (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ 94 + TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ 95 + TPM_TIS_CAP_DATA_TRANSFER_64B | \ 96 + TPM_TIS_CAP_INTERFACE_VERSION1_3 | \ 97 + TPM_TIS_INTERRUPTS_SUPPORTED) 98 + 99 + #define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \ 100 + (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ 101 + TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ 102 + TPM_TIS_CAP_DATA_TRANSFER_64B | \ 103 + TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \ 104 + TPM_TIS_INTERRUPTS_SUPPORTED) 105 + 106 + #define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 (0xf) /* TPM 2.0 */ 107 + #define TPM_TIS_IFACE_ID_INTERFACE_FIFO (0x0) /* TPM 2.0 */ 108 + #define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4) /* TPM 2.0 */ 109 + #define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES (1 << 8) /* TPM 2.0 */ 110 + #define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED (1 << 13) /* TPM 2.0 */ 111 + #define TPM_TIS_IFACE_ID_INT_SEL_LOCK (1 << 19) /* TPM 2.0 */ 112 + 113 + #define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \ 114 + (TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \ 115 + (~0u << 4)/* all of it is don't care */) 116 + 117 + /* if backend was a TPM 2.0: */ 118 + #define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \ 119 + (TPM_TIS_IFACE_ID_INTERFACE_FIFO | \ 120 + TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \ 121 + TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \ 122 + TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED) 123 + 124 + #define TPM_TIS_TPM_DID 0x0001 125 + #define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM 126 + #define TPM_TIS_TPM_RID 0x0001 127 + 128 + #define TPM_TIS_NO_DATA_BYTE 0xff 129 + 130 + 26 131 REG32(CRB_LOC_STATE, 0x00) 27 132 FIELD(CRB_LOC_STATE, tpmEstablished, 0, 1) 28 133 FIELD(CRB_LOC_STATE, locAssigned, 1, 1)
+3 -1
tests/Makefile.include
··· 287 287 check-qtest-x86_64-$(CONFIG_VHOST_USER_NET_TEST_x86_64) += tests/vhost-user-test$(EXESUF) 288 288 endif 289 289 check-qtest-i386-$(CONFIG_TPM) += tests/tpm-crb-test$(EXESUF) 290 + check-qtest-i386-$(CONFIG_TPM) += tests/tpm-tis-test$(EXESUF) 290 291 check-qtest-i386-$(CONFIG_SLIRP) += tests/test-netfilter$(EXESUF) 291 292 check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-mirror$(EXESUF) 292 293 check-qtest-i386-$(CONFIG_POSIX) += tests/test-filter-redirector$(EXESUF) ··· 714 715 tests/test-io-task$(EXESUF): tests/test-io-task.o $(test-io-obj-y) 715 716 tests/test-io-channel-socket$(EXESUF): tests/test-io-channel-socket.o \ 716 717 tests/io-channel-helpers.o $(test-io-obj-y) 717 - tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o $(test-io-obj-y) 718 + tests/tpm-crb-test$(EXESUF): tests/tpm-crb-test.o tests/tpm-emu.o $(test-io-obj-y) 719 + tests/tpm-tis-test$(EXESUF): tests/tpm-tis-test.o tests/tpm-emu.o $(test-io-obj-y) 718 720 tests/test-io-channel-file$(EXESUF): tests/test-io-channel-file.o \ 719 721 tests/io-channel-helpers.o $(test-io-obj-y) 720 722 tests/test-io-channel-tls$(EXESUF): tests/test-io-channel-tls.o \
+3 -171
tests/tpm-crb-test.c
··· 14 14 #include <glib/gstdio.h> 15 15 16 16 #include "hw/acpi/tpm.h" 17 - #include "hw/tpm/tpm_ioctl.h" 18 17 #include "io/channel-socket.h" 19 18 #include "libqtest.h" 20 - #include "qapi/error.h" 21 - 22 - #define TPM_RC_FAILURE 0x101 23 - #define TPM2_ST_NO_SESSIONS 0x8001 24 - 25 - struct tpm_hdr { 26 - uint16_t tag; 27 - uint32_t len; 28 - uint32_t code; /*ordinal/error */ 29 - char buffer[]; 30 - } QEMU_PACKED; 31 - 32 - typedef struct TestState { 33 - CompatGMutex data_mutex; 34 - CompatGCond data_cond; 35 - SocketAddress *addr; 36 - QIOChannel *tpm_ioc; 37 - GThread *emu_tpm_thread; 38 - struct tpm_hdr *tpm_msg; 39 - } TestState; 40 - 41 - static void test_wait_cond(TestState *s) 42 - { 43 - gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; 44 - 45 - g_mutex_lock(&s->data_mutex); 46 - if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) { 47 - g_assert_not_reached(); 48 - } 49 - g_mutex_unlock(&s->data_mutex); 50 - } 51 - 52 - static void *emu_tpm_thread(void *data) 53 - { 54 - TestState *s = data; 55 - QIOChannel *ioc = s->tpm_ioc; 56 - 57 - s->tpm_msg = g_new(struct tpm_hdr, 1); 58 - while (true) { 59 - int minhlen = sizeof(s->tpm_msg->tag) + sizeof(s->tpm_msg->len); 60 - 61 - if (!qio_channel_read(ioc, (char *)s->tpm_msg, minhlen, &error_abort)) { 62 - break; 63 - } 64 - s->tpm_msg->tag = be16_to_cpu(s->tpm_msg->tag); 65 - s->tpm_msg->len = be32_to_cpu(s->tpm_msg->len); 66 - g_assert_cmpint(s->tpm_msg->len, >=, minhlen); 67 - g_assert_cmpint(s->tpm_msg->tag, ==, TPM2_ST_NO_SESSIONS); 68 - 69 - s->tpm_msg = g_realloc(s->tpm_msg, s->tpm_msg->len); 70 - qio_channel_read(ioc, (char *)&s->tpm_msg->code, 71 - s->tpm_msg->len - minhlen, &error_abort); 72 - s->tpm_msg->code = be32_to_cpu(s->tpm_msg->code); 73 - 74 - /* reply error */ 75 - s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); 76 - s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr)); 77 - s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE); 78 - qio_channel_write(ioc, (char *)s->tpm_msg, be32_to_cpu(s->tpm_msg->len), 79 - &error_abort); 80 - } 81 - 82 - g_free(s->tpm_msg); 83 - s->tpm_msg = NULL; 84 - object_unref(OBJECT(s->tpm_ioc)); 85 - return NULL; 86 - } 87 - 88 - static void *emu_ctrl_thread(void *data) 89 - { 90 - TestState *s = data; 91 - QIOChannelSocket *lioc = qio_channel_socket_new(); 92 - QIOChannel *ioc; 93 - 94 - qio_channel_socket_listen_sync(lioc, s->addr, &error_abort); 95 - g_cond_signal(&s->data_cond); 96 - 97 - qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN); 98 - ioc = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort)); 99 - g_assert(ioc); 100 - 101 - { 102 - uint32_t cmd = 0; 103 - struct iovec iov = { .iov_base = &cmd, .iov_len = sizeof(cmd) }; 104 - int *pfd = NULL; 105 - size_t nfd = 0; 106 - 107 - qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, &error_abort); 108 - cmd = be32_to_cpu(cmd); 109 - g_assert_cmpint(cmd, ==, CMD_SET_DATAFD); 110 - g_assert_cmpint(nfd, ==, 1); 111 - s->tpm_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(*pfd, &error_abort)); 112 - g_free(pfd); 113 - 114 - cmd = 0; 115 - qio_channel_write(ioc, (char *)&cmd, sizeof(cmd), &error_abort); 116 - 117 - s->emu_tpm_thread = g_thread_new(NULL, emu_tpm_thread, s); 118 - } 119 - 120 - while (true) { 121 - uint32_t cmd; 122 - ssize_t ret; 123 - 124 - ret = qio_channel_read(ioc, (char *)&cmd, sizeof(cmd), NULL); 125 - if (ret <= 0) { 126 - break; 127 - } 128 - 129 - cmd = be32_to_cpu(cmd); 130 - switch (cmd) { 131 - case CMD_GET_CAPABILITY: { 132 - ptm_cap cap = cpu_to_be64(0x3fff); 133 - qio_channel_write(ioc, (char *)&cap, sizeof(cap), &error_abort); 134 - break; 135 - } 136 - case CMD_INIT: { 137 - ptm_init init; 138 - qio_channel_read(ioc, (char *)&init.u.req, sizeof(init.u.req), 139 - &error_abort); 140 - init.u.resp.tpm_result = 0; 141 - qio_channel_write(ioc, (char *)&init.u.resp, sizeof(init.u.resp), 142 - &error_abort); 143 - break; 144 - } 145 - case CMD_SHUTDOWN: { 146 - ptm_res res = 0; 147 - qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort); 148 - qio_channel_close(s->tpm_ioc, &error_abort); 149 - g_thread_join(s->emu_tpm_thread); 150 - break; 151 - } 152 - case CMD_STOP: { 153 - ptm_res res = 0; 154 - qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort); 155 - break; 156 - } 157 - case CMD_SET_BUFFERSIZE: { 158 - ptm_setbuffersize sbs; 159 - qio_channel_read(ioc, (char *)&sbs.u.req, sizeof(sbs.u.req), 160 - &error_abort); 161 - sbs.u.resp.buffersize = sbs.u.req.buffersize ?: cpu_to_be32(4096); 162 - sbs.u.resp.tpm_result = 0; 163 - sbs.u.resp.minsize = cpu_to_be32(128); 164 - sbs.u.resp.maxsize = cpu_to_be32(4096); 165 - qio_channel_write(ioc, (char *)&sbs.u.resp, sizeof(sbs.u.resp), 166 - &error_abort); 167 - break; 168 - } 169 - case CMD_SET_LOCALITY: { 170 - ptm_loc loc; 171 - /* Note: this time it's not u.req / u.resp... */ 172 - qio_channel_read(ioc, (char *)&loc, sizeof(loc), &error_abort); 173 - g_assert_cmpint(loc.u.req.loc, ==, 0); 174 - loc.u.resp.tpm_result = 0; 175 - qio_channel_write(ioc, (char *)&loc, sizeof(loc), &error_abort); 176 - break; 177 - } 178 - default: 179 - g_debug("unimplemented %u", cmd); 180 - g_assert_not_reached(); 181 - } 182 - } 183 - 184 - object_unref(OBJECT(ioc)); 185 - object_unref(OBJECT(lioc)); 186 - return NULL; 187 - } 19 + #include "tpm-emu.h" 188 20 189 21 #define TPM_CMD "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00" 190 22 ··· 250 82 g_mutex_init(&test.data_mutex); 251 83 g_cond_init(&test.data_cond); 252 84 253 - thread = g_thread_new(NULL, emu_ctrl_thread, &test); 254 - test_wait_cond(&test); 85 + thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); 86 + tpm_emu_test_wait_cond(&test); 255 87 256 88 args = g_strdup_printf( 257 89 "-chardev socket,id=chr,path=%s "
+174
tests/tpm-emu.c
··· 1 + /* 2 + * Minimal TPM emulator for TPM test cases 3 + * 4 + * Copyright (c) 2018 Red Hat, Inc. 5 + * 6 + * Authors: 7 + * Marc-André Lureau <marcandre.lureau@redhat.com> 8 + * 9 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 + * See the COPYING file in the top-level directory. 11 + */ 12 + 13 + #include "qemu/osdep.h" 14 + #include <glib/gstdio.h> 15 + 16 + #include "hw/tpm/tpm_ioctl.h" 17 + #include "io/channel-socket.h" 18 + #include "qapi/error.h" 19 + #include "tpm-emu.h" 20 + 21 + void tpm_emu_test_wait_cond(TestState *s) 22 + { 23 + gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND; 24 + 25 + g_mutex_lock(&s->data_mutex); 26 + if (!g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) { 27 + g_assert_not_reached(); 28 + } 29 + g_mutex_unlock(&s->data_mutex); 30 + } 31 + 32 + static void *tpm_emu_tpm_thread(void *data) 33 + { 34 + TestState *s = data; 35 + QIOChannel *ioc = s->tpm_ioc; 36 + 37 + s->tpm_msg = g_new(struct tpm_hdr, 1); 38 + while (true) { 39 + int minhlen = sizeof(s->tpm_msg->tag) + sizeof(s->tpm_msg->len); 40 + 41 + if (!qio_channel_read(ioc, (char *)s->tpm_msg, minhlen, &error_abort)) { 42 + break; 43 + } 44 + s->tpm_msg->tag = be16_to_cpu(s->tpm_msg->tag); 45 + s->tpm_msg->len = be32_to_cpu(s->tpm_msg->len); 46 + g_assert_cmpint(s->tpm_msg->len, >=, minhlen); 47 + g_assert_cmpint(s->tpm_msg->tag, ==, TPM2_ST_NO_SESSIONS); 48 + 49 + s->tpm_msg = g_realloc(s->tpm_msg, s->tpm_msg->len); 50 + qio_channel_read(ioc, (char *)&s->tpm_msg->code, 51 + s->tpm_msg->len - minhlen, &error_abort); 52 + s->tpm_msg->code = be32_to_cpu(s->tpm_msg->code); 53 + 54 + /* reply error */ 55 + s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); 56 + s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr)); 57 + s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE); 58 + qio_channel_write(ioc, (char *)s->tpm_msg, be32_to_cpu(s->tpm_msg->len), 59 + &error_abort); 60 + } 61 + 62 + g_free(s->tpm_msg); 63 + s->tpm_msg = NULL; 64 + object_unref(OBJECT(s->tpm_ioc)); 65 + return NULL; 66 + } 67 + 68 + void *tpm_emu_ctrl_thread(void *data) 69 + { 70 + TestState *s = data; 71 + QIOChannelSocket *lioc = qio_channel_socket_new(); 72 + QIOChannel *ioc; 73 + 74 + qio_channel_socket_listen_sync(lioc, s->addr, &error_abort); 75 + g_cond_signal(&s->data_cond); 76 + 77 + qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN); 78 + ioc = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort)); 79 + g_assert(ioc); 80 + 81 + { 82 + uint32_t cmd = 0; 83 + struct iovec iov = { .iov_base = &cmd, .iov_len = sizeof(cmd) }; 84 + int *pfd = NULL; 85 + size_t nfd = 0; 86 + 87 + qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, &error_abort); 88 + cmd = be32_to_cpu(cmd); 89 + g_assert_cmpint(cmd, ==, CMD_SET_DATAFD); 90 + g_assert_cmpint(nfd, ==, 1); 91 + s->tpm_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(*pfd, &error_abort)); 92 + g_free(pfd); 93 + 94 + cmd = 0; 95 + qio_channel_write(ioc, (char *)&cmd, sizeof(cmd), &error_abort); 96 + 97 + s->emu_tpm_thread = g_thread_new(NULL, tpm_emu_tpm_thread, s); 98 + } 99 + 100 + while (true) { 101 + uint32_t cmd; 102 + ssize_t ret; 103 + 104 + ret = qio_channel_read(ioc, (char *)&cmd, sizeof(cmd), NULL); 105 + if (ret <= 0) { 106 + break; 107 + } 108 + 109 + cmd = be32_to_cpu(cmd); 110 + switch (cmd) { 111 + case CMD_GET_CAPABILITY: { 112 + ptm_cap cap = cpu_to_be64(0x3fff); 113 + qio_channel_write(ioc, (char *)&cap, sizeof(cap), &error_abort); 114 + break; 115 + } 116 + case CMD_INIT: { 117 + ptm_init init; 118 + qio_channel_read(ioc, (char *)&init.u.req, sizeof(init.u.req), 119 + &error_abort); 120 + init.u.resp.tpm_result = 0; 121 + qio_channel_write(ioc, (char *)&init.u.resp, sizeof(init.u.resp), 122 + &error_abort); 123 + break; 124 + } 125 + case CMD_SHUTDOWN: { 126 + ptm_res res = 0; 127 + qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort); 128 + qio_channel_close(s->tpm_ioc, &error_abort); 129 + g_thread_join(s->emu_tpm_thread); 130 + break; 131 + } 132 + case CMD_STOP: { 133 + ptm_res res = 0; 134 + qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort); 135 + break; 136 + } 137 + case CMD_SET_BUFFERSIZE: { 138 + ptm_setbuffersize sbs; 139 + qio_channel_read(ioc, (char *)&sbs.u.req, sizeof(sbs.u.req), 140 + &error_abort); 141 + sbs.u.resp.buffersize = sbs.u.req.buffersize ?: cpu_to_be32(4096); 142 + sbs.u.resp.tpm_result = 0; 143 + sbs.u.resp.minsize = cpu_to_be32(128); 144 + sbs.u.resp.maxsize = cpu_to_be32(4096); 145 + qio_channel_write(ioc, (char *)&sbs.u.resp, sizeof(sbs.u.resp), 146 + &error_abort); 147 + break; 148 + } 149 + case CMD_SET_LOCALITY: { 150 + ptm_loc loc; 151 + /* Note: this time it's not u.req / u.resp... */ 152 + qio_channel_read(ioc, (char *)&loc, sizeof(loc), &error_abort); 153 + g_assert_cmpint(loc.u.req.loc, ==, 0); 154 + loc.u.resp.tpm_result = 0; 155 + qio_channel_write(ioc, (char *)&loc, sizeof(loc), &error_abort); 156 + break; 157 + } 158 + case CMD_GET_TPMESTABLISHED: { 159 + ptm_est est = { 160 + .u.resp.bit = 0, 161 + }; 162 + qio_channel_write(ioc, (char *)&est, sizeof(est), &error_abort); 163 + break; 164 + } 165 + default: 166 + g_debug("unimplemented %u", cmd); 167 + g_assert_not_reached(); 168 + } 169 + } 170 + 171 + object_unref(OBJECT(ioc)); 172 + object_unref(OBJECT(lioc)); 173 + return NULL; 174 + }
+38
tests/tpm-emu.h
··· 1 + /* 2 + * Minimal TPM emulator for TPM test cases 3 + * 4 + * Copyright (c) 2018 Red Hat, Inc. 5 + * 6 + * Authors: 7 + * Marc-André Lureau <marcandre.lureau@redhat.com> 8 + * 9 + * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 + * See the COPYING file in the top-level directory. 11 + */ 12 + 13 + #ifndef TESTS_TPM_EMU_H 14 + #define TESTS_TPM_EMU_H 15 + 16 + #define TPM_RC_FAILURE 0x101 17 + #define TPM2_ST_NO_SESSIONS 0x8001 18 + 19 + struct tpm_hdr { 20 + uint16_t tag; 21 + uint32_t len; 22 + uint32_t code; /*ordinal/error */ 23 + char buffer[]; 24 + } QEMU_PACKED; 25 + 26 + typedef struct TestState { 27 + CompatGMutex data_mutex; 28 + CompatGCond data_cond; 29 + SocketAddress *addr; 30 + QIOChannel *tpm_ioc; 31 + GThread *emu_tpm_thread; 32 + struct tpm_hdr *tpm_msg; 33 + } TestState; 34 + 35 + void tpm_emu_test_wait_cond(TestState *s); 36 + void *tpm_emu_ctrl_thread(void *data); 37 + 38 + #endif /* TEST_TPM_EMU_H */
+486
tests/tpm-tis-test.c
··· 1 + /* 2 + * QTest testcase for 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 "hw/acpi/tpm.h" 19 + #include "io/channel-socket.h" 20 + #include "libqtest.h" 21 + #include "tpm-emu.h" 22 + 23 + #define TIS_REG(LOCTY, REG) \ 24 + (TPM_TIS_ADDR_BASE + ((LOCTY) << 12) + REG) 25 + 26 + #define DEBUG_TIS_TEST 0 27 + 28 + #define DPRINTF(fmt, ...) do { \ 29 + if (DEBUG_TIS_TEST) { \ 30 + printf(fmt, ## __VA_ARGS__); \ 31 + } \ 32 + } while (0) 33 + 34 + #define DPRINTF_ACCESS \ 35 + DPRINTF("%s: %d: locty=%d l=%d access=0x%02x pending_request_flag=0x%x\n", \ 36 + __func__, __LINE__, locty, l, access, pending_request_flag) 37 + 38 + #define DPRINTF_STS \ 39 + DPRINTF("%s: %d: sts = 0x%08x\n", __func__, __LINE__, sts) 40 + 41 + static const uint8_t TPM_CMD[12] = 42 + "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; 43 + 44 + static void tpm_tis_test_check_localities(const void *data) 45 + { 46 + uint8_t locty; 47 + uint8_t access; 48 + uint32_t ifaceid; 49 + uint32_t capability; 50 + uint32_t didvid; 51 + uint32_t rid; 52 + 53 + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES; locty++) { 54 + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 55 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 56 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 57 + 58 + capability = readl(TIS_REG(locty, TPM_TIS_REG_INTF_CAPABILITY)); 59 + g_assert_cmpint(capability, ==, TPM_TIS_CAPABILITIES_SUPPORTED2_0); 60 + 61 + ifaceid = readl(TIS_REG(locty, TPM_TIS_REG_INTERFACE_ID)); 62 + g_assert_cmpint(ifaceid, ==, TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0); 63 + 64 + didvid = readl(TIS_REG(locty, TPM_TIS_REG_DID_VID)); 65 + g_assert_cmpint(didvid, !=, 0); 66 + g_assert_cmpint(didvid, !=, 0xffffffff); 67 + 68 + rid = readl(TIS_REG(locty, TPM_TIS_REG_RID)); 69 + g_assert_cmpint(rid, !=, 0); 70 + g_assert_cmpint(rid, !=, 0xffffffff); 71 + } 72 + } 73 + 74 + static void tpm_tis_test_check_access_reg(const void *data) 75 + { 76 + uint8_t locty; 77 + uint8_t access; 78 + 79 + /* do not test locality 4 (hw only) */ 80 + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { 81 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 82 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 83 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 84 + 85 + /* request use of locality */ 86 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 87 + 88 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 89 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 90 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 91 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 92 + 93 + /* release access */ 94 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), 95 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 96 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 97 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 98 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 99 + } 100 + } 101 + 102 + /* 103 + * Test case for seizing access by a higher number locality 104 + */ 105 + static void tpm_tis_test_check_access_reg_seize(const void *data) 106 + { 107 + int locty, l; 108 + uint8_t access; 109 + uint8_t pending_request_flag; 110 + 111 + /* do not test locality 4 (hw only) */ 112 + for (locty = 0; locty < TPM_TIS_NUM_LOCALITIES - 1; locty++) { 113 + pending_request_flag = 0; 114 + 115 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 116 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 117 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 118 + 119 + /* request use of locality */ 120 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 121 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 122 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 123 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 124 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 125 + 126 + /* lower localities cannot seize access */ 127 + for (l = 0; l < locty; l++) { 128 + /* lower locality is not active */ 129 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 130 + DPRINTF_ACCESS; 131 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 132 + pending_request_flag | 133 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 134 + 135 + /* try to request use from 'l' */ 136 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 137 + 138 + /* requesting use from 'l' was not possible; 139 + we must see REQUEST_USE and possibly PENDING_REQUEST */ 140 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 141 + DPRINTF_ACCESS; 142 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 143 + TPM_TIS_ACCESS_REQUEST_USE | 144 + pending_request_flag | 145 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 146 + 147 + /* locality 'locty' must be unchanged; 148 + we must see PENDING_REQUEST */ 149 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 150 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 151 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 152 + TPM_TIS_ACCESS_PENDING_REQUEST | 153 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 154 + 155 + /* try to seize from 'l' */ 156 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); 157 + /* seize from 'l' was not possible */ 158 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 159 + DPRINTF_ACCESS; 160 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 161 + TPM_TIS_ACCESS_REQUEST_USE | 162 + pending_request_flag | 163 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 164 + 165 + /* locality 'locty' must be unchanged */ 166 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 167 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 168 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 169 + TPM_TIS_ACCESS_PENDING_REQUEST | 170 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 171 + 172 + /* on the next loop we will have a PENDING_REQUEST flag 173 + set for locality 'l' */ 174 + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; 175 + } 176 + 177 + /* higher localities can 'seize' access but not 'request use'; 178 + note: this will activate first l+1, then l+2 etc. */ 179 + for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 180 + /* try to 'request use' from 'l' */ 181 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 182 + 183 + /* requesting use from 'l' was not possible; we should see 184 + REQUEST_USE and may see PENDING_REQUEST */ 185 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 186 + DPRINTF_ACCESS; 187 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 188 + TPM_TIS_ACCESS_REQUEST_USE | 189 + pending_request_flag | 190 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 191 + 192 + /* locality 'l-1' must be unchanged; we should always 193 + see PENDING_REQUEST from 'l' requesting access */ 194 + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 195 + DPRINTF_ACCESS; 196 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 197 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 198 + TPM_TIS_ACCESS_PENDING_REQUEST | 199 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 200 + 201 + /* try to seize from 'l' */ 202 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_SEIZE); 203 + 204 + /* seize from 'l' was possible */ 205 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 206 + DPRINTF_ACCESS; 207 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 208 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 209 + pending_request_flag | 210 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 211 + 212 + /* l - 1 should show that it has BEEN_SEIZED */ 213 + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 214 + DPRINTF_ACCESS; 215 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 216 + TPM_TIS_ACCESS_BEEN_SEIZED | 217 + pending_request_flag | 218 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 219 + 220 + /* clear the BEEN_SEIZED flag and make sure it's gone */ 221 + writeb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS), 222 + TPM_TIS_ACCESS_BEEN_SEIZED); 223 + 224 + access = readb(TIS_REG(l - 1, TPM_TIS_REG_ACCESS)); 225 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 226 + pending_request_flag | 227 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 228 + } 229 + 230 + /* PENDING_REQUEST will not be set if locty = 0 since all localities 231 + were active; in case of locty = 1, locality 0 will be active 232 + but no PENDING_REQUEST anywhere */ 233 + if (locty <= 1) { 234 + pending_request_flag = 0; 235 + } 236 + 237 + /* release access from l - 1; this activates locty - 1 */ 238 + l--; 239 + 240 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 241 + DPRINTF_ACCESS; 242 + 243 + DPRINTF("%s: %d: relinquishing control on l = %d\n", 244 + __func__, __LINE__, l); 245 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 246 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 247 + 248 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 249 + DPRINTF_ACCESS; 250 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 251 + pending_request_flag | 252 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 253 + 254 + for (l = locty - 1; l >= 0; l--) { 255 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 256 + DPRINTF_ACCESS; 257 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 258 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 259 + pending_request_flag | 260 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 261 + 262 + /* release this locality */ 263 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 264 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 265 + 266 + if (l == 1) { 267 + pending_request_flag = 0; 268 + } 269 + } 270 + 271 + /* no locality may be active now */ 272 + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 273 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 274 + DPRINTF_ACCESS; 275 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 276 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 277 + } 278 + } 279 + } 280 + 281 + /* 282 + * Test case for getting access when higher number locality relinquishes access 283 + */ 284 + static void tpm_tis_test_check_access_reg_release(const void *data) 285 + { 286 + int locty, l; 287 + uint8_t access; 288 + uint8_t pending_request_flag; 289 + 290 + /* do not test locality 4 (hw only) */ 291 + for (locty = TPM_TIS_NUM_LOCALITIES - 2; locty >= 0; locty--) { 292 + pending_request_flag = 0; 293 + 294 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 295 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 296 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 297 + 298 + /* request use of locality */ 299 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 300 + access = readb(TIS_REG(locty, TPM_TIS_REG_ACCESS)); 301 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 302 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 303 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 304 + 305 + /* request use of all other localities */ 306 + for (l = 0; l < TPM_TIS_NUM_LOCALITIES - 1; l++) { 307 + if (l == locty) { 308 + continue; 309 + } 310 + /* request use of locality 'l' -- we MUST see REQUEST USE and 311 + may see PENDING_REQUEST */ 312 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 313 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 314 + DPRINTF_ACCESS; 315 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 316 + TPM_TIS_ACCESS_REQUEST_USE | 317 + pending_request_flag | 318 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 319 + pending_request_flag = TPM_TIS_ACCESS_PENDING_REQUEST; 320 + } 321 + /* release locality 'locty' */ 322 + writeb(TIS_REG(locty, TPM_TIS_REG_ACCESS), 323 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 324 + /* highest locality should now be active; release it and make sure the 325 + next higest locality is active afterwards */ 326 + for (l = TPM_TIS_NUM_LOCALITIES - 2; l >= 0; l--) { 327 + if (l == locty) { 328 + continue; 329 + } 330 + /* 'l' should be active now */ 331 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 332 + DPRINTF_ACCESS; 333 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 334 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 335 + pending_request_flag | 336 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 337 + /* 'l' relinquishes access */ 338 + writeb(TIS_REG(l, TPM_TIS_REG_ACCESS), 339 + TPM_TIS_ACCESS_ACTIVE_LOCALITY); 340 + access = readb(TIS_REG(l, TPM_TIS_REG_ACCESS)); 341 + DPRINTF_ACCESS; 342 + if (l == 1 || (locty <= 1 && l == 2)) { 343 + pending_request_flag = 0; 344 + } 345 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 346 + pending_request_flag | 347 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 348 + } 349 + } 350 + } 351 + 352 + /* 353 + * Test case for transmitting packets 354 + */ 355 + static void tpm_tis_test_check_transmit(const void *data) 356 + { 357 + const TestState *s = data; 358 + uint8_t access; 359 + uint32_t sts; 360 + uint16_t bcount; 361 + size_t i; 362 + 363 + /* request use of locality 0 */ 364 + writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_REQUEST_USE); 365 + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 366 + g_assert_cmpint(access, ==, TPM_TIS_ACCESS_TPM_REG_VALID_STS | 367 + TPM_TIS_ACCESS_ACTIVE_LOCALITY | 368 + TPM_TIS_ACCESS_TPM_ESTABLISHMENT); 369 + 370 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 371 + DPRINTF_STS; 372 + 373 + g_assert_cmpint(sts & 0xff, ==, 0); 374 + g_assert_cmpint(sts & TPM_TIS_STS_TPM_FAMILY_MASK, ==, 375 + TPM_TIS_STS_TPM_FAMILY2_0); 376 + 377 + bcount = (sts >> 8) & 0xffff; 378 + g_assert_cmpint(bcount, >=, 128); 379 + 380 + writel(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_COMMAND_READY); 381 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 382 + DPRINTF_STS; 383 + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_COMMAND_READY); 384 + 385 + /* transmit command */ 386 + for (i = 0; i < sizeof(TPM_CMD); i++) { 387 + writeb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO), TPM_CMD[i]); 388 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 389 + DPRINTF_STS; 390 + if (i < sizeof(TPM_CMD) - 1) { 391 + g_assert_cmpint(sts & 0xff, ==, 392 + TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID); 393 + } else { 394 + g_assert_cmpint(sts & 0xff, ==, TPM_TIS_STS_VALID); 395 + } 396 + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); 397 + } 398 + /* start processing */ 399 + writeb(TIS_REG(0, TPM_TIS_REG_STS), TPM_TIS_STS_TPM_GO); 400 + 401 + uint64_t end_time = g_get_monotonic_time() + 50 * G_TIME_SPAN_SECOND; 402 + do { 403 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 404 + if ((sts & TPM_TIS_STS_DATA_AVAILABLE) != 0) { 405 + break; 406 + } 407 + } while (g_get_monotonic_time() < end_time); 408 + 409 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 410 + DPRINTF_STS; 411 + g_assert_cmpint(sts & 0xff, == , 412 + TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); 413 + bcount = (sts >> 8) & 0xffff; 414 + 415 + /* read response */ 416 + uint8_t tpm_msg[sizeof(struct tpm_hdr)]; 417 + g_assert_cmpint(sizeof(tpm_msg), ==, bcount); 418 + 419 + for (i = 0; i < sizeof(tpm_msg); i++) { 420 + tpm_msg[i] = readb(TIS_REG(0, TPM_TIS_REG_DATA_FIFO)); 421 + sts = readl(TIS_REG(0, TPM_TIS_REG_STS)); 422 + DPRINTF_STS; 423 + if (sts & TPM_TIS_STS_DATA_AVAILABLE) { 424 + g_assert_cmpint((sts >> 8) & 0xffff, ==, --bcount); 425 + } 426 + } 427 + g_assert_cmpmem(tpm_msg, sizeof(tpm_msg), s->tpm_msg, sizeof(*s->tpm_msg)); 428 + 429 + /* relinquish use of locality 0 */ 430 + writeb(TIS_REG(0, TPM_TIS_REG_ACCESS), TPM_TIS_ACCESS_ACTIVE_LOCALITY); 431 + access = readb(TIS_REG(0, TPM_TIS_REG_ACCESS)); 432 + } 433 + 434 + int main(int argc, char **argv) 435 + { 436 + int ret; 437 + char *args, *tmp_path = g_dir_make_tmp("qemu-tpm-tis-test.XXXXXX", NULL); 438 + GThread *thread; 439 + TestState test; 440 + 441 + module_call_init(MODULE_INIT_QOM); 442 + g_test_init(&argc, &argv, NULL); 443 + 444 + test.addr = g_new0(SocketAddress, 1); 445 + test.addr->type = SOCKET_ADDRESS_TYPE_UNIX; 446 + test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL); 447 + g_mutex_init(&test.data_mutex); 448 + g_cond_init(&test.data_cond); 449 + 450 + thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); 451 + tpm_emu_test_wait_cond(&test); 452 + 453 + args = g_strdup_printf( 454 + "-chardev socket,id=chr,path=%s " 455 + "-tpmdev emulator,id=dev,chardev=chr " 456 + "-device tpm-tis,tpmdev=dev", 457 + test.addr->u.q_unix.path); 458 + qtest_start(args); 459 + 460 + qtest_add_data_func("/tpm-tis/test_check_localities", &test, 461 + tpm_tis_test_check_localities); 462 + 463 + qtest_add_data_func("/tpm-tis/test_check_access_reg", &test, 464 + tpm_tis_test_check_access_reg); 465 + 466 + qtest_add_data_func("/tpm-tis/test_check_access_reg_seize", &test, 467 + tpm_tis_test_check_access_reg_seize); 468 + 469 + qtest_add_data_func("/tpm-tis/test_check_access_reg_release", &test, 470 + tpm_tis_test_check_access_reg_release); 471 + 472 + qtest_add_data_func("/tpm-tis/test_check_transmit", &test, 473 + tpm_tis_test_check_transmit); 474 + 475 + ret = g_test_run(); 476 + 477 + qtest_end(); 478 + 479 + g_thread_join(thread); 480 + g_unlink(test.addr->u.q_unix.path); 481 + qapi_free_SocketAddress(test.addr); 482 + g_rmdir(tmp_path); 483 + g_free(tmp_path); 484 + g_free(args); 485 + return ret; 486 + }