Index: qemu-git/hw/pc.h
===================================================================
--- qemu-git.orig/hw/pc.h
+++ qemu-git/hw/pc.h
@@ -6,6 +6,7 @@
 #include "isa.h"
 #include "fdc.h"
 #include "net.h"
+#include "tpm_tis.h"
 
 /* PC-style peripherals (also used by other machines).  */
 
@@ -128,6 +129,12 @@ void pc_register_ferr_irq(qemu_irq irq);
 void pc_cmos_set_s3_resume(void *opaque, int irq, int level);
 void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
+/* tpm_tis.c */
+extern bool has_tpm;
+const BackendTPMDriver *tis_set_backend_driver(const char *tpm_type);
+void tis_display_backend_drivers(FILE *);
+
+
 void pc_cpus_init(const char *cpu_model);
 void pc_memory_init(ram_addr_t ram_size,
                     const char *kernel_filename,
Index: qemu-git/qemu-options.hx
===================================================================
--- qemu-git.orig/qemu-options.hx
+++ qemu-git/qemu-options.hx
@@ -1041,6 +1041,17 @@ Specify SMBIOS type 0 fields
 Specify SMBIOS type 1 fields
 ETEXI
 
+#ifndef _WIN32
+# ifdef CONFIG_TPM
+DEF("tpm", HAS_ARG, QEMU_OPTION_tpm, \
+    ""
+    "-tpm type=<type>,path=<path>\n" \
+    "                enable a TPM with state from file in given path\n"
+    "                use -tpm ? to get a list of supported TPM types\n",
+    QEMU_ARCH_I386)
+# endif
+#endif
+
 DEFHEADING()
 STEXI
 @end table
Index: qemu-git/vl.c
===================================================================
--- qemu-git.orig/vl.c
+++ qemu-git/vl.c
@@ -244,6 +244,8 @@ int nb_numa_nodes;
 uint64_t node_mem[MAX_NODES];
 uint64_t node_cpumask[MAX_NODES];
 
+bool has_tpm = false;
+
 static QEMUTimer *nographic_timer;
 
 uint8_t qemu_uuid[16];
@@ -2333,6 +2335,15 @@ int main(int argc, char **argv, char **e
                 ram_size = value;
                 break;
             }
+#ifdef CONFIG_TPM
+            case QEMU_OPTION_tpm:
+                if (!(tpm_available())) {
+                    printf("Option %s not supported for this target\n", popt->name);
+                    exit(1);
+                }
+                select_tpm(optarg);
+                break;
+#endif
             case QEMU_OPTION_mempath:
                 mem_path = optarg;
                 break;
Index: qemu-git/qemu-config.c
===================================================================
--- qemu-git.orig/qemu-config.c
+++ qemu-git/qemu-config.c
@@ -451,6 +451,25 @@ QemuOptsList qemu_option_rom_opts = {
     },
 };
 
+static QemuOptsList qemu_tpm_opts = {
+    .name = "tpm",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_tpm_opts.head),
+    .desc = {
+        {
+            .name = "type",
+            .type = QEMU_OPT_STRING,
+            .help = "Type of TPM backend",
+        },
+        {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+            .help = "Persitent storage for TPM state",
+        },
+        { /* end of list */ }
+    },
+};
+
+
 static QemuOptsList *vm_config_groups[32] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
@@ -465,6 +484,7 @@ static QemuOptsList *vm_config_groups[32
     &qemu_trace_opts,
 #endif
     &qemu_option_rom_opts,
+    &qemu_tpm_opts,
     NULL,
 };
 
Index: qemu-git/arch_init.c
===================================================================
--- qemu-git.orig/arch_init.c
+++ qemu-git/arch_init.c
@@ -41,6 +41,8 @@
 #include "net.h"
 #include "gdbstub.h"
 #include "hw/smbios.h"
+#include "blockdev.h"
+#include "hw/tpm_tis.h"
 
 #ifdef TARGET_SPARC
 int graphic_width = 1024;
@@ -726,3 +728,78 @@ int xen_available(void)
     return 0;
 #endif
 }
+
+int tpm_available(void) {
+#ifdef CONFIG_TPM
+    return 1;
+#else
+    return 0;
+#endif
+}
+
+#ifdef CONFIG_TPM
+
+#if defined (TARGET_I386) || defined (TARGET_X86_64)
+
+
+static int configure_tpm(QemuOpts *opts)
+{
+    const char *value;
+    const BackendTPMDriver *be;
+
+    if (has_tpm) {
+        fprintf(stderr,"Only one TPM is allowed\n");
+        return 1;
+    }
+
+    value = qemu_opt_get(opts, "type");
+    if (!value) {
+        fprintf(stderr,
+                "Missing TPM backend type.");
+        tis_display_backend_drivers(stderr);
+        return 1;
+    }
+
+    be = tis_set_backend_driver(value);
+    if (be == NULL) {
+        fprintf(stderr,
+                "A TPM backend driver of type %s is not supported.\n",
+                value);
+        tis_display_backend_drivers(stderr);
+        return 1;
+    }
+
+    has_tpm = be->handle_options(opts);
+    if (!has_tpm)
+        return 1;
+
+    return 0;
+}
+
+
+void select_tpm(const char *optarg)
+{
+    QemuOpts *opts;
+
+    if (strcmp("none", optarg) != 0) {
+        if (*optarg == '?') {
+            tis_display_backend_drivers(stdout);
+            exit(0);
+        }
+        opts = qemu_opts_parse(qemu_find_opts("tpm"), optarg, 0);
+        if (!opts)
+            exit(1);
+        if (configure_tpm(opts))
+            exit(1);
+    }
+}
+
+# else /* CONFIG_TPM */
+
+void select_tpm(const char *optarg)
+{
+    (void)optarg;
+}
+
+# endif
+#endif /* CONFIG_TPM */
Index: qemu-git/arch_init.h
===================================================================
--- qemu-git.orig/arch_init.h
+++ qemu-git/arch_init.h
@@ -31,5 +31,7 @@ int audio_available(void);
 void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus);
 int kvm_available(void);
 int xen_available(void);
+int tpm_available(void);
+void select_tpm(const char *optarg);
 
 #endif
Index: qemu-git/hw/tpm_tis.h
===================================================================
--- /dev/null
+++ qemu-git/hw/tpm_tis.h
@@ -0,0 +1,142 @@
+/*
+ * tpm_tis.h - include file for tpm_tis.c
+ *
+ * Copyright (C) 2006,2010,2011 IBM Corporation
+ *
+ * Author: Stefan Berger <stefanb@us.ibm.com>
+ *         David Safford <safford@us.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+#ifndef _HW_TPM_TIS_H
+#define _HW_TPM_TIS_H
+
+#include "isa.h"
+#include "block_int.h"
+#include "qemu-thread.h"
+
+#include <stdint.h>
+
+#define TIS_ADDR_BASE       0xFED40000
+
+#define NUM_LOCALITIES      5     /* per spec */
+#define NO_LOCALITY         0xff
+
+#define IS_VALID_LOCTY(x)   ((x) < NUM_LOCALITIES)
+
+
+#define TPM_TIS_IRQ         11
+
+#define TIS_TPM_BUFFER_MAX  4096
+
+
+typedef struct TPMSizedBuffer
+{
+    uint32_t size;
+    uint8_t  *buffer;
+} TPMSizedBuffer;
+
+
+enum tis_state {
+    STATE_IDLE = 0,
+    STATE_READY,
+    STATE_COMPLETION,
+    STATE_EXECUTION,
+    STATE_RECEPTION,
+};
+
+
+/* locality data  -- all fields are persisted */
+typedef struct TPMLocality {
+    enum tis_state state;
+    uint8_t access;
+    uint8_t sts;
+    uint32_t inte;
+    uint32_t ints;
+
+    uint16_t w_offset;
+    uint16_t r_offset;
+    TPMSizedBuffer w_buffer;
+    TPMSizedBuffer r_buffer;
+} TPMLocality;
+
+
+/* overall state of the TPM interface; 's' marks a persisted field */
+typedef struct TPMState {
+    ISADevice busdev;
+
+    uint32_t offset;
+    uint8_t buf[TIS_TPM_BUFFER_MAX];
+
+    uint8_t active_locty;
+    uint8_t aborting_locty;
+    uint8_t next_locty;
+
+    uint8_t command_locty;
+    TPMLocality loc[NUM_LOCALITIES];
+
+    qemu_irq irq;
+    uint32_t irq_num;
+
+    QemuMutex state_lock;
+    QemuCond  from_tpm_cond;
+    QemuCond  to_tpm_cond;
+    bool      to_tpm_execute;
+
+    bool      tpm_initialized;
+} TPMState;
+
+
+typedef void (TPMRecvDataCB)(TPMState *s, uint8_t locty);
+
+typedef struct BackendTPMDriver {
+    const char *id;
+    const char *(*desc)(void);
+
+    void (*job_for_main_thread)(void *);
+
+    bool (*handle_options)(QemuOpts *);
+
+    int (*init)(TPMState *s, TPMRecvDataCB *datacb);
+    int (*early_startup_tpm)(void);
+    int (*late_startup_tpm)(void);
+    bool (*had_startup_error)(void);
+
+    size_t (*realloc_buffer)(TPMSizedBuffer *sb);
+
+    void (*reset)(void);
+
+    int (*save_volatile_data)(void);
+    int (*load_volatile_data)(TPMState *s);
+
+    bool (*get_tpm_established_flag)(void);
+} BackendTPMDriver;
+
+
+void tis_reset_for_snapshot_resume(TPMState *s);
+const BackendTPMDriver *tis_get_active_backend(void);
+
+/* utility functions */
+
+static inline uint16_t tis_get_size_from_buffer(const TPMSizedBuffer *sb)
+{
+    return (sb->buffer[4] << 8) + sb->buffer[5];
+}
+
+static inline void dumpBuffer(FILE *stream,
+                              unsigned char *buffer, unsigned int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        if (i && !(i % 16))
+            fprintf(stream, "\n");
+         fprintf(stream, "%.2X ", buffer[i]);
+    }
+    fprintf(stream, "\n");
+}
+
+#endif /* _HW_TPM_TIS_H */
Index: qemu-git/hw/pc.c
===================================================================
--- qemu-git.orig/hw/pc.c
+++ qemu-git/hw/pc.c
@@ -1154,6 +1154,9 @@ void pc_basic_device_init(qemu_irq *isa_
         fd[i] = drive_get(IF_FLOPPY, 0, i);
     }
     fdctrl_init_isa(fd);
+
+    if (has_tpm)
+        isa_create_simple("tpm-tis");
 }
 
 void pc_pci_device_init(PCIBus *pci_bus)
