From patchwork Mon May 13 20:17:45 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 243522 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2AAED2C009F for ; Tue, 14 May 2013 06:18:07 +1000 (EST) Received: from localhost ([::1]:38670 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UbzC9-0000ER-80 for incoming@patchwork.ozlabs.org; Mon, 13 May 2013 16:18:05 -0400 Received: from eggs.gnu.org ([208.118.235.92]:39445) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UbzBs-0000EB-Td for qemu-devel@nongnu.org; Mon, 13 May 2013 16:17:50 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UbzBr-0005Ac-QN for qemu-devel@nongnu.org; Mon, 13 May 2013 16:17:48 -0400 Received: from mx1.redhat.com ([209.132.183.28]:56645) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UbzBr-0005AY-IJ for qemu-devel@nongnu.org; Mon, 13 May 2013 16:17:47 -0400 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r4DKHkpj010290 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 13 May 2013 16:17:46 -0400 Received: from bling.home (ovpn-113-58.phx2.redhat.com [10.3.113.58]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r4DKHkSe018574; Mon, 13 May 2013 16:17:46 -0400 To: alex.williamson@redhat.com From: Alex Williamson Date: Mon, 13 May 2013 14:17:45 -0600 Message-ID: <20130513201623.5326.54179.stgit@bling.home> User-Agent: StGit/0.16 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.68 on 10.5.11.25 X-MIME-Autoconverted: from 8bit to quoted-printable by mx1.redhat.com id r4DKHkpj010290 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: qemu-devel@nongnu.org Subject: [Qemu-devel] [PATCH v2] vfio-pci: Add support for MSI affinity X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org When MSI is accelerated through KVM the vectors are only programmed when the guest first enables MSI support.  Subsequent writes to the vector address or data fields are ignored.  Unfortunately that means wee ignore updates done to adjust SMP affinity of the vectors. MSI SMP affinity already works in non-KVM mode because the address and data fields are read from their backing store on each interrupt. Update the message any time the address or data fields are written. Signed-off-by: Alex Williamson --- v2: Don't cache MSIMessage, therefore filter only address/data writes hw/misc/vfio.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index 693a9ff..46b3be4 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -163,6 +163,7 @@ typedef struct VFIODevice { #define VFIO_FEATURE_ENABLE_VGA (1 << VFIO_FEATURE_ENABLE_VGA_BIT) int32_t bootindex; uint8_t pm_cap; + bool msi_64bit; bool reset_works; bool has_vga; } VFIODevice; @@ -898,6 +899,22 @@ static void vfio_disable_msi(VFIODevice *vdev) vdev->host.bus, vdev->host.slot, vdev->host.function); } +static void vfio_update_msi(VFIODevice *vdev) +{ + int i; + + for (i = 0; i < vdev->nr_vectors; i++) { + VFIOMSIVector *vector = &vdev->msi_vectors[i]; + + if (!vector->use || vector->virq < 0) { + continue; + } + + kvm_irqchip_update_msi_route(kvm_state, vector->virq, + msi_get_message(&vdev->pdev, i)); + } +} + /* * IO Port/MMIO - Beware of the endians, VFIO is always little endian */ @@ -1850,10 +1867,18 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, is_enabled = msi_enabled(pdev); - if (!was_enabled && is_enabled) { - vfio_enable_msi(vdev); - } else if (was_enabled && !is_enabled) { - vfio_disable_msi(vdev); + if (!was_enabled) { + if (is_enabled) { + vfio_enable_msi(vdev); + } + } else { + if (!is_enabled) { + vfio_disable_msi(vdev); + } else if (ranges_overlap(addr, len, + pdev->msi_cap + PCI_MSI_ADDRESS_LO, + 2 + (vdev->msi_64bit ? 8 : 4))) { + vfio_update_msi(vdev); + } } } else if (pdev->cap_present & QEMU_PCI_CAP_MSIX && ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) { @@ -2046,7 +2071,7 @@ static void vfio_disable_interrupts(VFIODevice *vdev) static int vfio_setup_msi(VFIODevice *vdev, int pos) { uint16_t ctrl; - bool msi_64bit, msi_maskbit; + bool msi_maskbit; int ret, entries; if (pread(vdev->fd, &ctrl, sizeof(ctrl), @@ -2055,14 +2080,14 @@ static int vfio_setup_msi(VFIODevice *vdev, int pos) } ctrl = le16_to_cpu(ctrl); - msi_64bit = !!(ctrl & PCI_MSI_FLAGS_64BIT); + vdev->msi_64bit = !!(ctrl & PCI_MSI_FLAGS_64BIT); msi_maskbit = !!(ctrl & PCI_MSI_FLAGS_MASKBIT); entries = 1 << ((ctrl & PCI_MSI_FLAGS_QMASK) >> 1); DPRINTF("%04x:%02x:%02x.%x PCI MSI CAP @0x%x\n", vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function, pos); - ret = msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit); + ret = msi_init(&vdev->pdev, pos, entries, vdev->msi_64bit, msi_maskbit); if (ret < 0) { if (ret == -ENOTSUP) { return 0; @@ -2070,7 +2095,8 @@ static int vfio_setup_msi(VFIODevice *vdev, int pos) error_report("vfio: msi_init failed"); return ret; } - vdev->msi_cap_size = 0xa + (msi_maskbit ? 0xa : 0) + (msi_64bit ? 0x4 : 0); + vdev->msi_cap_size = 0xa + (msi_maskbit ? 0xa : 0) + + (vdev->msi_64bit ? 0x4 : 0); return 0; }