1 /* 2 * tpm_tis.c - QEMU's TPM TIS interface emulator 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.21, revision 1.0. 18 * In the developers menu choose the PC Client section then find the TIS 19 * specification. 20 */ 21 22 #include "sysemu/tpm_backend.h" 23 #include "tpm_int.h" 24 #include "sysemu/block-backend.h" 25 #include "exec/address-spaces.h" 26 #include "hw/hw.h" 27 #include "hw/i386/pc.h" 28 #include "hw/pci/pci_ids.h" 29 #include "tpm_tis.h" 30 #include "qemu-common.h" 31 #include "qemu/main-loop.h" 32 33 /*#define DEBUG_TIS */ 34 35 #ifdef DEBUG_TIS 36 #define DPRINTF(fmt, ...) \ 37 do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) 38 #else 39 #define DPRINTF(fmt, ...) \ 40 do { } while (0) 41 #endif 42 43 /* whether the STS interrupt is supported */ 44 #define RAISE_STS_IRQ 45 46 /* tis registers */ 47 #define TPM_TIS_REG_ACCESS 0x00 48 #define TPM_TIS_REG_INT_ENABLE 0x08 49 #define TPM_TIS_REG_INT_VECTOR 0x0c 50 #define TPM_TIS_REG_INT_STATUS 0x10 51 #define TPM_TIS_REG_INTF_CAPABILITY 0x14 52 #define TPM_TIS_REG_STS 0x18 53 #define TPM_TIS_REG_DATA_FIFO 0x24 54 #define TPM_TIS_REG_DATA_XFIFO 0x80 55 #define TPM_TIS_REG_DATA_XFIFO_END 0xbc 56 #define TPM_TIS_REG_DID_VID 0xf00 57 #define TPM_TIS_REG_RID 0xf04 58 59 /* vendor-specific registers */ 60 #define TPM_TIS_REG_DEBUG 0xf90 61 62 #define TPM_TIS_STS_VALID (1 << 7) 63 #define TPM_TIS_STS_COMMAND_READY (1 << 6) 64 #define TPM_TIS_STS_TPM_GO (1 << 5) 65 #define TPM_TIS_STS_DATA_AVAILABLE (1 << 4) 66 #define TPM_TIS_STS_EXPECT (1 << 3) 67 #define TPM_TIS_STS_RESPONSE_RETRY (1 << 1) 68 69 #define TPM_TIS_BURST_COUNT_SHIFT 8 70 #define TPM_TIS_BURST_COUNT(X) \ 71 ((X) << TPM_TIS_BURST_COUNT_SHIFT) 72 73 #define TPM_TIS_ACCESS_TPM_REG_VALID_STS (1 << 7) 74 #define TPM_TIS_ACCESS_ACTIVE_LOCALITY (1 << 5) 75 #define TPM_TIS_ACCESS_BEEN_SEIZED (1 << 4) 76 #define TPM_TIS_ACCESS_SEIZE (1 << 3) 77 #define TPM_TIS_ACCESS_PENDING_REQUEST (1 << 2) 78 #define TPM_TIS_ACCESS_REQUEST_USE (1 << 1) 79 #define TPM_TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0) 80 81 #define TPM_TIS_INT_ENABLED (1 << 31) 82 #define TPM_TIS_INT_DATA_AVAILABLE (1 << 0) 83 #define TPM_TIS_INT_STS_VALID (1 << 1) 84 #define TPM_TIS_INT_LOCALITY_CHANGED (1 << 2) 85 #define TPM_TIS_INT_COMMAND_READY (1 << 7) 86 87 #define TPM_TIS_INT_POLARITY_MASK (3 << 3) 88 #define TPM_TIS_INT_POLARITY_LOW_LEVEL (1 << 3) 89 90 #ifndef RAISE_STS_IRQ 91 92 #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \ 93 TPM_TIS_INT_DATA_AVAILABLE | \ 94 TPM_TIS_INT_COMMAND_READY) 95 96 #else 97 98 #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \ 99 TPM_TIS_INT_DATA_AVAILABLE | \ 100 TPM_TIS_INT_STS_VALID | \ 101 TPM_TIS_INT_COMMAND_READY) 102 103 #endif 104 105 #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ 106 #define TPM_TIS_CAPABILITIES_SUPPORTED (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ 107 TPM_TIS_INTERRUPTS_SUPPORTED) 108 109 #define TPM_TIS_TPM_DID 0x0001 110 #define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM 111 #define TPM_TIS_TPM_RID 0x0001 112 113 #define TPM_TIS_NO_DATA_BYTE 0xff 114 115 /* local prototypes */ 116 117 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, 118 unsigned size); 119 120 /* utility functions */ 121 122 static uint8_t tpm_tis_locality_from_addr(hwaddr addr) 123 { 124 return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7); 125 } 126 127 static uint32_t tpm_tis_get_size_from_buffer(const TPMSizedBuffer *sb) 128 { 129 return be32_to_cpu(*(uint32_t *)&sb->buffer[2]); 130 } 131 132 static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string) 133 { 134 #ifdef DEBUG_TIS 135 uint32_t len, i; 136 137 len = tpm_tis_get_size_from_buffer(sb); 138 DPRINTF("tpm_tis: %s length = %d\n", string, len); 139 for (i = 0; i < len; i++) { 140 if (i && !(i % 16)) { 141 DPRINTF("\n"); 142 } 143 DPRINTF("%.2X ", sb->buffer[i]); 144 } 145 DPRINTF("\n"); 146 #endif 147 } 148 149 /* 150 * Send a request to the TPM. 151 */ 152 static void tpm_tis_tpm_send(TPMState *s, uint8_t locty) 153 { 154 TPMTISEmuState *tis = &s->s.tis; 155 156 tpm_tis_show_buffer(&tis->loc[locty].w_buffer, "tpm_tis: To TPM"); 157 158 s->locty_number = locty; 159 s->locty_data = &tis->loc[locty]; 160 161 /* 162 * w_offset serves as length indicator for length of data; 163 * it's reset when the response comes back 164 */ 165 tis->loc[locty].state = TPM_TIS_STATE_EXECUTION; 166 167 tpm_backend_deliver_request(s->be_driver); 168 } 169 170 /* raise an interrupt if allowed */ 171 static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask) 172 { 173 TPMTISEmuState *tis = &s->s.tis; 174 175 if (!TPM_TIS_IS_VALID_LOCTY(locty)) { 176 return; 177 } 178 179 if ((tis->loc[locty].inte & TPM_TIS_INT_ENABLED) && 180 (tis->loc[locty].inte & irqmask)) { 181 DPRINTF("tpm_tis: Raising IRQ for flag %08x\n", irqmask); 182 qemu_irq_raise(s->s.tis.irq); 183 tis->loc[locty].ints |= irqmask; 184 } 185 } 186 187 static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty) 188 { 189 uint8_t l; 190 191 for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { 192 if (l == locty) { 193 continue; 194 } 195 if ((s->s.tis.loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) { 196 return 1; 197 } 198 } 199 200 return 0; 201 } 202 203 static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty) 204 { 205 TPMTISEmuState *tis = &s->s.tis; 206 bool change = (s->s.tis.active_locty != new_active_locty); 207 bool is_seize; 208 uint8_t mask; 209 210 if (change && TPM_TIS_IS_VALID_LOCTY(s->s.tis.active_locty)) { 211 is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) && 212 tis->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE; 213 214 if (is_seize) { 215 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY); 216 } else { 217 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY| 218 TPM_TIS_ACCESS_REQUEST_USE); 219 } 220 /* reset flags on the old active locality */ 221 tis->loc[s->s.tis.active_locty].access &= mask; 222 223 if (is_seize) { 224 tis->loc[tis->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED; 225 } 226 } 227 228 tis->active_locty = new_active_locty; 229 230 DPRINTF("tpm_tis: Active locality is now %d\n", s->s.tis.active_locty); 231 232 if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) { 233 /* set flags on the new active locality */ 234 tis->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY; 235 tis->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE | 236 TPM_TIS_ACCESS_SEIZE); 237 } 238 239 if (change) { 240 tpm_tis_raise_irq(s, tis->active_locty, TPM_TIS_INT_LOCALITY_CHANGED); 241 } 242 } 243 244 /* abort -- this function switches the locality */ 245 static void tpm_tis_abort(TPMState *s, uint8_t locty) 246 { 247 TPMTISEmuState *tis = &s->s.tis; 248 249 tis->loc[locty].r_offset = 0; 250 tis->loc[locty].w_offset = 0; 251 252 DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", tis->next_locty); 253 254 /* 255 * Need to react differently depending on who's aborting now and 256 * which locality will become active afterwards. 257 */ 258 if (tis->aborting_locty == tis->next_locty) { 259 tis->loc[tis->aborting_locty].state = TPM_TIS_STATE_READY; 260 tis->loc[tis->aborting_locty].sts = TPM_TIS_STS_COMMAND_READY; 261 tpm_tis_raise_irq(s, tis->aborting_locty, TPM_TIS_INT_COMMAND_READY); 262 } 263 264 /* locality after abort is another one than the current one */ 265 tpm_tis_new_active_locality(s, tis->next_locty); 266 267 tis->next_locty = TPM_TIS_NO_LOCALITY; 268 /* nobody's aborting a command anymore */ 269 tis->aborting_locty = TPM_TIS_NO_LOCALITY; 270 } 271 272 /* prepare aborting current command */ 273 static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty) 274 { 275 TPMTISEmuState *tis = &s->s.tis; 276 uint8_t busy_locty; 277 278 tis->aborting_locty = locty; 279 tis->next_locty = newlocty; /* locality after successful abort */ 280 281 /* 282 * only abort a command using an interrupt if currently executing 283 * a command AND if there's a valid connection to the vTPM. 284 */ 285 for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) { 286 if (tis->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) { 287 /* 288 * request the backend to cancel. Some backends may not 289 * support it 290 */ 291 tpm_backend_cancel_cmd(s->be_driver); 292 return; 293 } 294 } 295 296 tpm_tis_abort(s, locty); 297 } 298 299 static void tpm_tis_receive_bh(void *opaque) 300 { 301 TPMState *s = opaque; 302 TPMTISEmuState *tis = &s->s.tis; 303 uint8_t locty = s->locty_number; 304 305 tis->loc[locty].sts = TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE; 306 tis->loc[locty].state = TPM_TIS_STATE_COMPLETION; 307 tis->loc[locty].r_offset = 0; 308 tis->loc[locty].w_offset = 0; 309 310 if (TPM_TIS_IS_VALID_LOCTY(tis->next_locty)) { 311 tpm_tis_abort(s, locty); 312 } 313 314 #ifndef RAISE_STS_IRQ 315 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_DATA_AVAILABLE); 316 #else 317 tpm_tis_raise_irq(s, locty, 318 TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); 319 #endif 320 } 321 322 /* 323 * Callback from the TPM to indicate that the response was received. 324 */ 325 static void tpm_tis_receive_cb(TPMState *s, uint8_t locty) 326 { 327 TPMTISEmuState *tis = &s->s.tis; 328 329 assert(s->locty_number == locty); 330 331 qemu_bh_schedule(tis->bh); 332 } 333 334 /* 335 * Read a byte of response data 336 */ 337 static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty) 338 { 339 TPMTISEmuState *tis = &s->s.tis; 340 uint32_t ret = TPM_TIS_NO_DATA_BYTE; 341 uint16_t len; 342 343 if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { 344 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer); 345 346 ret = tis->loc[locty].r_buffer.buffer[tis->loc[locty].r_offset++]; 347 if (tis->loc[locty].r_offset >= len) { 348 /* got last byte */ 349 tis->loc[locty].sts = TPM_TIS_STS_VALID; 350 #ifdef RAISE_STS_IRQ 351 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); 352 #endif 353 } 354 DPRINTF("tpm_tis: tpm_tis_data_read byte 0x%02x [%d]\n", 355 ret, tis->loc[locty].r_offset-1); 356 } 357 358 return ret; 359 } 360 361 #ifdef DEBUG_TIS 362 static void tpm_tis_dump_state(void *opaque, hwaddr addr) 363 { 364 static const unsigned regs[] = { 365 TPM_TIS_REG_ACCESS, 366 TPM_TIS_REG_INT_ENABLE, 367 TPM_TIS_REG_INT_VECTOR, 368 TPM_TIS_REG_INT_STATUS, 369 TPM_TIS_REG_INTF_CAPABILITY, 370 TPM_TIS_REG_STS, 371 TPM_TIS_REG_DID_VID, 372 TPM_TIS_REG_RID, 373 0xfff}; 374 int idx; 375 uint8_t locty = tpm_tis_locality_from_addr(addr); 376 hwaddr base = addr & ~0xfff; 377 TPMState *s = opaque; 378 TPMTISEmuState *tis = &s->s.tis; 379 380 DPRINTF("tpm_tis: active locality : %d\n" 381 "tpm_tis: state of locality %d : %d\n" 382 "tpm_tis: register dump:\n", 383 tis->active_locty, 384 locty, tis->loc[locty].state); 385 386 for (idx = 0; regs[idx] != 0xfff; idx++) { 387 DPRINTF("tpm_tis: 0x%04x : 0x%08x\n", regs[idx], 388 (uint32_t)tpm_tis_mmio_read(opaque, base + regs[idx], 4)); 389 } 390 391 DPRINTF("tpm_tis: read offset : %d\n" 392 "tpm_tis: result buffer : ", 393 tis->loc[locty].r_offset); 394 for (idx = 0; 395 idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer); 396 idx++) { 397 DPRINTF("%c%02x%s", 398 tis->loc[locty].r_offset == idx ? '>' : ' ', 399 tis->loc[locty].r_buffer.buffer[idx], 400 ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); 401 } 402 DPRINTF("\n" 403 "tpm_tis: write offset : %d\n" 404 "tpm_tis: request buffer: ", 405 tis->loc[locty].w_offset); 406 for (idx = 0; 407 idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer); 408 idx++) { 409 DPRINTF("%c%02x%s", 410 tis->loc[locty].w_offset == idx ? '>' : ' ', 411 tis->loc[locty].w_buffer.buffer[idx], 412 ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : ""); 413 } 414 DPRINTF("\n"); 415 } 416 #endif 417 418 /* 419 * Read a register of the TIS interface 420 * See specs pages 33-63 for description of the registers 421 */ 422 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr, 423 unsigned size) 424 { 425 TPMState *s = opaque; 426 TPMTISEmuState *tis = &s->s.tis; 427 uint16_t offset = addr & 0xffc; 428 uint8_t shift = (addr & 0x3) * 8; 429 uint32_t val = 0xffffffff; 430 uint8_t locty = tpm_tis_locality_from_addr(addr); 431 uint32_t avail; 432 uint8_t v; 433 434 if (tpm_backend_had_startup_error(s->be_driver)) { 435 return val; 436 } 437 438 switch (offset) { 439 case TPM_TIS_REG_ACCESS: 440 /* never show the SEIZE flag even though we use it internally */ 441 val = tis->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE; 442 /* the pending flag is always calculated */ 443 if (tpm_tis_check_request_use_except(s, locty)) { 444 val |= TPM_TIS_ACCESS_PENDING_REQUEST; 445 } 446 val |= !tpm_backend_get_tpm_established_flag(s->be_driver); 447 break; 448 case TPM_TIS_REG_INT_ENABLE: 449 val = tis->loc[locty].inte; 450 break; 451 case TPM_TIS_REG_INT_VECTOR: 452 val = tis->irq_num; 453 break; 454 case TPM_TIS_REG_INT_STATUS: 455 val = tis->loc[locty].ints; 456 break; 457 case TPM_TIS_REG_INTF_CAPABILITY: 458 val = TPM_TIS_CAPABILITIES_SUPPORTED; 459 break; 460 case TPM_TIS_REG_STS: 461 if (tis->active_locty == locty) { 462 if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { 463 val = TPM_TIS_BURST_COUNT( 464 tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer) 465 - tis->loc[locty].r_offset) | tis->loc[locty].sts; 466 } else { 467 avail = tis->loc[locty].w_buffer.size 468 - tis->loc[locty].w_offset; 469 /* 470 * byte-sized reads should not return 0x00 for 0x100 471 * available bytes. 472 */ 473 if (size == 1 && avail > 0xff) { 474 avail = 0xff; 475 } 476 val = TPM_TIS_BURST_COUNT(avail) | tis->loc[locty].sts; 477 } 478 } 479 break; 480 case TPM_TIS_REG_DATA_FIFO: 481 case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: 482 if (tis->active_locty == locty) { 483 if (size > 4 - (addr & 0x3)) { 484 /* prevent access beyond FIFO */ 485 size = 4 - (addr & 0x3); 486 } 487 val = 0; 488 shift = 0; 489 while (size > 0) { 490 switch (tis->loc[locty].state) { 491 case TPM_TIS_STATE_COMPLETION: 492 v = tpm_tis_data_read(s, locty); 493 break; 494 default: 495 v = TPM_TIS_NO_DATA_BYTE; 496 break; 497 } 498 val |= (v << shift); 499 shift += 8; 500 size--; 501 } 502 shift = 0; /* no more adjustments */ 503 } 504 break; 505 case TPM_TIS_REG_DID_VID: 506 val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID; 507 break; 508 case TPM_TIS_REG_RID: 509 val = TPM_TIS_TPM_RID; 510 break; 511 #ifdef DEBUG_TIS 512 case TPM_TIS_REG_DEBUG: 513 tpm_tis_dump_state(opaque, addr); 514 break; 515 #endif 516 } 517 518 if (shift) { 519 val >>= shift; 520 } 521 522 DPRINTF("tpm_tis: read.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val); 523 524 return val; 525 } 526 527 /* 528 * Write a value to a register of the TIS interface 529 * See specs pages 33-63 for description of the registers 530 */ 531 static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, 532 uint64_t val, unsigned size, 533 bool hw_access) 534 { 535 TPMState *s = opaque; 536 TPMTISEmuState *tis = &s->s.tis; 537 uint16_t off = addr & 0xffc; 538 uint8_t shift = (addr & 0x3) * 8; 539 uint8_t locty = tpm_tis_locality_from_addr(addr); 540 uint8_t active_locty, l; 541 int c, set_new_locty = 1; 542 uint16_t len; 543 uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0); 544 545 DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val); 546 547 if (locty == 4 && !hw_access) { 548 DPRINTF("tpm_tis: Access to locality 4 only allowed from hardware\n"); 549 return; 550 } 551 552 if (tpm_backend_had_startup_error(s->be_driver)) { 553 return; 554 } 555 556 val &= mask; 557 558 if (shift) { 559 val <<= shift; 560 mask <<= shift; 561 } 562 563 mask ^= 0xffffffff; 564 565 switch (off) { 566 case TPM_TIS_REG_ACCESS: 567 568 if ((val & TPM_TIS_ACCESS_SEIZE)) { 569 val &= ~(TPM_TIS_ACCESS_REQUEST_USE | 570 TPM_TIS_ACCESS_ACTIVE_LOCALITY); 571 } 572 573 active_locty = tis->active_locty; 574 575 if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) { 576 /* give up locality if currently owned */ 577 if (tis->active_locty == locty) { 578 DPRINTF("tpm_tis: Releasing locality %d\n", locty); 579 580 uint8_t newlocty = TPM_TIS_NO_LOCALITY; 581 /* anybody wants the locality ? */ 582 for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) { 583 if ((tis->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) { 584 DPRINTF("tpm_tis: Locality %d requests use.\n", c); 585 newlocty = c; 586 break; 587 } 588 } 589 DPRINTF("tpm_tis: TPM_TIS_ACCESS_ACTIVE_LOCALITY: " 590 "Next active locality: %d\n", 591 newlocty); 592 593 if (TPM_TIS_IS_VALID_LOCTY(newlocty)) { 594 set_new_locty = 0; 595 tpm_tis_prep_abort(s, locty, newlocty); 596 } else { 597 active_locty = TPM_TIS_NO_LOCALITY; 598 } 599 } else { 600 /* not currently the owner; clear a pending request */ 601 tis->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE; 602 } 603 } 604 605 if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) { 606 tis->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED; 607 } 608 609 if ((val & TPM_TIS_ACCESS_SEIZE)) { 610 /* 611 * allow seize if a locality is active and the requesting 612 * locality is higher than the one that's active 613 * OR 614 * allow seize for requesting locality if no locality is 615 * active 616 */ 617 while ((TPM_TIS_IS_VALID_LOCTY(tis->active_locty) && 618 locty > tis->active_locty) || 619 !TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) { 620 bool higher_seize = FALSE; 621 622 /* already a pending SEIZE ? */ 623 if ((tis->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) { 624 break; 625 } 626 627 /* check for ongoing seize by a higher locality */ 628 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) { 629 if ((tis->loc[l].access & TPM_TIS_ACCESS_SEIZE)) { 630 higher_seize = TRUE; 631 break; 632 } 633 } 634 635 if (higher_seize) { 636 break; 637 } 638 639 /* cancel any seize by a lower locality */ 640 for (l = 0; l < locty - 1; l++) { 641 tis->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE; 642 } 643 644 tis->loc[locty].access |= TPM_TIS_ACCESS_SEIZE; 645 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: " 646 "Locality %d seized from locality %d\n", 647 locty, tis->active_locty); 648 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: Initiating abort.\n"); 649 set_new_locty = 0; 650 tpm_tis_prep_abort(s, tis->active_locty, locty); 651 break; 652 } 653 } 654 655 if ((val & TPM_TIS_ACCESS_REQUEST_USE)) { 656 if (tis->active_locty != locty) { 657 if (TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) { 658 tis->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE; 659 } else { 660 /* no locality active -> make this one active now */ 661 active_locty = locty; 662 } 663 } 664 } 665 666 if (set_new_locty) { 667 tpm_tis_new_active_locality(s, active_locty); 668 } 669 670 break; 671 case TPM_TIS_REG_INT_ENABLE: 672 if (tis->active_locty != locty) { 673 break; 674 } 675 676 tis->loc[locty].inte &= mask; 677 tis->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | 678 TPM_TIS_INT_POLARITY_MASK | 679 TPM_TIS_INTERRUPTS_SUPPORTED)); 680 break; 681 case TPM_TIS_REG_INT_VECTOR: 682 /* hard wired -- ignore */ 683 break; 684 case TPM_TIS_REG_INT_STATUS: 685 if (tis->active_locty != locty) { 686 break; 687 } 688 689 /* clearing of interrupt flags */ 690 if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && 691 (tis->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { 692 tis->loc[locty].ints &= ~val; 693 if (tis->loc[locty].ints == 0) { 694 qemu_irq_lower(tis->irq); 695 DPRINTF("tpm_tis: Lowering IRQ\n"); 696 } 697 } 698 tis->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED); 699 break; 700 case TPM_TIS_REG_STS: 701 if (tis->active_locty != locty) { 702 break; 703 } 704 705 val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO | 706 TPM_TIS_STS_RESPONSE_RETRY); 707 708 if (val == TPM_TIS_STS_COMMAND_READY) { 709 switch (tis->loc[locty].state) { 710 711 case TPM_TIS_STATE_READY: 712 tis->loc[locty].w_offset = 0; 713 tis->loc[locty].r_offset = 0; 714 break; 715 716 case TPM_TIS_STATE_IDLE: 717 tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; 718 tis->loc[locty].state = TPM_TIS_STATE_READY; 719 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 720 break; 721 722 case TPM_TIS_STATE_EXECUTION: 723 case TPM_TIS_STATE_RECEPTION: 724 /* abort currently running command */ 725 DPRINTF("tpm_tis: %s: Initiating abort.\n", 726 __func__); 727 tpm_tis_prep_abort(s, locty, locty); 728 break; 729 730 case TPM_TIS_STATE_COMPLETION: 731 tis->loc[locty].w_offset = 0; 732 tis->loc[locty].r_offset = 0; 733 /* shortcut to ready state with C/R set */ 734 tis->loc[locty].state = TPM_TIS_STATE_READY; 735 if (!(tis->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) { 736 tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; 737 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 738 } 739 tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE); 740 break; 741 742 } 743 } else if (val == TPM_TIS_STS_TPM_GO) { 744 switch (tis->loc[locty].state) { 745 case TPM_TIS_STATE_RECEPTION: 746 if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) { 747 tpm_tis_tpm_send(s, locty); 748 } 749 break; 750 default: 751 /* ignore */ 752 break; 753 } 754 } else if (val == TPM_TIS_STS_RESPONSE_RETRY) { 755 switch (tis->loc[locty].state) { 756 case TPM_TIS_STATE_COMPLETION: 757 tis->loc[locty].r_offset = 0; 758 tis->loc[locty].sts = TPM_TIS_STS_VALID | 759 TPM_TIS_STS_DATA_AVAILABLE; 760 break; 761 default: 762 /* ignore */ 763 break; 764 } 765 } 766 break; 767 case TPM_TIS_REG_DATA_FIFO: 768 case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END: 769 /* data fifo */ 770 if (tis->active_locty != locty) { 771 break; 772 } 773 774 if (tis->loc[locty].state == TPM_TIS_STATE_IDLE || 775 tis->loc[locty].state == TPM_TIS_STATE_EXECUTION || 776 tis->loc[locty].state == TPM_TIS_STATE_COMPLETION) { 777 /* drop the byte */ 778 } else { 779 DPRINTF("tpm_tis: Data to send to TPM: %08x (size=%d)\n", 780 val, size); 781 if (tis->loc[locty].state == TPM_TIS_STATE_READY) { 782 tis->loc[locty].state = TPM_TIS_STATE_RECEPTION; 783 tis->loc[locty].sts = TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID; 784 } 785 786 val >>= shift; 787 if (size > 4 - (addr & 0x3)) { 788 /* prevent access beyond FIFO */ 789 size = 4 - (addr & 0x3); 790 } 791 792 while ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) { 793 if (tis->loc[locty].w_offset < tis->loc[locty].w_buffer.size) { 794 tis->loc[locty].w_buffer. 795 buffer[tis->loc[locty].w_offset++] = (uint8_t)val; 796 val >>= 8; 797 size--; 798 } else { 799 tis->loc[locty].sts = TPM_TIS_STS_VALID; 800 } 801 } 802 803 /* check for complete packet */ 804 if (tis->loc[locty].w_offset > 5 && 805 (tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) { 806 /* we have a packet length - see if we have all of it */ 807 #ifdef RAISE_STS_IRQ 808 bool needIrq = !(tis->loc[locty].sts & TPM_TIS_STS_VALID); 809 #endif 810 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer); 811 if (len > tis->loc[locty].w_offset) { 812 tis->loc[locty].sts = TPM_TIS_STS_EXPECT | 813 TPM_TIS_STS_VALID; 814 } else { 815 /* packet complete */ 816 tis->loc[locty].sts = TPM_TIS_STS_VALID; 817 } 818 #ifdef RAISE_STS_IRQ 819 if (needIrq) { 820 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); 821 } 822 #endif 823 } 824 } 825 break; 826 } 827 } 828 829 static void tpm_tis_mmio_write(void *opaque, hwaddr addr, 830 uint64_t val, unsigned size) 831 { 832 return tpm_tis_mmio_write_intern(opaque, addr, val, size, false); 833 } 834 835 static const MemoryRegionOps tpm_tis_memory_ops = { 836 .read = tpm_tis_mmio_read, 837 .write = tpm_tis_mmio_write, 838 .endianness = DEVICE_LITTLE_ENDIAN, 839 .valid = { 840 .min_access_size = 1, 841 .max_access_size = 4, 842 }, 843 }; 844 845 static int tpm_tis_do_startup_tpm(TPMState *s) 846 { 847 return tpm_backend_startup_tpm(s->be_driver); 848 } 849 850 /* 851 * This function is called when the machine starts, resets or due to 852 * S3 resume. 853 */ 854 static void tpm_tis_reset(DeviceState *dev) 855 { 856 TPMState *s = TPM(dev); 857 TPMTISEmuState *tis = &s->s.tis; 858 int c; 859 860 tpm_backend_reset(s->be_driver); 861 862 tis->active_locty = TPM_TIS_NO_LOCALITY; 863 tis->next_locty = TPM_TIS_NO_LOCALITY; 864 tis->aborting_locty = TPM_TIS_NO_LOCALITY; 865 866 for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) { 867 tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS; 868 tis->loc[c].sts = 0; 869 tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL; 870 tis->loc[c].ints = 0; 871 tis->loc[c].state = TPM_TIS_STATE_IDLE; 872 873 tis->loc[c].w_offset = 0; 874 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer); 875 tis->loc[c].r_offset = 0; 876 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer); 877 } 878 879 tpm_tis_do_startup_tpm(s); 880 } 881 882 static const VMStateDescription vmstate_tpm_tis = { 883 .name = "tpm", 884 .unmigratable = 1, 885 }; 886 887 static Property tpm_tis_properties[] = { 888 DEFINE_PROP_UINT32("irq", TPMState, 889 s.tis.irq_num, TPM_TIS_IRQ), 890 DEFINE_PROP_STRING("tpmdev", TPMState, backend), 891 DEFINE_PROP_END_OF_LIST(), 892 }; 893 894 static void tpm_tis_realizefn(DeviceState *dev, Error **errp) 895 { 896 TPMState *s = TPM(dev); 897 TPMTISEmuState *tis = &s->s.tis; 898 899 s->be_driver = qemu_find_tpm(s->backend); 900 if (!s->be_driver) { 901 error_setg(errp, "tpm_tis: backend driver with id %s could not be " 902 "found", s->backend); 903 return; 904 } 905 906 s->be_driver->fe_model = TPM_MODEL_TPM_TIS; 907 908 if (tpm_backend_init(s->be_driver, s, tpm_tis_receive_cb)) { 909 error_setg(errp, "tpm_tis: backend driver with id %s could not be " 910 "initialized", s->backend); 911 return; 912 } 913 914 if (tis->irq_num > 15) { 915 error_setg(errp, "tpm_tis: IRQ %d for TPM TIS is outside valid range " 916 "of 0 to 15.\n", tis->irq_num); 917 return; 918 } 919 920 tis->bh = qemu_bh_new(tpm_tis_receive_bh, s); 921 922 isa_init_irq(&s->busdev, &tis->irq, tis->irq_num); 923 } 924 925 static void tpm_tis_initfn(Object *obj) 926 { 927 ISADevice *dev = ISA_DEVICE(obj); 928 TPMState *s = TPM(obj); 929 930 memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, 931 s, "tpm-tis-mmio", 932 TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); 933 memory_region_add_subregion(isa_address_space(dev), TPM_TIS_ADDR_BASE, 934 &s->mmio); 935 } 936 937 static void tpm_tis_class_init(ObjectClass *klass, void *data) 938 { 939 DeviceClass *dc = DEVICE_CLASS(klass); 940 941 dc->realize = tpm_tis_realizefn; 942 dc->props = tpm_tis_properties; 943 dc->reset = tpm_tis_reset; 944 dc->vmsd = &vmstate_tpm_tis; 945 } 946 947 static const TypeInfo tpm_tis_info = { 948 .name = TYPE_TPM_TIS, 949 .parent = TYPE_ISA_DEVICE, 950 .instance_size = sizeof(TPMState), 951 .instance_init = tpm_tis_initfn, 952 .class_init = tpm_tis_class_init, 953 }; 954 955 static void tpm_tis_register(void) 956 { 957 type_register_static(&tpm_tis_info); 958 tpm_register_model(TPM_MODEL_TPM_TIS); 959 } 960 961 type_init(tpm_tis_register) 962