From mboxrd@z Thu Jan 1 00:00:00 1970 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 From: Alex Williamson Date: Mon, 13 May 2013 14:17:45 -0600 Message-ID: <20130513201623.5326.54179.stgit@bling.home> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PATCH v2] vfio-pci: Add support for MSI affinity List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: alex.williamson@redhat.com Cc: qemu-devel@nongnu.org When MSI is accelerated through KVM the vectors are only programmed when the guest first enables MSI support.=C2=A0 Subsequent writes to the vector address or data fields are ignored.=C2=A0 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); } =20 +static void vfio_update_msi(VFIODevice *vdev) +{ + int i; + + for (i =3D 0; i < vdev->nr_vectors; i++) { + VFIOMSIVector *vector =3D &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, =20 is_enabled =3D msi_enabled(pdev); =20 - 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 *vde= v) static int vfio_setup_msi(VFIODevice *vdev, int pos) { uint16_t ctrl; - bool msi_64bit, msi_maskbit; + bool msi_maskbit; int ret, entries; =20 if (pread(vdev->fd, &ctrl, sizeof(ctrl), @@ -2055,14 +2080,14 @@ static int vfio_setup_msi(VFIODevice *vdev, int p= os) } ctrl =3D le16_to_cpu(ctrl); =20 - msi_64bit =3D !!(ctrl & PCI_MSI_FLAGS_64BIT); + vdev->msi_64bit =3D !!(ctrl & PCI_MSI_FLAGS_64BIT); msi_maskbit =3D !!(ctrl & PCI_MSI_FLAGS_MASKBIT); entries =3D 1 << ((ctrl & PCI_MSI_FLAGS_QMASK) >> 1); =20 DPRINTF("%04x:%02x:%02x.%x PCI MSI CAP @0x%x\n", vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function, pos); =20 - ret =3D msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit); + ret =3D msi_init(&vdev->pdev, pos, entries, vdev->msi_64bit, msi_mas= kbit); if (ret < 0) { if (ret =3D=3D -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 =3D 0xa + (msi_maskbit ? 0xa : 0) + (msi_64bit ? = 0x4 : 0); + vdev->msi_cap_size =3D 0xa + (msi_maskbit ? 0xa : 0) + + (vdev->msi_64bit ? 0x4 : 0); =20 return 0; }