tpm: Support for capability flags of TIS 1.3
[qemu/ar7.git] / hw / tpm / tpm_tis.c
blobd0bb97f7d93ba7f942eb2b63afccd2c2fc5f1b61
1 /*
2 * tpm_tis.c - QEMU's TPM TIS interface emulator
4 * Copyright (C) 2006,2010-2013 IBM Corporation
6 * Authors:
7 * Stefan Berger <stefanb@us.ibm.com>
8 * David Safford <safford@us.ibm.com>
10 * Xen 4 support: Andrease Niederl <andreas.niederl@iaik.tugraz.at>
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.
15 * Implementation of the TIS interface according to specs found at
16 * http://www.trustedcomputinggroup.org. This implementation currently
17 * supports version 1.3, 21 March 2013
18 * In the developers menu choose the PC Client section then find the TIS
19 * specification.
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"
33 /*#define DEBUG_TIS */
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
43 /* whether the STS interrupt is supported */
44 #define RAISE_STS_IRQ
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
59 /* vendor-specific registers */
60 #define TPM_TIS_REG_DEBUG 0xf90
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_SELFTEST_DONE (1 << 2)
68 #define TPM_TIS_STS_RESPONSE_RETRY (1 << 1)
70 #define TPM_TIS_BURST_COUNT_SHIFT 8
71 #define TPM_TIS_BURST_COUNT(X) \
72 ((X) << TPM_TIS_BURST_COUNT_SHIFT)
74 #define TPM_TIS_ACCESS_TPM_REG_VALID_STS (1 << 7)
75 #define TPM_TIS_ACCESS_ACTIVE_LOCALITY (1 << 5)
76 #define TPM_TIS_ACCESS_BEEN_SEIZED (1 << 4)
77 #define TPM_TIS_ACCESS_SEIZE (1 << 3)
78 #define TPM_TIS_ACCESS_PENDING_REQUEST (1 << 2)
79 #define TPM_TIS_ACCESS_REQUEST_USE (1 << 1)
80 #define TPM_TIS_ACCESS_TPM_ESTABLISHMENT (1 << 0)
82 #define TPM_TIS_INT_ENABLED (1 << 31)
83 #define TPM_TIS_INT_DATA_AVAILABLE (1 << 0)
84 #define TPM_TIS_INT_STS_VALID (1 << 1)
85 #define TPM_TIS_INT_LOCALITY_CHANGED (1 << 2)
86 #define TPM_TIS_INT_COMMAND_READY (1 << 7)
88 #define TPM_TIS_INT_POLARITY_MASK (3 << 3)
89 #define TPM_TIS_INT_POLARITY_LOW_LEVEL (1 << 3)
91 #ifndef RAISE_STS_IRQ
93 #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \
94 TPM_TIS_INT_DATA_AVAILABLE | \
95 TPM_TIS_INT_COMMAND_READY)
97 #else
99 #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \
100 TPM_TIS_INT_DATA_AVAILABLE | \
101 TPM_TIS_INT_STS_VALID | \
102 TPM_TIS_INT_COMMAND_READY)
104 #endif
106 #define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28)
107 #define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9)
108 #define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9)
109 #define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8)
110 #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */
111 #define TPM_TIS_CAPABILITIES_SUPPORTED (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \
112 TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \
113 TPM_TIS_CAP_DATA_TRANSFER_64B | \
114 TPM_TIS_CAP_INTERFACE_VERSION1_3 | \
115 TPM_TIS_INTERRUPTS_SUPPORTED)
117 #define TPM_TIS_TPM_DID 0x0001
118 #define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM
119 #define TPM_TIS_TPM_RID 0x0001
121 #define TPM_TIS_NO_DATA_BYTE 0xff
123 /* local prototypes */
125 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
126 unsigned size);
128 /* utility functions */
130 static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
132 return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7);
135 static uint32_t tpm_tis_get_size_from_buffer(const TPMSizedBuffer *sb)
137 return be32_to_cpu(*(uint32_t *)&sb->buffer[2]);
140 static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
142 #ifdef DEBUG_TIS
143 uint32_t len, i;
145 len = tpm_tis_get_size_from_buffer(sb);
146 DPRINTF("tpm_tis: %s length = %d\n", string, len);
147 for (i = 0; i < len; i++) {
148 if (i && !(i % 16)) {
149 DPRINTF("\n");
151 DPRINTF("%.2X ", sb->buffer[i]);
153 DPRINTF("\n");
154 #endif
158 * Set the given flags in the STS register by clearing the register but
159 * preserving the SELFTEST_DONE flag and then setting the new flags.
161 * The SELFTEST_DONE flag is acquired from the backend that determines it by
162 * peeking into TPM commands.
164 * A VM suspend/resume will preserve the flag by storing it into the VM
165 * device state, but the backend will not remember it when QEMU is started
166 * again. Therefore, we cache the flag here. Once set, it will not be unset
167 * except by a reset.
169 static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
171 l->sts &= TPM_TIS_STS_SELFTEST_DONE;
172 l->sts |= flags;
176 * Send a request to the TPM.
178 static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
180 TPMTISEmuState *tis = &s->s.tis;
182 tpm_tis_show_buffer(&tis->loc[locty].w_buffer, "tpm_tis: To TPM");
184 s->locty_number = locty;
185 s->locty_data = &tis->loc[locty];
188 * w_offset serves as length indicator for length of data;
189 * it's reset when the response comes back
191 tis->loc[locty].state = TPM_TIS_STATE_EXECUTION;
193 tpm_backend_deliver_request(s->be_driver);
196 /* raise an interrupt if allowed */
197 static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask)
199 TPMTISEmuState *tis = &s->s.tis;
201 if (!TPM_TIS_IS_VALID_LOCTY(locty)) {
202 return;
205 if ((tis->loc[locty].inte & TPM_TIS_INT_ENABLED) &&
206 (tis->loc[locty].inte & irqmask)) {
207 DPRINTF("tpm_tis: Raising IRQ for flag %08x\n", irqmask);
208 qemu_irq_raise(s->s.tis.irq);
209 tis->loc[locty].ints |= irqmask;
213 static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty)
215 uint8_t l;
217 for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
218 if (l == locty) {
219 continue;
221 if ((s->s.tis.loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) {
222 return 1;
226 return 0;
229 static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty)
231 TPMTISEmuState *tis = &s->s.tis;
232 bool change = (s->s.tis.active_locty != new_active_locty);
233 bool is_seize;
234 uint8_t mask;
236 if (change && TPM_TIS_IS_VALID_LOCTY(s->s.tis.active_locty)) {
237 is_seize = TPM_TIS_IS_VALID_LOCTY(new_active_locty) &&
238 tis->loc[new_active_locty].access & TPM_TIS_ACCESS_SEIZE;
240 if (is_seize) {
241 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY);
242 } else {
243 mask = ~(TPM_TIS_ACCESS_ACTIVE_LOCALITY|
244 TPM_TIS_ACCESS_REQUEST_USE);
246 /* reset flags on the old active locality */
247 tis->loc[s->s.tis.active_locty].access &= mask;
249 if (is_seize) {
250 tis->loc[tis->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED;
254 tis->active_locty = new_active_locty;
256 DPRINTF("tpm_tis: Active locality is now %d\n", s->s.tis.active_locty);
258 if (TPM_TIS_IS_VALID_LOCTY(new_active_locty)) {
259 /* set flags on the new active locality */
260 tis->loc[new_active_locty].access |= TPM_TIS_ACCESS_ACTIVE_LOCALITY;
261 tis->loc[new_active_locty].access &= ~(TPM_TIS_ACCESS_REQUEST_USE |
262 TPM_TIS_ACCESS_SEIZE);
265 if (change) {
266 tpm_tis_raise_irq(s, tis->active_locty, TPM_TIS_INT_LOCALITY_CHANGED);
270 /* abort -- this function switches the locality */
271 static void tpm_tis_abort(TPMState *s, uint8_t locty)
273 TPMTISEmuState *tis = &s->s.tis;
275 tis->loc[locty].r_offset = 0;
276 tis->loc[locty].w_offset = 0;
278 DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", tis->next_locty);
281 * Need to react differently depending on who's aborting now and
282 * which locality will become active afterwards.
284 if (tis->aborting_locty == tis->next_locty) {
285 tis->loc[tis->aborting_locty].state = TPM_TIS_STATE_READY;
286 tpm_tis_sts_set(&tis->loc[tis->aborting_locty],
287 TPM_TIS_STS_COMMAND_READY);
288 tpm_tis_raise_irq(s, tis->aborting_locty, TPM_TIS_INT_COMMAND_READY);
291 /* locality after abort is another one than the current one */
292 tpm_tis_new_active_locality(s, tis->next_locty);
294 tis->next_locty = TPM_TIS_NO_LOCALITY;
295 /* nobody's aborting a command anymore */
296 tis->aborting_locty = TPM_TIS_NO_LOCALITY;
299 /* prepare aborting current command */
300 static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
302 TPMTISEmuState *tis = &s->s.tis;
303 uint8_t busy_locty;
305 tis->aborting_locty = locty;
306 tis->next_locty = newlocty; /* locality after successful abort */
309 * only abort a command using an interrupt if currently executing
310 * a command AND if there's a valid connection to the vTPM.
312 for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) {
313 if (tis->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) {
315 * request the backend to cancel. Some backends may not
316 * support it
318 tpm_backend_cancel_cmd(s->be_driver);
319 return;
323 tpm_tis_abort(s, locty);
326 static void tpm_tis_receive_bh(void *opaque)
328 TPMState *s = opaque;
329 TPMTISEmuState *tis = &s->s.tis;
330 uint8_t locty = s->locty_number;
332 tpm_tis_sts_set(&tis->loc[locty],
333 TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE);
334 tis->loc[locty].state = TPM_TIS_STATE_COMPLETION;
335 tis->loc[locty].r_offset = 0;
336 tis->loc[locty].w_offset = 0;
338 if (TPM_TIS_IS_VALID_LOCTY(tis->next_locty)) {
339 tpm_tis_abort(s, locty);
342 #ifndef RAISE_STS_IRQ
343 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_DATA_AVAILABLE);
344 #else
345 tpm_tis_raise_irq(s, locty,
346 TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID);
347 #endif
351 * Callback from the TPM to indicate that the response was received.
353 static void tpm_tis_receive_cb(TPMState *s, uint8_t locty,
354 bool is_selftest_done)
356 TPMTISEmuState *tis = &s->s.tis;
357 uint8_t l;
359 assert(s->locty_number == locty);
361 if (is_selftest_done) {
362 for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
363 tis->loc[locty].sts |= TPM_TIS_STS_SELFTEST_DONE;
367 qemu_bh_schedule(tis->bh);
371 * Read a byte of response data
373 static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
375 TPMTISEmuState *tis = &s->s.tis;
376 uint32_t ret = TPM_TIS_NO_DATA_BYTE;
377 uint16_t len;
379 if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
380 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer);
382 ret = tis->loc[locty].r_buffer.buffer[tis->loc[locty].r_offset++];
383 if (tis->loc[locty].r_offset >= len) {
384 /* got last byte */
385 tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID);
386 #ifdef RAISE_STS_IRQ
387 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
388 #endif
390 DPRINTF("tpm_tis: tpm_tis_data_read byte 0x%02x [%d]\n",
391 ret, tis->loc[locty].r_offset-1);
394 return ret;
397 #ifdef DEBUG_TIS
398 static void tpm_tis_dump_state(void *opaque, hwaddr addr)
400 static const unsigned regs[] = {
401 TPM_TIS_REG_ACCESS,
402 TPM_TIS_REG_INT_ENABLE,
403 TPM_TIS_REG_INT_VECTOR,
404 TPM_TIS_REG_INT_STATUS,
405 TPM_TIS_REG_INTF_CAPABILITY,
406 TPM_TIS_REG_STS,
407 TPM_TIS_REG_DID_VID,
408 TPM_TIS_REG_RID,
409 0xfff};
410 int idx;
411 uint8_t locty = tpm_tis_locality_from_addr(addr);
412 hwaddr base = addr & ~0xfff;
413 TPMState *s = opaque;
414 TPMTISEmuState *tis = &s->s.tis;
416 DPRINTF("tpm_tis: active locality : %d\n"
417 "tpm_tis: state of locality %d : %d\n"
418 "tpm_tis: register dump:\n",
419 tis->active_locty,
420 locty, tis->loc[locty].state);
422 for (idx = 0; regs[idx] != 0xfff; idx++) {
423 DPRINTF("tpm_tis: 0x%04x : 0x%08x\n", regs[idx],
424 (uint32_t)tpm_tis_mmio_read(opaque, base + regs[idx], 4));
427 DPRINTF("tpm_tis: read offset : %d\n"
428 "tpm_tis: result buffer : ",
429 tis->loc[locty].r_offset);
430 for (idx = 0;
431 idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer);
432 idx++) {
433 DPRINTF("%c%02x%s",
434 tis->loc[locty].r_offset == idx ? '>' : ' ',
435 tis->loc[locty].r_buffer.buffer[idx],
436 ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : "");
438 DPRINTF("\n"
439 "tpm_tis: write offset : %d\n"
440 "tpm_tis: request buffer: ",
441 tis->loc[locty].w_offset);
442 for (idx = 0;
443 idx < tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer);
444 idx++) {
445 DPRINTF("%c%02x%s",
446 tis->loc[locty].w_offset == idx ? '>' : ' ',
447 tis->loc[locty].w_buffer.buffer[idx],
448 ((idx & 0xf) == 0xf) ? "\ntpm_tis: " : "");
450 DPRINTF("\n");
452 #endif
455 * Read a register of the TIS interface
456 * See specs pages 33-63 for description of the registers
458 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
459 unsigned size)
461 TPMState *s = opaque;
462 TPMTISEmuState *tis = &s->s.tis;
463 uint16_t offset = addr & 0xffc;
464 uint8_t shift = (addr & 0x3) * 8;
465 uint32_t val = 0xffffffff;
466 uint8_t locty = tpm_tis_locality_from_addr(addr);
467 uint32_t avail;
468 uint8_t v;
470 if (tpm_backend_had_startup_error(s->be_driver)) {
471 return val;
474 switch (offset) {
475 case TPM_TIS_REG_ACCESS:
476 /* never show the SEIZE flag even though we use it internally */
477 val = tis->loc[locty].access & ~TPM_TIS_ACCESS_SEIZE;
478 /* the pending flag is always calculated */
479 if (tpm_tis_check_request_use_except(s, locty)) {
480 val |= TPM_TIS_ACCESS_PENDING_REQUEST;
482 val |= !tpm_backend_get_tpm_established_flag(s->be_driver);
483 break;
484 case TPM_TIS_REG_INT_ENABLE:
485 val = tis->loc[locty].inte;
486 break;
487 case TPM_TIS_REG_INT_VECTOR:
488 val = tis->irq_num;
489 break;
490 case TPM_TIS_REG_INT_STATUS:
491 val = tis->loc[locty].ints;
492 break;
493 case TPM_TIS_REG_INTF_CAPABILITY:
494 val = TPM_TIS_CAPABILITIES_SUPPORTED;
495 break;
496 case TPM_TIS_REG_STS:
497 if (tis->active_locty == locty) {
498 if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
499 val = TPM_TIS_BURST_COUNT(
500 tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer)
501 - tis->loc[locty].r_offset) | tis->loc[locty].sts;
502 } else {
503 avail = tis->loc[locty].w_buffer.size
504 - tis->loc[locty].w_offset;
506 * byte-sized reads should not return 0x00 for 0x100
507 * available bytes.
509 if (size == 1 && avail > 0xff) {
510 avail = 0xff;
512 val = TPM_TIS_BURST_COUNT(avail) | tis->loc[locty].sts;
515 break;
516 case TPM_TIS_REG_DATA_FIFO:
517 case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
518 if (tis->active_locty == locty) {
519 if (size > 4 - (addr & 0x3)) {
520 /* prevent access beyond FIFO */
521 size = 4 - (addr & 0x3);
523 val = 0;
524 shift = 0;
525 while (size > 0) {
526 switch (tis->loc[locty].state) {
527 case TPM_TIS_STATE_COMPLETION:
528 v = tpm_tis_data_read(s, locty);
529 break;
530 default:
531 v = TPM_TIS_NO_DATA_BYTE;
532 break;
534 val |= (v << shift);
535 shift += 8;
536 size--;
538 shift = 0; /* no more adjustments */
540 break;
541 case TPM_TIS_REG_DID_VID:
542 val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID;
543 break;
544 case TPM_TIS_REG_RID:
545 val = TPM_TIS_TPM_RID;
546 break;
547 #ifdef DEBUG_TIS
548 case TPM_TIS_REG_DEBUG:
549 tpm_tis_dump_state(opaque, addr);
550 break;
551 #endif
554 if (shift) {
555 val >>= shift;
558 DPRINTF("tpm_tis: read.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val);
560 return val;
564 * Write a value to a register of the TIS interface
565 * See specs pages 33-63 for description of the registers
567 static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
568 uint64_t val, unsigned size,
569 bool hw_access)
571 TPMState *s = opaque;
572 TPMTISEmuState *tis = &s->s.tis;
573 uint16_t off = addr & 0xffc;
574 uint8_t shift = (addr & 0x3) * 8;
575 uint8_t locty = tpm_tis_locality_from_addr(addr);
576 uint8_t active_locty, l;
577 int c, set_new_locty = 1;
578 uint16_t len;
579 uint32_t mask = (size == 1) ? 0xff : ((size == 2) ? 0xffff : ~0);
581 DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val);
583 if (locty == 4 && !hw_access) {
584 DPRINTF("tpm_tis: Access to locality 4 only allowed from hardware\n");
585 return;
588 if (tpm_backend_had_startup_error(s->be_driver)) {
589 return;
592 val &= mask;
594 if (shift) {
595 val <<= shift;
596 mask <<= shift;
599 mask ^= 0xffffffff;
601 switch (off) {
602 case TPM_TIS_REG_ACCESS:
604 if ((val & TPM_TIS_ACCESS_SEIZE)) {
605 val &= ~(TPM_TIS_ACCESS_REQUEST_USE |
606 TPM_TIS_ACCESS_ACTIVE_LOCALITY);
609 active_locty = tis->active_locty;
611 if ((val & TPM_TIS_ACCESS_ACTIVE_LOCALITY)) {
612 /* give up locality if currently owned */
613 if (tis->active_locty == locty) {
614 DPRINTF("tpm_tis: Releasing locality %d\n", locty);
616 uint8_t newlocty = TPM_TIS_NO_LOCALITY;
617 /* anybody wants the locality ? */
618 for (c = TPM_TIS_NUM_LOCALITIES - 1; c >= 0; c--) {
619 if ((tis->loc[c].access & TPM_TIS_ACCESS_REQUEST_USE)) {
620 DPRINTF("tpm_tis: Locality %d requests use.\n", c);
621 newlocty = c;
622 break;
625 DPRINTF("tpm_tis: TPM_TIS_ACCESS_ACTIVE_LOCALITY: "
626 "Next active locality: %d\n",
627 newlocty);
629 if (TPM_TIS_IS_VALID_LOCTY(newlocty)) {
630 set_new_locty = 0;
631 tpm_tis_prep_abort(s, locty, newlocty);
632 } else {
633 active_locty = TPM_TIS_NO_LOCALITY;
635 } else {
636 /* not currently the owner; clear a pending request */
637 tis->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE;
641 if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) {
642 tis->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED;
645 if ((val & TPM_TIS_ACCESS_SEIZE)) {
647 * allow seize if a locality is active and the requesting
648 * locality is higher than the one that's active
649 * OR
650 * allow seize for requesting locality if no locality is
651 * active
653 while ((TPM_TIS_IS_VALID_LOCTY(tis->active_locty) &&
654 locty > tis->active_locty) ||
655 !TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) {
656 bool higher_seize = FALSE;
658 /* already a pending SEIZE ? */
659 if ((tis->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
660 break;
663 /* check for ongoing seize by a higher locality */
664 for (l = locty + 1; l < TPM_TIS_NUM_LOCALITIES; l++) {
665 if ((tis->loc[l].access & TPM_TIS_ACCESS_SEIZE)) {
666 higher_seize = TRUE;
667 break;
671 if (higher_seize) {
672 break;
675 /* cancel any seize by a lower locality */
676 for (l = 0; l < locty - 1; l++) {
677 tis->loc[l].access &= ~TPM_TIS_ACCESS_SEIZE;
680 tis->loc[locty].access |= TPM_TIS_ACCESS_SEIZE;
681 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: "
682 "Locality %d seized from locality %d\n",
683 locty, tis->active_locty);
684 DPRINTF("tpm_tis: TPM_TIS_ACCESS_SEIZE: Initiating abort.\n");
685 set_new_locty = 0;
686 tpm_tis_prep_abort(s, tis->active_locty, locty);
687 break;
691 if ((val & TPM_TIS_ACCESS_REQUEST_USE)) {
692 if (tis->active_locty != locty) {
693 if (TPM_TIS_IS_VALID_LOCTY(tis->active_locty)) {
694 tis->loc[locty].access |= TPM_TIS_ACCESS_REQUEST_USE;
695 } else {
696 /* no locality active -> make this one active now */
697 active_locty = locty;
702 if (set_new_locty) {
703 tpm_tis_new_active_locality(s, active_locty);
706 break;
707 case TPM_TIS_REG_INT_ENABLE:
708 if (tis->active_locty != locty) {
709 break;
712 tis->loc[locty].inte &= mask;
713 tis->loc[locty].inte |= (val & (TPM_TIS_INT_ENABLED |
714 TPM_TIS_INT_POLARITY_MASK |
715 TPM_TIS_INTERRUPTS_SUPPORTED));
716 break;
717 case TPM_TIS_REG_INT_VECTOR:
718 /* hard wired -- ignore */
719 break;
720 case TPM_TIS_REG_INT_STATUS:
721 if (tis->active_locty != locty) {
722 break;
725 /* clearing of interrupt flags */
726 if (((val & TPM_TIS_INTERRUPTS_SUPPORTED)) &&
727 (tis->loc[locty].ints & TPM_TIS_INTERRUPTS_SUPPORTED)) {
728 tis->loc[locty].ints &= ~val;
729 if (tis->loc[locty].ints == 0) {
730 qemu_irq_lower(tis->irq);
731 DPRINTF("tpm_tis: Lowering IRQ\n");
734 tis->loc[locty].ints &= ~(val & TPM_TIS_INTERRUPTS_SUPPORTED);
735 break;
736 case TPM_TIS_REG_STS:
737 if (tis->active_locty != locty) {
738 break;
741 val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
742 TPM_TIS_STS_RESPONSE_RETRY);
744 if (val == TPM_TIS_STS_COMMAND_READY) {
745 switch (tis->loc[locty].state) {
747 case TPM_TIS_STATE_READY:
748 tis->loc[locty].w_offset = 0;
749 tis->loc[locty].r_offset = 0;
750 break;
752 case TPM_TIS_STATE_IDLE:
753 tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_COMMAND_READY);
754 tis->loc[locty].state = TPM_TIS_STATE_READY;
755 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
756 break;
758 case TPM_TIS_STATE_EXECUTION:
759 case TPM_TIS_STATE_RECEPTION:
760 /* abort currently running command */
761 DPRINTF("tpm_tis: %s: Initiating abort.\n",
762 __func__);
763 tpm_tis_prep_abort(s, locty, locty);
764 break;
766 case TPM_TIS_STATE_COMPLETION:
767 tis->loc[locty].w_offset = 0;
768 tis->loc[locty].r_offset = 0;
769 /* shortcut to ready state with C/R set */
770 tis->loc[locty].state = TPM_TIS_STATE_READY;
771 if (!(tis->loc[locty].sts & TPM_TIS_STS_COMMAND_READY)) {
772 tpm_tis_sts_set(&tis->loc[locty],
773 TPM_TIS_STS_COMMAND_READY);
774 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_COMMAND_READY);
776 tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE);
777 break;
780 } else if (val == TPM_TIS_STS_TPM_GO) {
781 switch (tis->loc[locty].state) {
782 case TPM_TIS_STATE_RECEPTION:
783 if ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) == 0) {
784 tpm_tis_tpm_send(s, locty);
786 break;
787 default:
788 /* ignore */
789 break;
791 } else if (val == TPM_TIS_STS_RESPONSE_RETRY) {
792 switch (tis->loc[locty].state) {
793 case TPM_TIS_STATE_COMPLETION:
794 tis->loc[locty].r_offset = 0;
795 tpm_tis_sts_set(&tis->loc[locty],
796 TPM_TIS_STS_VALID|
797 TPM_TIS_STS_DATA_AVAILABLE);
798 break;
799 default:
800 /* ignore */
801 break;
804 break;
805 case TPM_TIS_REG_DATA_FIFO:
806 case TPM_TIS_REG_DATA_XFIFO ... TPM_TIS_REG_DATA_XFIFO_END:
807 /* data fifo */
808 if (tis->active_locty != locty) {
809 break;
812 if (tis->loc[locty].state == TPM_TIS_STATE_IDLE ||
813 tis->loc[locty].state == TPM_TIS_STATE_EXECUTION ||
814 tis->loc[locty].state == TPM_TIS_STATE_COMPLETION) {
815 /* drop the byte */
816 } else {
817 DPRINTF("tpm_tis: Data to send to TPM: %08x (size=%d)\n",
818 val, size);
819 if (tis->loc[locty].state == TPM_TIS_STATE_READY) {
820 tis->loc[locty].state = TPM_TIS_STATE_RECEPTION;
821 tpm_tis_sts_set(&tis->loc[locty],
822 TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
825 val >>= shift;
826 if (size > 4 - (addr & 0x3)) {
827 /* prevent access beyond FIFO */
828 size = 4 - (addr & 0x3);
831 while ((tis->loc[locty].sts & TPM_TIS_STS_EXPECT) && size > 0) {
832 if (tis->loc[locty].w_offset < tis->loc[locty].w_buffer.size) {
833 tis->loc[locty].w_buffer.
834 buffer[tis->loc[locty].w_offset++] = (uint8_t)val;
835 val >>= 8;
836 size--;
837 } else {
838 tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID);
842 /* check for complete packet */
843 if (tis->loc[locty].w_offset > 5 &&
844 (tis->loc[locty].sts & TPM_TIS_STS_EXPECT)) {
845 /* we have a packet length - see if we have all of it */
846 #ifdef RAISE_STS_IRQ
847 bool needIrq = !(tis->loc[locty].sts & TPM_TIS_STS_VALID);
848 #endif
849 len = tpm_tis_get_size_from_buffer(&tis->loc[locty].w_buffer);
850 if (len > tis->loc[locty].w_offset) {
851 tpm_tis_sts_set(&tis->loc[locty],
852 TPM_TIS_STS_EXPECT | TPM_TIS_STS_VALID);
853 } else {
854 /* packet complete */
855 tpm_tis_sts_set(&tis->loc[locty], TPM_TIS_STS_VALID);
857 #ifdef RAISE_STS_IRQ
858 if (needIrq) {
859 tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
861 #endif
864 break;
868 static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
869 uint64_t val, unsigned size)
871 return tpm_tis_mmio_write_intern(opaque, addr, val, size, false);
874 static const MemoryRegionOps tpm_tis_memory_ops = {
875 .read = tpm_tis_mmio_read,
876 .write = tpm_tis_mmio_write,
877 .endianness = DEVICE_LITTLE_ENDIAN,
878 .valid = {
879 .min_access_size = 1,
880 .max_access_size = 4,
884 static int tpm_tis_do_startup_tpm(TPMState *s)
886 return tpm_backend_startup_tpm(s->be_driver);
890 * This function is called when the machine starts, resets or due to
891 * S3 resume.
893 static void tpm_tis_reset(DeviceState *dev)
895 TPMState *s = TPM(dev);
896 TPMTISEmuState *tis = &s->s.tis;
897 int c;
899 tpm_backend_reset(s->be_driver);
901 tis->active_locty = TPM_TIS_NO_LOCALITY;
902 tis->next_locty = TPM_TIS_NO_LOCALITY;
903 tis->aborting_locty = TPM_TIS_NO_LOCALITY;
905 for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) {
906 tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS;
907 tis->loc[c].sts = 0;
908 tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL;
909 tis->loc[c].ints = 0;
910 tis->loc[c].state = TPM_TIS_STATE_IDLE;
912 tis->loc[c].w_offset = 0;
913 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].w_buffer);
914 tis->loc[c].r_offset = 0;
915 tpm_backend_realloc_buffer(s->be_driver, &tis->loc[c].r_buffer);
918 tpm_tis_do_startup_tpm(s);
921 static const VMStateDescription vmstate_tpm_tis = {
922 .name = "tpm",
923 .unmigratable = 1,
926 static Property tpm_tis_properties[] = {
927 DEFINE_PROP_UINT32("irq", TPMState,
928 s.tis.irq_num, TPM_TIS_IRQ),
929 DEFINE_PROP_STRING("tpmdev", TPMState, backend),
930 DEFINE_PROP_END_OF_LIST(),
933 static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
935 TPMState *s = TPM(dev);
936 TPMTISEmuState *tis = &s->s.tis;
938 s->be_driver = qemu_find_tpm(s->backend);
939 if (!s->be_driver) {
940 error_setg(errp, "tpm_tis: backend driver with id %s could not be "
941 "found", s->backend);
942 return;
945 s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
947 if (tpm_backend_init(s->be_driver, s, tpm_tis_receive_cb)) {
948 error_setg(errp, "tpm_tis: backend driver with id %s could not be "
949 "initialized", s->backend);
950 return;
953 if (tis->irq_num > 15) {
954 error_setg(errp, "tpm_tis: IRQ %d for TPM TIS is outside valid range "
955 "of 0 to 15.\n", tis->irq_num);
956 return;
959 tis->bh = qemu_bh_new(tpm_tis_receive_bh, s);
961 isa_init_irq(&s->busdev, &tis->irq, tis->irq_num);
964 static void tpm_tis_initfn(Object *obj)
966 ISADevice *dev = ISA_DEVICE(obj);
967 TPMState *s = TPM(obj);
969 memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops,
970 s, "tpm-tis-mmio",
971 TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
972 memory_region_add_subregion(isa_address_space(dev), TPM_TIS_ADDR_BASE,
973 &s->mmio);
976 static void tpm_tis_class_init(ObjectClass *klass, void *data)
978 DeviceClass *dc = DEVICE_CLASS(klass);
980 dc->realize = tpm_tis_realizefn;
981 dc->props = tpm_tis_properties;
982 dc->reset = tpm_tis_reset;
983 dc->vmsd = &vmstate_tpm_tis;
986 static const TypeInfo tpm_tis_info = {
987 .name = TYPE_TPM_TIS,
988 .parent = TYPE_ISA_DEVICE,
989 .instance_size = sizeof(TPMState),
990 .instance_init = tpm_tis_initfn,
991 .class_init = tpm_tis_class_init,
994 static void tpm_tis_register(void)
996 type_register_static(&tpm_tis_info);
997 tpm_register_model(TPM_MODEL_TPM_TIS);
1000 type_init(tpm_tis_register)