On Fri, Jan 17, 2020 at 5:41 PM Stefan Berger <stef...@linux.ibm.com> wrote: > > On 1/17/20 8:31 AM, Marc-André Lureau wrote: > > Hi > > > > On Wed, Jan 8, 2020 at 8:14 PM Stefan Berger <stef...@linux.ibm.com> wrote: > >> From: Stefan Berger <stef...@linux.vnet.ibm.com> > >> > >> Extend the tpm_spapr frontend with VM suspend and resume support. > >> > >> Signed-off-by: Stefan Berger <stef...@linux.vnet.ibm.com> > >> --- > >> hw/tpm/tpm_spapr.c | 67 ++++++++++++++++++++++++++++++++++++++++++++- > >> hw/tpm/trace-events | 2 ++ > >> 2 files changed, 68 insertions(+), 1 deletion(-) > >> > >> diff --git a/hw/tpm/tpm_spapr.c b/hw/tpm/tpm_spapr.c > >> index ab184fbb82..cf5c7851e7 100644 > >> --- a/hw/tpm/tpm_spapr.c > >> +++ b/hw/tpm/tpm_spapr.c > >> @@ -76,6 +76,9 @@ typedef struct { > >> > >> unsigned char buffer[TPM_SPAPR_BUFFER_MAX]; > >> > >> + uint32_t numbytes; /* number of bytes in suspend_buffer */ > >> + unsigned char *suspend_buffer; > > Why do you need a copy suspend_buffer? Why not use and save buffer[] > > directly? > > > This addresses David's comment: > > "Transferring the whole 4kiB buffer unconditionally when it mostly > won't have anything useful in it doesn't seem like a great idea." > > https://lists.nongnu.org/archive/html/qemu-devel/2019-12/msg02601.html
Oh ok.. (well really I don't think 4k (usually compressed) will really matter much in multi-gigabytes streams ;) > > > > > > Also numbytes wouldn't be necessary, you would just need a bool flag > > to say if the request_completed is pending. > > > >> + > >> TPMBackendCmd cmd; > >> > >> TPMBackend *be_driver; > >> @@ -240,6 +243,13 @@ static void tpm_spapr_request_completed(TPMIf *ti, > >> int ret) > >> > >> /* a max. of be_buffer_size bytes can be transported */ > >> len = MIN(tpm_cmd_get_size(s->buffer), s->be_buffer_size); > >> + > >> + if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { > >> + /* defer delivery of response until .post_load */ > >> + s->numbytes = len; > >> + return; > >> + } > >> + > >> rc = spapr_vio_dma_write(&s->vdev, be32_to_cpu(crq->data), > >> s->buffer, len); > >> > >> @@ -288,11 +298,13 @@ static void tpm_spapr_reset(SpaprVioDevice *dev) > >> SpaprTpmState *s = VIO_SPAPR_VTPM(dev); > >> > >> s->state = SPAPR_VTPM_STATE_NONE; > >> + s->numbytes = 0; > >> > >> s->be_tpm_version = tpm_backend_get_tpm_version(s->be_driver); > >> > >> s->be_buffer_size = MIN(tpm_backend_get_buffer_size(s->be_driver), > >> TPM_SPAPR_BUFFER_MAX); > >> + s->suspend_buffer = g_realloc(s->suspend_buffer, s->be_buffer_size); > >> > >> tpm_backend_reset(s->be_driver); > >> tpm_spapr_do_startup_tpm(s, s->be_buffer_size); > >> @@ -309,9 +321,62 @@ static enum TPMVersion tpm_spapr_get_version(TPMIf > >> *ti) > >> return tpm_backend_get_tpm_version(s->be_driver); > >> } > >> > >> +/* persistent state handling */ > >> + > >> +static int tpm_spapr_pre_save(void *opaque) > >> +{ > >> + SpaprTpmState *s = opaque; > >> + > >> + tpm_backend_finish_sync(s->be_driver); > >> + > >> + if (s->numbytes) { > >> + memcpy(s->suspend_buffer, s->buffer, s->numbytes); > >> + } > >> + > >> + trace_tpm_spapr_pre_save(s->numbytes); > >> + /* > >> + * we cannot deliver the results to the VM since DMA would touch VM > >> memory > >> + */ > >> + > >> + return 0; > >> +} > >> + > >> +static int tpm_spapr_post_load(void *opaque, int version_id) > >> +{ > >> + SpaprTpmState *s = opaque; > >> + > >> + if (s->numbytes) { > >> + trace_tpm_spapr_post_load(); > >> + > >> + memcpy(s->buffer, s->suspend_buffer, > >> + MIN(s->numbytes, s->be_buffer_size)); > >> + /* deliver the results to the VM via DMA */ > >> + tpm_spapr_request_completed(TPM_IF(s), 0); > >> + s->numbytes = 0; > >> + } > >> + > >> + return 0; > >> +} > >> + > >> static const VMStateDescription vmstate_spapr_vtpm = { > >> .name = "tpm-spapr", > >> - .unmigratable = 1, > >> + .version_id = 1, > >> + .minimum_version_id = 0, > >> + .minimum_version_id_old = 0, > > > > Yyou should leave all the fields to 0 (there is no version 0 so far). > > Thus no need to have them set explicitly either. > > > Ok, I will fix. > > Thanks. -- Marc-André Lureau