xref: /qemu/hw/tpm/tpm_tis_common.c (revision e7ae771f6de2c7b3fa87823f87d6e10caeb91ec6)
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.3, 21 March 2013
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_SELFTEST_DONE         (1 << 2)
68 #define TPM_TIS_STS_RESPONSE_RETRY        (1 << 1)
69 
70 #define TPM_TIS_BURST_COUNT_SHIFT         8
71 #define TPM_TIS_BURST_COUNT(X) \
72     ((X) << TPM_TIS_BURST_COUNT_SHIFT)
73 
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)
81 
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)
87 
88 #define TPM_TIS_INT_POLARITY_MASK         (3 << 3)
89 #define TPM_TIS_INT_POLARITY_LOW_LEVEL    (1 << 3)
90 
91 #ifndef RAISE_STS_IRQ
92 
93 #define TPM_TIS_INTERRUPTS_SUPPORTED (TPM_TIS_INT_LOCALITY_CHANGED | \
94                                       TPM_TIS_INT_DATA_AVAILABLE   | \
95                                       TPM_TIS_INT_COMMAND_READY)
96 
97 #else
98 
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)
103 
104 #endif
105 
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)
116 
117 #define TPM_TIS_TPM_DID       0x0001
118 #define TPM_TIS_TPM_VID       PCI_VENDOR_ID_IBM
119 #define TPM_TIS_TPM_RID       0x0001
120 
121 #define TPM_TIS_NO_DATA_BYTE  0xff
122 
123 /* local prototypes */
124 
125 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
126                                   unsigned size);
127 
128 /* utility functions */
129 
130 static uint8_t tpm_tis_locality_from_addr(hwaddr addr)
131 {
132     return (uint8_t)((addr >> TPM_TIS_LOCALITY_SHIFT) & 0x7);
133 }
134 
135 static uint32_t tpm_tis_get_size_from_buffer(const TPMSizedBuffer *sb)
136 {
137     return be32_to_cpu(*(uint32_t *)&sb->buffer[2]);
138 }
139 
140 static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, const char *string)
141 {
142 #ifdef DEBUG_TIS
143     uint32_t len, i;
144 
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");
150         }
151         DPRINTF("%.2X ", sb->buffer[i]);
152     }
153     DPRINTF("\n");
154 #endif
155 }
156 
157 /*
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.
160  *
161  * The SELFTEST_DONE flag is acquired from the backend that determines it by
162  * peeking into TPM commands.
163  *
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.
168  */
169 static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags)
170 {
171     l->sts &= TPM_TIS_STS_SELFTEST_DONE;
172     l->sts |= flags;
173 }
174 
175 /*
176  * Send a request to the TPM.
177  */
178 static void tpm_tis_tpm_send(TPMState *s, uint8_t locty)
179 {
180     TPMTISEmuState *tis = &s->s.tis;
181 
182     tpm_tis_show_buffer(&tis->loc[locty].w_buffer, "tpm_tis: To TPM");
183 
184     s->locty_number = locty;
185     s->locty_data = &tis->loc[locty];
186 
187     /*
188      * w_offset serves as length indicator for length of data;
189      * it's reset when the response comes back
190      */
191     tis->loc[locty].state = TPM_TIS_STATE_EXECUTION;
192 
193     tpm_backend_deliver_request(s->be_driver);
194 }
195 
196 /* raise an interrupt if allowed */
197 static void tpm_tis_raise_irq(TPMState *s, uint8_t locty, uint32_t irqmask)
198 {
199     TPMTISEmuState *tis = &s->s.tis;
200 
201     if (!TPM_TIS_IS_VALID_LOCTY(locty)) {
202         return;
203     }
204 
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;
210     }
211 }
212 
213 static uint32_t tpm_tis_check_request_use_except(TPMState *s, uint8_t locty)
214 {
215     uint8_t l;
216 
217     for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) {
218         if (l == locty) {
219             continue;
220         }
221         if ((s->s.tis.loc[l].access & TPM_TIS_ACCESS_REQUEST_USE)) {
222             return 1;
223         }
224     }
225 
226     return 0;
227 }
228 
229 static void tpm_tis_new_active_locality(TPMState *s, uint8_t new_active_locty)
230 {
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;
235 
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;
239 
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);
245         }
246         /* reset flags on the old active locality */
247         tis->loc[s->s.tis.active_locty].access &= mask;
248 
249         if (is_seize) {
250             tis->loc[tis->active_locty].access |= TPM_TIS_ACCESS_BEEN_SEIZED;
251         }
252     }
253 
254     tis->active_locty = new_active_locty;
255 
256     DPRINTF("tpm_tis: Active locality is now %d\n", s->s.tis.active_locty);
257 
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);
263     }
264 
265     if (change) {
266         tpm_tis_raise_irq(s, tis->active_locty, TPM_TIS_INT_LOCALITY_CHANGED);
267     }
268 }
269 
270 /* abort -- this function switches the locality */
271 static void tpm_tis_abort(TPMState *s, uint8_t locty)
272 {
273     TPMTISEmuState *tis = &s->s.tis;
274 
275     tis->loc[locty].r_offset = 0;
276     tis->loc[locty].w_offset = 0;
277 
278     DPRINTF("tpm_tis: tis_abort: new active locality is %d\n", tis->next_locty);
279 
280     /*
281      * Need to react differently depending on who's aborting now and
282      * which locality will become active afterwards.
283      */
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);
289     }
290 
291     /* locality after abort is another one than the current one */
292     tpm_tis_new_active_locality(s, tis->next_locty);
293 
294     tis->next_locty = TPM_TIS_NO_LOCALITY;
295     /* nobody's aborting a command anymore */
296     tis->aborting_locty = TPM_TIS_NO_LOCALITY;
297 }
298 
299 /* prepare aborting current command */
300 static void tpm_tis_prep_abort(TPMState *s, uint8_t locty, uint8_t newlocty)
301 {
302     TPMTISEmuState *tis = &s->s.tis;
303     uint8_t busy_locty;
304 
305     tis->aborting_locty = locty;
306     tis->next_locty = newlocty;  /* locality after successful abort */
307 
308     /*
309      * only abort a command using an interrupt if currently executing
310      * a command AND if there's a valid connection to the vTPM.
311      */
312     for (busy_locty = 0; busy_locty < TPM_TIS_NUM_LOCALITIES; busy_locty++) {
313         if (tis->loc[busy_locty].state == TPM_TIS_STATE_EXECUTION) {
314             /*
315              * request the backend to cancel. Some backends may not
316              * support it
317              */
318             tpm_backend_cancel_cmd(s->be_driver);
319             return;
320         }
321     }
322 
323     tpm_tis_abort(s, locty);
324 }
325 
326 static void tpm_tis_receive_bh(void *opaque)
327 {
328     TPMState *s = opaque;
329     TPMTISEmuState *tis = &s->s.tis;
330     uint8_t locty = s->locty_number;
331 
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;
337 
338     if (TPM_TIS_IS_VALID_LOCTY(tis->next_locty)) {
339         tpm_tis_abort(s, locty);
340     }
341 
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
348 }
349 
350 /*
351  * Callback from the TPM to indicate that the response was received.
352  */
353 static void tpm_tis_receive_cb(TPMState *s, uint8_t locty,
354                                bool is_selftest_done)
355 {
356     TPMTISEmuState *tis = &s->s.tis;
357     uint8_t l;
358 
359     assert(s->locty_number == locty);
360 
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;
364         }
365     }
366 
367     qemu_bh_schedule(tis->bh);
368 }
369 
370 /*
371  * Read a byte of response data
372  */
373 static uint32_t tpm_tis_data_read(TPMState *s, uint8_t locty)
374 {
375     TPMTISEmuState *tis = &s->s.tis;
376     uint32_t ret = TPM_TIS_NO_DATA_BYTE;
377     uint16_t len;
378 
379     if ((tis->loc[locty].sts & TPM_TIS_STS_DATA_AVAILABLE)) {
380         len = tpm_tis_get_size_from_buffer(&tis->loc[locty].r_buffer);
381 
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
389         }
390         DPRINTF("tpm_tis: tpm_tis_data_read byte 0x%02x   [%d]\n",
391                 ret, tis->loc[locty].r_offset-1);
392     }
393 
394     return ret;
395 }
396 
397 #ifdef DEBUG_TIS
398 static void tpm_tis_dump_state(void *opaque, hwaddr addr)
399 {
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;
415 
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);
421 
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));
425     }
426 
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:                 " : "");
437     }
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:                 " : "");
449     }
450     DPRINTF("\n");
451 }
452 #endif
453 
454 /*
455  * Read a register of the TIS interface
456  * See specs pages 33-63 for description of the registers
457  */
458 static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr addr,
459                                   unsigned size)
460 {
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;
469 
470     if (tpm_backend_had_startup_error(s->be_driver)) {
471         return val;
472     }
473 
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;
481         }
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;
505                 /*
506                  * byte-sized reads should not return 0x00 for 0x100
507                  * available bytes.
508                  */
509                 if (size == 1 && avail > 0xff) {
510                     avail = 0xff;
511                 }
512                 val = TPM_TIS_BURST_COUNT(avail) | tis->loc[locty].sts;
513             }
514         }
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);
522             }
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;
533                 }
534                 val |= (v << shift);
535                 shift += 8;
536                 size--;
537             }
538             shift = 0; /* no more adjustments */
539         }
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
552     }
553 
554     if (shift) {
555         val >>= shift;
556     }
557 
558     DPRINTF("tpm_tis:  read.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val);
559 
560     return val;
561 }
562 
563 /*
564  * Write a value to a register of the TIS interface
565  * See specs pages 33-63 for description of the registers
566  */
567 static void tpm_tis_mmio_write_intern(void *opaque, hwaddr addr,
568                                       uint64_t val, unsigned size,
569                                       bool hw_access)
570 {
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);
580 
581     DPRINTF("tpm_tis: write.%u(%08x) = %08x\n", size, (int)addr, (uint32_t)val);
582 
583     if (locty == 4 && !hw_access) {
584         DPRINTF("tpm_tis: Access to locality 4 only allowed from hardware\n");
585         return;
586     }
587 
588     if (tpm_backend_had_startup_error(s->be_driver)) {
589         return;
590     }
591 
592     val &= mask;
593 
594     if (shift) {
595         val <<= shift;
596         mask <<= shift;
597     }
598 
599     mask ^= 0xffffffff;
600 
601     switch (off) {
602     case TPM_TIS_REG_ACCESS:
603 
604         if ((val & TPM_TIS_ACCESS_SEIZE)) {
605             val &= ~(TPM_TIS_ACCESS_REQUEST_USE |
606                      TPM_TIS_ACCESS_ACTIVE_LOCALITY);
607         }
608 
609         active_locty = tis->active_locty;
610 
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);
615 
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;
623                     }
624                 }
625                 DPRINTF("tpm_tis: TPM_TIS_ACCESS_ACTIVE_LOCALITY: "
626                         "Next active locality: %d\n",
627                         newlocty);
628 
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;
634                 }
635             } else {
636                 /* not currently the owner; clear a pending request */
637                 tis->loc[locty].access &= ~TPM_TIS_ACCESS_REQUEST_USE;
638             }
639         }
640 
641         if ((val & TPM_TIS_ACCESS_BEEN_SEIZED)) {
642             tis->loc[locty].access &= ~TPM_TIS_ACCESS_BEEN_SEIZED;
643         }
644 
645         if ((val & TPM_TIS_ACCESS_SEIZE)) {
646             /*
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
652              */
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;
657 
658                 /* already a pending SEIZE ? */
659                 if ((tis->loc[locty].access & TPM_TIS_ACCESS_SEIZE)) {
660                     break;
661                 }
662 
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;
668                     }
669                 }
670 
671                 if (higher_seize) {
672                     break;
673                 }
674 
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;
678                 }
679 
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;
688             }
689         }
690 
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;
698                 }
699             }
700         }
701 
702         if (set_new_locty) {
703             tpm_tis_new_active_locality(s, active_locty);
704         }
705 
706         break;
707     case TPM_TIS_REG_INT_ENABLE:
708         if (tis->active_locty != locty) {
709             break;
710         }
711 
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;
723         }
724 
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");
732             }
733         }
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;
739         }
740 
741         val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO |
742                 TPM_TIS_STS_RESPONSE_RETRY);
743 
744         if (val == TPM_TIS_STS_COMMAND_READY) {
745             switch (tis->loc[locty].state) {
746 
747             case TPM_TIS_STATE_READY:
748                 tis->loc[locty].w_offset = 0;
749                 tis->loc[locty].r_offset = 0;
750             break;
751 
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;
757 
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;
765 
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);
775                 }
776                 tis->loc[locty].sts &= ~(TPM_TIS_STS_DATA_AVAILABLE);
777             break;
778 
779             }
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);
785                 }
786                 break;
787             default:
788                 /* ignore */
789                 break;
790             }
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;
802             }
803         }
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;
810         }
811 
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);
823             }
824 
825             val >>= shift;
826             if (size > 4 - (addr & 0x3)) {
827                 /* prevent access beyond FIFO */
828                 size = 4 - (addr & 0x3);
829             }
830 
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);
839                 }
840             }
841 
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);
856                 }
857 #ifdef RAISE_STS_IRQ
858                 if (needIrq) {
859                     tpm_tis_raise_irq(s, locty, TPM_TIS_INT_STS_VALID);
860                 }
861 #endif
862             }
863         }
864         break;
865     }
866 }
867 
868 static void tpm_tis_mmio_write(void *opaque, hwaddr addr,
869                                uint64_t val, unsigned size)
870 {
871     tpm_tis_mmio_write_intern(opaque, addr, val, size, false);
872 }
873 
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,
881     },
882 };
883 
884 static int tpm_tis_do_startup_tpm(TPMState *s)
885 {
886     return tpm_backend_startup_tpm(s->be_driver);
887 }
888 
889 /*
890  * This function is called when the machine starts, resets or due to
891  * S3 resume.
892  */
893 static void tpm_tis_reset(DeviceState *dev)
894 {
895     TPMState *s = TPM(dev);
896     TPMTISEmuState *tis = &s->s.tis;
897     int c;
898 
899     tpm_backend_reset(s->be_driver);
900 
901     tis->active_locty = TPM_TIS_NO_LOCALITY;
902     tis->next_locty = TPM_TIS_NO_LOCALITY;
903     tis->aborting_locty = TPM_TIS_NO_LOCALITY;
904 
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;
911 
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);
916     }
917 
918     tpm_tis_do_startup_tpm(s);
919 }
920 
921 static const VMStateDescription vmstate_tpm_tis = {
922     .name = "tpm",
923     .unmigratable = 1,
924 };
925 
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(),
931 };
932 
933 static void tpm_tis_realizefn(DeviceState *dev, Error **errp)
934 {
935     TPMState *s = TPM(dev);
936     TPMTISEmuState *tis = &s->s.tis;
937 
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;
943     }
944 
945     s->be_driver->fe_model = TPM_MODEL_TPM_TIS;
946 
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;
951     }
952 
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;
957     }
958 
959     tis->bh = qemu_bh_new(tpm_tis_receive_bh, s);
960 
961     isa_init_irq(&s->busdev, &tis->irq, tis->irq_num);
962 
963     memory_region_add_subregion(isa_address_space(ISA_DEVICE(dev)),
964                                 TPM_TIS_ADDR_BASE, &s->mmio);
965 }
966 
967 static void tpm_tis_initfn(Object *obj)
968 {
969     TPMState *s = TPM(obj);
970 
971     memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops,
972                           s, "tpm-tis-mmio",
973                           TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT);
974 }
975 
976 static void tpm_tis_class_init(ObjectClass *klass, void *data)
977 {
978     DeviceClass *dc = DEVICE_CLASS(klass);
979 
980     dc->realize = tpm_tis_realizefn;
981     dc->props = tpm_tis_properties;
982     dc->reset = tpm_tis_reset;
983     dc->vmsd  = &vmstate_tpm_tis;
984 }
985 
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,
992 };
993 
994 static void tpm_tis_register(void)
995 {
996     type_register_static(&tpm_tis_info);
997     tpm_register_model(TPM_MODEL_TPM_TIS);
998 }
999 
1000 type_init(tpm_tis_register)
1001