diff options
author | Alexey Kardashevskiy <aik@ozlabs.ru> | 2017-07-20 17:22:29 +1000 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2017-09-08 09:30:55 +1000 |
commit | f5509b6bebc68fc781f0823e628fead884fd69d4 (patch) | |
tree | 6ab59b29ad74cde8fb03f724288dda87272a306a | |
parent | 54a50dae93fa3c0b0bd6188ecf1777474d55648e (diff) |
spapr_iommu: Realloc guest visible TCE table when hot(un)plugging vfio-pci
This replaces g_malloc() with spapr_tce_alloc_table() as this is
the standard way of allocating tables and this allows moving the table
back to KVM when unplugging a VFIO PCI device and VFIO TCE acceleration
support is not present in the KVM.
Although spapr_tce_alloc_table() is expected to fail with EBUSY
if called when previous fd is not closed yet, in practice we will not
see it because cap_spapr_vfio is false at the moment.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
-rw-r--r-- | hw/ppc/spapr_iommu.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index a75584c947..fa8b969840 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -275,33 +275,26 @@ static void spapr_tce_table_realize(DeviceState *dev, Error **errp) void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio) { size_t table_size = tcet->nb_table * sizeof(uint64_t); - void *newtable; + uint64_t *oldtable; + int newfd = -1; - if (need_vfio == tcet->need_vfio) { - /* Nothing to do */ - return; - } - - if (!need_vfio) { - /* FIXME: We don't support transition back to KVM accelerated - * TCEs yet */ - return; - } + g_assert(need_vfio != tcet->need_vfio); - tcet->need_vfio = true; + tcet->need_vfio = need_vfio; - if (tcet->fd < 0) { - /* Table is already in userspace, nothing to be do */ - return; - } + oldtable = tcet->table; - newtable = g_malloc(table_size); - memcpy(newtable, tcet->table, table_size); + tcet->table = spapr_tce_alloc_table(tcet->liobn, + tcet->page_shift, + tcet->bus_offset, + tcet->nb_table, + &newfd, + need_vfio); + memcpy(tcet->table, oldtable, table_size); - kvmppc_remove_spapr_tce(tcet->table, tcet->fd, tcet->nb_table); + spapr_tce_free_table(oldtable, tcet->fd, tcet->nb_table); - tcet->fd = -1; - tcet->table = newtable; + tcet->fd = newfd; } sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn) |