[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/2] ioemu: passthrough: MSI-X mask bit acceleration
Read MSI-X mask bit directly from the device, since buffered version may not be up-to-date when MSI-X mask bit interception is working. Also rebind every MSI-X vector on guest PCI BAR rebalancing so that MSI-X mask bit intercept handler can get the correct gpa Signed-off-by: Qing He <qing.he@xxxxxxxxx> --- pass-through.c | 3 +++ pt-msi.c | 41 ++++++++++++++++++++++++++++++++++++++--- pt-msi.h | 3 +++ 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/hw/pass-through.c b/hw/pass-through.c index 96e7160..df6bd1e 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -983,6 +983,9 @@ void pt_iomem_map(PCIDevice *d, int i, uint32_t e_phys, uint32_t e_size, ret = remove_msix_mapping(assigned_device, i); if ( ret != 0 ) PT_LOG("Error: remove MSI-X mmio mapping failed!\n"); + + if ( old_ebase != e_phys && old_ebase != -1 ) + pt_msix_update_remap(assigned_device, i); } } diff --git a/hw/pt-msi.c b/hw/pt-msi.c index ba86d7a..887f0a2 100644 --- a/hw/pt-msi.c +++ b/hw/pt-msi.c @@ -127,7 +127,7 @@ int pt_msi_update(struct pt_dev *d) PT_LOG("Update msi with pirq %x gvec %x\n", d->msi->pirq, gvec); return xc_domain_update_msi_irq(xc_handle, domid, gvec, - d->msi->pirq, gflags); + d->msi->pirq, gflags, 0); } void pt_msi_disable(struct pt_dev *dev) @@ -304,7 +304,8 @@ static int pt_msix_update_one(struct pt_dev *dev, int entry_nr) PT_LOG("Update msix entry %x with pirq %x gvec %x\n", entry_nr, pirq, gvec); - ret = xc_domain_update_msi_irq(xc_handle, domid, gvec, pirq, gflags); + ret = xc_domain_update_msi_irq(xc_handle, domid, gvec, pirq, gflags, + dev->msix->mmio_base_addr); if ( ret ) { PT_LOG("Error: Updating msix irq info for entry %d\n", entry_nr); @@ -375,6 +376,31 @@ void pt_msix_disable(struct pt_dev *dev) } } +int pt_msix_update_remap(struct pt_dev *dev, int bar_index) +{ + struct msix_entry_info *entry; + int i, ret; + + if ( !(dev->msix && dev->msix->bar_index == bar_index) ) + return 0; + + for ( i = 0; i < dev->msix->total_entries; i++ ) + { + entry = &dev->msix->msix_entry[i]; + if ( entry->pirq != -1 ) + { + ret = xc_domain_unbind_pt_irq(xc_handle, domid, entry->pirq, + PT_IRQ_TYPE_MSI, 0, 0, 0, 0); + if ( ret ) + PT_LOG("Error: unbind MSI-X entry %d failed\n", entry->pirq); + entry->flags = 1; + } + } + pt_msix_update(dev); + + return 0; +} + static void pci_msix_invalid_write(void *opaque, target_phys_addr_t addr, uint32_t val) { @@ -388,6 +414,8 @@ static void pci_msix_writel(void *opaque, target_phys_addr_t addr, uint32_t val) struct pt_msix_info *msix = dev->msix; struct msix_entry_info *entry; int entry_nr, offset; + void *phys_off; + uint32_t vec_ctrl; if ( addr % 4 ) { @@ -400,7 +428,14 @@ static void pci_msix_writel(void *opaque, target_phys_addr_t addr, uint32_t val) entry = &msix->msix_entry[entry_nr]; offset = ((addr - msix->mmio_base_addr) % 16) / 4; - if ( offset != 3 && msix->enabled && !(entry->io_mem[3] & 0x1) ) + /* + * If Xen intercepts the mask bit access, io_mem[3] may not be + * up-to-date. Read from hardware directly. + */ + phys_off = dev->msix->phys_iomem_base + 16 * entry_nr + 12; + vec_ctrl = *(uint32_t *)phys_off; + + if ( offset != 3 && msix->enabled && !(vec_ctrl & 0x1) ) { PT_LOG("Error: Can't update msix entry %d since MSI-X is already \ function.\n", entry_nr); diff --git a/hw/pt-msi.h b/hw/pt-msi.h index dea0848..d9c3f88 100644 --- a/hw/pt-msi.h +++ b/hw/pt-msi.h @@ -95,6 +95,9 @@ void pt_disable_msi_translate(struct pt_dev *dev); int +pt_msi_update_remap(struct pt_dev *d, int bar_index); + +int pt_msix_update(struct pt_dev *dev); void _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |