From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alex Williamson Subject: [PULL 1/6] vfio-pci: Add support for MSI affinity Date: Thu, 03 Oct 2013 09:38:44 -0600 Message-ID: <20131003153831.26487.72827.stgit@bling.home> References: <20131003153601.26487.70022.stgit@bling.home> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: QUOTED-PRINTABLE Cc: aik@ozlabs.ru, qemu-devel@nongnu.org, kvm@vger.kernel.org To: anthony@codemonkey.ws Return-path: Received: from mx1.redhat.com ([209.132.183.28]:5984 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753777Ab3JCPis (ORCPT ); Thu, 3 Oct 2013 11:38:48 -0400 In-Reply-To: <20131003153601.26487.70022.stgit@bling.home> Sender: kvm-owner@vger.kernel.org List-ID: When MSI is accelerated through KVM the vectors are only programmed when the guest first enables MSI support.=C2=A0 Subsequent writes to th= e vector address or data fields are ignored.=C2=A0 Unfortunately that mea= ns we're 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. This patch stores the MSIMessage programmed into KVM so that we can determine when changes are made and update the routes. Signed-off-by: Alex Williamson --- hw/misc/vfio.c | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index a1c08fb..75a53e2 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -119,6 +119,7 @@ typedef struct VFIOINTx { typedef struct VFIOMSIVector { EventNotifier interrupt; /* eventfd triggered on interrupt */ struct VFIODevice *vdev; /* back pointer to device */ + MSIMessage msg; /* cache the MSI message so we know when it change= s */ int virq; /* KVM irqchip route for QEMU bypass */ bool use; } VFIOMSIVector; @@ -795,7 +796,6 @@ retry: vdev->msi_vectors =3D g_malloc0(vdev->nr_vectors * sizeof(VFIOMSIV= ector)); =20 for (i =3D 0; i < vdev->nr_vectors; i++) { - MSIMessage msg; VFIOMSIVector *vector =3D &vdev->msi_vectors[i]; =20 vector->vdev =3D vdev; @@ -805,13 +805,13 @@ retry: error_report("vfio: Error: event_notifier_init failed"); } =20 - msg =3D msi_get_message(&vdev->pdev, i); + vector->msg =3D msi_get_message(&vdev->pdev, i); =20 /* * Attempt to enable route through KVM irqchip, * default to userspace handling if unavailable. */ - vector->virq =3D kvm_irqchip_add_msi_route(kvm_state, msg); + vector->virq =3D kvm_irqchip_add_msi_route(kvm_state, vector->= msg); if (vector->virq < 0 || kvm_irqchip_add_irqfd_notifier(kvm_state, &vector->interru= pt, NULL, vector->virq) < 0) { @@ -917,6 +917,33 @@ 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]; + MSIMessage msg; + + if (!vector->use || vector->virq < 0) { + continue; + } + + msg =3D msi_get_message(&vdev->pdev, i); + + if (msg.address !=3D vector->msg.address || + msg.data !=3D vector->msg.data) { + + DPRINTF("%s(%04x:%02x:%02x.%x) MSI vector %d changed\n", + __func__, vdev->host.domain, vdev->host.bus, + vdev->host.slot, vdev->host.function, i); + + kvm_irqchip_update_msi_route(kvm_state, vector->virq, msg)= ; + vector->msg =3D msg; + } + } +} + /* * IO Port/MMIO - Beware of the endians, VFIO is always little endian */ @@ -1834,10 +1861,16 @@ static void vfio_pci_write_config(PCIDevice *pd= ev, 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 { + vfio_update_msi(vdev); + } } } else if (pdev->cap_present & QEMU_PCI_CAP_MSIX && ranges_overlap(addr, len, pdev->msix_cap, MSIX_CAP_LENGTH)) {