diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-10-18 11:40:27 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-10-18 11:40:27 +0100 |
commit | 1b0d3845b454eaaac0b2064c78926ca4d739a080 (patch) | |
tree | e5a4399f69877093db4fa5a28ea8972496fb745c /hw | |
parent | f525c8a6cb9e445ceef6e73aeccab553866b2f36 (diff) | |
parent | 893bfc3cc893ed36cedc364e99cf483e9b08c294 (diff) |
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-updates-20161017.0' into staging
VFIO updates 2016-10-17
- Convert to realize & improve error reporting (Eric Auger)
- RTL quirk bug fix (Thorsten Kohfeldt)
- Skip duplicate pre/post reset (Cao jin)
# gpg: Signature made Mon 17 Oct 2016 20:42:44 BST
# gpg: using RSA key 0x239B9B6E3BB08B22
# gpg: Good signature from "Alex Williamson <alex.williamson@redhat.com>"
# gpg: aka "Alex Williamson <alex@shazbot.org>"
# gpg: aka "Alex Williamson <alwillia@redhat.com>"
# gpg: aka "Alex Williamson <alex.l.williamson@gmail.com>"
# Primary key fingerprint: 42F6 C04E 540B D1A9 9E7B 8A90 239B 9B6E 3BB0 8B22
* remotes/awilliam/tags/vfio-updates-20161017.0:
vfio: fix duplicate function call
vfio/pci: Fix vfio_rtl8168_quirk_data_read address offset
vfio/pci: Handle host oversight
vfio/pci: Remove vfio_populate_device returned value
vfio/pci: Remove vfio_msix_early_setup returned value
vfio/pci: Conversion to realize
vfio/platform: Pass an error object to vfio_base_device_init
vfio/platform: fix a wrong returned value in vfio_populate_device
vfio/platform: Pass an error object to vfio_populate_device
vfio: Pass an error object to vfio_get_device
vfio: Pass an error object to vfio_get_group
vfio: Pass an Error object to vfio_connect_container
vfio/pci: Pass an error object to vfio_pci_igd_opregion_init
vfio/pci: Pass an error object to vfio_add_capabilities
vfio/pci: Pass an error object to vfio_intx_enable
vfio/pci: Pass an error object to vfio_msix_early_setup
vfio/pci: Pass an error object to vfio_populate_device
vfio/pci: Pass an error object to vfio_populate_vga
vfio/pci: Use local error object in vfio_initfn
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/vfio/common.c | 69 | ||||
-rw-r--r-- | hw/vfio/pci-quirks.c | 16 | ||||
-rw-r--r-- | hw/vfio/pci.c | 279 | ||||
-rw-r--r-- | hw/vfio/pci.h | 5 | ||||
-rw-r--r-- | hw/vfio/platform.c | 66 | ||||
-rw-r--r-- | hw/vfio/trace-events | 2 |
6 files changed, 248 insertions, 189 deletions
diff --git a/hw/vfio/common.c b/hw/vfio/common.c index 29188a12fc..9505fb3040 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -34,6 +34,7 @@ #include "qemu/range.h" #include "sysemu/kvm.h" #include "trace.h" +#include "qapi/error.h" struct vfio_group_head vfio_group_list = QLIST_HEAD_INITIALIZER(vfio_group_list); @@ -900,7 +901,8 @@ static void vfio_put_address_space(VFIOAddressSpace *space) } } -static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) +static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, + Error **errp) { VFIOContainer *container; int ret, fd; @@ -918,15 +920,15 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) fd = qemu_open("/dev/vfio/vfio", O_RDWR); if (fd < 0) { - error_report("vfio: failed to open /dev/vfio/vfio: %m"); + error_setg_errno(errp, errno, "failed to open /dev/vfio/vfio"); ret = -errno; goto put_space_exit; } ret = ioctl(fd, VFIO_GET_API_VERSION); if (ret != VFIO_API_VERSION) { - error_report("vfio: supported vfio version: %d, " - "reported version: %d", VFIO_API_VERSION, ret); + error_setg(errp, "supported vfio version: %d, " + "reported version: %d", VFIO_API_VERSION, ret); ret = -EINVAL; goto close_fd_exit; } @@ -941,7 +943,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); if (ret) { - error_report("vfio: failed to set group container: %m"); + error_setg_errno(errp, errno, "failed to set group container"); ret = -errno; goto free_container_exit; } @@ -949,7 +951,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) container->iommu_type = v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU; ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type); if (ret) { - error_report("vfio: failed to set iommu for container: %m"); + error_setg_errno(errp, errno, "failed to set iommu for container"); ret = -errno; goto free_container_exit; } @@ -976,7 +978,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd); if (ret) { - error_report("vfio: failed to set group container: %m"); + error_setg_errno(errp, errno, "failed to set group container"); ret = -errno; goto free_container_exit; } @@ -984,7 +986,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) v2 ? VFIO_SPAPR_TCE_v2_IOMMU : VFIO_SPAPR_TCE_IOMMU; ret = ioctl(fd, VFIO_SET_IOMMU, container->iommu_type); if (ret) { - error_report("vfio: failed to set iommu for container: %m"); + error_setg_errno(errp, errno, "failed to set iommu for container"); ret = -errno; goto free_container_exit; } @@ -997,7 +999,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) if (!v2) { ret = ioctl(fd, VFIO_IOMMU_ENABLE); if (ret) { - error_report("vfio: failed to enable container: %m"); + error_setg_errno(errp, errno, "failed to enable container"); ret = -errno; goto free_container_exit; } @@ -1008,7 +1010,9 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) &address_space_memory); if (container->error) { memory_listener_unregister(&container->prereg_listener); - error_report("vfio: RAM memory listener initialization failed for container"); + ret = container->error; + error_setg(errp, + "RAM memory listener initialization failed for container"); goto free_container_exit; } } @@ -1016,7 +1020,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) info.argsz = sizeof(info); ret = ioctl(fd, VFIO_IOMMU_SPAPR_TCE_GET_INFO, &info); if (ret) { - error_report("vfio: VFIO_IOMMU_SPAPR_TCE_GET_INFO failed: %m"); + error_setg_errno(errp, errno, + "VFIO_IOMMU_SPAPR_TCE_GET_INFO failed"); ret = -errno; if (v2) { memory_listener_unregister(&container->prereg_listener); @@ -1033,6 +1038,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) */ ret = vfio_spapr_remove_window(container, info.dma32_window_start); if (ret) { + error_setg_errno(errp, -ret, + "failed to remove existing window"); goto free_container_exit; } } else { @@ -1043,7 +1050,7 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) 0x1000); } } else { - error_report("vfio: No available IOMMU models"); + error_setg(errp, "No available IOMMU models"); ret = -EINVAL; goto free_container_exit; } @@ -1054,7 +1061,8 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as) if (container->error) { ret = container->error; - error_report("vfio: memory listener initialization failed for container"); + error_setg_errno(errp, -ret, + "memory listener initialization failed for container"); goto listener_release_exit; } @@ -1115,7 +1123,7 @@ static void vfio_disconnect_container(VFIOGroup *group) } } -VFIOGroup *vfio_get_group(int groupid, AddressSpace *as) +VFIOGroup *vfio_get_group(int groupid, AddressSpace *as, Error **errp) { VFIOGroup *group; char path[32]; @@ -1127,8 +1135,8 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as) if (group->container->space->as == as) { return group; } else { - error_report("vfio: group %d used in multiple address spaces", - group->groupid); + error_setg(errp, "group %d used in multiple address spaces", + group->groupid); return NULL; } } @@ -1139,27 +1147,29 @@ VFIOGroup *vfio_get_group(int groupid, AddressSpace *as) snprintf(path, sizeof(path), "/dev/vfio/%d", groupid); group->fd = qemu_open(path, O_RDWR); if (group->fd < 0) { - error_report("vfio: error opening %s: %m", path); + error_setg_errno(errp, errno, "failed to open %s", path); goto free_group_exit; } if (ioctl(group->fd, VFIO_GROUP_GET_STATUS, &status)) { - error_report("vfio: error getting group status: %m"); + error_setg_errno(errp, errno, "failed to get group %d status", groupid); goto close_fd_exit; } if (!(status.flags & VFIO_GROUP_FLAGS_VIABLE)) { - error_report("vfio: error, group %d is not viable, please ensure " - "all devices within the iommu_group are bound to their " - "vfio bus driver.", groupid); + error_setg(errp, "group %d is not viable", groupid); + error_append_hint(errp, + "Please ensure all devices within the iommu_group " + "are bound to their vfio bus driver.\n"); goto close_fd_exit; } group->groupid = groupid; QLIST_INIT(&group->device_list); - if (vfio_connect_container(group, as)) { - error_report("vfio: failed to setup container for group %d", groupid); + if (vfio_connect_container(group, as, errp)) { + error_prepend(errp, "failed to setup container for group %d: ", + groupid); goto close_fd_exit; } @@ -1201,23 +1211,24 @@ void vfio_put_group(VFIOGroup *group) } int vfio_get_device(VFIOGroup *group, const char *name, - VFIODevice *vbasedev) + VFIODevice *vbasedev, Error **errp) { struct vfio_device_info dev_info = { .argsz = sizeof(dev_info) }; int ret, fd; fd = ioctl(group->fd, VFIO_GROUP_GET_DEVICE_FD, name); if (fd < 0) { - error_report("vfio: error getting device %s from group %d: %m", - name, group->groupid); - error_printf("Verify all devices in group %d are bound to vfio-<bus> " - "or pci-stub and not already in use\n", group->groupid); + error_setg_errno(errp, errno, "error getting device from group %d", + group->groupid); + error_append_hint(errp, + "Verify all devices in group %d are bound to vfio-<bus> " + "or pci-stub and not already in use\n", group->groupid); return fd; } ret = ioctl(fd, VFIO_DEVICE_GET_INFO, &dev_info); if (ret) { - error_report("vfio: error getting device info: %m"); + error_setg_errno(errp, errno, "error getting device info"); close(fd); return ret; } diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c index bec694c8d8..811eecd1b4 100644 --- a/hw/vfio/pci-quirks.c +++ b/hw/vfio/pci-quirks.c @@ -898,7 +898,7 @@ static uint64_t vfio_rtl8168_quirk_data_read(void *opaque, { VFIOrtl8168Quirk *rtl = opaque; VFIOPCIDevice *vdev = rtl->vdev; - uint64_t data = vfio_region_read(&vdev->bars[2].region, addr + 0x74, size); + uint64_t data = vfio_region_read(&vdev->bars[2].region, addr + 0x70, size); if (rtl->enabled && (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) { hwaddr offset = rtl->addr & 0xfff; @@ -1056,7 +1056,7 @@ typedef struct VFIOIGDQuirk { * of the IGD device. */ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, - struct vfio_region_info *info) + struct vfio_region_info *info, Error **errp) { int ret; @@ -1064,7 +1064,7 @@ int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, ret = pread(vdev->vbasedev.fd, vdev->igd_opregion, info->size, info->offset); if (ret != info->size) { - error_report("vfio: Error reading IGD OpRegion"); + error_setg(errp, "failed to read IGD OpRegion"); g_free(vdev->igd_opregion); vdev->igd_opregion = NULL; return -EINVAL; @@ -1363,6 +1363,7 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) uint64_t *bdsm_size; uint32_t gmch; uint16_t cmd_orig, cmd; + Error *err = NULL; /* * This must be an Intel VGA device at address 00:02.0 for us to even @@ -1464,7 +1465,8 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) * try to enable it. Probably shouldn't be using legacy mode without VGA, * but also no point in us enabling VGA if disabled in hardware. */ - if (!(gmch & 0x2) && !vdev->vga && vfio_populate_vga(vdev)) { + if (!(gmch & 0x2) && !vdev->vga && vfio_populate_vga(vdev, &err)) { + error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name); error_report("IGD device %s failed to enable VGA access, " "legacy mode disabled", vdev->vbasedev.name); goto out; @@ -1487,10 +1489,10 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) } /* Setup OpRegion access */ - ret = vfio_pci_igd_opregion_init(vdev, opregion); + ret = vfio_pci_igd_opregion_init(vdev, opregion, &err); if (ret) { - error_report("IGD device %s failed to setup OpRegion, " - "legacy mode disabled", vdev->vbasedev.name); + error_append_hint(&err, "IGD legacy mode disabled\n"); + error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name); goto out; } diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index a5a620a0c4..65d30fdef9 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -100,7 +100,7 @@ static void vfio_intx_eoi(VFIODevice *vbasedev) vfio_unmask_single_irqindex(vbasedev, VFIO_PCI_INTX_IRQ_INDEX); } -static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev) +static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp) { #ifdef CONFIG_KVM struct kvm_irqfd irqfd = { @@ -126,7 +126,7 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev) /* Get an eventfd for resample/unmask */ if (event_notifier_init(&vdev->intx.unmask, 0)) { - error_report("vfio: Error: event_notifier_init failed eoi"); + error_setg(errp, "event_notifier_init failed eoi"); goto fail; } @@ -134,7 +134,7 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev) irqfd.resamplefd = event_notifier_get_fd(&vdev->intx.unmask); if (kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd)) { - error_report("vfio: Error: Failed to setup resample irqfd: %m"); + error_setg_errno(errp, errno, "failed to setup resample irqfd"); goto fail_irqfd; } @@ -153,7 +153,7 @@ static void vfio_intx_enable_kvm(VFIOPCIDevice *vdev) 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"); + error_setg_errno(errp, -ret, "failed to setup INTx unmask fd"); goto fail_vfio; } @@ -222,6 +222,7 @@ static void vfio_intx_update(PCIDevice *pdev) { VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev); PCIINTxRoute route; + Error *err = NULL; if (vdev->interrupt != VFIO_INT_INTx) { return; @@ -244,18 +245,22 @@ static void vfio_intx_update(PCIDevice *pdev) return; } - vfio_intx_enable_kvm(vdev); + vfio_intx_enable_kvm(vdev, &err); + if (err) { + error_reportf_err(err, WARN_PREFIX, vdev->vbasedev.name); + } /* Re-enable the interrupt in cased we missed an EOI */ vfio_intx_eoi(&vdev->vbasedev); } -static int vfio_intx_enable(VFIOPCIDevice *vdev) +static int vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp) { uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1); int ret, argsz; struct vfio_irq_set *irq_set; int32_t *pfd; + Error *err = NULL; if (!pin) { return 0; @@ -279,7 +284,7 @@ static int vfio_intx_enable(VFIOPCIDevice *vdev) ret = event_notifier_init(&vdev->intx.interrupt, 0); if (ret) { - error_report("vfio: Error: event_notifier_init failed"); + error_setg_errno(errp, -ret, "event_notifier_init failed"); return ret; } @@ -299,13 +304,16 @@ static int vfio_intx_enable(VFIOPCIDevice *vdev) 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"); + error_setg_errno(errp, -ret, "failed to setup INTx fd"); qemu_set_fd_handler(*pfd, NULL, NULL, vdev); event_notifier_cleanup(&vdev->intx.interrupt); return -errno; } - vfio_intx_enable_kvm(vdev); + vfio_intx_enable_kvm(vdev, &err); + if (err) { + error_reportf_err(err, WARN_PREFIX, vdev->vbasedev.name); + } vdev->interrupt = VFIO_INT_INTx; @@ -707,6 +715,7 @@ retry: static void vfio_msi_disable_common(VFIOPCIDevice *vdev) { + Error *err = NULL; int i; for (i = 0; i < vdev->nr_vectors; i++) { @@ -726,7 +735,10 @@ static void vfio_msi_disable_common(VFIOPCIDevice *vdev) vdev->nr_vectors = 0; vdev->interrupt = VFIO_INT_NONE; - vfio_intx_enable(vdev); + vfio_intx_enable(vdev, &err); + if (err) { + error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name); + } } static void vfio_msix_disable(VFIOPCIDevice *vdev) @@ -1168,7 +1180,7 @@ static void vfio_disable_interrupts(VFIOPCIDevice *vdev) } } -static int vfio_msi_setup(VFIOPCIDevice *vdev, int pos) +static int vfio_msi_setup(VFIOPCIDevice *vdev, int pos, Error **errp) { uint16_t ctrl; bool msi_64bit, msi_maskbit; @@ -1177,6 +1189,7 @@ static int vfio_msi_setup(VFIOPCIDevice *vdev, int pos) if (pread(vdev->vbasedev.fd, &ctrl, sizeof(ctrl), vdev->config_offset + pos + PCI_CAP_FLAGS) != sizeof(ctrl)) { + error_setg_errno(errp, errno, "failed reading MSI PCI_CAP_FLAGS"); return -errno; } ctrl = le16_to_cpu(ctrl); @@ -1192,8 +1205,8 @@ static int vfio_msi_setup(VFIOPCIDevice *vdev, int pos) if (ret == -ENOTSUP) { return 0; } - error_prepend(&err, "vfio: msi_init failed: "); - error_report_err(err); + error_prepend(&err, "msi_init failed: "); + error_propagate(errp, err); return ret; } vdev->msi_cap_size = 0xa + (msi_maskbit ? 0xa : 0) + (msi_64bit ? 0x4 : 0); @@ -1277,7 +1290,7 @@ static void vfio_pci_fixup_msix_region(VFIOPCIDevice *vdev) * need to first look for where the MSI-X table lives. So we * unfortunately split MSI-X setup across two functions. */ -static int vfio_msix_early_setup(VFIOPCIDevice *vdev) +static void vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp) { uint8_t pos; uint16_t ctrl; @@ -1287,22 +1300,25 @@ static int vfio_msix_early_setup(VFIOPCIDevice *vdev) pos = pci_find_capability(&vdev->pdev, PCI_CAP_ID_MSIX); if (!pos) { - return 0; + return; } if (pread(fd, &ctrl, sizeof(ctrl), vdev->config_offset + pos + PCI_MSIX_FLAGS) != sizeof(ctrl)) { - return -errno; + error_setg_errno(errp, errno, "failed to read PCI MSIX FLAGS"); + return; } if (pread(fd, &table, sizeof(table), vdev->config_offset + pos + PCI_MSIX_TABLE) != sizeof(table)) { - return -errno; + error_setg_errno(errp, errno, "failed to read PCI MSIX TABLE"); + return; } if (pread(fd, &pba, sizeof(pba), vdev->config_offset + pos + PCI_MSIX_PBA) != sizeof(pba)) { - return -errno; + error_setg_errno(errp, errno, "failed to read PCI MSIX PBA"); + return; } ctrl = le16_to_cpu(ctrl); @@ -1332,10 +1348,10 @@ static int vfio_msix_early_setup(VFIOPCIDevice *vdev) (vdev->device_id & 0xff00) == 0x5800) { msix->pba_offset = 0x1000; } else { - error_report("vfio: Hardware reports invalid configuration, " - "MSIX PBA outside of specified BAR"); + error_setg(errp, "hardware reports invalid configuration, " + "MSIX PBA outside of specified BAR"); g_free(msix); - return -EINVAL; + return; } } @@ -1344,11 +1360,9 @@ static int vfio_msix_early_setup(VFIOPCIDevice *vdev) vdev->msix = msix; vfio_pci_fixup_msix_region(vdev); - - return 0; } -static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos) +static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp) { int ret; @@ -1363,7 +1377,7 @@ static int vfio_msix_setup(VFIOPCIDevice *vdev, int pos) if (ret == -ENOTSUP) { return 0; } - error_report("vfio: msix_init failed"); + error_setg(errp, "msix_init failed"); return ret; } @@ -1548,7 +1562,8 @@ static void vfio_add_emulated_long(VFIOPCIDevice *vdev, int pos, vfio_set_long_bits(vdev->emulated_config_bits + pos, mask, mask); } -static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size) +static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size, + Error **errp) { uint16_t flags; uint8_t type; @@ -1560,8 +1575,8 @@ static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size) type != PCI_EXP_TYPE_LEG_END && type != PCI_EXP_TYPE_RC_END) { - error_report("vfio: Assignment of PCIe type 0x%x " - "devices is not currently supported", type); + error_setg(errp, "assignment of PCIe type 0x%x " + "devices is not currently supported", type); return -EINVAL; } @@ -1695,7 +1710,7 @@ static void vfio_check_af_flr(VFIOPCIDevice *vdev, uint8_t pos) } } -static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos) +static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos, Error **errp) { PCIDevice *pdev = &vdev->pdev; uint8_t cap_id, next, size; @@ -1720,9 +1735,9 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos) * will be changed as we unwind the stack. */ if (next) { - ret = vfio_add_std_cap(vdev, next); + ret = vfio_add_std_cap(vdev, next, errp); if (ret) { - return ret; + goto out; } } else { /* Begin the rebuild, use QEMU emulated list bits */ @@ -1736,40 +1751,40 @@ static int vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos) switch (cap_id) { case PCI_CAP_ID_MSI: - ret = vfio_msi_setup(vdev, pos); + ret = vfio_msi_setup(vdev, pos, errp); break; case PCI_CAP_ID_EXP: vfio_check_pcie_flr(vdev, pos); - ret = vfio_setup_pcie_cap(vdev, pos, size); + ret = vfio_setup_pcie_cap(vdev, pos, size, errp); break; case PCI_CAP_ID_MSIX: - ret = vfio_msix_setup(vdev, pos); + ret = vfio_msix_setup(vdev, pos, errp); break; case PCI_CAP_ID_PM: vfio_check_pm_reset(vdev, pos); vdev->pm_cap = pos; - ret = pci_add_capability(pdev, cap_id, pos, size); + ret = pci_add_capability2(pdev, cap_id, pos, size, errp); break; case PCI_CAP_ID_AF: vfio_check_af_flr(vdev, pos); - ret = pci_add_capability(pdev, cap_id, pos, size); + ret = pci_add_capability2(pdev, cap_id, pos, size, errp); break; default: - ret = pci_add_capability(pdev, cap_id, pos, size); + ret = pci_add_capability2(pdev, cap_id, pos, size, errp); break; } - +out: if (ret < 0) { - error_report("vfio: %s Error adding PCI capability " - "0x%x[0x%x]@0x%x: %d", vdev->vbasedev.name, - cap_id, size, pos, ret); + error_prepend(errp, + "failed to add PCI capability 0x%x[0x%x]@0x%x: ", + cap_id, size, pos); return ret; } return 0; } -static int vfio_add_ext_cap(VFIOPCIDevice *vdev) +static void vfio_add_ext_cap(VFIOPCIDevice *vdev) { PCIDevice *pdev = &vdev->pdev; uint32_t header; @@ -1780,7 +1795,7 @@ static int vfio_add_ext_cap(VFIOPCIDevice *vdev) /* Only add extended caps if we have them and the guest can see them */ if (!pci_is_express(pdev) || !pci_bus_is_express(pdev->bus) || !pci_get_long(pdev->config + PCI_CONFIG_SPACE_SIZE)) { - return 0; + return; } /* @@ -1845,10 +1860,10 @@ static int vfio_add_ext_cap(VFIOPCIDevice *vdev) } g_free(config); - return 0; + return; } -static int vfio_add_capabilities(VFIOPCIDevice *vdev) +static int vfio_add_capabilities(VFIOPCIDevice *vdev, Error **errp) { PCIDevice *pdev = &vdev->pdev; int ret; @@ -1858,12 +1873,13 @@ static int vfio_add_capabilities(VFIOPCIDevice *vdev) return 0; /* Nothing to add */ } - ret = vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST]); + ret = vfio_add_std_cap(vdev, pdev->config[PCI_CAPABILITY_LIST], errp); if (ret) { return ret; } - return vfio_add_ext_cap(vdev); + vfio_add_ext_cap(vdev); + return 0; } static void vfio_pci_pre_reset(VFIOPCIDevice *vdev) @@ -1905,7 +1921,12 @@ static void vfio_pci_pre_reset(VFIOPCIDevice *vdev) static void vfio_pci_post_reset(VFIOPCIDevice *vdev) { - vfio_intx_enable(vdev); + Error *err = NULL; + + vfio_intx_enable(vdev, &err); + if (err) { + error_reportf_err(err, ERR_PREFIX, vdev->vbasedev.name); + } } static bool vfio_pci_host_match(PCIHostDeviceAddress *addr, const char *name) @@ -1930,7 +1951,9 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single) trace_vfio_pci_hot_reset(vdev->vbasedev.name, single ? "one" : "multi"); - vfio_pci_pre_reset(vdev); + if (!single) { + vfio_pci_pre_reset(vdev); + } vdev->vbasedev.needs_reset = false; info = g_malloc0(sizeof(*info)); @@ -2088,7 +2111,9 @@ out: } } out_single: - vfio_pci_post_reset(vdev); + if (!single) { + vfio_pci_post_reset(vdev); + } g_free(info); return ret; @@ -2134,7 +2159,7 @@ static VFIODeviceOps vfio_pci_ops = { .vfio_eoi = vfio_intx_eoi, }; -int vfio_populate_vga(VFIOPCIDevice *vdev) +int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp) { VFIODevice *vbasedev = &vdev->vbasedev; struct vfio_region_info *reg_info; @@ -2142,15 +2167,18 @@ int vfio_populate_vga(VFIOPCIDevice *vdev) ret = vfio_get_region_info(vbasedev, VFIO_PCI_VGA_REGION_INDEX, ®_info); if (ret) { + error_setg_errno(errp, -ret, + "failed getting region info for VGA region index %d", + VFIO_PCI_VGA_REGION_INDEX); return ret; } if (!(reg_info->flags & VFIO_REGION_INFO_FLAG_READ) || !(reg_info->flags & VFIO_REGION_INFO_FLAG_WRITE) || reg_info->size < 0xbffff + 1) { - error_report("vfio: Unexpected VGA info, flags 0x%lx, size 0x%lx", - (unsigned long)reg_info->flags, - (unsigned long)reg_info->size); + error_setg(errp, "unexpected VGA info, flags 0x%lx, size 0x%lx", + (unsigned long)reg_info->flags, + (unsigned long)reg_info->size); g_free(reg_info); return -EINVAL; } @@ -2199,7 +2227,7 @@ int vfio_populate_vga(VFIOPCIDevice *vdev) return 0; } -static int vfio_populate_device(VFIOPCIDevice *vdev) +static void vfio_populate_device(VFIOPCIDevice *vdev, Error **errp) { VFIODevice *vbasedev = &vdev->vbasedev; struct vfio_region_info *reg_info; @@ -2208,19 +2236,19 @@ static int vfio_populate_device(VFIOPCIDevice *vdev) /* Sanity check device */ if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PCI)) { - error_report("vfio: Um, this isn't a PCI device"); - goto error; + error_setg(errp, "this isn't a PCI device"); + return; } if (vbasedev->num_regions < VFIO_PCI_CONFIG_REGION_INDEX + 1) { - error_report("vfio: unexpected number of io regions %u", - vbasedev->num_regions); - goto error; + error_setg(errp, "unexpected number of io regions %u", + vbasedev->num_regions); + return; } if (vbasedev->num_irqs < VFIO_PCI_MSIX_IRQ_INDEX + 1) { - error_report("vfio: unexpected number of irqs %u", vbasedev->num_irqs); - goto error; + error_setg(errp, "unexpected number of irqs %u", vbasedev->num_irqs); + return; } for (i = VFIO_PCI_BAR0_REGION_INDEX; i < VFIO_PCI_ROM_REGION_INDEX; i++) { @@ -2231,8 +2259,8 @@ static int vfio_populate_device(VFIOPCIDevice *vdev) g_free(name); if (ret) { - error_report("vfio: Error getting region %d info: %m", i); - goto error; + error_setg_errno(errp, -ret, "failed to get region %d info", i); + return; } QLIST_INIT(&vdev->bars[i].quirks); @@ -2241,8 +2269,8 @@ static int vfio_populate_device(VFIOPCIDevice *vdev) ret = vfio_get_region_info(vbasedev, VFIO_PCI_CONFIG_REGION_INDEX, ®_info); if (ret) { - error_report("vfio: Error getting config info: %m"); - goto error; + error_setg_errno(errp, -ret, "failed to get config info"); + return; } trace_vfio_populate_device_config(vdev->vbasedev.name, @@ -2259,11 +2287,11 @@ static int vfio_populate_device(VFIOPCIDevice *vdev) g_free(reg_info); if (vdev->features & VFIO_FEATURE_ENABLE_VGA) { - ret = vfio_populate_vga(vdev); + ret = vfio_populate_vga(vdev, errp); if (ret) { - error_report( - "vfio: Device does not support requested feature x-vga"); - goto error; + error_append_hint(errp, "device does not support " + "requested feature x-vga\n"); + return; } } @@ -2273,17 +2301,13 @@ static int vfio_populate_device(VFIOPCIDevice *vdev) if (ret) { /* This can fail for an old kernel or legacy PCI dev */ trace_vfio_populate_device_get_irq_info_failure(); - ret = 0; } else if (irq_info.count == 1) { vdev->pci_aer = true; } else { - error_report("vfio: %s " + error_report(WARN_PREFIX "Could not enable error recovery for the device", vbasedev->name); } - -error: - return ret; } static void vfio_put_device(VFIOPCIDevice *vdev) @@ -2487,18 +2511,26 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev) vdev->req_enabled = false; } -static int vfio_initfn(PCIDevice *pdev) +static void vfio_realize(PCIDevice *pdev, Error **errp) { VFIOPCIDevice *vdev = DO_UPCAST(VFIOPCIDevice, pdev, pdev); VFIODevice *vbasedev_iter; VFIOGroup *group; char *tmp, group_path[PATH_MAX], *group_name; + Error *err = NULL; ssize_t len; struct stat st; int groupid; int i, ret; if (!vdev->vbasedev.sysfsdev) { + if (!(~vdev->host.domain || ~vdev->host.bus || + ~vdev->host.slot || ~vdev->host.function)) { + error_setg(errp, "No provided host device"); + error_append_hint(errp, "Use -vfio-pci,host=DDDD:BB:DD.F " + "or -vfio-pci,sysfsdev=PATH_TO_DEVICE\n"); + return; + } vdev->vbasedev.sysfsdev = g_strdup_printf("/sys/bus/pci/devices/%04x:%02x:%02x.%01x", vdev->host.domain, vdev->host.bus, @@ -2506,9 +2538,9 @@ static int vfio_initfn(PCIDevice *pdev) } if (stat(vdev->vbasedev.sysfsdev, &st) < 0) { - error_report("vfio: error: no such host device: %s", - vdev->vbasedev.sysfsdev); - return -errno; + error_setg_errno(errp, errno, "no such host device"); + error_prepend(errp, ERR_PREFIX, vdev->vbasedev.sysfsdev); + return; } vdev->vbasedev.name = g_strdup(basename(vdev->vbasedev.sysfsdev)); @@ -2520,45 +2552,44 @@ static int vfio_initfn(PCIDevice *pdev) g_free(tmp); if (len <= 0 || len >= sizeof(group_path)) { - error_report("vfio: error no iommu_group for device"); - return len < 0 ? -errno : -ENAMETOOLONG; + error_setg_errno(errp, len < 0 ? errno : ENAMETOOLONG, + "no iommu_group found"); + goto error; } group_path[len] = 0; group_name = basename(group_path); if (sscanf(group_name, "%d", &groupid) != 1) { - error_report("vfio: error reading %s: %m", group_path); - return -errno; + error_setg_errno(errp, errno, "failed to read %s", group_path); + goto error; } - trace_vfio_initfn(vdev->vbasedev.name, groupid); + trace_vfio_realize(vdev->vbasedev.name, groupid); - group = vfio_get_group(groupid, pci_device_iommu_address_space(pdev)); + group = vfio_get_group(groupid, pci_device_iommu_address_space(pdev), errp); if (!group) { - error_report("vfio: failed to get group %d", groupid); - return -ENOENT; + goto error; } QLIST_FOREACH(vbasedev_iter, &group->device_list, next) { if (strcmp(vbasedev_iter->name, vdev->vbasedev.name) == 0) { - error_report("vfio: error: device %s is already attached", - vdev->vbasedev.name); + error_setg(errp, "device is already attached"); vfio_put_group(group); - return -EBUSY; + goto error; } } - ret = vfio_get_device(group, vdev->vbasedev.name, &vdev->vbasedev); + ret = vfio_get_device(group, vdev->vbasedev.name, &vdev->vbasedev, errp); if (ret) { - error_report("vfio: failed to get device %s", vdev->vbasedev.name); vfio_put_group(group); - return ret; + goto error; } - ret = vfio_populate_device(vdev); - if (ret) { - return ret; + vfio_populate_device(vdev, &err); + if (err) { + error_propagate(errp, err); + goto error; } /* Get a copy of config space */ @@ -2567,8 +2598,8 @@ static int vfio_initfn(PCIDevice *pdev) vdev->config_offset); if (ret < (int)MIN(pci_config_size(&vdev->pdev), vdev->config_size)) { ret = ret < 0 ? -errno : -EFAULT; - error_report("vfio: Failed to read device config space"); - return ret; + error_setg_errno(errp, -ret, "failed to read device config space"); + goto error; } /* vfio emulates a lot for us, but some bits need extra love */ @@ -2584,8 +2615,8 @@ static int vfio_initfn(PCIDevice *pdev) */ if (vdev->vendor_id != PCI_ANY_ID) { if (vdev->vendor_id >= 0xffff) { - error_report("vfio: Invalid PCI vendor ID provided"); - return -EINVAL; + error_setg(errp, "invalid PCI vendor ID provided"); + goto error; } vfio_add_emulated_word(vdev, PCI_VENDOR_ID, vdev->vendor_id, ~0); trace_vfio_pci_emulated_vendor_id(vdev->vbasedev.name, vdev->vendor_id); @@ -2595,8 +2626,8 @@ static int vfio_initfn(PCIDevice *pdev) if (vdev->device_id != PCI_ANY_ID) { if (vdev->device_id > 0xffff) { - error_report("vfio: Invalid PCI device ID provided"); - return -EINVAL; + error_setg(errp, "invalid PCI device ID provided"); + goto error; } vfio_add_emulated_word(vdev, PCI_DEVICE_ID, vdev->device_id, ~0); trace_vfio_pci_emulated_device_id(vdev->vbasedev.name, vdev->device_id); @@ -2606,8 +2637,8 @@ static int vfio_initfn(PCIDevice *pdev) if (vdev->sub_vendor_id != PCI_ANY_ID) { if (vdev->sub_vendor_id > 0xffff) { - error_report("vfio: Invalid PCI subsystem vendor ID provided"); - return -EINVAL; + error_setg(errp, "invalid PCI subsystem vendor ID provided"); + goto error; } vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_VENDOR_ID, vdev->sub_vendor_id, ~0); @@ -2617,8 +2648,8 @@ static int vfio_initfn(PCIDevice *pdev) if (vdev->sub_device_id != PCI_ANY_ID) { if (vdev->sub_device_id > 0xffff) { - error_report("vfio: Invalid PCI subsystem device ID provided"); - return -EINVAL; + error_setg(errp, "invalid PCI subsystem device ID provided"); + goto error; } vfio_add_emulated_word(vdev, PCI_SUBSYSTEM_ID, vdev->sub_device_id, ~0); trace_vfio_pci_emulated_sub_device_id(vdev->vbasedev.name, @@ -2646,14 +2677,15 @@ static int vfio_initfn(PCIDevice *pdev) vfio_pci_size_rom(vdev); - ret = vfio_msix_early_setup(vdev); - if (ret) { - return ret; + vfio_msix_early_setup(vdev, &err); + if (err) { + error_propagate(errp, err); + goto error; } vfio_bars_setup(vdev); - ret = vfio_add_capabilities(vdev); + ret = vfio_add_capabilities(vdev, errp); if (ret) { goto out_teardown; } @@ -2671,9 +2703,9 @@ static int vfio_initfn(PCIDevice *pdev) struct vfio_region_info *opregion; if (vdev->pdev.qdev.hotplugged) { - error_report("Cannot support IGD OpRegion feature on hotplugged " - "device %s", vdev->vbasedev.name); - ret = -EINVAL; + error_setg(errp, + "cannot support IGD OpRegion feature on hotplugged " + "device"); goto out_teardown; } @@ -2681,16 +2713,14 @@ static int vfio_initfn(PCIDevice *pdev) VFIO_REGION_TYPE_PCI_VENDOR_TYPE | PCI_VENDOR_ID_INTEL, VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION, &opregion); if (ret) { - error_report("Device %s does not support requested IGD OpRegion " - "feature", vdev->vbasedev.name); + error_setg_errno(errp, -ret, + "does not support requested IGD OpRegion feature"); goto out_teardown; } - ret = vfio_pci_igd_opregion_init(vdev, opregion); + ret = vfio_pci_igd_opregion_init(vdev, opregion, errp); g_free(opregion); if (ret) { - error_report("Device %s IGD OpRegion initialization failed", - vdev->vbasedev.name); goto out_teardown; } } @@ -2710,7 +2740,7 @@ static int vfio_initfn(PCIDevice *pdev) vdev->intx.mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, vfio_intx_mmap_enable, vdev); pci_device_set_intx_routing_notifier(&vdev->pdev, vfio_intx_update); - ret = vfio_intx_enable(vdev); + ret = vfio_intx_enable(vdev, errp); if (ret) { goto out_teardown; } @@ -2720,13 +2750,14 @@ static int vfio_initfn(PCIDevice *pdev) vfio_register_req_notifier(vdev); vfio_setup_resetfn_quirk(vdev); - return 0; + return; out_teardown: pci_device_set_intx_routing_notifier(&vdev->pdev, NULL); vfio_teardown_msi(vdev); vfio_bars_exit(vdev); - return ret; +error: + error_prepend(errp, ERR_PREFIX, vdev->vbasedev.name); } static void vfio_instance_finalize(Object *obj) @@ -2808,6 +2839,10 @@ static void vfio_instance_init(Object *obj) device_add_bootindex_property(obj, &vdev->bootindex, "bootindex", NULL, &pci_dev->qdev, NULL); + vdev->host.domain = ~0U; + vdev->host.bus = ~0U; + vdev->host.slot = ~0U; + vdev->host.function = ~0U; } static Property vfio_pci_dev_properties[] = { @@ -2855,7 +2890,7 @@ static void vfio_pci_dev_class_init(ObjectClass *klass, void *data) dc->vmsd = &vfio_pci_vmstate; dc->desc = "VFIO-based PCI device assignment"; set_bit(DEVICE_CATEGORY_MISC, dc->categories); - pdc->init = vfio_initfn; + pdc->realize = vfio_realize; pdc->exit = vfio_exitfn; pdc->config_read = vfio_pci_read_config; pdc->config_write = vfio_pci_write_config; diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h index 7d482d9d21..a8366bb2a7 100644 --- a/hw/vfio/pci.h +++ b/hw/vfio/pci.h @@ -161,9 +161,10 @@ void vfio_bar_quirk_exit(VFIOPCIDevice *vdev, int nr); void vfio_bar_quirk_finalize(VFIOPCIDevice *vdev, int nr); void vfio_setup_resetfn_quirk(VFIOPCIDevice *vdev); -int vfio_populate_vga(VFIOPCIDevice *vdev); +int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp); int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, - struct vfio_region_info *info); + struct vfio_region_info *info, + Error **errp); #endif /* HW_VFIO_VFIO_PCI_H */ diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c index a559e7b659..a4663c918e 100644 --- a/hw/vfio/platform.c +++ b/hw/vfio/platform.c @@ -44,9 +44,10 @@ static inline bool vfio_irq_is_automasked(VFIOINTp *intp) * and add it into the list of IRQs * @vbasedev: the VFIO device handle * @info: irq info struct retrieved from VFIO driver + * @errp: error object */ static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev, - struct vfio_irq_info info) + struct vfio_irq_info info, Error **errp) { int ret; VFIOPlatformDevice *vdev = @@ -69,7 +70,8 @@ static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev, if (ret) { g_free(intp->interrupt); g_free(intp); - error_report("vfio: Error: trigger event_notifier_init failed "); + error_setg_errno(errp, -ret, + "failed to initialize trigger eventd notifier"); return NULL; } if (vfio_irq_is_automasked(intp)) { @@ -80,7 +82,8 @@ static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev, g_free(intp->interrupt); g_free(intp->unmask); g_free(intp); - error_report("vfio: Error: resamplefd event_notifier_init failed"); + error_setg_errno(errp, -ret, + "failed to initialize resample eventd notifier"); return NULL; } } @@ -456,9 +459,10 @@ static int vfio_platform_hot_reset_multi(VFIODevice *vbasedev) * vfio_populate_device - Allocate and populate MMIO region * and IRQ structs according to driver returned information * @vbasedev: the VFIO device handle + * @errp: error object * */ -static int vfio_populate_device(VFIODevice *vbasedev) +static int vfio_populate_device(VFIODevice *vbasedev, Error **errp) { VFIOINTp *intp, *tmp; int i, ret = -1; @@ -466,7 +470,7 @@ static int vfio_populate_device(VFIODevice *vbasedev) container_of(vbasedev, VFIOPlatformDevice, vbasedev); if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PLATFORM)) { - error_report("vfio: Um, this isn't a platform device"); + error_setg(errp, "this isn't a platform device"); return ret; } @@ -480,7 +484,7 @@ static int vfio_populate_device(VFIODevice *vbasedev) vdev->regions[i], i, name); g_free(name); if (ret) { - error_report("vfio: Error getting region %d info: %m", i); + error_setg_errno(errp, -ret, "failed to get region %d info", i); goto reg_error; } } @@ -496,16 +500,15 @@ static int vfio_populate_device(VFIODevice *vbasedev) irq.index = i; ret = ioctl(vbasedev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq); if (ret) { - error_report("vfio: error getting device %s irq info", - vbasedev->name); + error_setg_errno(errp, -ret, "failed to get device irq info"); goto irq_err; } else { trace_vfio_platform_populate_interrupts(irq.index, irq.count, irq.flags); - intp = vfio_init_intp(vbasedev, irq); + intp = vfio_init_intp(vbasedev, irq, errp); if (!intp) { - error_report("vfio: Error installing IRQ %d up", i); + ret = -1; goto irq_err; } } @@ -538,13 +541,14 @@ static VFIODeviceOps vfio_platform_ops = { /** * vfio_base_device_init - perform preliminary VFIO setup * @vbasedev: the VFIO device handle + * @errp: error object * * Implement the VFIO command sequence that allows to discover * assigned device resources: group extraction, device * fd retrieval, resource query. * Precondition: the device name must be initialized */ -static int vfio_base_device_init(VFIODevice *vbasedev) +static int vfio_base_device_init(VFIODevice *vbasedev, Error **errp) { VFIOGroup *group; VFIODevice *vbasedev_iter; @@ -560,6 +564,7 @@ static int vfio_base_device_init(VFIODevice *vbasedev) vbasedev->name = g_strdup(basename(vbasedev->sysfsdev)); } else { if (!vbasedev->name || strchr(vbasedev->name, '/')) { + error_setg(errp, "wrong host device name"); return -EINVAL; } @@ -568,8 +573,8 @@ static int vfio_base_device_init(VFIODevice *vbasedev) } if (stat(vbasedev->sysfsdev, &st) < 0) { - error_report("vfio: error: no such host device: %s", - vbasedev->sysfsdev); + error_setg_errno(errp, errno, + "failed to get the sysfs host device file status"); return -errno; } @@ -578,44 +583,41 @@ static int vfio_base_device_init(VFIODevice *vbasedev) g_free(tmp); if (len < 0 || len >= sizeof(group_path)) { - error_report("vfio: error no iommu_group for device"); - return len < 0 ? -errno : -ENAMETOOLONG; + ret = len < 0 ? -errno : -ENAMETOOLONG; + error_setg_errno(errp, -ret, "no iommu_group found"); + return ret; } group_path[len] = 0; group_name = basename(group_path); if (sscanf(group_name, "%d", &groupid) != 1) { - error_report("vfio: error reading %s: %m", group_path); + error_setg_errno(errp, errno, "failed to read %s", group_path); return -errno; } trace_vfio_platform_base_device_init(vbasedev->name, groupid); - group = vfio_get_group(groupid, &address_space_memory); + group = vfio_get_group(groupid, &address_space_memory, errp); if (!group) { - error_report("vfio: failed to get group %d", groupid); return -ENOENT; } QLIST_FOREACH(vbasedev_iter, &group->device_list, next) { if (strcmp(vbasedev_iter->name, vbasedev->name) == 0) { - error_report("vfio: error: device %s is already attached", - vbasedev->name); + error_setg(errp, "device is already attached"); vfio_put_group(group); return -EBUSY; } } - ret = vfio_get_device(group, vbasedev->name, vbasedev); + ret = vfio_get_device(group, vbasedev->name, vbasedev, errp); if (ret) { - error_report("vfio: failed to get device %s", vbasedev->name); vfio_put_group(group); return ret; } - ret = vfio_populate_device(vbasedev); + ret = vfio_populate_device(vbasedev, errp); if (ret) { - error_report("vfio: failed to populate device %s", vbasedev->name); vfio_put_group(group); } @@ -644,11 +646,9 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp) vbasedev->sysfsdev : vbasedev->name, vdev->compat); - ret = vfio_base_device_init(vbasedev); + ret = vfio_base_device_init(vbasedev, errp); if (ret) { - error_setg(errp, "vfio: vfio_base_device_init failed for %s", - vbasedev->name); - return; + goto out; } for (i = 0; i < vbasedev->num_regions; i++) { @@ -658,6 +658,16 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp) } sysbus_init_mmio(sbdev, vdev->regions[i]->mem); } +out: + if (!ret) { + return; + } + + if (vdev->vbasedev.name) { + error_prepend(errp, ERR_PREFIX, vdev->vbasedev.name); + } else { + error_prepend(errp, "vfio error: "); + } } static const VMStateDescription vfio_platform_vmstate = { diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events index da133221de..ef81609b98 100644 --- a/hw/vfio/trace-events +++ b/hw/vfio/trace-events @@ -36,7 +36,7 @@ vfio_pci_hot_reset_dep_devices(int domain, int bus, int slot, int function, int vfio_pci_hot_reset_result(const char *name, const char *result) "%s hot reset: %s" vfio_populate_device_config(const char *name, unsigned long size, unsigned long offset, unsigned long flags) "Device %s config:\n size: 0x%lx, offset: 0x%lx, flags: 0x%lx" vfio_populate_device_get_irq_info_failure(void) "VFIO_DEVICE_GET_IRQ_INFO failure: %m" -vfio_initfn(const char *name, int group_id) " (%s) group %d" +vfio_realize(const char *name, int group_id) " (%s) group %d" vfio_add_ext_cap_dropped(const char *name, uint16_t cap, uint16_t offset) "%s %x@%x" vfio_pci_reset(const char *name) " (%s)" vfio_pci_reset_flr(const char *name) "%s FLR/VFIO_DEVICE_RESET" |