[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 4/6] vfio: unmap and free BAR data in instance_finali
From: |
Alex Williamson |
Subject: |
[Qemu-devel] [PULL 4/6] vfio: unmap and free BAR data in instance_finalize |
Date: |
Tue, 10 Feb 2015 11:37:33 -0700 |
User-agent: |
StGit/0.17.1-dirty |
From: Paolo Bonzini <address@hidden>
In the case of VFIO, the unrealize callback is too early to munmap the
BARs. The munmap must be delayed until memory accesses are complete.
To do this, split vfio_unmap_bars in two. The removal step, now called
vfio_unregister_bars, remains in vfio_exitfn. The reclamation step
is vfio_unmap_bars and is moved to the instance_finalize callback.
Similarly, quirk MemoryRegions have to be removed during
vfio_unregister_bars, but freeing the data structure must be delayed
to vfio_unmap_bars.
Signed-off-by: Paolo Bonzini <address@hidden>
Signed-off-by: Alex Williamson <address@hidden>
---
hw/vfio/pci.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 57 insertions(+), 8 deletions(-)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 0271c80..fa6a5e9 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -1996,12 +1996,23 @@ static void vfio_vga_quirk_setup(VFIOPCIDevice *vdev)
static void vfio_vga_quirk_teardown(VFIOPCIDevice *vdev)
{
+ VFIOQuirk *quirk;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
+ QLIST_FOREACH(quirk, &vdev->vga.region[i].quirks, next) {
+ memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem);
+ }
+ }
+}
+
+static void vfio_vga_quirk_free(VFIOPCIDevice *vdev)
+{
int i;
for (i = 0; i < ARRAY_SIZE(vdev->vga.region); i++) {
while (!QLIST_EMPTY(&vdev->vga.region[i].quirks)) {
VFIOQuirk *quirk = QLIST_FIRST(&vdev->vga.region[i].quirks);
- memory_region_del_subregion(&vdev->vga.region[i].mem, &quirk->mem);
object_unparent(OBJECT(&quirk->mem));
QLIST_REMOVE(quirk, next);
g_free(quirk);
@@ -2022,10 +2033,19 @@ static void vfio_bar_quirk_setup(VFIOPCIDevice *vdev,
int nr)
static void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int nr)
{
VFIOBAR *bar = &vdev->bars[nr];
+ VFIOQuirk *quirk;
+
+ QLIST_FOREACH(quirk, &bar->quirks, next) {
+ memory_region_del_subregion(&bar->region.mem, &quirk->mem);
+ }
+}
+
+static void vfio_bar_quirk_free(VFIOPCIDevice *vdev, int nr)
+{
+ VFIOBAR *bar = &vdev->bars[nr];
while (!QLIST_EMPTY(&bar->quirks)) {
VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
- memory_region_del_subregion(&bar->region.mem, &quirk->mem);
object_unparent(OBJECT(&quirk->mem));
QLIST_REMOVE(quirk, next);
g_free(quirk);
@@ -2281,7 +2301,7 @@ static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev,
bool enabled)
}
}
-static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
+static void vfio_unregister_bar(VFIOPCIDevice *vdev, int nr)
{
VFIOBAR *bar = &vdev->bars[nr];
@@ -2292,10 +2312,25 @@ static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
vfio_bar_quirk_teardown(vdev, nr);
memory_region_del_subregion(&bar->region.mem, &bar->region.mmap_mem);
- munmap(bar->region.mmap, memory_region_size(&bar->region.mmap_mem));
if (vdev->msix && vdev->msix->table_bar == nr) {
memory_region_del_subregion(&bar->region.mem, &vdev->msix->mmap_mem);
+ }
+}
+
+static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
+{
+ VFIOBAR *bar = &vdev->bars[nr];
+
+ if (!bar->region.size) {
+ return;
+ }
+
+ vfio_bar_quirk_free(vdev, nr);
+
+ munmap(bar->region.mmap, memory_region_size(&bar->region.mmap_mem));
+
+ if (vdev->msix && vdev->msix->table_bar == nr) {
munmap(vdev->msix->mmap, memory_region_size(&vdev->msix->mmap_mem));
}
}
@@ -2403,12 +2438,12 @@ static void vfio_map_bars(VFIOPCIDevice *vdev)
}
}
-static void vfio_unmap_bars(VFIOPCIDevice *vdev)
+static void vfio_unregister_bars(VFIOPCIDevice *vdev)
{
int i;
for (i = 0; i < PCI_ROM_SLOT; i++) {
- vfio_unmap_bar(vdev, i);
+ vfio_unregister_bar(vdev, i);
}
if (vdev->has_vga) {
@@ -2417,6 +2452,19 @@ static void vfio_unmap_bars(VFIOPCIDevice *vdev)
}
}
+static void vfio_unmap_bars(VFIOPCIDevice *vdev)
+{
+ int i;
+
+ for (i = 0; i < PCI_ROM_SLOT; i++) {
+ vfio_unmap_bar(vdev, i);
+ }
+
+ if (vdev->has_vga) {
+ vfio_vga_quirk_free(vdev);
+ }
+}
+
/*
* General setup
*/
@@ -3328,7 +3376,7 @@ static int vfio_initfn(PCIDevice *pdev)
out_teardown:
pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
vfio_teardown_msi(vdev);
- vfio_unmap_bars(vdev);
+ vfio_unregister_bars(vdev);
return ret;
}
@@ -3338,6 +3386,7 @@ static void vfio_instance_finalize(Object *obj)
VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pci_dev);
VFIOGroup *group = vdev->vbasedev.group;
+ vfio_unmap_bars(vdev);
g_free(vdev->emulated_config_bits);
g_free(vdev->rom);
vfio_put_device(vdev);
@@ -3355,7 +3404,7 @@ static void vfio_exitfn(PCIDevice *pdev)
timer_free(vdev->intx.mmap_timer);
}
vfio_teardown_msi(vdev);
- vfio_unmap_bars(vdev);
+ vfio_unregister_bars(vdev);
}
static void vfio_pci_reset(DeviceState *dev)
- [Qemu-devel] [PULL 0/6] vfio fixes, Alex Williamson, 2015/02/10
- [Qemu-devel] [PULL 1/6] memory: unregister AddressSpace MemoryListener within BQL, Alex Williamson, 2015/02/10
- [Qemu-devel] [PULL 2/6] vfio: cleanup vfio_get_device error path, remove vfio_populate_device callback, Alex Williamson, 2015/02/10
- [Qemu-devel] [PULL 3/6] vfio: free dynamically-allocated data in instance_finalize, Alex Williamson, 2015/02/10
- [Qemu-devel] [PULL 4/6] vfio: unmap and free BAR data in instance_finalize,
Alex Williamson <=
- [Qemu-devel] [PULL 5/6] vfio: Use vfio type1 v2 IOMMU interface, Alex Williamson, 2015/02/10
- [Qemu-devel] [PULL 6/6] vfio: Fix debug message compile error, Alex Williamson, 2015/02/10
- Re: [Qemu-devel] [PULL 0/6] vfio fixes, Peter Maydell, 2015/02/11