[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 {
>
>
> .
>
- [Qemu-devel] [PULL 02/19] vfio/pci: Cleanup vfio_early_setup_msix() error path, (continued)
- [Qemu-devel] [PULL 02/19] vfio/pci: Cleanup vfio_early_setup_msix() error path, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 03/19] vfio/pci: Rename INTx functions for easier tracing, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 04/19] vfio/pci: Rename MSI/X functions for easier tracing, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 05/19] vfio/pci: Make interrupt bypass runtime configurable, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 06/19] vfio: Change polarity of our no-mmap option, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 07/19] vfio/pci: Extract PCI structures to a separate header, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 09/19] vfio/pci: Cleanup ROM blacklist quirk, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 08/19] vfio/pci: Split quirks to a separate file, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 11/19] vfio/pci: Cleanup ATI 0x3c3 quirk, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 10/19] vfio/pci: Foundation for new quirk structure, Alex Williamson, 2015/09/23
- Re: [Qemu-devel] [PULL 10/19] vfio/pci: Foundation for new quirk structure,
Wen Congyang <=
- [Qemu-devel] [PULL 12/19] vfio/pci: Cleanup Nvidia 0x3d0 quirk, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 13/19] vfio/pci: Rework RTL8168 quirk, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 14/19] vfio/pci: Config window quirks, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 15/19] vfio/pci: Config mirror quirk, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 16/19] vfio/pci: Remove old config window and mirror quirks, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 17/19] vfio/pci: Move AMD device specific reset to quirks, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 18/19] vfio/pci: Cache vendor and device ID, Alex Williamson, 2015/09/23
- [Qemu-devel] [PULL 19/19] vfio/pci: Add emulated PCI IDs, Alex Williamson, 2015/09/23