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