mirror of https://github.com/xqemu/xqemu.git
vfio: Wrap VFIO_DEVICE_GET_REGION_INFO
In preparation for supporting capability chains on regions, wrap ioctl(VFIO_DEVICE_GET_REGION_INFO) so we don't duplicate the code for each caller. Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
7df9381b7a
commit
469002263a
|
@ -959,6 +959,24 @@ void vfio_put_base_device(VFIODevice *vbasedev)
|
||||||
close(vbasedev->fd);
|
close(vbasedev->fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vfio_get_region_info(VFIODevice *vbasedev, int index,
|
||||||
|
struct vfio_region_info **info)
|
||||||
|
{
|
||||||
|
size_t argsz = sizeof(struct vfio_region_info);
|
||||||
|
|
||||||
|
*info = g_malloc0(argsz);
|
||||||
|
|
||||||
|
(*info)->index = index;
|
||||||
|
(*info)->argsz = argsz;
|
||||||
|
|
||||||
|
if (ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, *info)) {
|
||||||
|
g_free(*info);
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int vfio_container_do_ioctl(AddressSpace *as, int32_t groupid,
|
static int vfio_container_do_ioctl(AddressSpace *as, int32_t groupid,
|
||||||
int req, void *param)
|
int req, void *param)
|
||||||
{
|
{
|
||||||
|
|
|
@ -783,25 +783,25 @@ static void vfio_update_msi(VFIOPCIDevice *vdev)
|
||||||
|
|
||||||
static void vfio_pci_load_rom(VFIOPCIDevice *vdev)
|
static void vfio_pci_load_rom(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
struct vfio_region_info reg_info = {
|
struct vfio_region_info *reg_info;
|
||||||
.argsz = sizeof(reg_info),
|
|
||||||
.index = VFIO_PCI_ROM_REGION_INDEX
|
|
||||||
};
|
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
off_t off = 0;
|
off_t off = 0;
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
|
|
||||||
if (ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info)) {
|
if (vfio_get_region_info(&vdev->vbasedev,
|
||||||
|
VFIO_PCI_ROM_REGION_INDEX, ®_info)) {
|
||||||
error_report("vfio: Error getting ROM info: %m");
|
error_report("vfio: Error getting ROM info: %m");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_vfio_pci_load_rom(vdev->vbasedev.name, (unsigned long)reg_info.size,
|
trace_vfio_pci_load_rom(vdev->vbasedev.name, (unsigned long)reg_info->size,
|
||||||
(unsigned long)reg_info.offset,
|
(unsigned long)reg_info->offset,
|
||||||
(unsigned long)reg_info.flags);
|
(unsigned long)reg_info->flags);
|
||||||
|
|
||||||
vdev->rom_size = size = reg_info.size;
|
vdev->rom_size = size = reg_info->size;
|
||||||
vdev->rom_offset = reg_info.offset;
|
vdev->rom_offset = reg_info->offset;
|
||||||
|
|
||||||
|
g_free(reg_info);
|
||||||
|
|
||||||
if (!vdev->rom_size) {
|
if (!vdev->rom_size) {
|
||||||
vdev->rom_read_failed = true;
|
vdev->rom_read_failed = true;
|
||||||
|
@ -2027,7 +2027,7 @@ static VFIODeviceOps vfio_pci_ops = {
|
||||||
static int vfio_populate_device(VFIOPCIDevice *vdev)
|
static int vfio_populate_device(VFIOPCIDevice *vdev)
|
||||||
{
|
{
|
||||||
VFIODevice *vbasedev = &vdev->vbasedev;
|
VFIODevice *vbasedev = &vdev->vbasedev;
|
||||||
struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
|
struct vfio_region_info *reg_info;
|
||||||
struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
|
struct vfio_irq_info irq_info = { .argsz = sizeof(irq_info) };
|
||||||
int i, ret = -1;
|
int i, ret = -1;
|
||||||
|
|
||||||
|
@ -2049,72 +2049,73 @@ static int vfio_populate_device(VFIOPCIDevice *vdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) {
|
for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) {
|
||||||
reg_info.index = i;
|
ret = vfio_get_region_info(vbasedev, i, ®_info);
|
||||||
|
|
||||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_report("vfio: Error getting region %d info: %m", i);
|
error_report("vfio: Error getting region %d info: %m", i);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_vfio_populate_device_region(vbasedev->name, i,
|
trace_vfio_populate_device_region(vbasedev->name, i,
|
||||||
(unsigned long)reg_info.size,
|
(unsigned long)reg_info->size,
|
||||||
(unsigned long)reg_info.offset,
|
(unsigned long)reg_info->offset,
|
||||||
(unsigned long)reg_info.flags);
|
(unsigned long)reg_info->flags);
|
||||||
|
|
||||||
vdev->bars[i].region.vbasedev = vbasedev;
|
vdev->bars[i].region.vbasedev = vbasedev;
|
||||||
vdev->bars[i].region.flags = reg_info.flags;
|
vdev->bars[i].region.flags = reg_info->flags;
|
||||||
vdev->bars[i].region.size = reg_info.size;
|
vdev->bars[i].region.size = reg_info->size;
|
||||||
vdev->bars[i].region.fd_offset = reg_info.offset;
|
vdev->bars[i].region.fd_offset = reg_info->offset;
|
||||||
vdev->bars[i].region.nr = i;
|
vdev->bars[i].region.nr = i;
|
||||||
QLIST_INIT(&vdev->bars[i].quirks);
|
QLIST_INIT(&vdev->bars[i].quirks);
|
||||||
|
|
||||||
|
g_free(reg_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
reg_info.index = VFIO_PCI_CONFIG_REGION_INDEX;
|
ret = vfio_get_region_info(vbasedev,
|
||||||
|
VFIO_PCI_CONFIG_REGION_INDEX, ®_info);
|
||||||
ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_report("vfio: Error getting config info: %m");
|
error_report("vfio: Error getting config info: %m");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_vfio_populate_device_config(vdev->vbasedev.name,
|
trace_vfio_populate_device_config(vdev->vbasedev.name,
|
||||||
(unsigned long)reg_info.size,
|
(unsigned long)reg_info->size,
|
||||||
(unsigned long)reg_info.offset,
|
(unsigned long)reg_info->offset,
|
||||||
(unsigned long)reg_info.flags);
|
(unsigned long)reg_info->flags);
|
||||||
|
|
||||||
vdev->config_size = reg_info.size;
|
vdev->config_size = reg_info->size;
|
||||||
if (vdev->config_size == PCI_CONFIG_SPACE_SIZE) {
|
if (vdev->config_size == PCI_CONFIG_SPACE_SIZE) {
|
||||||
vdev->pdev.cap_present &= ~QEMU_PCI_CAP_EXPRESS;
|
vdev->pdev.cap_present &= ~QEMU_PCI_CAP_EXPRESS;
|
||||||
}
|
}
|
||||||
vdev->config_offset = reg_info.offset;
|
vdev->config_offset = reg_info->offset;
|
||||||
|
|
||||||
|
g_free(reg_info);
|
||||||
|
|
||||||
if ((vdev->features & VFIO_FEATURE_ENABLE_VGA) &&
|
if ((vdev->features & VFIO_FEATURE_ENABLE_VGA) &&
|
||||||
vbasedev->num_regions > VFIO_PCI_VGA_REGION_INDEX) {
|
vbasedev->num_regions > VFIO_PCI_VGA_REGION_INDEX) {
|
||||||
struct vfio_region_info vga_info = {
|
ret = vfio_get_region_info(vbasedev,
|
||||||
.argsz = sizeof(vga_info),
|
VFIO_PCI_VGA_REGION_INDEX, ®_info);
|
||||||
.index = VFIO_PCI_VGA_REGION_INDEX,
|
|
||||||
};
|
|
||||||
|
|
||||||
ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_report(
|
error_report(
|
||||||
"vfio: Device does not support requested feature x-vga");
|
"vfio: Device does not support requested feature x-vga");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(vga_info.flags & VFIO_REGION_INFO_FLAG_READ) ||
|
if (!(reg_info->flags & VFIO_REGION_INFO_FLAG_READ) ||
|
||||||
!(vga_info.flags & VFIO_REGION_INFO_FLAG_WRITE) ||
|
!(reg_info->flags & VFIO_REGION_INFO_FLAG_WRITE) ||
|
||||||
vga_info.size < 0xbffff + 1) {
|
reg_info->size < 0xbffff + 1) {
|
||||||
error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx",
|
error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx",
|
||||||
(unsigned long)vga_info.flags,
|
(unsigned long)reg_info->flags,
|
||||||
(unsigned long)vga_info.size);
|
(unsigned long)reg_info->size);
|
||||||
|
g_free(reg_info);
|
||||||
|
ret = -1;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
vdev->vga.fd_offset = vga_info.offset;
|
vdev->vga.fd_offset = reg_info->offset;
|
||||||
vdev->vga.fd = vdev->vbasedev.fd;
|
vdev->vga.fd = vdev->vbasedev.fd;
|
||||||
|
|
||||||
|
g_free(reg_info);
|
||||||
|
|
||||||
vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
|
vdev->vga.region[QEMU_PCI_VGA_MEM].offset = QEMU_PCI_VGA_MEM_BASE;
|
||||||
vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
|
vdev->vga.region[QEMU_PCI_VGA_MEM].nr = QEMU_PCI_VGA_MEM;
|
||||||
QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_MEM].quirks);
|
QLIST_INIT(&vdev->vga.region[QEMU_PCI_VGA_MEM].quirks);
|
||||||
|
|
|
@ -476,23 +476,24 @@ static int vfio_populate_device(VFIODevice *vbasedev)
|
||||||
vdev->regions = g_new0(VFIORegion *, vbasedev->num_regions);
|
vdev->regions = g_new0(VFIORegion *, vbasedev->num_regions);
|
||||||
|
|
||||||
for (i = 0; i < vbasedev->num_regions; i++) {
|
for (i = 0; i < vbasedev->num_regions; i++) {
|
||||||
struct vfio_region_info reg_info = { .argsz = sizeof(reg_info) };
|
struct vfio_region_info *reg_info;
|
||||||
VFIORegion *ptr;
|
VFIORegion *ptr;
|
||||||
|
|
||||||
vdev->regions[i] = g_new0(VFIORegion, 1);
|
vdev->regions[i] = g_new0(VFIORegion, 1);
|
||||||
ptr = vdev->regions[i];
|
ptr = vdev->regions[i];
|
||||||
reg_info.index = i;
|
ret = vfio_get_region_info(vbasedev, i, ®_info);
|
||||||
ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_REGION_INFO, ®_info);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
error_report("vfio: Error getting region %d info: %m", i);
|
error_report("vfio: Error getting region %d info: %m", i);
|
||||||
goto reg_error;
|
goto reg_error;
|
||||||
}
|
}
|
||||||
ptr->flags = reg_info.flags;
|
ptr->flags = reg_info->flags;
|
||||||
ptr->size = reg_info.size;
|
ptr->size = reg_info->size;
|
||||||
ptr->fd_offset = reg_info.offset;
|
ptr->fd_offset = reg_info->offset;
|
||||||
ptr->nr = i;
|
ptr->nr = i;
|
||||||
ptr->vbasedev = vbasedev;
|
ptr->vbasedev = vbasedev;
|
||||||
|
|
||||||
|
g_free(reg_info);
|
||||||
|
|
||||||
trace_vfio_platform_populate_regions(ptr->nr,
|
trace_vfio_platform_populate_regions(ptr->nr,
|
||||||
(unsigned long)ptr->flags,
|
(unsigned long)ptr->flags,
|
||||||
(unsigned long)ptr->size,
|
(unsigned long)ptr->size,
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#include "exec/memory.h"
|
#include "exec/memory.h"
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "qemu/notify.h"
|
#include "qemu/notify.h"
|
||||||
|
#ifdef CONFIG_LINUX
|
||||||
|
#include <linux/vfio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/*#define DEBUG_VFIO*/
|
/*#define DEBUG_VFIO*/
|
||||||
#ifdef DEBUG_VFIO
|
#ifdef DEBUG_VFIO
|
||||||
|
@ -139,4 +142,8 @@ extern const MemoryRegionOps vfio_region_ops;
|
||||||
extern QLIST_HEAD(vfio_group_head, VFIOGroup) vfio_group_list;
|
extern QLIST_HEAD(vfio_group_head, VFIOGroup) vfio_group_list;
|
||||||
extern QLIST_HEAD(vfio_as_head, VFIOAddressSpace) vfio_address_spaces;
|
extern QLIST_HEAD(vfio_as_head, VFIOAddressSpace) vfio_address_spaces;
|
||||||
|
|
||||||
|
#ifdef CONFIG_LINUX
|
||||||
|
int vfio_get_region_info(VFIODevice *vbasedev, int index,
|
||||||
|
struct vfio_region_info **info);
|
||||||
|
#endif
|
||||||
#endif /* !HW_VFIO_VFIO_COMMON_H */
|
#endif /* !HW_VFIO_VFIO_COMMON_H */
|
||||||
|
|
Loading…
Reference in New Issue