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