@@ -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);
}
}
@@ -2113,7 +2113,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);
@@ -2194,7 +2195,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);
@@ -2644,6 +2646,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));
@@ -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 ?
@@ -115,6 +115,7 @@ typedef struct VFIODevice {
struct VFIOGroup *group;
char *sysfsdev;
char *name;
+ DeviceState *dev;
int fd;
int type;
bool reset_works;
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(-)