From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54628) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y9cSg-0005Js-Ra for qemu-devel@nongnu.org; Fri, 09 Jan 2015 11:31:04 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y9cSg-00021I-0A for qemu-devel@nongnu.org; Fri, 09 Jan 2015 11:30:58 -0500 Received: from mx1.redhat.com ([209.132.183.28]:45303) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y9cSf-000216-P4 for qemu-devel@nongnu.org; Fri, 09 Jan 2015 11:30:57 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id t09GUvg9021497 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Fri, 9 Jan 2015 11:30:57 -0500 From: Alex Williamson Date: Fri, 09 Jan 2015 09:30:56 -0700 Message-ID: <20150109163056.23623.74322.stgit@bling.home> In-Reply-To: <20150109162948.23623.92260.stgit@bling.home> References: <20150109162948.23623.92260.stgit@bling.home> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PULL 2/2] vfio-pci: Fix interrupt disabling List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: alex.williamson@redhat.com When disabling MSI/X interrupts the disable functions will leave the device in INTx mode (when available). This matches how hardware operates, INTx is enabled unless MSI/X is enabled (DisINTx is handled separately). Therefore when we really want to disable all interrupts, such as when removing the device, and we start with the device in MSI/X mode, we need to pass through INTx on our way to being completely quiesced. In well behaved situations, the guest driver will have shutdown the device and it will start vfio_exitfn() in INTx mode, producing the desired result. If hot-unplug causes the guest to crash, we may get the device in MSI/X state, which will leave QEMU with a bogus handler installed. Fix this by re-ordering our disable routine so that it should always finish in VFIO_INT_NONE state, which is what all callers expect. Signed-off-by: Alex Williamson --- hw/vfio/pci.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index b6703c7..014a92c 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2129,16 +2129,19 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, */ static void vfio_disable_interrupts(VFIOPCIDevice *vdev) { - switch (vdev->interrupt) { - case VFIO_INT_INTx: - vfio_disable_intx(vdev); - break; - case VFIO_INT_MSI: - vfio_disable_msi(vdev); - break; - case VFIO_INT_MSIX: + /* + * More complicated than it looks. Disabling MSI/X transitions the + * device to INTx mode (if supported). Therefore we need to first + * disable MSI/X and then cleanup by disabling INTx. + */ + if (vdev->interrupt == VFIO_INT_MSIX) { vfio_disable_msix(vdev); - break; + } else if (vdev->interrupt == VFIO_INT_MSI) { + vfio_disable_msi(vdev); + } + + if (vdev->interrupt == VFIO_INT_INTx) { + vfio_disable_intx(vdev); } }