Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/awilliam/tags/vfio-updates-2016…
Browse files Browse the repository at this point in the history
…1017.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>
  • Loading branch information
pm215 committed Oct 18, 2016
2 parents f525c8a + 893bfc3 commit 1b0d384
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 191 deletions.
69 changes: 40 additions & 29 deletions hw/vfio/common.c
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -941,15 +943,15 @@ 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;
}

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;
}
Expand All @@ -976,15 +978,15 @@ 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;
}
container->iommu_type =
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;
}
Expand All @@ -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;
}
Expand All @@ -1008,15 +1010,18 @@ 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;
}
}

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);
Expand All @@ -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 {
Expand All @@ -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;
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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];
Expand All @@ -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;
}
}
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down
16 changes: 9 additions & 7 deletions hw/vfio/pci-quirks.c
Expand Up @@ -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;
Expand Down Expand Up @@ -1056,15 +1056,15 @@ 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;

vdev->igd_opregion = g_malloc0(info->size);
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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down

0 comments on commit 1b0d384

Please sign in to comment.