From patchwork Thu Jun 17 17:51:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 106723 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o5HHpxF9026799 for ; Thu, 17 Jun 2010 17:52:20 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760386Ab0FQRv5 (ORCPT ); Thu, 17 Jun 2010 13:51:57 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55738 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755146Ab0FQRv5 (ORCPT ); Thu, 17 Jun 2010 13:51:57 -0400 Received: from int-mx05.intmail.prod.int.phx2.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.18]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o5HHpuW7003592 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 17 Jun 2010 13:51:56 -0400 Received: from localhost.localdomain (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx05.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o5HHpts9022334; Thu, 17 Jun 2010 13:51:55 -0400 From: Alex Williamson Subject: [PATCH] device-assignment: be more selective in interrupt disabling To: kvm@vger.kernel.org Cc: chrisw@redhat.com, alex.williamson@redhat.com Date: Thu, 17 Jun 2010 11:51:55 -0600 Message-ID: <20100617174948.4792.54699.stgit@localhost.localdomain> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.67 on 10.5.11.18 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Thu, 17 Jun 2010 17:53:22 +0000 (UTC) diff --git a/hw/device-assignment.c b/hw/device-assignment.c index ba02157..85cd414 100644 --- a/hw/device-assignment.c +++ b/hw/device-assignment.c @@ -1031,13 +1031,20 @@ static void assigned_dev_update_msi(PCIDevice *pci_dev, unsigned int ctrl_pos) calc_assigned_dev_id(assigned_dev->h_segnr, assigned_dev->h_busnr, (uint8_t)assigned_dev->h_devfn); - if (assigned_dev->irq_requested_type) { - assigned_irq_data.flags = assigned_dev->irq_requested_type; - free_dev_irq_entries(assigned_dev); - r = kvm_deassign_irq(kvm_context, &assigned_irq_data); - /* -ENXIO means no assigned irq */ - if (r && r != -ENXIO) - perror("assigned_dev_update_msi: deassign irq"); + /* Some guests gratuitously disable MSI even if they're not using it, + * try to catch this by only deassigning irqs if the guest is using + * MSI or intends to start. */ + if ((assigned_dev->irq_requested_type & KVM_DEV_IRQ_GUEST_MSI) || + (ctrl_byte & PCI_MSI_FLAGS_ENABLE)) { + + assigned_irq_data.flags = assigned_dev->irq_requested_type; + free_dev_irq_entries(assigned_dev); + r = kvm_deassign_irq(kvm_context, &assigned_irq_data); + /* -ENXIO means no assigned irq */ + if (r && r != -ENXIO) + perror("assigned_dev_update_msi: deassign irq"); + + assigned_irq_data.flags = 0; } if (ctrl_byte & PCI_MSI_FLAGS_ENABLE) { @@ -1188,17 +1195,26 @@ static void assigned_dev_update_msix(PCIDevice *pci_dev, unsigned int ctrl_pos) calc_assigned_dev_id(assigned_dev->h_segnr, assigned_dev->h_busnr, (uint8_t)assigned_dev->h_devfn); - if (assigned_dev->irq_requested_type) { + /* Some guests gratuitously disable MSIX even if they're not using it, + * try to catch this by only deassigning irqs if the guest is using + * MSIX or intends to start. */ + if ((assigned_dev->irq_requested_type & KVM_DEV_IRQ_GUEST_MSIX) || + (*ctrl_word & PCI_MSIX_ENABLE)) { + assigned_irq_data.flags = assigned_dev->irq_requested_type; free_dev_irq_entries(assigned_dev); r = kvm_deassign_irq(kvm_context, &assigned_irq_data); /* -ENXIO means no assigned irq */ if (r && r != -ENXIO) perror("assigned_dev_update_msix: deassign irq"); + + assigned_irq_data.flags = 0; } - assigned_irq_data.flags = KVM_DEV_IRQ_HOST_MSIX | KVM_DEV_IRQ_GUEST_MSIX; if (*ctrl_word & PCI_MSIX_ENABLE) { + assigned_irq_data.flags = KVM_DEV_IRQ_HOST_MSIX | + KVM_DEV_IRQ_GUEST_MSIX; + if (assigned_dev_update_msix_mmio(pci_dev) < 0) { perror("assigned_dev_update_msix_mmio"); return;