On Mon, Nov 06, 2017 at 07:58:55PM -0500, Stefan Berger wrote: > Convert the tpm_emulator backend to get the current buffer size > of the external device and set it to the buffer size that the > frontend (TIS) requests. > > Signed-off-by: Stefan Berger <stef...@linux.vnet.ibm.com> > --- > backends/tpm.c | 4 +-- > hw/tpm/tpm_emulator.c | 79 > +++++++++++++++++++++++++++++++++++++++++--- > hw/tpm/tpm_ioctl.h | 28 +++++++++++++++- > hw/tpm/tpm_tis.c | 6 ++-- > include/sysemu/tpm_backend.h | 6 ++-- > 5 files changed, 111 insertions(+), 12 deletions(-) > > diff --git a/backends/tpm.c b/backends/tpm.c > index e7d0f9a..f024c27 100644 > --- a/backends/tpm.c > +++ b/backends/tpm.c > @@ -68,7 +68,7 @@ int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error > **errp) > return 0; > } > > -int tpm_backend_startup_tpm(TPMBackend *s) > +int tpm_backend_startup_tpm(TPMBackend *s, uint32_t buffersize) > { > int res = 0; > TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s); > @@ -79,7 +79,7 @@ int tpm_backend_startup_tpm(TPMBackend *s) > s->thread_pool = g_thread_pool_new(tpm_backend_worker_thread, s, 1, TRUE, > NULL); > > - res = k->startup_tpm ? k->startup_tpm(s) : 0; > + res = k->startup_tpm ? k->startup_tpm(s, buffersize) : 0; > > s->had_startup_error = (res != 0); > > diff --git a/hw/tpm/tpm_emulator.c b/hw/tpm/tpm_emulator.c > index 5a6107e..a16de7a 100644 > --- a/hw/tpm/tpm_emulator.c > +++ b/hw/tpm/tpm_emulator.c > @@ -232,13 +232,14 @@ static int tpm_emulator_check_caps(TPMEmulator *tpm_emu) > switch (tpm_emu->tpm_version) { > case TPM_VERSION_1_2: > caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | > - PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD; > + PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD | PTM_CAP_STOP | > + PTM_CAP_SET_BUFFERSIZE; > tpm = "1.2"; > break; > case TPM_VERSION_2_0: > caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | > PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED | > - PTM_CAP_SET_DATAFD; > + PTM_CAP_SET_DATAFD | PTM_CAP_STOP | PTM_CAP_SET_BUFFERSIZE; > tpm = "2"; > break; > case TPM_VERSION_UNSPEC: > @@ -255,12 +256,76 @@ static int tpm_emulator_check_caps(TPMEmulator *tpm_emu) > return 0; > } > > -static int tpm_emulator_startup_tpm(TPMBackend *tb) > +static int tpm_emulator_stop_tpm(TPMBackend *tb) > +{ > + TPMEmulator *tpm_emu = TPM_EMULATOR(tb); > + ptm_res res; > + > + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) { > + error_report("tpm-emulator: Could not stop TPM: %s", > + strerror(errno)); > + return -1; > + } > + > + res = be32_to_cpu(res); > + if (res) { > + error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x", res); > + return -1; > + } > + > + return 0; > +} > + > +static int tpm_emulator_set_buffer_size(TPMBackend *tb, > + uint32_t wanted_size, > + uint32_t *actual_size) > +{ > + TPMEmulator *tpm_emu = TPM_EMULATOR(tb); > + ptm_setbuffersize psbs; > + > + if (tpm_emulator_stop_tpm(tb) < 0) { > + return -1; > + } > + > + psbs.u.req.buffersize = cpu_to_be32(wanted_size); > + > + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs, > + sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) { > + error_report("tpm-emulator: Could not set buffer size: %s", > + strerror(errno)); > + return -1; > + } > + > + psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result); > + if (psbs.u.resp.tpm_result != 0) { > + error_report("tpm-emulator: TPM result for set buffer size : 0x%x", > + psbs.u.resp.tpm_result); > + return -1; > + } > + > + if (actual_size) { > + *actual_size = be32_to_cpu(psbs.u.resp.buffersize); > + } > + > + DPRINTF("buffer size: %u, min: %u, max: %u\n", > + be32_to_cpu(psbs.u.resp.buffersize), > + be32_to_cpu(psbs.u.resp.minsize), > + be32_to_cpu(psbs.u.resp.maxsize)); > + > + return 0; > +} > + > +static int tpm_emulator_startup_tpm(TPMBackend *tb, uint32_t buffersize) > { > TPMEmulator *tpm_emu = TPM_EMULATOR(tb); > ptm_init init; > ptm_res res; > > + if (buffersize != 0 && > + tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) { > + goto err_exit; > + } > + > DPRINTF("%s", __func__); > if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init), > sizeof(init)) < 0) { > @@ -358,7 +423,13 @@ static TPMVersion > tpm_emulator_get_tpm_version(TPMBackend *tb) > > static uint32_t tpm_emulator_get_buffer_size(TPMBackend *tb) > { > - return 4096; > + uint32_t actual_size; > + > + if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) { > + return 4096; > + } > + > + return actual_size; > } > > static int tpm_emulator_block_migration(TPMEmulator *tpm_emu) > diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h > index 33564b1..54c8d34 100644 > --- a/hw/tpm/tpm_ioctl.h > +++ b/hw/tpm/tpm_ioctl.h > @@ -169,6 +169,28 @@ struct ptm_getconfig { > #define PTM_CONFIG_FLAG_FILE_KEY 0x1 > #define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2 > > +/* > + * PTM_SET_BUFFERSIZE: Set the buffer size to be used by the TPM. > + * A 0 on input queries for the current buffer size. Any other > + * number will try to set the buffer size. The returned number is > + * the buffer size that will be used, which can be larger than the > + * requested one, if it was below the minimum, or smaller than the > + * requested one, if it was above the maximum. > + */ > +struct ptm_setbuffersize { > + union { > + struct { > + uint32_t buffersize; /* 0 to query for current buffer size */ > + } req; /* request */ > + struct { > + ptm_res tpm_result; > + uint32_t buffersize; /* buffer size in use */ > + uint32_t minsize; /* min. supported buffer size */ > + uint32_t maxsize; /* max. supported buffer size */ > + } resp; /* response */ > + } u; > +}; > + > > typedef uint64_t ptm_cap; > typedef struct ptm_est ptm_est; > @@ -179,6 +201,7 @@ typedef struct ptm_init ptm_init; > typedef struct ptm_getstate ptm_getstate; > typedef struct ptm_setstate ptm_setstate; > typedef struct ptm_getconfig ptm_getconfig; > +typedef struct ptm_setbuffersize ptm_setbuffersize; > > /* capability flags returned by PTM_GET_CAPABILITY */ > #define PTM_CAP_INIT (1) > @@ -194,6 +217,7 @@ typedef struct ptm_getconfig ptm_getconfig; > #define PTM_CAP_STOP (1 << 10) > #define PTM_CAP_GET_CONFIG (1 << 11) > #define PTM_CAP_SET_DATAFD (1 << 12) > +#define PTM_CAP_SET_BUFFERSIZE (1 << 13) > > enum { > PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap), > @@ -212,6 +236,7 @@ enum { > PTM_STOP = _IOR('P', 13, ptm_res), > PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig), > PTM_SET_DATAFD = _IOR('P', 15, ptm_res), > + PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize), > }; > > /* > @@ -240,7 +265,8 @@ enum { > CMD_SET_STATEBLOB, > CMD_STOP, > CMD_GET_CONFIG, > - CMD_SET_DATAFD > + CMD_SET_DATAFD, > + CMD_SET_BUFFERSIZE, > }; > > #endif /* _TPM_IOCTL_H */ > diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c > index a3df40f..8d7310e 100644 > --- a/hw/tpm/tpm_tis.c > +++ b/hw/tpm/tpm_tis.c > @@ -974,9 +974,9 @@ static const MemoryRegionOps tpm_tis_memory_ops = { > }, > }; > > -static int tpm_tis_do_startup_tpm(TPMState *s) > +static int tpm_tis_do_startup_tpm(TPMState *s, uint32_t buffersize) > { > - return tpm_backend_startup_tpm(s->be_driver); > + return tpm_backend_startup_tpm(s->be_driver, buffersize); > } > > static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb, > @@ -1040,7 +1040,7 @@ static void tpm_tis_reset(DeviceState *dev) > tpm_tis_realloc_buffer(&s->loc[c].r_buffer, s->be_buffer_size); > } > > - tpm_tis_do_startup_tpm(s); > + tpm_tis_do_startup_tpm(s, s->be_buffer_size);
It is a bit convoluted: get the buffer size from the backend to give it back to startup, perhaps use 0/default value to make it more explicit it doesn't intend to change it. > } > > static const VMStateDescription vmstate_tpm_tis = { > diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h > index d23cef2..3978d98 100644 > --- a/include/sysemu/tpm_backend.h > +++ b/include/sysemu/tpm_backend.h > @@ -66,7 +66,7 @@ struct TPMBackendClass { > TPMBackend *(*create)(QemuOpts *opts); > > /* start up the TPM on the backend - optional */ > - int (*startup_tpm)(TPMBackend *t); > + int (*startup_tpm)(TPMBackend *t, uint32_t buffersize); > > /* optional */ > void (*reset)(TPMBackend *t); > @@ -111,10 +111,12 @@ int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error > **errp); > /** > * tpm_backend_startup_tpm: > * @s: the backend whose TPM support is to be started > + * @buffersize: the buffer size the TPM is supposed to use, > + * 0 to leave it as-is > * > * Returns 0 on success. > */ > -int tpm_backend_startup_tpm(TPMBackend *s); > +int tpm_backend_startup_tpm(TPMBackend *s, uint32_t buffersize); > > /** > * tpm_backend_had_startup_error: > -- > 2.5.5 > > looks ok overall, Reviewed-by: Marc-André Lureau <marcandre.lur...@redhat.com>