On Tue, Mar 31, 2015 at 03:40:11PM -0400, Stefan Berger wrote: > Following the recent upgrade to version 1.3, extend the TPM TIS > interface with capabilities introduced for support of a TPM 2. > > TPM TIS for TPM 2 introduced the following extensions beyond the > TPM TIS 1.3 (used for TPM 1.2): > > - A new 32bit interface Id register was introduced. > - New flags for the status (STS) register were defined. > - New flags for the capability flags were defined. > > Support the above if a TPM TIS 1.3 for TPM 2 is used with a TPM 2 > on the backend side. Support the old TPM TIS 1.3 configuration if a > TPM 1.2 is being used. A subsequent patch will then determine which > TPM version is being used in the backend. > > Signed-off-by: Stefan Berger <stef...@linux.vnet.ibm.com> > --- > backends/tpm.c | 14 ++++++ > hw/tpm/tpm_int.h | 1 + > hw/tpm/tpm_passthrough.c | 14 ++++++ > hw/tpm/tpm_tis.c | 109 > +++++++++++++++++++++++++++++++++++++++---- > hw/tpm/tpm_tis.h | 1 + > include/sysemu/tpm.h | 7 +++ > include/sysemu/tpm_backend.h | 23 +++++++++ > 7 files changed, 160 insertions(+), 9 deletions(-) > > diff --git a/backends/tpm.c b/backends/tpm.c > index 4efe367..3ebb603 100644 > --- a/backends/tpm.c > +++ b/backends/tpm.c > @@ -96,6 +96,20 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s) > return k->ops->get_tpm_established_flag(s); > } > > +int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty) > +{ > + TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); > + > + return k->ops->reset_tpm_established_flag(s, locty); > +} > + > +enum TPMVersion tpm_backend_get_tpm_version(TPMBackend *s)
use typedef without enum pls > +{ > + TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); > + > + return k->ops->get_tpm_version(s); > +} > + > static bool tpm_backend_prop_get_opened(Object *obj, Error **errp) > { > TPMBackend *s = TPM_BACKEND(obj); > diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h > index 2b35fe2..24e12ce 100644 > --- a/hw/tpm/tpm_int.h > +++ b/hw/tpm/tpm_int.h > @@ -29,6 +29,7 @@ struct TPMState { > > char *backend; > TPMBackend *be_driver; > + enum TPMVersion be_tpm_version; same > }; > > #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) > diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c > index 73ca906..dd769a7 100644 > --- a/hw/tpm/tpm_passthrough.c > +++ b/hw/tpm/tpm_passthrough.c > @@ -267,6 +267,13 @@ static bool > tpm_passthrough_get_tpm_established_flag(TPMBackend *tb) > return false; > } > > +static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb, > + uint8_t locty) > +{ > + /* only a TPM 2.0 will support this */ > + return 0; > +} > + > static bool tpm_passthrough_get_startup_error(TPMBackend *tb) > { > TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); > @@ -324,6 +331,11 @@ static const char *tpm_passthrough_create_desc(void) > return "Passthrough TPM backend driver"; > } > > +static enum TPMVersion tpm_passthrough_get_tpm_version(TPMBackend *tb) > +{ > + return TPMVersion1_2; > +} > + > /* > * A basic test of a TPM device. We expect a well formatted response header > * (error response is fine) within one second. > @@ -540,6 +552,8 @@ static const TPMDriverOps tpm_passthrough_driver = { > .deliver_request = tpm_passthrough_deliver_request, > .cancel_cmd = tpm_passthrough_cancel_cmd, > .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag, > + .reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag, > + .get_tpm_version = tpm_passthrough_get_tpm_version, > }; > > static void tpm_passthrough_inst_init(Object *obj) > diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c > index 4b6d601..89e401d 100644 > --- a/hw/tpm/tpm_tis.c > +++ b/hw/tpm/tpm_tis.c > @@ -17,6 +17,9 @@ > * supports version 1.3, 21 March 2013 > * In the developers menu choose the PC Client section then find the TIS > * specification. > + * > + * TPM TIS for TPM 2 implementation following TCG PC Client Platform > + * TPM Profile (PTP) Specification, Familiy 2.0, Revision 00.43 > */ > > #include "sysemu/tpm_backend.h" > @@ -49,6 +52,7 @@ > #define TPM_TIS_REG_INTF_CAPABILITY 0x14 > #define TPM_TIS_REG_STS 0x18 > #define TPM_TIS_REG_DATA_FIFO 0x24 > +#define TPM_TIS_REG_INTERFACE_ID 0x30 > #define TPM_TIS_REG_DATA_XFIFO 0x80 > #define TPM_TIS_REG_DATA_XFIFO_END 0xbc > #define TPM_TIS_REG_DID_VID 0xf00 > @@ -57,6 +61,12 @@ > /* vendor-specific registers */ > #define TPM_TIS_REG_DEBUG 0xf90 > > +#define TPM_TIS_STS_TPM_FAMILY_MASK (0x3 << 26)/* TPM 2.0 */ > +#define TPM_TIS_STS_TPM_FAMILY1_2 (0 << 26) /* TPM 2.0 */ > +#define TPM_TIS_STS_TPM_FAMILY2_0 (1 << 26) /* TPM 2.0 */ > +#define TPM_TIS_STS_RESET_ESTABLISHMENT_BIT (1 << 25) /* TPM 2.0 */ > +#define TPM_TIS_STS_COMMAND_CANCEL (1 << 24) /* TPM 2.0 */ > + > #define TPM_TIS_STS_VALID (1 << 7) > #define TPM_TIS_STS_COMMAND_READY (1 << 6) > #define TPM_TIS_STS_TPM_GO (1 << 5) > @@ -102,15 +112,42 @@ > #endif > > #define TPM_TIS_CAP_INTERFACE_VERSION1_3 (2 << 28) > +#define TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 (3 << 28) > #define TPM_TIS_CAP_DATA_TRANSFER_64B (3 << 9) > #define TPM_TIS_CAP_DATA_TRANSFER_LEGACY (0 << 9) > #define TPM_TIS_CAP_BURST_COUNT_DYNAMIC (0 << 8) > #define TPM_TIS_CAP_INTERRUPT_LOW_LEVEL (1 << 4) /* support is mandatory */ > -#define TPM_TIS_CAPABILITIES_SUPPORTED (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ > - TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ > - TPM_TIS_CAP_DATA_TRANSFER_64B | \ > - TPM_TIS_CAP_INTERFACE_VERSION1_3 | > \ > - TPM_TIS_INTERRUPTS_SUPPORTED) > +#define TPM_TIS_CAPABILITIES_SUPPORTED1_3 \ > + (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ > + TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ > + TPM_TIS_CAP_DATA_TRANSFER_64B | \ > + TPM_TIS_CAP_INTERFACE_VERSION1_3 | \ > + TPM_TIS_INTERRUPTS_SUPPORTED) > + > +#define TPM_TIS_CAPABILITIES_SUPPORTED2_0 \ > + (TPM_TIS_CAP_INTERRUPT_LOW_LEVEL | \ > + TPM_TIS_CAP_BURST_COUNT_DYNAMIC | \ > + TPM_TIS_CAP_DATA_TRANSFER_64B | \ > + TPM_TIS_CAP_INTERFACE_VERSION1_3_FOR_TPM2_0 | \ > + TPM_TIS_INTERRUPTS_SUPPORTED) > + > +#define TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 (0xf) /* TPM 2.0 */ > +#define TPM_TIS_IFACE_ID_INTERFACE_FIFO (0x0) /* TPM 2.0 */ > +#define TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO (0 << 4) /* TPM 2.0 */ > +#define TPM_TIS_IFACE_ID_CAP_5_LOCALITIES (1 << 8) /* TPM 2.0 */ > +#define TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED (1 << 13) /* TPM 2.0 */ > +#define TPM_TIS_IFACE_ID_INT_SEL_LOCK (1 << 19) /* TPM 2.0 */ > + > +#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3 \ > + (TPM_TIS_IFACE_ID_INTERFACE_TIS1_3 | \ > + (~0 << 4)/* all of it is don't care */) > + > +/* if backend was a TPM 2.0: */ > +#define TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0 \ > + (TPM_TIS_IFACE_ID_INTERFACE_FIFO | \ > + TPM_TIS_IFACE_ID_INTERFACE_VER_FIFO | \ > + TPM_TIS_IFACE_ID_CAP_5_LOCALITIES | \ > + TPM_TIS_IFACE_ID_CAP_TIS_SUPPORTED) > > #define TPM_TIS_TPM_DID 0x0001 > #define TPM_TIS_TPM_VID PCI_VENDOR_ID_IBM > @@ -154,7 +191,8 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, > const char *string) > > /* > * Set the given flags in the STS register by clearing the register but > - * preserving the SELFTEST_DONE flag and then setting the new flags. > + * preserving the SELFTEST_DONE and TPMFAMILY_MASK flags and then setting > + * the new flags. > * > * The SELFTEST_DONE flag is acquired from the backend that determines it by > * peeking into TPM commands. > @@ -166,7 +204,7 @@ static void tpm_tis_show_buffer(const TPMSizedBuffer *sb, > const char *string) > */ > static void tpm_tis_sts_set(TPMLocality *l, uint32_t flags) > { > - l->sts &= TPM_TIS_STS_SELFTEST_DONE; > + l->sts &= (TPM_TIS_STS_SELFTEST_DONE | TPM_TIS_STS_TPM_FAMILY_MASK); no () to right of = please. > l->sts |= flags; > } > > @@ -489,7 +527,17 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr > addr, > val = tis->loc[locty].ints; > break; > case TPM_TIS_REG_INTF_CAPABILITY: > - val = TPM_TIS_CAPABILITIES_SUPPORTED; > + switch (s->be_tpm_version) { > + case TPMVersion_Unspec: > + val = 0; > + break; > + case TPMVersion1_2: > + val = TPM_TIS_CAPABILITIES_SUPPORTED1_3; > + break; > + case TPMVersion2_0: > + val = TPM_TIS_CAPABILITIES_SUPPORTED2_0; > + break; > + } > break; > case TPM_TIS_REG_STS: > if (tis->active_locty == locty) { > @@ -536,6 +584,9 @@ static uint64_t tpm_tis_mmio_read(void *opaque, hwaddr > addr, > shift = 0; /* no more adjustments */ > } > break; > + case TPM_TIS_REG_INTERFACE_ID: > + val = tis->loc[locty].iface_id; > + break; > case TPM_TIS_REG_DID_VID: > val = (TPM_TIS_TPM_DID << 16) | TPM_TIS_TPM_VID; > break; > @@ -736,6 +787,25 @@ static void tpm_tis_mmio_write_intern(void *opaque, > hwaddr addr, > break; > } > > + if (s->be_tpm_version == TPMVersion2_0) { > + /* some flags that are only supported for TPM 2 */ > + if (val & TPM_TIS_STS_COMMAND_CANCEL) { > + if (tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) { > + /* > + * request the backend to cancel. Some backends may not > + * support it > + */ > + tpm_backend_cancel_cmd(s->be_driver); > + } > + } > + > + if (val & TPM_TIS_STS_RESET_ESTABLISHMENT_BIT) { > + if (locty == 3 || locty == 4) { > + tpm_backend_reset_tpm_established_flag(s->be_driver, > locty); > + } > + } > + } > + > val &= (TPM_TIS_STS_COMMAND_READY | TPM_TIS_STS_TPM_GO | > TPM_TIS_STS_RESPONSE_RETRY); > > @@ -860,6 +930,14 @@ static void tpm_tis_mmio_write_intern(void *opaque, > hwaddr addr, > } > } > break; > + case TPM_TIS_REG_INTERFACE_ID: > + if (val & TPM_TIS_IFACE_ID_INT_SEL_LOCK) { > + for (l = 0; l < TPM_TIS_NUM_LOCALITIES; l++) { > + tis->loc[l].iface_id |= TPM_TIS_IFACE_ID_INT_SEL_LOCK; > + } > + } > + > + break; > } > } > > @@ -894,6 +972,8 @@ static void tpm_tis_reset(DeviceState *dev) > TPMTISEmuState *tis = &s->s.tis; > int c; > > + s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); > + > tpm_backend_reset(s->be_driver); > > tis->active_locty = TPM_TIS_NO_LOCALITY; > @@ -902,7 +982,18 @@ static void tpm_tis_reset(DeviceState *dev) > > for (c = 0; c < TPM_TIS_NUM_LOCALITIES; c++) { > tis->loc[c].access = TPM_TIS_ACCESS_TPM_REG_VALID_STS; > - tis->loc[c].sts = 0; > + switch (s->be_tpm_version) { > + case TPMVersion_Unspec: > + break; > + case TPMVersion1_2: > + tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY1_2; > + tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS1_3; > + break; > + case TPMVersion2_0: > + tis->loc[c].sts = TPM_TIS_STS_TPM_FAMILY2_0; > + tis->loc[c].iface_id = TPM_TIS_IFACE_ID_SUPPORTED_FLAGS2_0; > + break; > + } > tis->loc[c].inte = TPM_TIS_INT_POLARITY_LOW_LEVEL; > tis->loc[c].ints = 0; > tis->loc[c].state = TPM_TIS_STATE_IDLE; > diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h > index db78d51..a1df41f 100644 > --- a/hw/tpm/tpm_tis.h > +++ b/hw/tpm/tpm_tis.h > @@ -42,6 +42,7 @@ typedef struct TPMLocality { > TPMTISState state; > uint8_t access; > uint32_t sts; > + uint32_t iface_id; > uint32_t inte; > uint32_t ints; > > diff --git a/include/sysemu/tpm.h b/include/sysemu/tpm.h > index 9b81ce9..9a77889 100644 > --- a/include/sysemu/tpm.h > +++ b/include/sysemu/tpm.h > @@ -20,6 +20,13 @@ int tpm_config_parse(QemuOptsList *opts_list, const char > *optarg); > int tpm_init(void); > void tpm_cleanup(void); > > +enum TPMVersion { > + TPMVersion_Unspec = 0, > + TPMVersion1_2 = 1, > + TPMVersion2_0 = 2, > +}; needs a typedef > + > + don't add two empty lines pls > #define TYPE_TPM_TIS "tpm-tis" > > static inline bool tpm_find(void) > diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h > index 540ee25..cbe064f 100644 > --- a/include/sysemu/tpm_backend.h > +++ b/include/sysemu/tpm_backend.h > @@ -88,6 +88,10 @@ struct TPMDriverOps { > void (*cancel_cmd)(TPMBackend *t); > > bool (*get_tpm_established_flag)(TPMBackend *t); > + > + int (*reset_tpm_established_flag)(TPMBackend *t, uint8_t locty); > + > + enum TPMVersion (*get_tpm_version)(TPMBackend *t); drop enum > }; > > > @@ -192,6 +196,15 @@ void tpm_backend_cancel_cmd(TPMBackend *s); > bool tpm_backend_get_tpm_established_flag(TPMBackend *s); > > /** > + * tpm_backend_reset_tpm_established_flag: > + * @s: the backend > + * @locty: the locality number > + * > + * Reset the TPM establishment flag. > + */ > +int tpm_backend_reset_tpm_established_flag(TPMBackend *s, uint8_t locty); > + > +/** > * tpm_backend_open: > * @s: the backend to open > * @errp: a pointer to return the #Error object if an error occurs. > @@ -201,6 +214,16 @@ bool tpm_backend_get_tpm_established_flag(TPMBackend *s); > */ > void tpm_backend_open(TPMBackend *s, Error **errp); > > +/** > + * tpm_backend_get_tpm_version: > + * @s: the backend to call into > + * > + * Get the TPM Version that is emulated at the backend. > + * > + * Returns an enum TPMVersion. > + */ > +enum TPMVersion tpm_backend_get_tpm_version(TPMBackend *s); > + same > TPMBackend *qemu_find_tpm(const char *id); > > const TPMDriverOps *tpm_get_backend_driver(const char *type); > -- > 1.9.3