Message ID | 1458546426-26222-8-git-send-email-aik@ozlabs.ru (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Mon, Mar 21, 2016 at 06:46:55PM +1100, Alexey Kardashevskiy wrote: > The source guest could have reallocated the default TCE table and > migrate bigger/smaller table. This adds reallocation in post_load() > if the default table size is different on source and destination. > > Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> > --- > Changes: > v14: > * new to the series > --- > hw/ppc/spapr_iommu.c | 36 ++++++++++++++++++++++++++++++++++-- > include/hw/ppc/spapr.h | 2 ++ > 2 files changed, 36 insertions(+), 2 deletions(-) > > diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c > index 9bcd3f6..549cd94 100644 > --- a/hw/ppc/spapr_iommu.c > +++ b/hw/ppc/spapr_iommu.c > @@ -137,6 +137,16 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr, > return ret; > } > > +static void spapr_tce_table_pre_save(void *opaque) > +{ > + sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); > + > + tcet->mig_table = tcet->table; Don't you need to set mig_nb_table here as well? I can't see anywhere else it's initialized. > +} > + > +static void spapr_tce_table_do_enable(sPAPRTCETable *tcet); > +static void spapr_tce_table_do_disable(sPAPRTCETable *tcet); > + > static int spapr_tce_table_post_load(void *opaque, int version_id) > { > sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); > @@ -145,6 +155,26 @@ static int spapr_tce_table_post_load(void *opaque, int version_id) > spapr_vio_set_bypass(tcet->vdev, tcet->bypass); > } > > + if (tcet->enabled) { > + if (tcet->nb_table != tcet->mig_nb_table) { > + if (tcet->nb_table) { > + spapr_tce_table_do_disable(tcet); > + } > + tcet->nb_table = tcet->mig_nb_table; > + spapr_tce_table_do_enable(tcet); > + } > + > + memcpy(tcet->table, tcet->mig_table, > + tcet->nb_table * sizeof(tcet->table[0])); > + > + free(tcet->mig_table); > + tcet->mig_table = NULL; > + > + } else if (tcet->table) { > + /* Destination guest has a default table but source does not -> free */ > + spapr_tce_table_do_disable(tcet); > + } > + Clunky, but I don't know of a better way. > return 0; > } > > @@ -152,15 +182,17 @@ static const VMStateDescription vmstate_spapr_tce_table = { > .name = "spapr_iommu", > .version_id = 2, > .minimum_version_id = 2, > + .pre_save = spapr_tce_table_pre_save, > .post_load = spapr_tce_table_post_load, > .fields = (VMStateField []) { > /* Sanity check */ > VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable), > - VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable), > > /* IOMMU state */ > + VMSTATE_UINT32(mig_nb_table, sPAPRTCETable), > VMSTATE_BOOL(bypass, sPAPRTCETable), > - VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t), > + VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, nb_table, 0, > + vmstate_info_uint64, uint64_t), > > VMSTATE_END_OF_LIST() > }, > diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h > index 75b0b55..c1ea49c 100644 > --- a/include/hw/ppc/spapr.h > +++ b/include/hw/ppc/spapr.h > @@ -545,6 +545,8 @@ struct sPAPRTCETable { > uint64_t bus_offset; > uint32_t page_shift; > uint64_t *table; > + uint32_t mig_nb_table; > + uint64_t *mig_table; > bool bypass; > bool need_vfio; > int fd;
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 9bcd3f6..549cd94 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -137,6 +137,16 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr, return ret; } +static void spapr_tce_table_pre_save(void *opaque) +{ + sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); + + tcet->mig_table = tcet->table; +} + +static void spapr_tce_table_do_enable(sPAPRTCETable *tcet); +static void spapr_tce_table_do_disable(sPAPRTCETable *tcet); + static int spapr_tce_table_post_load(void *opaque, int version_id) { sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque); @@ -145,6 +155,26 @@ static int spapr_tce_table_post_load(void *opaque, int version_id) spapr_vio_set_bypass(tcet->vdev, tcet->bypass); } + if (tcet->enabled) { + if (tcet->nb_table != tcet->mig_nb_table) { + if (tcet->nb_table) { + spapr_tce_table_do_disable(tcet); + } + tcet->nb_table = tcet->mig_nb_table; + spapr_tce_table_do_enable(tcet); + } + + memcpy(tcet->table, tcet->mig_table, + tcet->nb_table * sizeof(tcet->table[0])); + + free(tcet->mig_table); + tcet->mig_table = NULL; + + } else if (tcet->table) { + /* Destination guest has a default table but source does not -> free */ + spapr_tce_table_do_disable(tcet); + } + return 0; } @@ -152,15 +182,17 @@ static const VMStateDescription vmstate_spapr_tce_table = { .name = "spapr_iommu", .version_id = 2, .minimum_version_id = 2, + .pre_save = spapr_tce_table_pre_save, .post_load = spapr_tce_table_post_load, .fields = (VMStateField []) { /* Sanity check */ VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable), - VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable), /* IOMMU state */ + VMSTATE_UINT32(mig_nb_table, sPAPRTCETable), VMSTATE_BOOL(bypass, sPAPRTCETable), - VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t), + VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, nb_table, 0, + vmstate_info_uint64, uint64_t), VMSTATE_END_OF_LIST() }, diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 75b0b55..c1ea49c 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -545,6 +545,8 @@ struct sPAPRTCETable { uint64_t bus_offset; uint32_t page_shift; uint64_t *table; + uint32_t mig_nb_table; + uint64_t *mig_table; bool bypass; bool need_vfio; int fd;
The source guest could have reallocated the default TCE table and migrate bigger/smaller table. This adds reallocation in post_load() if the default table size is different on source and destination. Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru> --- Changes: v14: * new to the series --- hw/ppc/spapr_iommu.c | 36 ++++++++++++++++++++++++++++++++++-- include/hw/ppc/spapr.h | 2 ++ 2 files changed, 36 insertions(+), 2 deletions(-)