An MSI-address is allocated and programmed in pcie device during interrupt configuration. Now for a pass-through device, try to create the iommu mapping for this allocted/programmed msi-address. If the iommu mapping is created and the msi address programmed in the pcie device is different from msi-iova as per iommu programming then reconfigure the pci device to use msi-iova as msi address. Signed-off-by: Bharat Bhushan <Bharat.Bhushan@xxxxxxxxxxxxx> --- drivers/vfio/pci/vfio_pci_intrs.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 1f577b4..c9690af 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -312,13 +312,23 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, int irq = msix ? vdev->msix[vector].vector : pdev->irq + vector; char *name = msix ? "vfio-msix" : "vfio-msi"; struct eventfd_ctx *trigger; + struct msi_msg msg; + struct vfio_device *device; + uint64_t msi_addr, msi_iova; int ret; if (vector >= vdev->num_ctx) return -EINVAL; + device = vfio_device_get_from_dev(&pdev->dev); + if (device == NULL) + return -EINVAL; + if (vdev->ctx[vector].trigger) { free_irq(irq, vdev->ctx[vector].trigger); + get_cached_msi_msg(irq, &msg); + msi_iova = ((u64)msg.address_hi << 32) | msg.address_lo; + vfio_device_unmap_msi(device, msi_iova, PAGE_SIZE); kfree(vdev->ctx[vector].name); eventfd_ctx_put(vdev->ctx[vector].trigger); vdev->ctx[vector].trigger = NULL; @@ -346,12 +356,11 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, * cached value of the message prior to enabling. */ if (msix) { - struct msi_msg msg; - get_cached_msi_msg(irq, &msg); pci_write_msi_msg(irq, &msg); } + ret = request_irq(irq, vfio_msihandler, 0, vdev->ctx[vector].name, trigger); if (ret) { @@ -360,6 +369,29 @@ static int vfio_msi_set_vector_signal(struct vfio_pci_device *vdev, return ret; } + /* Re-program the new-iova in pci-device in case there is + * different iommu-mapping created for programmed msi-address. + */ + get_cached_msi_msg(irq, &msg); + msi_iova = 0; + msi_addr = (u64)(msg.address_hi) << 32 | (u64)(msg.address_lo); + ret = vfio_device_map_msi(device, msi_addr, PAGE_SIZE, &msi_iova); + if (ret) { + free_irq(irq, vdev->ctx[vector].trigger); + kfree(vdev->ctx[vector].name); + eventfd_ctx_put(trigger); + return ret; + } + + /* Reprogram only if iommu-mapped iova is different from msi-address */ + if (msi_iova && (msi_iova != msi_addr)) { + msg.address_hi = (u32)(msi_iova >> 32); + /* Keep Lower bits from original msi message address */ + msg.address_lo &= PAGE_MASK; + msg.address_lo |= (u32)(msi_iova & 0x00000000ffffffff); + pci_write_msi_msg(irq, &msg); + } + vdev->ctx[vector].trigger = trigger; return 0; -- 1.9.3 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html