tpm-tis-util.c (17841B)
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 42static const uint8_t TPM_CMD[12] = 43 "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00"; 44 45void 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 75void 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 */ 106void 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 */ 299void 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 */ 374void tpm_tis_test_check_transmit(const void *data) 375{ 376 const TPMTestState *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}