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