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