summaryrefslogtreecommitdiffstats
path: root/hw/vfio
diff options
context:
space:
mode:
Diffstat (limited to 'hw/vfio')
-rw-r--r--hw/vfio/pci.c117
1 files changed, 63 insertions, 54 deletions
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 7083151..22d0c85 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -185,9 +185,13 @@ typedef struct VFIOMSIXInfo {
void *mmap;
} VFIOMSIXInfo;
+typedef struct VFIODevice {
+ int fd;
+} VFIODevice;
+
typedef struct VFIOPCIDevice {
PCIDevice pdev;
- int fd;
+ VFIODevice vbasedev;
VFIOINTx intx;
unsigned int config_size;
uint8_t *emulated_config_bits; /* QEMU emulated bits, little-endian */
@@ -277,7 +281,7 @@ static void vfio_mmap_set_enabled(VFIOPCIDevice *vdev, bool enabled);
/*
* Common VFIO interrupt disable
*/
-static void vfio_disable_irqindex(VFIOPCIDevice *vdev, int index)
+static void vfio_disable_irqindex(VFIODevice *vbasedev, int index)
{
struct vfio_irq_set irq_set = {
.argsz = sizeof(irq_set),
@@ -287,13 +291,13 @@ static void vfio_disable_irqindex(VFIOPCIDevice *vdev, int index)
.count = 0,
};
- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
+ ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
}
/*
* INTx
*/
-static void vfio_unmask_single_irqindex(VFIOPCIDevice *vdev, int index)
+static void vfio_unmask_single_irqindex(VFIODevice *vbasedev, int index)
{
struct vfio_irq_set irq_set = {
.argsz = sizeof(irq_set),
@@ -303,11 +307,11 @@ static void vfio_unmask_single_irqindex(VFIOPCIDevice *vdev, int index)
.count = 1,
};
- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
+ ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
}
#ifdef CONFIG_KVM /* Unused outside of CONFIG_KVM code */
-static void vfio_mask_single_irqindex(VFIOPCIDevice *vdev, int index)
+static void vfio_mask_single_irqindex(VFIODevice *vbasedev, int index)
{
struct vfio_irq_set irq_set = {
.argsz = sizeof(irq_set),
@@ -317,7 +321,7 @@ static void vfio_mask_single_irqindex(VFIOPCIDevice *vdev, int index)
.count = 1,
};
- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
+ ioctl(vbasedev->fd, VFIO_DEVICE_SET_IRQS, &irq_set);
}
#endif
@@ -381,7 +385,7 @@ static void vfio_eoi(VFIOPCIDevice *vdev)
vdev->intx.pending = false;
pci_irq_deassert(&vdev->pdev);
- vfio_unmask_single_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
+ vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
}
static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
@@ -404,7 +408,7 @@ static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
/* Get to a known interrupt state */
qemu_set_fd_handler(irqfd.fd, NULL, NULL, vdev);
- vfio_mask_single_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
+ vfio_mask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
pci_irq_deassert(&vdev->pdev);
@@ -434,7 +438,7 @@ static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
*pfd = irqfd.resamplefd;
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
g_free(irq_set);
if (ret) {
error_report("vfio: Error: Failed to setup INTx unmask fd: %m");
@@ -442,7 +446,7 @@ static void vfio_enable_intx_kvm(VFIOPCIDevice *vdev)
}
/* Let'em rip */
- vfio_unmask_single_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
+ vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.kvm_accel = true;
@@ -458,7 +462,7 @@ fail_irqfd:
event_notifier_cleanup(&vdev->intx.unmask);
fail:
qemu_set_fd_handler(irqfd.fd, vfio_intx_interrupt, NULL, vdev);
- vfio_unmask_single_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
+ vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
#endif
}
@@ -479,7 +483,7 @@ static void vfio_disable_intx_kvm(VFIOPCIDevice *vdev)
* Get to a known state, hardware masked, QEMU ready to accept new
* interrupts, QEMU IRQ de-asserted.
*/
- vfio_mask_single_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
+ vfio_mask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
pci_irq_deassert(&vdev->pdev);
@@ -497,7 +501,7 @@ static void vfio_disable_intx_kvm(VFIOPCIDevice *vdev)
vdev->intx.kvm_accel = false;
/* If we've missed an event, let it re-fire through QEMU */
- vfio_unmask_single_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
+ vfio_unmask_single_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
trace_vfio_disable_intx_kvm(vdev->host.domain, vdev->host.bus,
vdev->host.slot, vdev->host.function);
@@ -583,7 +587,7 @@ static int vfio_enable_intx(VFIOPCIDevice *vdev)
*pfd = event_notifier_get_fd(&vdev->intx.interrupt);
qemu_set_fd_handler(*pfd, vfio_intx_interrupt, NULL, vdev);
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
g_free(irq_set);
if (ret) {
error_report("vfio: Error: Failed to setup INTx fd: %m");
@@ -608,7 +612,7 @@ static void vfio_disable_intx(VFIOPCIDevice *vdev)
timer_del(vdev->intx.mmap_timer);
vfio_disable_intx_kvm(vdev);
- vfio_disable_irqindex(vdev, VFIO_PCI_INTX_IRQ_INDEX);
+ vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
pci_irq_deassert(&vdev->pdev);
vfio_mmap_set_enabled(vdev, true);
@@ -698,7 +702,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
fds[i] = fd;
}
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
g_free(irq_set);
@@ -795,7 +799,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
* increase them as needed.
*/
if (vdev->nr_vectors < nr + 1) {
- vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX);
+ vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
vdev->nr_vectors = nr + 1;
ret = vfio_enable_vectors(vdev, true);
if (ret) {
@@ -823,7 +827,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
*pfd = event_notifier_get_fd(&vector->interrupt);
}
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
g_free(irq_set);
if (ret) {
error_report("vfio: failed to modify vector, %d", ret);
@@ -874,7 +878,7 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
*pfd = event_notifier_get_fd(&vector->interrupt);
- ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
g_free(irq_set);
}
@@ -1033,7 +1037,7 @@ static void vfio_disable_msix(VFIOPCIDevice *vdev)
}
if (vdev->nr_vectors) {
- vfio_disable_irqindex(vdev, VFIO_PCI_MSIX_IRQ_INDEX);
+ vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSIX_IRQ_INDEX);
}
vfio_disable_msi_common(vdev);
@@ -1044,7 +1048,7 @@ static void vfio_disable_msix(VFIOPCIDevice *vdev)
static void vfio_disable_msi(VFIOPCIDevice *vdev)
{
- vfio_disable_irqindex(vdev, VFIO_PCI_MSI_IRQ_INDEX);
+ vfio_disable_irqindex(&vdev->vbasedev, VFIO_PCI_MSI_IRQ_INDEX);
vfio_disable_msi_common(vdev);
trace_vfio_disable_msi(vdev->host.domain, vdev->host.bus,
@@ -1188,7 +1192,7 @@ static void vfio_pci_load_rom(VFIOPCIDevice *vdev)
off_t off = 0;
size_t bytes;
- if (ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info)) {
+ if (ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info)) {
error_report("vfio: Error getting ROM info: %m");
return;
}
@@ -1218,7 +1222,8 @@ static void vfio_pci_load_rom(VFIOPCIDevice *vdev)
memset(vdev->rom, 0xff, size);
while (size) {
- bytes = pread(vdev->fd, vdev->rom + off, size, vdev->rom_offset + off);
+ bytes = pread(vdev->vbasedev.fd, vdev->rom + off,
+ size, vdev->rom_offset + off);
if (bytes == 0) {
break;
} else if (bytes > 0) {
@@ -1312,6 +1317,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
off_t offset = vdev->config_offset + PCI_ROM_ADDRESS;
DeviceState *dev = DEVICE(vdev);
char name[32];
+ int fd = vdev->vbasedev.fd;
if (vdev->pdev.romfile || !vdev->pdev.rom_bar) {
/* Since pci handles romfile, just print a message and return */
@@ -1330,10 +1336,10 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
* Use the same size ROM BAR as the physical device. The contents
* will get filled in later when the guest tries to read it.
*/
- if (pread(vdev->fd, &orig, 4, offset) != 4 ||
- pwrite(vdev->fd, &size, 4, offset) != 4 ||
- pread(vdev->fd, &size, 4, offset) != 4 ||
- pwrite(vdev->fd, &orig, 4, offset) != 4) {
+ if (pread(fd, &orig, 4, offset) != 4 ||
+ pwrite(fd, &size, 4, offset) != 4 ||
+ pread(fd, &size, 4, offset) != 4 ||
+ pwrite(fd, &orig, 4, offset) != 4) {
error_report("%s(%04x:%02x:%02x.%x) failed: %m",
__func__, vdev->host.domain, vdev->host.bus,
vdev->host.slot, vdev->host.function);
@@ -2345,7 +2351,8 @@ static uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len)
if (~emu_bits & (0xffffffffU >> (32 - len * 8))) {
ssize_t ret;
- ret = pread(vdev->fd, &phys_val, len, vdev->config_offset + addr);
+ ret = pread(vdev->vbasedev.fd, &phys_val, len,
+ vdev->config_offset + addr);
if (ret != len) {
error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x) failed: %m",
__func__, vdev->host.domain, vdev->host.bus,
@@ -2375,7 +2382,8 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr,
addr, val, len);
/* Write everything to VFIO, let it filter out what we can't write */
- if (pwrite(vdev->fd, &val_le, len, vdev->config_offset + addr) != len) {
+ if (pwrite(vdev->vbasedev.fd, &val_le, len, vdev->config_offset + addr)
+ != len) {
error_report("%s(%04x:%02x:%02x.%x, 0x%x, 0x%x, 0x%x) failed: %m",
__func__, vdev->host.domain, vdev->host.bus,
vdev->host.slot, vdev->host.function, addr, val, len);
@@ -2743,7 +2751,7 @@ static int vfio_setup_msi(VFIOPCIDevice *vdev, int pos)
bool msi_64bit, msi_maskbit;
int ret, entries;
- if (pread(vdev->fd, &ctrl, sizeof(ctrl),
+ if (pread(vdev->vbasedev.fd, &ctrl, sizeof(ctrl),
vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) {
return -errno;
}
@@ -2782,23 +2790,24 @@ static int vfio_early_setup_msix(VFIOPCIDevice *vdev)
uint8_t pos;
uint16_t ctrl;
uint32_t table, pba;
+ int fd = vdev->vbasedev.fd;
pos = pci_find_capability(&vdev->pdev, PCI_CAP_ID_MSIX);
if (!pos) {
return 0;
}
- if (pread(vdev->fd, &ctrl, sizeof(ctrl),
+ if (pread(fd, &ctrl, sizeof(ctrl),
vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) {
return -errno;
}
- if (pread(vdev->fd, &table, sizeof(table),
+ if (pread(fd, &table, sizeof(table),
vdev->config_offset + pos + PCI_MSIX_TABLE) != sizeof(table)) {
return -errno;
}
- if (pread(vdev->fd, &pba, sizeof(pba),
+ if (pread(fd, &pba, sizeof(pba),
vdev->config_offset + pos + PCI_MSIX_PBA) != sizeof(pba)) {
return -errno;
}
@@ -2951,7 +2960,7 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr)
vdev->host.function, nr);
/* Determine what type of BAR this is for registration */
- ret = pread(vdev->fd, &pci_bar, sizeof(pci_bar),
+ ret = pread(vdev->vbasedev.fd, &pci_bar, sizeof(pci_bar),
vdev->config_offset + PCI_BASE_ADDRESS_0 + (4 * nr));
if (ret != sizeof(pci_bar)) {
error_report("vfio: Failed to read BAR %d (%m)", nr);
@@ -3371,7 +3380,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
info = g_malloc0(sizeof(*info));
info->argsz = sizeof(*info);
- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
if (ret && errno != ENOSPC) {
ret = -errno;
if (!vdev->has_pm_reset) {
@@ -3387,7 +3396,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
info->argsz = sizeof(*info) + (count * sizeof(*devices));
devices = &info->devices[0];
- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_PCI_HOT_RESET_INFO, info);
if (ret) {
ret = -errno;
error_report("vfio: hot reset info failed: %m");
@@ -3483,7 +3492,7 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
}
/* Bus reset! */
- ret = ioctl(vdev->fd, VFIO_DEVICE_PCI_HOT_RESET, reset);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_PCI_HOT_RESET, reset);
g_free(reset);
trace_vfio_pci_hot_reset_result(vdev->host.domain,
@@ -3914,12 +3923,12 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
return ret;
}
- vdev->fd = ret;
+ vdev->vbasedev.fd = ret;
vdev->group = group;
QLIST_INSERT_HEAD(&group->device_list, vdev, next);
/* Sanity check device */
- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_INFO, &dev_info);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_INFO, &dev_info);
if (ret) {
error_report("vfio: error getting device info: %m");
goto error;
@@ -3949,7 +3958,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) {
reg_info.index = i;
- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
if (ret) {
error_report("vfio: Error getting region %d info: %m", i);
goto error;
@@ -3963,14 +3972,14 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
vdev->bars[i].flags = reg_info.flags;
vdev->bars[i].size = reg_info.size;
vdev->bars[i].fd_offset = reg_info.offset;
- vdev->bars[i].fd = vdev->fd;
+ vdev->bars[i].fd = vdev->vbasedev.fd;
vdev->bars[i].nr = i;
QLIST_INIT(&vdev->bars[i].quirks);
}
reg_info.index = VFIO_PCI_CONFIG_REGION_INDEX;
- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, &reg_info);
if (ret) {
error_report("vfio: Error getting config info: %m");
goto error;
@@ -3993,7 +4002,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
.index = VFIO_PCI_VGA_REGION_INDEX,
};
- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_REGION_INFO, &vga_info);
if (ret) {
error_report(
"vfio: Device does not support requested feature x-vga");
@@ -4010,7 +4019,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
}
vdev->vga.fd_offset = vga_info.offset;
- vdev->vga.fd = vdev->fd;
+ vdev->vga.fd = vdev->vbasedev.fd;
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;
@@ -4028,7 +4037,7 @@ static int vfio_get_device(VFIOGroup *group, const char *name,
}
irq_info.index = VFIO_PCI_ERR_IRQ_INDEX;
- ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info);
if (ret) {
/* This can fail for an old kernel or legacy PCI dev */
trace_vfio_get_device_get_irq_info_failure();
@@ -4046,7 +4055,7 @@ error:
if (ret) {
QLIST_REMOVE(vdev, next);
vdev->group = NULL;
- close(vdev->fd);
+ close(vdev->vbasedev.fd);
}
return ret;
}
@@ -4055,8 +4064,8 @@ static void vfio_put_device(VFIOPCIDevice *vdev)
{
QLIST_REMOVE(vdev, next);
vdev->group = NULL;
- trace_vfio_put_device(vdev->fd);
- close(vdev->fd);
+ trace_vfio_put_device(vdev->vbasedev.fd);
+ close(vdev->vbasedev.fd);
if (vdev->msix) {
g_free(vdev->msix);
vdev->msix = NULL;
@@ -4125,7 +4134,7 @@ static void vfio_register_err_notifier(VFIOPCIDevice *vdev)
*pfd = event_notifier_get_fd(&vdev->err_notifier);
qemu_set_fd_handler(*pfd, vfio_err_notifier_handler, NULL, vdev);
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
if (ret) {
error_report("vfio: Failed to set up error notification");
qemu_set_fd_handler(*pfd, NULL, NULL, vdev);
@@ -4158,7 +4167,7 @@ static void vfio_unregister_err_notifier(VFIOPCIDevice *vdev)
pfd = (int32_t *)&irq_set->data;
*pfd = -1;
- ret = ioctl(vdev->fd, VFIO_DEVICE_SET_IRQS, irq_set);
+ ret = ioctl(vdev->vbasedev.fd, VFIO_DEVICE_SET_IRQS, irq_set);
if (ret) {
error_report("vfio: Failed to de-assign error fd: %m");
}
@@ -4237,7 +4246,7 @@ static int vfio_initfn(PCIDevice *pdev)
}
/* Get a copy of config space */
- ret = pread(vdev->fd, vdev->pdev.config,
+ ret = pread(vdev->vbasedev.fd, vdev->pdev.config,
MIN(pci_config_size(&vdev->pdev), vdev->config_size),
vdev->config_offset);
if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) {
@@ -4351,7 +4360,7 @@ static void vfio_pci_reset(DeviceState *dev)
vfio_pci_pre_reset(vdev);
if (vdev->reset_works && (vdev->has_flr || !vdev->has_pm_reset) &&
- !ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
+ !ioctl(vdev->vbasedev.fd, VFIO_DEVICE_RESET)) {
trace_vfio_pci_reset_flr(vdev->host.domain, vdev->host.bus,
vdev->host.slot, vdev->host.function);
goto post_reset;
@@ -4364,7 +4373,7 @@ static void vfio_pci_reset(DeviceState *dev)
/* If nothing else works and the device supports PM reset, use it */
if (vdev->reset_works && vdev->has_pm_reset &&
- !ioctl(vdev->fd, VFIO_DEVICE_RESET)) {
+ !ioctl(vdev->vbasedev.fd, VFIO_DEVICE_RESET)) {
trace_vfio_pci_reset_pm(vdev->host.domain, vdev->host.bus,
vdev->host.slot, vdev->host.function);
goto post_reset;
OpenPOWER on IntegriCloud