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