From patchwork Fri Jun 9 17:30:38 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 9778947 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3671060350 for ; Fri, 9 Jun 2017 17:30:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 14C0F28640 for ; Fri, 9 Jun 2017 17:30:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 075E7286E5; Fri, 9 Jun 2017 17:30:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8FA8128640 for ; Fri, 9 Jun 2017 17:30:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751577AbdFIRan (ORCPT ); Fri, 9 Jun 2017 13:30:43 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48360 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751535AbdFIRan (ORCPT ); Fri, 9 Jun 2017 13:30:43 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8D24380F7D; Fri, 9 Jun 2017 17:30:42 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 8D24380F7D Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=alex.williamson@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 8D24380F7D Received: from gimli.home (ovpn-116-11.phx2.redhat.com [10.3.116.11]) by smtp.corp.redhat.com (Postfix) with ESMTP id 70CC51713D; Fri, 9 Jun 2017 17:30:38 +0000 (UTC) Subject: [PATCH] vfio: Test realized when using VFIOGroup.device_list iterator From: Alex Williamson To: qemu-devel@nongnu.org Cc: eric.auger@redhat.com, alex.williamson@redhat.com, kvm@vger.kernel.org Date: Fri, 09 Jun 2017 11:30:38 -0600 Message-ID: <20170609173021.24851.96804.stgit@gimli.home> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 09 Jun 2017 17:30:42 +0000 (UTC) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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 32aca7770177..8a1d70295fad 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -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)); 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;