qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PULL 10/19] vfio/pci: Foundation for new quirk structu


From: Wen Congyang
Subject: Re: [Qemu-devel] [PULL 10/19] vfio/pci: Foundation for new quirk structure
Date: Thu, 24 Sep 2015 10:54:46 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.2.0

On 09/24/2015 04:23 AM, Alex Williamson wrote:
> VFIOQuirk hosts a single memory region and a fixed set of data fields
> that try to handle all the quirk cases, but end up making those that
> don't exactly match really confusing.  This patch introduces a struct
> intended to provide more flexibility and simpler code.  VFIOQuirk is
> stripped to its basics, an opaque data pointer for quirk specific
> data and a pointer to an array of MemoryRegions with a counter.  This
> still allows us to have common teardown routines, but adds much
> greater flexibility to support multiple memory regions and quirk
> specific data structures that are easier to maintain.  The existing
> VFIOQuirk is transformed into VFIOLegacyQuirk, which further patches
> will eliminate entirely.
> 
> Signed-off-by: Alex Williamson <address@hidden>
> ---
>  hw/vfio/pci-quirks.c |  249 
> ++++++++++++++++++++++++++++++--------------------
>  hw/vfio/pci.h        |   12 ++
>  2 files changed, 157 insertions(+), 104 deletions(-)
> 
> diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
> index 17e300a..429fdad 100644
> --- a/hw/vfio/pci-quirks.c
> +++ b/hw/vfio/pci-quirks.c
> @@ -80,7 +80,7 @@ static bool vfio_flags_enabled(uint8_t flags, uint8_t mask)
>  static uint64_t vfio_generic_window_quirk_read(void *opaque,
>                                                 hwaddr addr, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      uint64_t data;
>  
> @@ -92,13 +92,13 @@ static uint64_t vfio_generic_window_quirk_read(void 
> *opaque,
>          if (!vfio_range_contained(addr, size, quirk->data.data_offset,
>                                    quirk->data.data_size)) {
>              hw_error("%s: window data read not fully contained: %s",
> -                     __func__, memory_region_name(&quirk->mem));
> +                     __func__, memory_region_name(quirk->mem));
>          }
>  
>          data = vfio_pci_read_config(&vdev->pdev,
>                                      quirk->data.address_val + offset, size);
>  
> -        trace_vfio_generic_window_quirk_read(memory_region_name(&quirk->mem),
> +        trace_vfio_generic_window_quirk_read(memory_region_name(quirk->mem),
>                                               vdev->vbasedev.name,
>                                               quirk->data.bar,
>                                               addr, size, data);
> @@ -113,7 +113,7 @@ static uint64_t vfio_generic_window_quirk_read(void 
> *opaque,
>  static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr,
>                                              uint64_t data, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>  
>      if (ranges_overlap(addr, size,
> @@ -121,7 +121,7 @@ static void vfio_generic_window_quirk_write(void *opaque, 
> hwaddr addr,
>  
>          if (addr != quirk->data.address_offset) {
>              hw_error("%s: offset write into address window: %s",
> -                     __func__, memory_region_name(&quirk->mem));
> +                     __func__, memory_region_name(quirk->mem));
>          }
>  
>          if ((data & ~quirk->data.address_mask) == quirk->data.address_match) 
> {
> @@ -142,12 +142,12 @@ static void vfio_generic_window_quirk_write(void 
> *opaque, hwaddr addr,
>          if (!vfio_range_contained(addr, size, quirk->data.data_offset,
>                                    quirk->data.data_size)) {
>              hw_error("%s: window data write not fully contained: %s",
> -                     __func__, memory_region_name(&quirk->mem));
> +                     __func__, memory_region_name(quirk->mem));
>          }
>  
>          vfio_pci_write_config(&vdev->pdev,
>                                quirk->data.address_val + offset, data, size);
> -        
> trace_vfio_generic_window_quirk_write(memory_region_name(&quirk->mem),
> +        trace_vfio_generic_window_quirk_write(memory_region_name(quirk->mem),
>                                                vdev->vbasedev.name,
>                                                quirk->data.bar,
>                                                addr, data, size);
> @@ -167,7 +167,7 @@ static const MemoryRegionOps vfio_generic_window_quirk = {
>  static uint64_t vfio_generic_quirk_read(void *opaque,
>                                          hwaddr addr, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK;
>      hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK;
> @@ -178,12 +178,12 @@ static uint64_t vfio_generic_quirk_read(void *opaque,
>          if (!vfio_range_contained(addr, size, offset,
>                                    quirk->data.address_mask + 1)) {
>              hw_error("%s: read not fully contained: %s",
> -                     __func__, memory_region_name(&quirk->mem));
> +                     __func__, memory_region_name(quirk->mem));
>          }
>  
>          data = vfio_pci_read_config(&vdev->pdev, addr - offset, size);
>  
> -        trace_vfio_generic_quirk_read(memory_region_name(&quirk->mem),
> +        trace_vfio_generic_quirk_read(memory_region_name(quirk->mem),
>                                        vdev->vbasedev.name, quirk->data.bar,
>                                        addr + base, size, data);
>      } else {
> @@ -197,7 +197,7 @@ static uint64_t vfio_generic_quirk_read(void *opaque,
>  static void vfio_generic_quirk_write(void *opaque, hwaddr addr,
>                                       uint64_t data, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK;
>      hwaddr offset = quirk->data.address_match & ~TARGET_PAGE_MASK;
> @@ -207,12 +207,12 @@ static void vfio_generic_quirk_write(void *opaque, 
> hwaddr addr,
>          if (!vfio_range_contained(addr, size, offset,
>                                    quirk->data.address_mask + 1)) {
>              hw_error("%s: write not fully contained: %s",
> -                     __func__, memory_region_name(&quirk->mem));
> +                     __func__, memory_region_name(quirk->mem));
>          }
>  
>          vfio_pci_write_config(&vdev->pdev, addr - offset, data, size);
>  
> -        trace_vfio_generic_quirk_write(memory_region_name(&quirk->mem),
> +        trace_vfio_generic_quirk_write(memory_region_name(quirk->mem),
>                                         vdev->vbasedev.name, quirk->data.bar,
>                                         addr + base, data, size);
>      } else {
> @@ -242,7 +242,7 @@ static const MemoryRegionOps vfio_generic_quirk = {
>  static uint64_t vfio_ati_3c3_quirk_read(void *opaque,
>                                          hwaddr addr, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      uint64_t data = vfio_pci_read_config(&vdev->pdev,
>                                           PCI_BASE_ADDRESS_0 + (4 * 4) + 1,
> @@ -261,6 +261,7 @@ static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice 
> *vdev)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>  
>      if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) {
>          return;
> @@ -275,12 +276,15 @@ static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice 
> *vdev)
>      }
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> +    legacy = quirk->data = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);

Why do you use g_malloc0_n() here? It is introduced in glib 2.24, but we only 
require glib 2.22.

Thanks
Wen Congyang

> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
>  
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, 
> quirk,
> +    memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, 
> legacy,
>                            "vfio-ati-3c3-quirk", 1);
>      memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
> -                                3 /* offset 3 bytes from 0x3c0 */, 
> &quirk->mem);
> +                                3 /* offset 3 bytes from 0x3c0 */, 
> quirk->mem);
>  
>      QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks,
>                        quirk, next);
> @@ -302,6 +306,7 @@ static void 
> vfio_probe_ati_bar4_window_quirk(VFIOPCIDevice *vdev, int nr)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>  
>      if (!vdev->has_vga || nr != 4 ||
>          pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_ATI) {
> @@ -309,20 +314,23 @@ static void 
> vfio_probe_ati_bar4_window_quirk(VFIOPCIDevice *vdev, int nr)
>      }
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> -    quirk->data.address_size = 4;
> -    quirk->data.data_offset = 4;
> -    quirk->data.data_size = 4;
> -    quirk->data.address_match = 0x4000;
> -    quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1;
> -    quirk->data.bar = nr;
> -    quirk->data.read_flags = quirk->data.write_flags = 1;
> -
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev),
> -                          &vfio_generic_window_quirk, quirk,
> +    quirk->data = legacy = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);
> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
> +    legacy->data.address_size = 4;
> +    legacy->data.data_offset = 4;
> +    legacy->data.data_size = 4;
> +    legacy->data.address_match = 0x4000;
> +    legacy->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1;
> +    legacy->data.bar = nr;
> +    legacy->data.read_flags = legacy->data.write_flags = 1;
> +
> +    memory_region_init_io(quirk->mem, OBJECT(vdev),
> +                          &vfio_generic_window_quirk, legacy,
>                            "vfio-ati-bar4-window-quirk", 8);
>      memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
> -                          quirk->data.base_offset, &quirk->mem, 1);
> +                          legacy->data.base_offset, quirk->mem, 1);
>  
>      QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
>  
> @@ -336,6 +344,7 @@ static void vfio_probe_ati_bar2_4000_quirk(VFIOPCIDevice 
> *vdev, int nr)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>  
>      /* Only enable on newer devices where BAR2 is 64bit */
>      if (!vdev->has_vga || nr != 2 || !vdev->bars[2].mem64 ||
> @@ -344,18 +353,21 @@ static void 
> vfio_probe_ati_bar2_4000_quirk(VFIOPCIDevice *vdev, int nr)
>      }
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> -    quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1;
> -    quirk->data.address_match = 0x4000;
> -    quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1;
> -    quirk->data.bar = nr;
> -
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, 
> quirk,
> +    quirk->data = legacy = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);
> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
> +    legacy->data.flags = legacy->data.read_flags = legacy->data.write_flags 
> = 1;
> +    legacy->data.address_match = 0x4000;
> +    legacy->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1;
> +    legacy->data.bar = nr;
> +
> +    memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_generic_quirk, 
> legacy,
>                            "vfio-ati-bar2-4000-quirk",
> -                          TARGET_PAGE_ALIGN(quirk->data.address_mask + 1));
> +                          TARGET_PAGE_ALIGN(legacy->data.address_mask + 1));
>      memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
> -                          quirk->data.address_match & TARGET_PAGE_MASK,
> -                          &quirk->mem, 1);
> +                          legacy->data.address_match & TARGET_PAGE_MASK,
> +                          quirk->mem, 1);
>  
>      QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
>  
> @@ -397,7 +409,7 @@ enum {
>  static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque,
>                                             hwaddr addr, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      PCIDevice *pdev = &vdev->pdev;
>      uint64_t data = vfio_vga_read(&vdev->vga.region[QEMU_PCI_VGA_IO_HI],
> @@ -416,7 +428,7 @@ static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque,
>  static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr,
>                                          uint64_t data, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      PCIDevice *pdev = &vdev->pdev;
>  
> @@ -468,6 +480,7 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice 
> *vdev)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>  
>      if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA ||
>          !vdev->bars[1].region.size) {
> @@ -475,19 +488,22 @@ static void 
> vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev)
>      }
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> -    quirk->data.base_offset = 0x10;
> -    quirk->data.address_offset = 4;
> -    quirk->data.address_size = 2;
> -    quirk->data.address_match = 0x1800;
> -    quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1;
> -    quirk->data.data_offset = 0;
> -    quirk->data.data_size = 4;
> -
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_3d0_quirk,
> -                          quirk, "vfio-nvidia-3d0-quirk", 6);
> +    quirk->data = legacy = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);
> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
> +    legacy->data.base_offset = 0x10;
> +    legacy->data.address_offset = 4;
> +    legacy->data.address_size = 2;
> +    legacy->data.address_match = 0x1800;
> +    legacy->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1;
> +    legacy->data.data_offset = 0;
> +    legacy->data.data_size = 4;
> +
> +    memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_nvidia_3d0_quirk,
> +                          legacy, "vfio-nvidia-3d0-quirk", 6);
>      memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem,
> -                                quirk->data.base_offset, &quirk->mem);
> +                                legacy->data.base_offset, quirk->mem);
>  
>      QLIST_INSERT_HEAD(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].quirks,
>                        quirk, next);
> @@ -512,7 +528,7 @@ enum {
>  static void vfio_nvidia_bar5_window_quirk_write(void *opaque, hwaddr addr,
>                                                  uint64_t data, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>  
>      switch (addr) {
>      case 0x0:
> @@ -558,6 +574,7 @@ static void 
> vfio_probe_nvidia_bar5_window_quirk(VFIOPCIDevice *vdev, int nr)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>  
>      if (!vdev->has_vga || nr != 5 ||
>          pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
> @@ -565,19 +582,22 @@ static void 
> vfio_probe_nvidia_bar5_window_quirk(VFIOPCIDevice *vdev, int nr)
>      }
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> -    quirk->data.read_flags = quirk->data.write_flags = NV_BAR5_VALID;
> -    quirk->data.address_offset = 0x8;
> -    quirk->data.address_size = 0; /* actually 4, but avoids generic code */
> -    quirk->data.data_offset = 0xc;
> -    quirk->data.data_size = 4;
> -    quirk->data.bar = nr;
> -
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev),
> -                          &vfio_nvidia_bar5_window_quirk, quirk,
> +    quirk->data = legacy = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);
> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
> +    legacy->data.read_flags = legacy->data.write_flags = NV_BAR5_VALID;
> +    legacy->data.address_offset = 0x8;
> +    legacy->data.address_size = 0; /* actually 4, but avoids generic code */
> +    legacy->data.data_offset = 0xc;
> +    legacy->data.data_size = 4;
> +    legacy->data.bar = nr;
> +
> +    memory_region_init_io(quirk->mem, OBJECT(vdev),
> +                          &vfio_nvidia_bar5_window_quirk, legacy,
>                            "vfio-nvidia-bar5-window-quirk", 16);
>      memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
> -                                        0, &quirk->mem, 1);
> +                                        0, quirk->mem, 1);
>  
>      QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
>  
> @@ -587,7 +607,7 @@ static void 
> vfio_probe_nvidia_bar5_window_quirk(VFIOPCIDevice *vdev, int nr)
>  static void vfio_nvidia_88000_quirk_write(void *opaque, hwaddr addr,
>                                            uint64_t data, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      PCIDevice *pdev = &vdev->pdev;
>      hwaddr base = quirk->data.address_match & TARGET_PAGE_MASK;
> @@ -626,6 +646,7 @@ static void 
> vfio_probe_nvidia_bar0_88000_quirk(VFIOPCIDevice *vdev, int nr)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>      uint16_t vendor, class;
>  
>      vendor = pci_get_word(pdev->config + PCI_VENDOR_ID);
> @@ -637,18 +658,21 @@ static void 
> vfio_probe_nvidia_bar0_88000_quirk(VFIOPCIDevice *vdev, int nr)
>      }
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> -    quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1;
> -    quirk->data.address_match = 0x88000;
> -    quirk->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1;
> -    quirk->data.bar = nr;
> -
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev), 
> &vfio_nvidia_88000_quirk,
> -                          quirk, "vfio-nvidia-bar0-88000-quirk",
> -                          TARGET_PAGE_ALIGN(quirk->data.address_mask + 1));
> +    quirk->data = legacy = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);
> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
> +    legacy->data.flags = legacy->data.read_flags = legacy->data.write_flags 
> = 1;
> +    legacy->data.address_match = 0x88000;
> +    legacy->data.address_mask = PCIE_CONFIG_SPACE_SIZE - 1;
> +    legacy->data.bar = nr;
> +
> +    memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_nvidia_88000_quirk,
> +                          legacy, "vfio-nvidia-bar0-88000-quirk",
> +                          TARGET_PAGE_ALIGN(legacy->data.address_mask + 1));
>      memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
> -                          quirk->data.address_match & TARGET_PAGE_MASK,
> -                          &quirk->mem, 1);
> +                          legacy->data.address_match & TARGET_PAGE_MASK,
> +                          quirk->mem, 1);
>  
>      QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
>  
> @@ -662,6 +686,7 @@ static void 
> vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>  
>      if (!vdev->has_vga || nr != 0 ||
>          pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA) {
> @@ -674,18 +699,21 @@ static void 
> vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr)
>              & 0xff);
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> -    quirk->data.flags = quirk->data.read_flags = quirk->data.write_flags = 1;
> -    quirk->data.address_match = 0x1800;
> -    quirk->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1;
> -    quirk->data.bar = nr;
> -
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_generic_quirk, 
> quirk,
> +    quirk->data = legacy = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);
> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
> +    legacy->data.flags = legacy->data.read_flags = legacy->data.write_flags 
> = 1;
> +    legacy->data.address_match = 0x1800;
> +    legacy->data.address_mask = PCI_CONFIG_SPACE_SIZE - 1;
> +    legacy->data.bar = nr;
> +
> +    memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_generic_quirk, 
> legacy,
>                            "vfio-nvidia-bar0-1800-quirk",
> -                          TARGET_PAGE_ALIGN(quirk->data.address_mask + 1));
> +                          TARGET_PAGE_ALIGN(legacy->data.address_mask + 1));
>      memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
> -                          quirk->data.address_match & TARGET_PAGE_MASK,
> -                          &quirk->mem, 1);
> +                          legacy->data.address_match & TARGET_PAGE_MASK,
> +                          quirk->mem, 1);
>  
>      QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
>  
> @@ -725,7 +753,7 @@ static void 
> vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr)
>  static uint64_t vfio_rtl8168_window_quirk_read(void *opaque,
>                                                 hwaddr addr, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>      uint64_t val = 0;
>  
> @@ -755,7 +783,7 @@ static uint64_t vfio_rtl8168_window_quirk_read(void 
> *opaque,
>  static void vfio_rtl8168_window_quirk_write(void *opaque, hwaddr addr,
>                                              uint64_t data, unsigned size)
>  {
> -    VFIOQuirk *quirk = opaque;
> +    VFIOLegacyQuirk *quirk = opaque;
>      VFIOPCIDevice *vdev = quirk->vdev;
>  
>      switch (addr) {
> @@ -809,6 +837,7 @@ static void 
> vfio_probe_rtl8168_bar2_window_quirk(VFIOPCIDevice *vdev, int nr)
>  {
>      PCIDevice *pdev = &vdev->pdev;
>      VFIOQuirk *quirk;
> +    VFIOLegacyQuirk *legacy;
>  
>      if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_REALTEK 
> ||
>          pci_get_word(pdev->config + PCI_DEVICE_ID) != 0x8168 || nr != 2) {
> @@ -816,13 +845,16 @@ static void 
> vfio_probe_rtl8168_bar2_window_quirk(VFIOPCIDevice *vdev, int nr)
>      }
>  
>      quirk = g_malloc0(sizeof(*quirk));
> -    quirk->vdev = vdev;
> -    quirk->data.bar = nr;
> -
> -    memory_region_init_io(&quirk->mem, OBJECT(vdev), 
> &vfio_rtl8168_window_quirk,
> -                          quirk, "vfio-rtl8168-window-quirk", 8);
> +    quirk->data = legacy = g_malloc0(sizeof(*legacy));
> +    quirk->mem = legacy->mem = g_malloc0_n(sizeof(MemoryRegion), 1);
> +    quirk->nr_mem = 1;
> +    legacy->vdev = vdev;
> +    legacy->data.bar = nr;
> +
> +    memory_region_init_io(quirk->mem, OBJECT(vdev), 
> &vfio_rtl8168_window_quirk,
> +                          legacy, "vfio-rtl8168-window-quirk", 8);
>      memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
> -                                        0x70, &quirk->mem, 1);
> +                                        0x70, quirk->mem, 1);
>  
>      QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
>  
> @@ -841,24 +873,31 @@ void vfio_vga_quirk_setup(VFIOPCIDevice *vdev)
>  void vfio_vga_quirk_teardown(VFIOPCIDevice *vdev)
>  {
>      VFIOQuirk *quirk;
> -    int i;
> +    int i, j;
>  
>      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);
> +            for (j = 0; j < quirk->nr_mem; j++) {
> +                memory_region_del_subregion(&vdev->vga.region[i].mem,
> +                                            &quirk->mem[j]);
> +            }
>          }
>      }
>  }
>  
>  void vfio_vga_quirk_free(VFIOPCIDevice *vdev)
>  {
> -    int i;
> +    int i, j;
>  
>      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);
> -            object_unparent(OBJECT(&quirk->mem));
>              QLIST_REMOVE(quirk, next);
> +            for (j = 0; j < quirk->nr_mem; j++) {
> +                object_unparent(OBJECT(&quirk->mem[j]));
> +            }
> +            g_free(quirk->mem);
> +            g_free(quirk->data);
>              g_free(quirk);
>          }
>      }
> @@ -878,20 +917,28 @@ void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int 
> nr)
>  {
>      VFIOBAR *bar = &vdev->bars[nr];
>      VFIOQuirk *quirk;
> +    int i;
>  
>      QLIST_FOREACH(quirk, &bar->quirks, next) {
> -        memory_region_del_subregion(&bar->region.mem, &quirk->mem);
> +        for (i = 0; i < quirk->nr_mem; i++) {
> +            memory_region_del_subregion(&bar->region.mem, &quirk->mem[i]);
> +        }
>      }
>  }
>  
>  void vfio_bar_quirk_free(VFIOPCIDevice *vdev, int nr)
>  {
>      VFIOBAR *bar = &vdev->bars[nr];
> +    int i;
>  
>      while (!QLIST_EMPTY(&bar->quirks)) {
>          VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
> -        object_unparent(OBJECT(&quirk->mem));
>          QLIST_REMOVE(quirk, next);
> +        for (i = 0; i < quirk->nr_mem; i++) {
> +            object_unparent(OBJECT(&quirk->mem[i]));
> +        }
> +        g_free(quirk->mem);
> +        g_free(quirk->data);
>          g_free(quirk);
>      }
>  }
> diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
> index f6dbe7f..8696976 100644
> --- a/hw/vfio/pci.h
> +++ b/hw/vfio/pci.h
> @@ -22,10 +22,9 @@
>  
>  struct VFIOPCIDevice;
>  
> -typedef struct VFIOQuirk {
> -    MemoryRegion mem;
> +typedef struct VFIOLegacyQuirk {
>      struct VFIOPCIDevice *vdev;
> -    QLIST_ENTRY(VFIOQuirk) next;
> +    MemoryRegion *mem;
>      struct {
>          uint32_t base_offset:TARGET_PAGE_BITS;
>          uint32_t address_offset:TARGET_PAGE_BITS;
> @@ -43,6 +42,13 @@ typedef struct VFIOQuirk {
>          uint8_t read_flags;
>          uint8_t write_flags;
>      } data;
> +} VFIOLegacyQuirk;
> +
> +typedef struct VFIOQuirk {
> +    QLIST_ENTRY(VFIOQuirk) next;
> +    void *data;
> +    int nr_mem;
> +    MemoryRegion *mem;
>  } VFIOQuirk;
>  
>  typedef struct VFIOBAR {
> 
> 
> .
> 




reply via email to

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