From: Alex Williamson <alex.williamson@redhat.com>
To: alex.williamson@redhat.com
Cc: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 08/17] vfio/pci: Foundation for new quirk structure
Date: Wed, 09 Sep 2015 12:30:25 -0600 [thread overview]
Message-ID: <20150909183025.8470.252.stgit@gimli.home> (raw)
In-Reply-To: <20150909180219.8470.68096.stgit@gimli.home>
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 <alex.williamson@redhat.com>
---
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);
+ 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 {
next prev parent reply other threads:[~2015-09-09 18:30 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-09 18:29 [Qemu-devel] [PATCH 00/17] vfio: quirks & tracing refactoring Alex Williamson
2015-09-09 18:29 ` [Qemu-devel] [PATCH 01/17] vfio/pci: Rename INTx functions for easier tracing Alex Williamson
2015-09-09 18:29 ` [Qemu-devel] [PATCH 02/17] vfio/pci: Rename MSI/X " Alex Williamson
2015-09-09 18:29 ` [Qemu-devel] [PATCH 03/17] vfio/pci: Make interrupt bypass runtime configurable Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 04/17] vfio: Change polarity of our no-mmap option Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 05/17] vfio/pci: Extract PCI structures to a separate header Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 06/17] vfio/pci: Split quirks to a separate file Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 07/17] vfio/pci: Cleanup ROM blacklist quirk Alex Williamson
2015-09-09 18:30 ` Alex Williamson [this message]
2015-09-09 18:30 ` [Qemu-devel] [PATCH 09/17] vfio/pci: Cleanup ATI 0x3c3 quirk Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 10/17] vfio/pci: Cleanup Nvidia 0x3d0 quirk Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 11/17] vfio/pci: Rework RTL8168 quirk Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 12/17] vfio/pci: Config window quirks Alex Williamson
2015-09-09 18:30 ` [Qemu-devel] [PATCH 13/17] vfio/pci: Config mirror quirk Alex Williamson
2015-09-09 18:31 ` [Qemu-devel] [PATCH 14/17] vfio/pci: Remove old config window and mirror quirks Alex Williamson
2015-09-09 18:31 ` [Qemu-devel] [PATCH 15/17] vfio/pci: Move AMD device specific reset to quirks Alex Williamson
2015-09-09 18:31 ` [Qemu-devel] [PATCH 16/17] vfio/pci: Cache vendor and device ID Alex Williamson
2015-09-09 18:31 ` [Qemu-devel] [PATCH 17/17] vfio/pci: Add emulated PCI IDs Alex Williamson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150909183025.8470.252.stgit@gimli.home \
--to=alex.williamson@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).