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_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 uint8_t v; 431 432 if (tpm_backend_had_startup_error(s->be_driver)) { 433 return val; 434 } 435 436 switch (offset) { 437 case TPM_TIS_REG_ACCESS: 438 /* never show the SEIZE flag even though we use it internally */ 439 val = tis->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE; 440 /* the pending flag is always calculated */ 441 if (tpm_tis_check_request_use_except(s, locty)) { 442 val |= TPM_TIS_ACCESS_PENDING_REQUEST; 443 } 444 val |= !tpm_backend_get_tpm_established_flag(s->be_driver); 445 break; 446 case TPM_TIS_REG_INT_ENABLE: 447 val = tis->loc[locty].inte; 448 break; 449 case TPM_TIS_REG_INT_VECTOR: 450 val = tis->irq_num; 451 break; 452 case TPM_TIS_REG_INT_STATUS: 453 val = tis->loc[locty].ints; 454 break; 455 case TPM_TIS_REG_INTF_CAPABILITY: 456 val = TPM_TIS_CAPABILITIES_SUPPORTED; 457 break; 458 case TPM_TIS_REG_STS: 459 if (tis->active_locty == locty) { 460 if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) { 461 val = TPM_TIS_BURST_COUNT( 462 tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer) 463 - tis->loc[locty].r_offset) | tis->loc[locty].sts; 464 } else { 465 avail = tis->loc[locty].w_buffer.size 466 - tis->loc[locty].w_offset; 467 /* 468 * byte-sized reads should not return 0x00 for 0x100 469 * available bytes. 470 */ 471 if (size == 1 && avail > 0xff) { 472 avail = 0xff; 473 } 474 val = TPM_TIS_BURST_COUNT(avail) | tis->loc[locty].sts; 475 } 476 } 477 break; 478 case TPM_TIS_REG_DATA_FIFO: 479 if (tis->active_locty == locty) { 480 if (size > 4 - (addr & 0x3)) { 481 /* prevent access beyond FIFO */ 482 size = 4 - (addr & 0x3); 483 } 484 val = 0; 485 shift = 0; 486 while (size > 0) { 487 switch (tis->loc[locty].state) { 488 case TPM_TIS_STATE_COMPLETION: 489 v = tpm_tis_data_read(s, locty); 490 break; 491 default: 492 v = TPM_TIS_NO_DATA_BYTE; 493 break; 494 } 495 val |= (v << shift); 496 shift += 8; 497 size--; 498 } 499 shift = 0; /* no more adjustments */ 500 } 501 break; 502 case TPM_TIS_REG_DID_VID: 503 val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID; 504 break; 505 case TPM_TIS_REG_RID: 506 val = TPM_TIS_TPM_RID; 507 break; 508 #ifdef DEBUG_TIS 509 case TPM_TIS_REG_DEBUG: 510 tpm_tis_dump_state(opaque, addr); 511 break; 512 #endif 513 } 514 515 if (shift) { 516 val >>= shift; 517 } 518 519 DPRINTF("tpm_tis: read.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val); 520 521 return val; 522 } 523 524 /* 525 * Write a value to a register of the TIS interface 526 * See specs pages 33-63 for description of the registers 527 */ 528 static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr, 529 uint64_t val, unsigned size, 530 bool hw_access) 531 { 532 TPMState *s = opaque; 533 TPMTISEmuState *tis = &s->s.tis; 534 uint16_t off = addr & 0xffc; 535 uint8_t shift = (addr & 0x3) * 8; 536 uint8_t locty = tpm_tis_locality_from_addr(addr); 537 uint8_t active_locty, l; 538 int c, set_new_locty = 1; 539 uint16_t len; 540 uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0); 541 542 DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val); 543 544 if (locty == 4 && !hw_access) { 545 DPRINTF("tpm_tis: Access to locality 4 only allowed from hardware\n"); 546 return; 547 } 548 549 if (tpm_backend_had_startup_error(s->be_driver)) { 550 return; 551 } 552 553 val &= mask; 554 555 if (shift) { 556 val <<= shift; 557 mask <<= shift; 558 } 559 560 mask ^= 0xffffffff; 561 562 switch (off) { 563 case TPM_TIS_REG_ACCESS: 564 565 if ((val & TPM_TIS_ACCESS_SEIZE)) { 566 val &= ~(TPM_TIS_ACCESS_REQUEST_USE | 567 TPM_TIS_ACCESS_ACTIVE_LOCALITY); 568 } 569 570 active_locty = tis->active_locty; 571 572 if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) { 573 /* give up locality if currently owned */ 574 if (tis->active_locty == locty) { 575 DPRINTF("tpm_tis: Releasing locality %d\n", locty); 576 577 uint8_t newlocty = TPM_TIS_NO_LOCALITY; 578 /* anybody wants the locality ? */ 579 for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) { 580 if ((tis->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) { 581 DPRINTF("tpm_tis: Locality %d requests use.\n", c); 582 newlocty = c; 583 break; 584 } 585 } 586 DPRINTF("tpm_tis: TPM_TIS_ACCESS_ACTIVE_LOCALITY: " 587 "Next active locality: %d\n", 588 newlocty); 589 590 if (TPM_TIS_IS_VALID_LOCTY(newlocty)) { 591 set_new_locty = 0; 592 tpm_tis_prep_abort(s, locty, newlocty); 593 } else { 594 active_locty = TPM_TIS_NO_LOCALITY; 595 } 596 } else { 597 /* not currently the owner; clear a pending request */ 598 tis->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE; 599 } 600 } 601 602 if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) { 603 tis->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED; 604 } 605 606 if ((val & TPM_TIS_ACCESS_SEIZE)) { 607 /* 608 * allow seize if a locality is active and the requesting 609 * locality is higher than the one that's active 610 * OR 611 * allow seize for requesting locality if no locality is 612 * active 613 */ 614 while ((TPM_TIS_IS_VALID_LOCTY(tis->active_locty) && 615 locty > tis->active_locty) || 616 !TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) { 617 bool higher_seize = FALSE; 618 619 /* already a pending SEIZE ? */ 620 if ((tis->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) { 621 break; 622 } 623 624 /* check for ongoing seize by a higher locality */ 625 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) { 626 if ((tis->loc[l].access & TPM_TIS_ACCESS_SEIZE)) { 627 higher_seize = TRUE; 628 break; 629 } 630 } 631 632 if (higher_seize) { 633 break; 634 } 635 636 /* cancel any seize by a lower locality */ 637 for (l = 0; l < locty - 1; l++) { 638 tis->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE; 639 } 640 641 tis->loc[locty].access |= TPM_TIS_ACCESS_SEIZE; 642 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: " 643 "Locality %d seized from locality %d\n", 644 locty, tis->active_locty); 645 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: Initiating abort.\n"); 646 set_new_locty = 0; 647 tpm_tis_prep_abort(s, tis->active_locty, locty); 648 break; 649 } 650 } 651 652 if ((val & TPM_TIS_ACCESS_REQUEST_USE)) { 653 if (tis->active_locty != locty) { 654 if (TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) { 655 tis->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE; 656 } else { 657 /* no locality active -> make this one active now */ 658 active_locty = locty; 659 } 660 } 661 } 662 663 if (set_new_locty) { 664 tpm_tis_new_active_locality(s, active_locty); 665 } 666 667 break; 668 case TPM_TIS_REG_INT_ENABLE: 669 if (tis->active_locty != locty) { 670 break; 671 } 672 673 tis->loc[locty].inte &= mask; 674 tis->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED | 675 TPM_TIS_INT_POLARITY_MASK | 676 TPM_TIS_INTERRUPTS_SUPPORTED)); 677 break; 678 case TPM_TIS_REG_INT_VECTOR: 679 /* hard wired -- ignore */ 680 break; 681 case TPM_TIS_REG_INT_STATUS: 682 if (tis->active_locty != locty) { 683 break; 684 } 685 686 /* clearing of interrupt flags */ 687 if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) && 688 (tis->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) { 689 tis->loc[locty].ints &= ~val; 690 if (tis->loc[locty].ints == 0) { 691 qemu_irq_lower(tis->irq); 692 DPRINTF("tpm_tis: Lowering IRQ\n"); 693 } 694 } 695 tis->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED); 696 break; 697 case TPM_TIS_REG_STS: 698 if (tis->active_locty != locty) { 699 break; 700 } 701 702 val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO | 703 TPM_TIS_STS_RESPONSE_RETRY); 704 705 if (val == TPM_TIS_STS_COMMAND_READY) { 706 switch (tis->loc[locty].state) { 707 708 case TPM_TIS_STATE_READY: 709 tis->loc[locty].w_offset = 0; 710 tis->loc[locty].r_offset = 0; 711 break; 712 713 case TPM_TIS_STATE_IDLE: 714 tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; 715 tis->loc[locty].state = TPM_TIS_STATE_READY; 716 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 717 break; 718 719 case TPM_TIS_STATE_EXECUTION: 720 case TPM_TIS_STATE_RECEPTION: 721 /* abort currently running command */ 722 DPRINTF("tpm_tis: %s: Initiating abort.\n", 723 __func__); 724 tpm_tis_prep_abort(s, locty, locty); 725 break; 726 727 case TPM_TIS_STATE_COMPLETION: 728 tis->loc[locty].w_offset = 0; 729 tis->loc[locty].r_offset = 0; 730 /* shortcut to ready state with C/R set */ 731 tis->loc[locty].state = TPM_TIS_STATE_READY; 732 if (!(tis->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) { 733 tis->loc[locty].sts = TPM_TIS_STS_COMMAND_READY; 734 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY); 735 } 736 tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE); 737 break; 738 739 } 740 } else if (val == TPM_TIS_STS_TPM_GO) { 741 switch (tis->loc[locty].state) { 742 case TPM_TIS_STATE_RECEPTION: 743 if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) { 744 tpm_tis_tpm_send(s, locty); 745 } 746 break; 747 default: 748 /* ignore */ 749 break; 750 } 751 } else if (val == TPM_TIS_STS_RESPONSE_RETRY) { 752 switch (tis->loc[locty].state) { 753 case TPM_TIS_STATE_COMPLETION: 754 tis->loc[locty].r_offset = 0; 755 tis->loc[locty].sts = TPM_TIS_STS_VALID | 756 TPM_TIS_STS_DATA_AVAILABLE; 757 break; 758 default: 759 /* ignore */ 760 break; 761 } 762 } 763 break; 764 case TPM_TIS_REG_DATA_FIFO: 765 /* data fifo */ 766 if (tis->active_locty != locty) { 767 break; 768 } 769 770 if (tis->loc[locty].state == TPM_TIS_STATE_IDLE || 771 tis->loc[locty].state == TPM_TIS_STATE_EXECUTION || 772 tis->loc[locty].state == TPM_TIS_STATE_COMPLETION) { 773 /* drop the byte */ 774 } else { 775 DPRINTF("tpm_tis: Data to send to TPM: %08x (size=%d)\n", 776 val, size); 777 if (tis->loc[locty].state == TPM_TIS_STATE_READY) { 778 tis->loc[locty].state = TPM_TIS_STATE_RECEPTION; 779 tis->loc[locty].sts = TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID; 780 } 781 782 val >>= shift; 783 if (size > 4 - (addr & 0x3)) { 784 /* prevent access beyond FIFO */ 785 size = 4 - (addr & 0x3); 786 } 787 788 while ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) { 789 if (tis->loc[locty].w_offset < tis->loc[locty].w_buffer.size) { 790 tis->loc[locty].w_buffer. 791 buffer[tis->loc[locty].w_offset++] = (uint8_t)val; 792 val >>= 8; 793 size--; 794 } else { 795 tis->loc[locty].sts = TPM_TIS_STS_VALID; 796 } 797 } 798 799 /* check for complete packet */ 800 if (tis->loc[locty].w_offset > 5 && 801 (tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) { 802 /* we have a packet length - see if we have all of it */ 803 #ifdef RAISE_STS_IRQ 804 bool needIrq = !(tis->loc[locty].sts & TPM_TIS_STS_VALID); 805 #endif 806 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer); 807 if (len > tis->loc[locty].w_offset) { 808 tis->loc[locty].sts = TPM_TIS_STS_EXPECT | 809 TPM_TIS_STS_VALID; 810 } else { 811 /* packet complete */ 812 tis->loc[locty].sts = TPM_TIS_STS_VALID; 813 } 814 #ifdef RAISE_STS_IRQ 815 if (needIrq) { 816 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID); 817 } 818 #endif 819 } 820 } 821 break; 822 } 823 } 824 825 static void tpm_tis_mmio_write(void *opaque, hwaddr addr, 826 uint64_t val, unsigned size) 827 { 828 return tpm_tis_mmio_write_intern(opaque, addr, val, size, false); 829 } 830 831 static const MemoryRegionOps tpm_tis_memory_ops = { 832 .read = tpm_tis_mmio_read, 833 .write = tpm_tis_mmio_write, 834 .endianness = DEVICE_LITTLE_ENDIAN, 835 .valid = { 836 .min_access_size = 1, 837 .max_access_size = 4, 838 }, 839 }; 840 841 static int tpm_tis_do_startup_tpm(TPMState *s) 842 { 843 return tpm_backend_startup_tpm(s->be_driver); 844 } 845 846 /* 847 * This function is called when the machine starts, resets or due to 848 * S3 resume. 849 */ 850 static void tpm_tis_reset(DeviceState *dev) 851 { 852 TPMState *s = TPM(dev); 853 TPMTISEmuState *tis = &s->s.tis; 854 int c; 855 856 tpm_backend_reset(s->be_driver); 857 858 tis->active_locty = TPM_TIS_NO_LOCALITY; 859 tis->next_locty = TPM_TIS_NO_LOCALITY; 860 tis->aborting_locty = TPM_TIS_NO_LOCALITY; 861 862 for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) { 863 tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS; 864 tis->loc[c].sts = 0; 865 tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL; 866 tis->loc[c].ints = 0; 867 tis->loc[c].state = TPM_TIS_STATE_IDLE; 868 869 tis->loc[c].w_offset = 0; 870 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer); 871 tis->loc[c].r_offset = 0; 872 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer); 873 } 874 875 tpm_tis_do_startup_tpm(s); 876 } 877 878 static const VMStateDescription vmstate_tpm_tis = { 879 .name = "tpm", 880 .unmigratable = 1, 881 }; 882 883 static Property tpm_tis_properties[] = { 884 DEFINE_PROP_UINT32("irq", TPMState, 885 s.tis.irq_num, TPM_TIS_IRQ), 886 DEFINE_PROP_STRING("tpmdev", TPMState, backend), 887 DEFINE_PROP_END_OF_LIST(), 888 }; 889 890 static void tpm_tis_realizefn(DeviceState *dev, Error **errp) 891 { 892 TPMState *s = TPM(dev); 893 TPMTISEmuState *tis = &s->s.tis; 894 895 s->be_driver = qemu_find_tpm(s->backend); 896 if (!s->be_driver) { 897 error_setg(errp, "tpm_tis: backend driver with id %s could not be " 898 "found", s->backend); 899 return; 900 } 901 902 s->be_driver->fe_model = TPM_MODEL_TPM_TIS; 903 904 if (tpm_backend_init(s->be_driver, s, tpm_tis_receive_cb)) { 905 error_setg(errp, "tpm_tis: backend driver with id %s could not be " 906 "initialized", s->backend); 907 return; 908 } 909 910 if (tis->irq_num > 15) { 911 error_setg(errp, "tpm_tis: IRQ %d for TPM TIS is outside valid range " 912 "of 0 to 15.\n", tis->irq_num); 913 return; 914 } 915 916 tis->bh = qemu_bh_new(tpm_tis_receive_bh, s); 917 918 isa_init_irq(&s->busdev, &tis->irq, tis->irq_num); 919 } 920 921 static void tpm_tis_initfn(Object *obj) 922 { 923 ISADevice *dev = ISA_DEVICE(obj); 924 TPMState *s = TPM(obj); 925 926 memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, 927 s, "tpm-tis-mmio", 928 TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); 929 memory_region_add_subregion(isa_address_space(dev), TPM_TIS_ADDR_BASE, 930 &s->mmio); 931 } 932 933 static void tpm_tis_class_init(ObjectClass *klass, void *data) 934 { 935 DeviceClass *dc = DEVICE_CLASS(klass); 936 937 dc->realize = tpm_tis_realizefn; 938 dc->props = tpm_tis_properties; 939 dc->reset = tpm_tis_reset; 940 dc->vmsd = &vmstate_tpm_tis; 941 } 942 943 static const TypeInfo tpm_tis_info = { 944 .name = TYPE_TPM_TIS, 945 .parent = TYPE_ISA_DEVICE, 946 .instance_size = sizeof(TPMState), 947 .instance_init = tpm_tis_initfn, 948 .class_init = tpm_tis_class_init, 949 }; 950 951 static void tpm_tis_register(void) 952 { 953 type_register_static(&tpm_tis_info); 954 tpm_register_model(TPM_MODEL_TPM_TIS); 955 } 956 957 type_init(tpm_tis_register) 958