qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] vfio: free dynamically-allocated data in instan


From: Alex Williamson
Subject: Re: [Qemu-devel] [PATCH] vfio: free dynamically-allocated data in instance_finalize
Date: Tue, 03 Feb 2015 08:20:08 -0700

On Tue, 2015-02-03 at 13:48 +0100, Paolo Bonzini wrote:
> In order to enable out-of-BQL address space lookup, destruction of
> devices needs to be split in two phases.
> 
> Unrealize is the first phase; once it complete no new accesses will
> be started, but there may still be pending memory accesses can still
> be completed.
> 
> The second part is freeing the device, which only happens once all memory
> accesses are complete.  At this point the reference count has dropped to
> zero, an RCU grace period must have completed (because the RCU-protected
> FlatViews hold a reference to the device via memory_region_ref).  This is
> when instance_finalize is called.
> 
> Freeing data belongs in an instance_finalize callback, because the
> dynamically allocated memory can still be used after unrealize by the
> pending memory accesses.
> 
> 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.
> 
> Cc: Alex Williamson <address@hidden>
> Signed-off-by: Paolo Bonzini <address@hidden>
> ---
>       This patch is part of the third installment 3 of the RCU work.
>       Sending it out separately for Alex to review it.
> 
>  hw/vfio/pci.c |   78 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 68 insertions(+), 10 deletions(-)

Looks good to me.  I don't see any external dependencies, so do you want
me to pull this in through my branch?  Thanks,

Alex

> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 014a92c..69d4a33 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -1997,12 +1997,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);
> @@ -2023,10 +2034,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);
> @@ -2282,7 +2302,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];
>  
> @@ -2293,10 +2313,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));
>      }
>  }
> @@ -2413,6 +2448,19 @@ static void vfio_unmap_bars(VFIOPCIDevice *vdev)
>      }
>  
>      if (vdev->has_vga) {
> +        vfio_vga_quirk_free(vdev);
> +    }
> +}
> +
> +static void vfio_unregister_bars(VFIOPCIDevice *vdev)
> +{
> +    int i;
> +
> +    for (i = 0; i < PCI_ROM_SLOT; i++) {
> +        vfio_unregister_bar(vdev, i);
> +    }
> +
> +    if (vdev->has_vga) {
>          vfio_vga_quirk_teardown(vdev);
>          pci_unregister_vga(&vdev->pdev);
>      }
> @@ -3324,6 +3372,7 @@ static int vfio_initfn(PCIDevice *pdev)
>  out_teardown:
>      pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
>      vfio_teardown_msi(vdev);
> +    vfio_unregister_bars(vdev);
>      vfio_unmap_bars(vdev);
>  out_put:
>      g_free(vdev->emulated_config_bits);
> @@ -3332,10 +3381,22 @@ out_put:
>      return ret;
>  }
>  
> +static void vfio_instance_finalize(Object *obj)
> +{
> +    PCIDevice *pci_dev = PCI_DEVICE(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);
> +    vfio_put_group(group);
> +}
> +
>  static void vfio_exitfn(PCIDevice *pdev)
>  {
>      VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev);
> -    VFIOGroup *group = vdev->vbasedev.group;
>  
>      vfio_unregister_err_notifier(vdev);
>      pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
> @@ -3344,11 +3405,7 @@ static void vfio_exitfn(PCIDevice *pdev)
>          timer_free(vdev->intx.mmap_timer);
>      }
>      vfio_teardown_msi(vdev);
> -    vfio_unmap_bars(vdev);
> -    g_free(vdev->emulated_config_bits);
> -    g_free(vdev->rom);
> -    vfio_put_device(vdev);
> -    vfio_put_group(group);
> +    vfio_unregister_bars(vdev);
>  }
>  
>  static void vfio_pci_reset(DeviceState *dev)
> @@ -3436,6 +3493,7 @@ static const TypeInfo vfio_pci_dev_info = {
>      .instance_size = sizeof(VFIOPCIDevice),
>      .class_init = vfio_pci_dev_class_init,
>      .instance_init = vfio_instance_init,
> +    .instance_finalize = vfio_instance_finalize,
>  };
>  
>  static void register_vfio_pci_dev_type(void)






reply via email to

[Prev in Thread] Current Thread [Next in Thread]