|
|
5d360b |
From 474ecfa2ca12dee5c07c974a166c27652b9c9a93 Mon Sep 17 00:00:00 2001
|
|
|
5d360b |
From: Alex Williamson <alex.williamson@redhat.com>
|
|
|
5d360b |
Date: Fri, 29 Sep 2017 21:45:50 +0200
|
|
|
5d360b |
Subject: [PATCH 13/27] vfio: Wrap VFIO_DEVICE_GET_REGION_INFO
|
|
|
5d360b |
|
|
|
5d360b |
RH-Author: Alex Williamson <alex.williamson@redhat.com>
|
|
|
5d360b |
Message-id: <20170929214550.16765.34651.stgit@gimli.home>
|
|
|
5d360b |
Patchwork-id: 76771
|
|
|
5d360b |
O-Subject: [RHEL-7.5 qemu-kvm PATCH 13/16] vfio: Wrap VFIO_DEVICE_GET_REGION_INFO
|
|
|
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 |
Upstream: 469002263a295ec471c1498c3b456ccd9f85a841
|
|
|
5d360b |
|
|
|
5d360b |
In preparation for supporting capability chains on regions, wrap
|
|
|
5d360b |
ioctl(VFIO_DEVICE_GET_REGION_INFO) so we don't duplicate the code for
|
|
|
5d360b |
each caller.
|
|
|
5d360b |
|
|
|
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 | 95 +++++++++++++++++++++++++++++++++++-----------------------
|
|
|
5d360b |
1 file changed, 58 insertions(+), 37 deletions(-)
|
|
|
5d360b |
|
|
|
5d360b |
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
|
|
|
5d360b |
index e2dc3f5..57a0065 100644
|
|
|
5d360b |
--- a/hw/misc/vfio.c
|
|
|
5d360b |
+++ b/hw/misc/vfio.c
|
|
|
5d360b |
@@ -292,6 +292,8 @@ static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
|
|
|
5d360b |
static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
|
|
|
5d360b |
uint32_t val, int len);
|
|
|
5d360b |
static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
|
|
|
5d360b |
+static int vfio_get_region_info(VFIODevice *vbasedev, int index,
|
|
|
5d360b |
+ struct vfio_region_info **info);
|
|
|
5d360b |
|
|
|
5d360b |
/*
|
|
|
5d360b |
* Common VFIO interrupt disable
|
|
|
5d360b |
@@ -1176,26 +1178,26 @@ static const MemoryRegionOps vfio_region_ops = {
|
|
|
5d360b |
|
|
|
5d360b |
static void vfio_pci_load_rom(VFIOPCIDevice *vdev)
|
|
|
5d360b |
{
|
|
|
5d360b |
- struct vfio_region_info reg_info = {
|
|
|
5d360b |
- .argsz = sizeof(reg_info),
|
|
|
5d360b |
- .index = VFIO_PCI_ROM_REGION_INDEX
|
|
|
5d360b |
- };
|
|
|
5d360b |
+ struct vfio_region_info *reg_info;
|
|
|
5d360b |
uint64_t size;
|
|
|
5d360b |
off_t off = 0;
|
|
|
5d360b |
size_t bytes;
|
|
|
5d360b |
|
|
|
5d360b |
- if (ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) {
|
|
|
5d360b |
+ if (vfio_get_region_info(&vdev->vbasedev,
|
|
|
5d360b |
+ VFIO_PCI_ROM_REGION_INDEX, ®_info)) {
|
|
|
5d360b |
error_report("vfio: Error getting ROM info: %m");
|
|
|
5d360b |
return;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
DPRINTF("Device %s ROM:\n", vdev->vbasedev.name);
|
|
|
5d360b |
DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n",
|
|
|
5d360b |
- (unsigned long)reg_info.size, (unsigned long)reg_info.offset,
|
|
|
5d360b |
- (unsigned long)reg_info.flags);
|
|
|
5d360b |
+ (unsigned long)reg_info->size, (unsigned long)reg_info->offset,
|
|
|
5d360b |
+ (unsigned long)reg_info->flags);
|
|
|
5d360b |
+
|
|
|
5d360b |
+ vdev->rom_size = size = reg_info->size;
|
|
|
5d360b |
+ vdev->rom_offset = reg_info->offset;
|
|
|
5d360b |
|
|
|
5d360b |
- vdev->rom_size = size = reg_info.size;
|
|
|
5d360b |
- vdev->rom_offset = reg_info.offset;
|
|
|
5d360b |
+ g_free(reg_info);
|
|
|
5d360b |
|
|
|
5d360b |
if (!vdev->rom_size) {
|
|
|
5d360b |
vdev->rom_read_failed = true;
|
|
|
5d360b |
@@ -3483,7 +3485,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
|
|
5d360b |
VFIOPCIDevice *vdev)
|
|
|
5d360b |
{
|
|
|
5d360b |
struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) };
|
|
|
5d360b |
- struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
|
|
|
5d360b |
+ struct vfio_region_info *reg_info;
|
|
|
5d360b |
struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
|
|
|
5d360b |
int ret, i;
|
|
|
5d360b |
|
|
|
5d360b |
@@ -3529,9 +3531,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) {
|
|
|
5d360b |
- reg_info.index = i;
|
|
|
5d360b |
-
|
|
|
5d360b |
- ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
|
|
|
5d360b |
+ ret = vfio_get_region_info(&vdev->vbasedev, i, ®_info);
|
|
|
5d360b |
if (ret) {
|
|
|
5d360b |
error_report("vfio: Error getting region %d info: %m", i);
|
|
|
5d360b |
goto error;
|
|
|
5d360b |
@@ -3539,20 +3539,21 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
|
|
5d360b |
|
|
|
5d360b |
DPRINTF("Device %s region %d:\n", name, i);
|
|
|
5d360b |
DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n",
|
|
|
5d360b |
- (unsigned long)reg_info.size, (unsigned long)reg_info.offset,
|
|
|
5d360b |
- (unsigned long)reg_info.flags);
|
|
|
5d360b |
+ (unsigned long)reg_info->size, (unsigned long)reg_info->offset,
|
|
|
5d360b |
+ (unsigned long)reg_info->flags);
|
|
|
5d360b |
|
|
|
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.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 |
- reg_info.index = VFIO_PCI_CONFIG_REGION_INDEX;
|
|
|
5d360b |
+ g_free(reg_info);
|
|
|
5d360b |
+ }
|
|
|
5d360b |
|
|
|
5d360b |
- ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
|
|
|
5d360b |
+ ret = vfio_get_region_info(&vdev->vbasedev,
|
|
|
5d360b |
+ VFIO_PCI_CONFIG_REGION_INDEX, ®_info);
|
|
|
5d360b |
if (ret) {
|
|
|
5d360b |
error_report("vfio: Error getting config info: %m");
|
|
|
5d360b |
goto error;
|
|
|
5d360b |
@@ -3560,41 +3561,43 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
|
|
|
5d360b |
|
|
|
5d360b |
DPRINTF("Device %s config:\n", name);
|
|
|
5d360b |
DPRINTF(" size: 0x%lx, offset: 0x%lx, flags: 0x%lx\n",
|
|
|
5d360b |
- (unsigned long)reg_info.size, (unsigned long)reg_info.offset,
|
|
|
5d360b |
- (unsigned long)reg_info.flags);
|
|
|
5d360b |
+ (unsigned long)reg_info->size, (unsigned long)reg_info->offset,
|
|
|
5d360b |
+ (unsigned long)reg_info->flags);
|
|
|
5d360b |
|
|
|
5d360b |
- vdev->config_size = reg_info.size;
|
|
|
5d360b |
+ vdev->config_size = reg_info->size;
|
|
|
5d360b |
if (vdev->config_size == PCI_CONFIG_SPACE_SIZE) {
|
|
|
5d360b |
vdev->pdev.cap_present &= ~QEMU_PCI_CAP_EXPRESS;
|
|
|
5d360b |
}
|
|
|
5d360b |
- vdev->config_offset = reg_info.offset;
|
|
|
5d360b |
+ vdev->config_offset = reg_info->offset;
|
|
|
5d360b |
+
|
|
|
5d360b |
+ g_free(reg_info);
|
|
|
5d360b |
|
|
|
5d360b |
if ((vdev->features & VFIO_FEATURE_ENABLE_VGA) &&
|
|
|
5d360b |
dev_info.num_regions > VFIO_PCI_VGA_REGION_INDEX) {
|
|
|
5d360b |
- struct vfio_region_info vga_info = {
|
|
|
5d360b |
- .argsz = sizeof(vga_info),
|
|
|
5d360b |
- .index = VFIO_PCI_VGA_REGION_INDEX,
|
|
|
5d360b |
- };
|
|
|
5d360b |
-
|
|
|
5d360b |
- ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
|
|
|
5d360b |
+ ret = vfio_get_region_info(&vdev->vbasedev,
|
|
|
5d360b |
+ VFIO_PCI_VGA_REGION_INDEX, ®_info);
|
|
|
5d360b |
if (ret) {
|
|
|
5d360b |
error_report(
|
|
|
5d360b |
"vfio: Device does not support requested feature x-vga");
|
|
|
5d360b |
goto error;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
- if (!(vga_info.flags & VFIO_REGION_INFO_FLAG_READ) ||
|
|
|
5d360b |
- !(vga_info.flags & VFIO_REGION_INFO_FLAG_WRITE) ||
|
|
|
5d360b |
- vga_info.size < 0xbffff + 1) {
|
|
|
5d360b |
+ if (!(reg_info->flags & VFIO_REGION_INFO_FLAG_READ) ||
|
|
|
5d360b |
+ !(reg_info->flags & VFIO_REGION_INFO_FLAG_WRITE) ||
|
|
|
5d360b |
+ reg_info->size < 0xbffff + 1) {
|
|
|
5d360b |
error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx",
|
|
|
5d360b |
- (unsigned long)vga_info.flags,
|
|
|
5d360b |
- (unsigned long)vga_info.size);
|
|
|
5d360b |
+ (unsigned long)reg_info->flags,
|
|
|
5d360b |
+ (unsigned long)reg_info->size);
|
|
|
5d360b |
+ g_free(reg_info);
|
|
|
5d360b |
+ ret = -1;
|
|
|
5d360b |
goto error;
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
- vdev->vga.fd_offset = vga_info.offset;
|
|
|
5d360b |
+ vdev->vga.fd_offset = reg_info->offset;
|
|
|
5d360b |
vdev->vga.fd = vdev->vbasedev.fd;
|
|
|
5d360b |
|
|
|
5d360b |
+ g_free(reg_info);
|
|
|
5d360b |
+
|
|
|
5d360b |
vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
|
|
|
5d360b |
vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
|
|
|
5d360b |
QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_MEM].quirks);
|
|
|
5d360b |
@@ -3647,6 +3650,24 @@ static void vfio_put_device(VFIOPCIDevice *vdev)
|
|
|
5d360b |
}
|
|
|
5d360b |
}
|
|
|
5d360b |
|
|
|
5d360b |
+static int vfio_get_region_info(VFIODevice *vbasedev, int index,
|
|
|
5d360b |
+ struct vfio_region_info **info)
|
|
|
5d360b |
+{
|
|
|
5d360b |
+ size_t argsz = sizeof(struct vfio_region_info);
|
|
|
5d360b |
+
|
|
|
5d360b |
+ *info = g_malloc0(argsz);
|
|
|
5d360b |
+
|
|
|
5d360b |
+ (*info)->index = index;
|
|
|
5d360b |
+ (*info)->argsz = argsz;
|
|
|
5d360b |
+
|
|
|
5d360b |
+ if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) {
|
|
|
5d360b |
+ g_free(*info);
|
|
|
5d360b |
+ return -errno;
|
|
|
5d360b |
+ }
|
|
|
5d360b |
+
|
|
|
5d360b |
+ return 0;
|
|
|
5d360b |
+}
|
|
|
5d360b |
+
|
|
|
5d360b |
static void vfio_err_notifier_handler(void *opaque)
|
|
|
5d360b |
{
|
|
|
5d360b |
VFIOPCIDevice *vdev = opaque;
|
|
|
5d360b |
--
|
|
|
5d360b |
1.8.3.1
|
|
|
5d360b |
|