|
|
5d360b |
From 725ad24f771adcc8aeacaf27b21a6d95cab41e69 Mon Sep 17 00:00:00 2001
|
|
|
5d360b |
From: Alex Williamson <alex.williamson@redhat.com>
|
|
|
5d360b |
Date: Fri, 29 Sep 2017 21:45:02 +0200
|
|
|
5d360b |
Subject: [PATCH 07/27] hw/vfio/pci: Introduce VFIORegion
|
|
|
5d360b |
|
|
|
5d360b |
RH-Author: Alex Williamson <alex.williamson@redhat.com>
|
|
|
5d360b |
Message-id: <20170929214502.16765.46217.stgit@gimli.home>
|
|
|
5d360b |
Patchwork-id: 76765
|
|
|
5d360b |
O-Subject: [RHEL-7.5 qemu-kvm PATCH 07/16] hw/vfio/pci: Introduce VFIORegion
|
|
|
5d360b |
Bugzilla: 1494181
|
|
|
5d360b |
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
5d360b |
RH-Acked-by: Auger Eric <eric.auger@redhat.com>
|
|
|
5d360b |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
5d360b |
|
|
|
5d360b |
From: Eric Auger <eric.auger@linaro.org>
|
|
|
5d360b |
|
|
|
5d360b |
Upstream: a664477db8dac84cc046e9d79701eefda1d58703
|
|
|
5d360b |
|
|
|
5d360b |
This structure is going to be shared by VFIOPCIDevice and
|
|
|
5d360b |
VFIOPlatformDevice. VFIOBAR includes it.
|
|
|
5d360b |
|
|
|
5d360b |
vfio_eoi becomes an ops of VFIODevice specialized by parent device.
|
|
|
5d360b |
This makes possible to transform vfio_bar_write/read into generic
|
|
|
5d360b |
vfio_region_write/read that will be used by VFIOPlatformDevice too.
|
|
|
5d360b |
|
|
|
5d360b |
vfio_mmap_bar becomes vfio_map_region
|
|
|
5d360b |
|
|
|
5d360b |
Signed-off-by: Eric Auger <eric.auger@linaro.org>
|
|
|
5d360b |
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
|
|
|
5d360b |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
5d360b |
---
|
|
|
5d360b |
hw/misc/vfio.c | 188 +++++++++++++++++++++++++++++----------------------------
|
|
|
5d360b |
1 file changed, 97 insertions(+), 91 deletions(-)
|
|
|
5d360b |
|
|
|
5d360b |
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
|
|
|
5d360b |
index 3e559ed..92414b9 100644
|
|
|
5d360b |
--- a/hw/misc/vfio.c
|
|
|
5d360b |
+++ b/hw/misc/vfio.c
|
|
|
5d360b |
@@ -84,15 +84,19 @@ typedef struct VFIOQuirk {
|
|
|
5d360b |
} data;
|
|
|
5d360b |
} VFIOQuirk;
|
|
|
5d360b |
|
|
|
5d360b |
-typedef struct VFIOBAR {
|
|
|
5d360b |
- off_t fd_offset; /* offset of BAR within device fd */
|
|
|
5d360b |
- int fd; /* device fd, allows us to pass VFIOBAR as opaque data */
|
|
|
5d360b |
+typedef struct VFIORegion {
|
|
|
5d360b |
+ struct VFIODevice *vbasedev;
|
|
|
5d360b |
+ off_t fd_offset; /* offset of region within device fd */
|
|
|
5d360b |
MemoryRegion mem; /* slow, read/write access */
|
|
|
5d360b |
MemoryRegion mmap_mem; /* direct mapped access */
|
|
|
5d360b |
void *mmap;
|
|
|
5d360b |
size_t size;
|
|
|
5d360b |
uint32_t flags; /* VFIO region flags (rd/wr/mmap) */
|
|
|
5d360b |
- uint8_t nr; /* cache the BAR number for debug */
|
|
|
5d360b |
+ uint8_t nr; /* cache the region number for debug */
|
|
|
5d360b |
+} VFIORegion;
|
|
|
5d360b |
+
|
|
|
5d360b |
+typedef struct VFIOBAR {
|
|
|
5d360b |
+ VFIORegion region;
|
|
|
5d360b |
bool ioport;
|
|
|
5d360b |
bool mem64;
|
|
|
5d360b |
QLIST_HEAD(, VFIOQuirk) quirks;
|
|
|
5d360b |
@@ -194,6 +198,7 @@ typedef struct VFIODevice {
|
|
|
5d360b |
struct VFIODeviceOps {
|
|
|
5d360b |
void (*vfio_compute_needs_reset)(VFIODevice *vdev);
|
|
|
5d360b |
int (*vfio_hot_reset_multi)(VFIODevice *vdev);
|
|
|
5d360b |
+ void (*vfio_eoi)(VFIODevice *vdev);
|
|
|
5d360b |
};
|
|
|
5d360b |
|
|
|
5d360b |
typedef struct VFIOPCIDevice {
|
|
|
5d360b |
@@ -383,8 +388,10 @@ static void vfio_intx_interrupt(void *opaque)
|
|
|
5d360b |
}
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
-static void vfio_eoi(VFIOPCIDevice *vdev)
|
|
|
5d360b |
+static void vfio_eoi(VFIODevice *vbasedev)
|
|
|
5d360b |
{
|
|
|
5d360b |
+ VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
|
|
|
5d360b |
+
|
|
|
5d360b |
if (!vdev->intx.pending) {
|
|
|
5d360b |
return;
|
|
|
5d360b |
}
|
|
|
5d360b |
@@ -394,7 +401,7 @@ static void vfio_eoi(VFIOPCIDevice *vdev)
|
|
|
5d360b |
|
|
|
5d360b |
vdev->intx.pending = false;
|
|
|
5d360b |
qemu_set_irq(vdev->pdev.irq[vdev->intx.pin], 0);
|
|
|
5d360b |
- vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
|
|
|
5d360b |
+ vfio_unmask_single_irqindex(vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
|
|
|
5d360b |
@@ -549,7 +556,7 @@ static void vfio_update_irq(PCIDevice *pdev)
|
|
|
5d360b |
vfio_enable_intx_kvm(vdev);
|
|
|
5d360b |
|
|
|
5d360b |
/* Re-enable the interrupt in cased we missed an EOI */
|
|
|
5d360b |
- vfio_eoi(vdev);
|
|
|
5d360b |
+ vfio_eoi(&vdev->vbasedev);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
static int vfio_enable_intx(VFIOPCIDevice *vdev)
|
|
|
5d360b |
@@ -1086,10 +1093,11 @@ static void vfio_update_msi(VFIOPCIDevice *vdev)
|
|
|
5d360b |
/*
|
|
|
5d360b |
* IO Port/MMIO - Beware of the endians, VFIO is always little endian
|
|
|
5d360b |
*/
|
|
|
5d360b |
-static void vfio_bar_write(void *opaque, hwaddr addr,
|
|
|
5d360b |
- uint64_t data, unsigned size)
|
|
|
5d360b |
+static void vfio_region_write(void *opaque, hwaddr addr,
|
|
|
5d360b |
+ uint64_t data, unsigned size)
|
|
|
5d360b |
{
|
|
|
5d360b |
- VFIOBAR *bar = opaque;
|
|
|
5d360b |
+ VFIORegion *region = opaque;
|
|
|
5d360b |
+ VFIODevice *vbasedev = region->vbasedev;
|
|
|
5d360b |
union {
|
|
|
5d360b |
uint8_t byte;
|
|
|
5d360b |
uint16_t word;
|
|
|
5d360b |
@@ -1112,21 +1120,15 @@ static void vfio_bar_write(void *opaque, hwaddr addr,
|
|
|
5d360b |
break;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
- if (pwrite(bar->fd, &buf, size, bar->fd_offset + addr) != size) {
|
|
|
5d360b |
- error_report("%s(,0x%"HWADDR_PRIx", 0x%"PRIx64", %d) failed: %m",
|
|
|
5d360b |
- __func__, addr, data, size);
|
|
|
5d360b |
+ if (pwrite(vbasedev->fd, &buf, size, region->fd_offset + addr) != size) {
|
|
|
5d360b |
+ error_report("%s(%s:region%d+0x%"HWADDR_PRIx", 0x%"PRIx64
|
|
|
5d360b |
+ ",%d) failed: %m",
|
|
|
5d360b |
+ __func__, vbasedev->name, region->nr,
|
|
|
5d360b |
+ addr, data, size);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
-#ifdef DEBUG_VFIO
|
|
|
5d360b |
- {
|
|
|
5d360b |
- VFIOPCIDevice *vdev = container_of(bar, VFIOPCIDevice, bars[bar->nr]);
|
|
|
5d360b |
-
|
|
|
5d360b |
- DPRINTF("%s(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx", 0x%"PRIx64
|
|
|
5d360b |
- ", %d)\n", __func__, vdev->host.domain, vdev->host.bus,
|
|
|
5d360b |
- vdev->host.slot, vdev->host.function, bar->nr, addr,
|
|
|
5d360b |
- data, size);
|
|
|
5d360b |
- }
|
|
|
5d360b |
-#endif
|
|
|
5d360b |
+ DPRINTF("%s(%s:BAR%d+0x%"HWADDR_PRIx", 0x%"PRIx64", %d)\n", __func__,
|
|
|
5d360b |
+ vbasedev->name, region->nr, addr, data, size);
|
|
|
5d360b |
|
|
|
5d360b |
/*
|
|
|
5d360b |
* A read or write to a BAR always signals an INTx EOI. This will
|
|
|
5d360b |
@@ -1136,13 +1138,14 @@ static void vfio_bar_write(void *opaque, hwaddr addr,
|
|
|
5d360b |
* which access will service the interrupt, so we're potentially
|
|
|
5d360b |
* getting quite a few host interrupts per guest interrupt.
|
|
|
5d360b |
*/
|
|
|
5d360b |
- vfio_eoi(container_of(bar, VFIOPCIDevice, bars[bar->nr]));
|
|
|
5d360b |
+ vbasedev->ops->vfio_eoi(vbasedev);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
-static uint64_t vfio_bar_read(void *opaque,
|
|
|
5d360b |
- hwaddr addr, unsigned size)
|
|
|
5d360b |
+static uint64_t vfio_region_read(void *opaque,
|
|
|
5d360b |
+ hwaddr addr, unsigned size)
|
|
|
5d360b |
{
|
|
|
5d360b |
- VFIOBAR *bar = opaque;
|
|
|
5d360b |
+ VFIORegion *region = opaque;
|
|
|
5d360b |
+ VFIODevice *vbasedev = region->vbasedev;
|
|
|
5d360b |
union {
|
|
|
5d360b |
uint8_t byte;
|
|
|
5d360b |
uint16_t word;
|
|
|
5d360b |
@@ -1151,9 +1154,10 @@ static uint64_t vfio_bar_read(void *opaque,
|
|
|
5d360b |
} buf;
|
|
|
5d360b |
uint64_t data = 0;
|
|
|
5d360b |
|
|
|
5d360b |
- if (pread(bar->fd, &buf, size, bar->fd_offset + addr) != size) {
|
|
|
5d360b |
- error_report("%s(,0x%"HWADDR_PRIx", %d) failed: %m",
|
|
|
5d360b |
- __func__, addr, size);
|
|
|
5d360b |
+ if (pread(vbasedev->fd, &buf, size, region->fd_offset + addr) != size) {
|
|
|
5d360b |
+ error_report("%s(%s:region%d+0x%"HWADDR_PRIx", %d) failed: %m",
|
|
|
5d360b |
+ __func__, vbasedev->name, region->nr,
|
|
|
5d360b |
+ addr, size);
|
|
|
5d360b |
return (uint64_t)-1;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
@@ -1172,26 +1176,18 @@ static uint64_t vfio_bar_read(void *opaque,
|
|
|
5d360b |
break;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
-#ifdef DEBUG_VFIO
|
|
|
5d360b |
- {
|
|
|
5d360b |
- VFIOPCIDevice *vdev = container_of(bar, VFIOPCIDevice, bars[bar->nr]);
|
|
|
5d360b |
-
|
|
|
5d360b |
- DPRINTF("%s(%04x:%02x:%02x.%x:BAR%d+0x%"HWADDR_PRIx
|
|
|
5d360b |
- ", %d) = 0x%"PRIx64"\n", __func__, vdev->host.domain,
|
|
|
5d360b |
- vdev->host.bus, vdev->host.slot, vdev->host.function,
|
|
|
5d360b |
- bar->nr, addr, size, data);
|
|
|
5d360b |
- }
|
|
|
5d360b |
-#endif
|
|
|
5d360b |
+ DPRINTF("%s(%s:BAR%d+0x%"HWADDR_PRIx", %d) = 0x%"PRIx64"\n", __func__,
|
|
|
5d360b |
+ vbasedev->name, region->nr, addr, size, data);
|
|
|
5d360b |
|
|
|
5d360b |
/* Same as write above */
|
|
|
5d360b |
- vfio_eoi(container_of(bar, VFIOPCIDevice, bars[bar->nr]));
|
|
|
5d360b |
+ vbasedev->ops->vfio_eoi(vbasedev);
|
|
|
5d360b |
|
|
|
5d360b |
return data;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
-static const MemoryRegionOps vfio_bar_ops = {
|
|
|
5d360b |
- .read = vfio_bar_read,
|
|
|
5d360b |
- .write = vfio_bar_write,
|
|
|
5d360b |
+static const MemoryRegionOps vfio_region_ops = {
|
|
|
5d360b |
+ .read = vfio_region_read,
|
|
|
5d360b |
+ .write = vfio_region_write,
|
|
|
5d360b |
.endianness = DEVICE_LITTLE_ENDIAN,
|
|
|
5d360b |
};
|
|
|
5d360b |
|
|
|
5d360b |
@@ -1505,8 +1501,8 @@ static uint64_t vfio_generic_window_quirk_read(void *opaque,
|
|
|
5d360b |
vdev->host.bus, vdev->host.slot, vdev->host.function,
|
|
|
5d360b |
quirk->data.bar, addr, size, data);
|
|
|
5d360b |
} else {
|
|
|
5d360b |
- data = vfio_bar_read(&vdev->bars[quirk->data.bar],
|
|
|
5d360b |
- addr + quirk->data.base_offset, size);
|
|
|
5d360b |
+ data = vfio_region_read(&vdev->bars[quirk->data.bar].region,
|
|
|
5d360b |
+ addr + quirk->data.base_offset, size);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
return data;
|
|
|
5d360b |
@@ -1556,7 +1552,7 @@ static void vfio_generic_window_quirk_write(void *opaque, hwaddr addr,
|
|
|
5d360b |
return;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
- vfio_bar_write(&vdev->bars[quirk->data.bar],
|
|
|
5d360b |
+ vfio_region_write(&vdev->bars[quirk->data.bar].region,
|
|
|
5d360b |
addr + quirk->data.base_offset, data, size);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
@@ -1590,7 +1586,8 @@ static uint64_t vfio_generic_quirk_read(void *opaque,
|
|
|
5d360b |
vdev->host.bus, vdev->host.slot, vdev->host.function,
|
|
|
5d360b |
quirk->data.bar, addr + base, size, data);
|
|
|
5d360b |
} else {
|
|
|
5d360b |
- data = vfio_bar_read(&vdev->bars[quirk->data.bar], addr + base, size);
|
|
|
5d360b |
+ data = vfio_region_read(&vdev->bars[quirk->data.bar].region,
|
|
|
5d360b |
+ addr + base, size);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
return data;
|
|
|
5d360b |
@@ -1619,7 +1616,8 @@ static void vfio_generic_quirk_write(void *opaque, hwaddr addr,
|
|
|
5d360b |
vdev->host.domain, vdev->host.bus, vdev->host.slot,
|
|
|
5d360b |
vdev->host.function, quirk->data.bar, addr + base, data, size);
|
|
|
5d360b |
} else {
|
|
|
5d360b |
- vfio_bar_write(&vdev->bars[quirk->data.bar], addr + base, data, size);
|
|
|
5d360b |
+ vfio_region_write(&vdev->bars[quirk->data.bar].region,
|
|
|
5d360b |
+ addr + base, data, size);
|
|
|
5d360b |
}
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
@@ -1672,7 +1670,7 @@ static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice *vdev)
|
|
|
5d360b |
* As long as the BAR is >= 256 bytes it will be aligned such that the
|
|
|
5d360b |
* lower byte is always zero. Filter out anything else, if it exists.
|
|
|
5d360b |
*/
|
|
|
5d360b |
- if (!vdev->bars[4].ioport || vdev->bars[4].size < 256) {
|
|
|
5d360b |
+ if (!vdev->bars[4].ioport || vdev->bars[4].region.size < 256) {
|
|
|
5d360b |
return;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
@@ -1725,7 +1723,7 @@ static void vfio_probe_ati_bar4_window_quirk(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
memory_region_init_io(&quirk->mem,
|
|
|
5d360b |
&vfio_generic_window_quirk, quirk,
|
|
|
5d360b |
"vfio-ati-bar4-window-quirk", 8);
|
|
|
5d360b |
- memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
|
|
|
5d360b |
+ memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
|
|
|
5d360b |
quirk->data.base_offset, &quirk->mem, 1);
|
|
|
5d360b |
|
|
|
5d360b |
QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
|
|
|
5d360b |
@@ -1759,7 +1757,7 @@ static void vfio_probe_ati_bar2_4000_quirk(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
memory_region_init_io(&quirk->mem, &vfio_generic_quirk, quirk,
|
|
|
5d360b |
"vfio-ati-bar2-4000-quirk",
|
|
|
5d360b |
TARGET_PAGE_ALIGN(quirk->data.address_mask + 1));
|
|
|
5d360b |
- memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
|
|
|
5d360b |
+ memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
|
|
|
5d360b |
quirk->data.address_match & TARGET_PAGE_MASK,
|
|
|
5d360b |
&quirk->mem, 1);
|
|
|
5d360b |
|
|
|
5d360b |
@@ -1878,7 +1876,7 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev)
|
|
|
5d360b |
VFIOQuirk *quirk;
|
|
|
5d360b |
|
|
|
5d360b |
if (pci_get_word(pdev->config + PCI_VENDOR_ID) != PCI_VENDOR_ID_NVIDIA ||
|
|
|
5d360b |
- !vdev->bars[1].size) {
|
|
|
5d360b |
+ !vdev->bars[1].region.size) {
|
|
|
5d360b |
return;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
@@ -1986,7 +1984,8 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
memory_region_init_io(&quirk->mem,
|
|
|
5d360b |
&vfio_nvidia_bar5_window_quirk, quirk,
|
|
|
5d360b |
"vfio-nvidia-bar5-window-quirk", 16);
|
|
|
5d360b |
- memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1);
|
|
|
5d360b |
+ memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
|
|
|
5d360b |
+ 0, &quirk->mem, 1);
|
|
|
5d360b |
|
|
|
5d360b |
QLIST_INSERT_HEAD(&vdev->bars[nr].quirks, quirk, next);
|
|
|
5d360b |
|
|
|
5d360b |
@@ -2024,7 +2023,7 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
memory_region_init_io(&quirk->mem, &vfio_generic_quirk,
|
|
|
5d360b |
quirk, "vfio-nvidia-bar0-88000-quirk",
|
|
|
5d360b |
TARGET_PAGE_ALIGN(quirk->data.address_mask + 1));
|
|
|
5d360b |
- memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
|
|
|
5d360b |
+ memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
|
|
|
5d360b |
quirk->data.address_match & TARGET_PAGE_MASK,
|
|
|
5d360b |
&quirk->mem, 1);
|
|
|
5d360b |
|
|
|
5d360b |
@@ -2050,7 +2049,8 @@ static void vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
|
|
|
5d360b |
/* Log the chipset ID */
|
|
|
5d360b |
DPRINTF("Nvidia NV%02x\n",
|
|
|
5d360b |
- (unsigned int)(vfio_bar_read(&vdev->bars[0], 0, 4) >> 20) & 0xff);
|
|
|
5d360b |
+ (unsigned int)(vfio_region_read(&vdev->bars[0].region, 0, 4) >> 20)
|
|
|
5d360b |
+ & 0xff);
|
|
|
5d360b |
|
|
|
5d360b |
quirk = g_malloc0(sizeof(*quirk));
|
|
|
5d360b |
quirk->vdev = vdev;
|
|
|
5d360b |
@@ -2062,7 +2062,7 @@ static void vfio_probe_nvidia_bar0_1800_quirk(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
memory_region_init_io(&quirk->mem, &vfio_generic_quirk, quirk,
|
|
|
5d360b |
"vfio-nvidia-bar0-1800-quirk",
|
|
|
5d360b |
TARGET_PAGE_ALIGN(quirk->data.address_mask + 1));
|
|
|
5d360b |
- memory_region_add_subregion_overlap(&vdev->bars[nr].mem,
|
|
|
5d360b |
+ memory_region_add_subregion_overlap(&vdev->bars[nr].region.mem,
|
|
|
5d360b |
quirk->data.address_match & TARGET_PAGE_MASK,
|
|
|
5d360b |
&quirk->mem, 1);
|
|
|
5d360b |
|
|
|
5d360b |
@@ -2118,7 +2118,7 @@ static void vfio_bar_quirk_teardown(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
|
|
|
5d360b |
while (!QLIST_EMPTY(&bar->quirks)) {
|
|
|
5d360b |
VFIOQuirk *quirk = QLIST_FIRST(&bar->quirks);
|
|
|
5d360b |
- memory_region_del_subregion(&bar->mem, &quirk->mem);
|
|
|
5d360b |
+ memory_region_del_subregion(&bar->region.mem, &quirk->mem);
|
|
|
5d360b |
memory_region_destroy(&quirk->mem);
|
|
|
5d360b |
QLIST_REMOVE(quirk, next);
|
|
|
5d360b |
g_free(quirk);
|
|
|
5d360b |
@@ -2495,7 +2495,7 @@ static int vfio_early_setup_msix(VFIOPCIDevice *vdev)
|
|
|
5d360b |
* specific quirk if the device is known or we have a broken configuration.
|
|
|
5d360b |
*/
|
|
|
5d360b |
if (vdev->msix->pba_offset >=
|
|
|
5d360b |
- vdev->bars[vdev->msix->pba_bar].size) {
|
|
|
5d360b |
+ vdev->bars[vdev->msix->pba_bar].region.size) {
|
|
|
5d360b |
|
|
|
5d360b |
PCIDevice *pdev = &vdev->pdev;
|
|
|
5d360b |
uint16_t vendor = pci_get_word(pdev->config + PCI_VENDOR_ID);
|
|
|
5d360b |
@@ -2524,9 +2524,9 @@ static int vfio_setup_msix(VFIOPCIDevice *vdev, int pos)
|
|
|
5d360b |
int ret;
|
|
|
5d360b |
|
|
|
5d360b |
ret = msix_init(&vdev->pdev, vdev->msix->entries,
|
|
|
5d360b |
- &vdev->bars[vdev->msix->table_bar].mem,
|
|
|
5d360b |
+ &vdev->bars[vdev->msix->table_bar].region.mem,
|
|
|
5d360b |
vdev->msix->table_bar, vdev->msix->table_offset,
|
|
|
5d360b |
- &vdev->bars[vdev->msix->pba_bar].mem,
|
|
|
5d360b |
+ &vdev->bars[vdev->msix->pba_bar].region.mem,
|
|
|
5d360b |
vdev->msix->pba_bar, vdev->msix->pba_offset, pos);
|
|
|
5d360b |
if (ret < 0) {
|
|
|
5d360b |
if (ret == -ENOTSUP) {
|
|
|
5d360b |
@@ -2544,8 +2544,9 @@ static void vfio_teardown_msi(VFIOPCIDevice *vdev)
|
|
|
5d360b |
msi_uninit(&vdev->pdev);
|
|
|
5d360b |
|
|
|
5d360b |
if (vdev->msix) {
|
|
|
5d360b |
- msix_uninit(&vdev->pdev, &vdev->bars[vdev->msix->table_bar].mem,
|
|
|
5d360b |
- &vdev->bars[vdev->msix->pba_bar].mem);
|
|
|
5d360b |
+ msix_uninit(&vdev->pdev,
|
|
|
5d360b |
+ &vdev->bars[vdev->msix->table_bar].region.mem,
|
|
|
5d360b |
+ &vdev->bars[vdev->msix->pba_bar].region.mem);
|
|
|
5d360b |
}
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
@@ -2559,11 +2560,11 @@ static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled)
|
|
|
5d360b |
for (i = 0; i < PCI_ROM_SLOT; i++) {
|
|
|
5d360b |
VFIOBAR *bar = &vdev->bars[i];
|
|
|
5d360b |
|
|
|
5d360b |
- if (!bar->size) {
|
|
|
5d360b |
+ if (!bar->region.size) {
|
|
|
5d360b |
continue;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
- memory_region_set_enabled(&bar->mmap_mem, enabled);
|
|
|
5d360b |
+ memory_region_set_enabled(&bar->region.mmap_mem, enabled);
|
|
|
5d360b |
if (vdev->msix && vdev->msix->table_bar == i) {
|
|
|
5d360b |
memory_region_set_enabled(&vdev->msix->mmap_mem, enabled);
|
|
|
5d360b |
}
|
|
|
5d360b |
@@ -2574,45 +2575,47 @@ static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
{
|
|
|
5d360b |
VFIOBAR *bar = &vdev->bars[nr];
|
|
|
5d360b |
|
|
|
5d360b |
- if (!bar->size) {
|
|
|
5d360b |
+ if (!bar->region.size) {
|
|
|
5d360b |
return;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
vfio_bar_quirk_teardown(vdev, nr);
|
|
|
5d360b |
|
|
|
5d360b |
- memory_region_del_subregion(&bar->mem, &bar->mmap_mem);
|
|
|
5d360b |
- munmap(bar->mmap, memory_region_size(&bar->mmap_mem));
|
|
|
5d360b |
- memory_region_destroy(&bar->mmap_mem);
|
|
|
5d360b |
+ memory_region_del_subregion(&bar->region.mem, &bar->region.mmap_mem);
|
|
|
5d360b |
+ munmap(bar->region.mmap, memory_region_size(&bar->region.mmap_mem));
|
|
|
5d360b |
+ memory_region_destroy(&bar->region.mmap_mem);
|
|
|
5d360b |
|
|
|
5d360b |
if (vdev->msix && vdev->msix->table_bar == nr) {
|
|
|
5d360b |
- memory_region_del_subregion(&bar->mem, &vdev->msix->mmap_mem);
|
|
|
5d360b |
+ memory_region_del_subregion(&bar->region.mem, &vdev->msix->mmap_mem);
|
|
|
5d360b |
munmap(vdev->msix->mmap, memory_region_size(&vdev->msix->mmap_mem));
|
|
|
5d360b |
memory_region_destroy(&vdev->msix->mmap_mem);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
- memory_region_destroy(&bar->mem);
|
|
|
5d360b |
+ memory_region_destroy(&bar->region.mem);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
-static int vfio_mmap_bar(VFIOPCIDevice *vdev, VFIOBAR *bar,
|
|
|
5d360b |
- MemoryRegion *mem, MemoryRegion *submem,
|
|
|
5d360b |
- void **map, size_t size, off_t offset,
|
|
|
5d360b |
- const char *name)
|
|
|
5d360b |
+static int vfio_mmap_region(Object *obj, VFIORegion *region,
|
|
|
5d360b |
+ MemoryRegion *mem, MemoryRegion *submem,
|
|
|
5d360b |
+ void **map, size_t size, off_t offset,
|
|
|
5d360b |
+ const char *name)
|
|
|
5d360b |
{
|
|
|
5d360b |
int ret = 0;
|
|
|
5d360b |
+ VFIODevice *vbasedev = region->vbasedev;
|
|
|
5d360b |
|
|
|
5d360b |
- if (VFIO_ALLOW_MMAP && size && bar->flags & VFIO_REGION_INFO_FLAG_MMAP) {
|
|
|
5d360b |
+ if (VFIO_ALLOW_MMAP && size && region->flags &
|
|
|
5d360b |
+ VFIO_REGION_INFO_FLAG_MMAP) {
|
|
|
5d360b |
int prot = 0;
|
|
|
5d360b |
|
|
|
5d360b |
- if (bar->flags & VFIO_REGION_INFO_FLAG_READ) {
|
|
|
5d360b |
+ if (region->flags & VFIO_REGION_INFO_FLAG_READ) {
|
|
|
5d360b |
prot |= PROT_READ;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
- if (bar->flags & VFIO_REGION_INFO_FLAG_WRITE) {
|
|
|
5d360b |
+ if (region->flags & VFIO_REGION_INFO_FLAG_WRITE) {
|
|
|
5d360b |
prot |= PROT_WRITE;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
*map = mmap(NULL, size, prot, MAP_SHARED,
|
|
|
5d360b |
- bar->fd, bar->fd_offset + offset);
|
|
|
5d360b |
+ vbasedev->fd, region->fd_offset + offset);
|
|
|
5d360b |
if (*map == MAP_FAILED) {
|
|
|
5d360b |
*map = NULL;
|
|
|
5d360b |
ret = -errno;
|
|
|
5d360b |
@@ -2635,7 +2638,7 @@ empty_region:
|
|
|
5d360b |
static void vfio_map_bar(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
{
|
|
|
5d360b |
VFIOBAR *bar = &vdev->bars[nr];
|
|
|
5d360b |
- uint64_t size = bar->size;
|
|
|
5d360b |
+ uint64_t size = bar->region.size;
|
|
|
5d360b |
char name[64];
|
|
|
5d360b |
uint32_t pci_bar;
|
|
|
5d360b |
uint8_t type;
|
|
|
5d360b |
@@ -2665,9 +2668,9 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
~PCI_BASE_ADDRESS_MEM_MASK);
|
|
|
5d360b |
|
|
|
5d360b |
/* A "slow" read/write mapping underlies all BARs */
|
|
|
5d360b |
- memory_region_init_io(&bar->mem, &vfio_bar_ops,
|
|
|
5d360b |
+ memory_region_init_io(&bar->region.mem, &vfio_region_ops,
|
|
|
5d360b |
bar, name, size);
|
|
|
5d360b |
- pci_register_bar(&vdev->pdev, nr, type, &bar->mem);
|
|
|
5d360b |
+ pci_register_bar(&vdev->pdev, nr, type, &bar->region.mem);
|
|
|
5d360b |
|
|
|
5d360b |
/*
|
|
|
5d360b |
* We can't mmap areas overlapping the MSIX vector table, so we
|
|
|
5d360b |
@@ -2678,8 +2681,9 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
strncat(name, " mmap", sizeof(name) - strlen(name) - 1);
|
|
|
5d360b |
- if (vfio_mmap_bar(vdev, bar, &bar->mem,
|
|
|
5d360b |
- &bar->mmap_mem, &bar->mmap, size, 0, name)) {
|
|
|
5d360b |
+ if (vfio_mmap_region(OBJECT(vdev), &bar->region, &bar->region.mem,
|
|
|
5d360b |
+ &bar->region.mmap_mem, &bar->region.mmap,
|
|
|
5d360b |
+ size, 0, name)) {
|
|
|
5d360b |
error_report("%s unsupported. Performance may be slow", name);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
@@ -2689,10 +2693,11 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr)
|
|
|
5d360b |
start = TARGET_PAGE_ALIGN((uint64_t)vdev->msix->table_offset +
|
|
|
5d360b |
(vdev->msix->entries * PCI_MSIX_ENTRY_SIZE));
|
|
|
5d360b |
|
|
|
5d360b |
- size = start < bar->size ? bar->size - start : 0;
|
|
|
5d360b |
+ size = start < bar->region.size ? bar->region.size - start : 0;
|
|
|
5d360b |
strncat(name, " msix-hi", sizeof(name) - strlen(name) - 1);
|
|
|
5d360b |
/* VFIOMSIXInfo contains another MemoryRegion for this mapping */
|
|
|
5d360b |
- if (vfio_mmap_bar(vdev, bar, &bar->mem, &vdev->msix->mmap_mem,
|
|
|
5d360b |
+ if (vfio_mmap_region(OBJECT(vdev), &bar->region, &bar->region.mem,
|
|
|
5d360b |
+ &vdev->msix->mmap_mem,
|
|
|
5d360b |
&vdev->msix->mmap, size, start, name)) {
|
|
|
5d360b |
error_report("%s unsupported. Performance may be slow", name);
|
|
|
5d360b |
}
|
|
|
5d360b |
@@ -3281,6 +3286,7 @@ static void vfio_pci_compute_needs_reset(VFIODevice *vbasedev)
|
|
|
5d360b |
static VFIODeviceOps vfio_pci_ops = {
|
|
|
5d360b |
.vfio_compute_needs_reset = vfio_pci_compute_needs_reset,
|
|
|
5d360b |
.vfio_hot_reset_multi = vfio_pci_hot_reset_multi,
|
|
|
5d360b |
+ .vfio_eoi = vfio_eoi,
|
|
|
5d360b |
};
|
|
|
5d360b |
|
|
|
5d360b |
static void vfio_reset_handler(void *opaque)
|
|
|
5d360b |
@@ -3607,11 +3613,11 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
|
|
5d360b |
(unsigned long)reg_info.size, (unsigned long)reg_info.offset,
|
|
|
5d360b |
(unsigned long)reg_info.flags);
|
|
|
5d360b |
|
|
|
5d360b |
- vdev->bars[i].flags = reg_info.flags;
|
|
|
5d360b |
- vdev->bars[i].size = reg_info.size;
|
|
|
5d360b |
- vdev->bars[i].fd_offset = reg_info.offset;
|
|
|
5d360b |
- vdev->bars[i].fd = vdev->vbasedev.fd;
|
|
|
5d360b |
- vdev->bars[i].nr = i;
|
|
|
5d360b |
+ vdev->bars[i].region.vbasedev = &vdev->vbasedev;
|
|
|
5d360b |
+ vdev->bars[i].region.flags = reg_info.flags;
|
|
|
5d360b |
+ vdev->bars[i].region.size = reg_info.size;
|
|
|
5d360b |
+ vdev->bars[i].region.fd_offset = reg_info.offset;
|
|
|
5d360b |
+ vdev->bars[i].region.nr = i;
|
|
|
5d360b |
QLIST_INIT(&vdev->bars[i].quirks);
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
--
|
|
|
5d360b |
1.8.3.1
|
|
|
5d360b |
|