* [Qemu-devel] [PULL 1/2] vfio: Test realized when using VFIOGroup.device_list iterator
2017-07-10 19:10 [Qemu-devel] [PULL 0/2] VFIO fixes 2017-07-10 Alex Williamson
@ 2017-07-10 19:10 ` Alex Williamson
2017-07-10 19:10 ` [Qemu-devel] [PULL 2/2] vfio/pci: Fixup v0 PCIe capabilities Alex Williamson
2017-07-11 15:33 ` [Qemu-devel] [PULL 0/2] VFIO fixes 2017-07-10 Peter Maydell
2 siblings, 0 replies; 4+ messages in thread
From: Alex Williamson @ 2017-07-10 19:10 UTC (permalink / raw)
To: qemu-devel
VFIOGroup.device_list is effectively our reference tracking mechanism
such that we can teardown a group when all of the device references
are removed. However, we also use this list from our machine reset
handler for processing resets that affect multiple devices. Generally
device removals are fully processed (exitfn + finalize) when this
reset handler is invoked, however if the removal is triggered via
another reset handler (piix4_reset->acpi_pcihp_reset) then the device
exitfn may run, but not finalize. In this case we hit asserts when
we start trying to access PCI helpers since much of the PCI state of
the device is released. To resolve this, add a pointer to the Object
DeviceState in our common base-device and skip non-realized devices
as we iterate.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
hw/vfio/common.c | 6 ++++--
hw/vfio/pci.c | 7 +++++--
hw/vfio/platform.c | 1 +
include/hw/vfio/vfio-common.h | 1 +
4 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b9abe77f5a7b..29923e499012 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -858,13 +858,15 @@ void vfio_reset_handler(void *opaque)
QLIST_FOREACH(group, &vfio_group_list, next) {
QLIST_FOREACH(vbasedev, &group->device_list, next) {
- vbasedev->ops->vfio_compute_needs_reset(vbasedev);
+ if (vbasedev->dev->realized) {
+ vbasedev->ops->vfio_compute_needs_reset(vbasedev);
+ }
}
}
QLIST_FOREACH(group, &vfio_group_list, next) {
QLIST_FOREACH(vbasedev, &group->device_list, next) {
- if (vbasedev->needs_reset) {
+ if (vbasedev->dev->realized && vbasedev->needs_reset) {
vbasedev->ops->vfio_hot_reset_multi(vbasedev);
}
}
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 8de8272e964d..ccdb6e1d632a 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -2116,7 +2116,8 @@ static int vfio_pci_hot_reset(VFIOPCIDevice *vdev, bool single)
/* Prep dependent devices for reset and clear our marker. */
QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
- if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
+ if (!vbasedev_iter->dev->realized ||
+ vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
continue;
}
tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
@@ -2197,7 +2198,8 @@ out:
}
QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
- if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
+ if (!vbasedev_iter->dev->realized ||
+ vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
continue;
}
tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
@@ -2647,6 +2649,7 @@ static void vfio_realize(PCIDevice *pdev, Error **errp)
vdev->vbasedev.name = g_strdup(basename(vdev->vbasedev.sysfsdev));
vdev->vbasedev.ops = &vfio_pci_ops;
vdev->vbasedev.type = VFIO_DEVICE_TYPE_PCI;
+ vdev->vbasedev.dev = &vdev->pdev.qdev;
tmp = g_strdup_printf("%s/iommu_group", vdev->vbasedev.sysfsdev);
len = readlink(tmp, group_path, sizeof(group_path));
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index a4663c918ea2..7c09deda6143 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -640,6 +640,7 @@ static void vfio_platform_realize(DeviceState *dev, Error **errp)
int i, ret;
vbasedev->type = VFIO_DEVICE_TYPE_PLATFORM;
+ vbasedev->dev = dev;
vbasedev->ops = &vfio_platform_ops;
trace_vfio_platform_realize(vbasedev->sysfsdev ?
diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h
index 9521013d52b3..0b475a3596fc 100644
--- a/include/hw/vfio/vfio-common.h
+++ b/include/hw/vfio/vfio-common.h
@@ -115,6 +115,7 @@ typedef struct VFIODevice {
struct VFIOGroup *group;
char *sysfsdev;
char *name;
+ DeviceState *dev;
int fd;
int type;
bool reset_works;
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [Qemu-devel] [PULL 2/2] vfio/pci: Fixup v0 PCIe capabilities
2017-07-10 19:10 [Qemu-devel] [PULL 0/2] VFIO fixes 2017-07-10 Alex Williamson
2017-07-10 19:10 ` [Qemu-devel] [PULL 1/2] vfio: Test realized when using VFIOGroup.device_list iterator Alex Williamson
@ 2017-07-10 19:10 ` Alex Williamson
2017-07-11 15:33 ` [Qemu-devel] [PULL 0/2] VFIO fixes 2017-07-10 Peter Maydell
2 siblings, 0 replies; 4+ messages in thread
From: Alex Williamson @ 2017-07-10 19:10 UTC (permalink / raw)
To: qemu-devel
Intel 82599 VFs report a PCIe capability version of 0, which is
invalid. The earliest version of the PCIe spec used version 1. This
causes Windows to fail startup on the device and it will be disabled
with error code 10. Our choices are either to drop the PCIe cap on
such devices, which has the side effect of likely preventing the guest
from discovering any extended capabilities, or performing a fixup to
update the capability to the earliest valid version. This implements
the latter.
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---
hw/vfio/pci.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index ccdb6e1d632a..d4051cb9513d 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -1743,6 +1743,18 @@ static int vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
PCI_EXP_LNKCAP_MLW | PCI_EXP_LNKCAP_SLS);
}
+ /*
+ * Intel 82599 SR-IOV VFs report an invalid PCIe capability version 0
+ * (Niantic errate #35) causing Windows to error with a Code 10 for the
+ * device on Q35. Fixup any such devices to report version 1. If we
+ * were to remove the capability entirely the guest would lose extended
+ * config space.
+ */
+ if ((flags & PCI_EXP_FLAGS_VERS) == 0) {
+ vfio_add_emulated_word(vdev, pos + PCI_CAP_FLAGS,
+ 1, PCI_EXP_FLAGS_VERS);
+ }
+
pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size,
errp);
if (pos < 0) {
^ permalink raw reply related [flat|nested] 4+ messages in thread