diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 073e22c315..a285d18197 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -191,6 +191,11 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr, unsigned size) { PCIDevice *dev = opaque; + if (dev->msix_vector_poll_notifier) { + unsigned vector_start = addr * 8; + unsigned vector_end = MIN(addr + size * 8, dev->msix_entries_nr); + dev->msix_vector_poll_notifier(dev, vector_start, vector_end); + } return pci_get_long(dev->msix_pba + addr); } @@ -513,7 +518,8 @@ static void msix_unset_notifier_for_vector(PCIDevice *dev, unsigned int vector) int msix_set_vector_notifiers(PCIDevice *dev, MSIVectorUseNotifier use_notifier, - MSIVectorReleaseNotifier release_notifier) + MSIVectorReleaseNotifier release_notifier, + MSIVectorPollNotifier poll_notifier) { int vector, ret; @@ -521,6 +527,7 @@ int msix_set_vector_notifiers(PCIDevice *dev, dev->msix_vector_use_notifier = use_notifier; dev->msix_vector_release_notifier = release_notifier; + dev->msix_vector_poll_notifier = poll_notifier; if ((dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & (MSIX_ENABLE_MASK | MSIX_MASKALL_MASK)) == MSIX_ENABLE_MASK) { @@ -531,6 +538,9 @@ int msix_set_vector_notifiers(PCIDevice *dev, } } } + if (dev->msix_vector_poll_notifier) { + dev->msix_vector_poll_notifier(dev, 0, dev->msix_entries_nr); + } return 0; undo: @@ -557,4 +567,5 @@ void msix_unset_vector_notifiers(PCIDevice *dev) } dev->msix_vector_use_notifier = NULL; dev->msix_vector_release_notifier = NULL; + dev->msix_vector_poll_notifier = NULL; } diff --git a/hw/pci/msix.h b/hw/pci/msix.h index ff07ae2e8f..ea85d02264 100644 --- a/hw/pci/msix.h +++ b/hw/pci/msix.h @@ -36,6 +36,7 @@ void msix_reset(PCIDevice *dev); int msix_set_vector_notifiers(PCIDevice *dev, MSIVectorUseNotifier use_notifier, - MSIVectorReleaseNotifier release_notifier); + MSIVectorReleaseNotifier release_notifier, + MSIVectorPollNotifier poll_notifier); void msix_unset_vector_notifiers(PCIDevice *dev); #endif diff --git a/hw/pci/pci.h b/hw/pci/pci.h index 3152050856..72927e3149 100644 --- a/hw/pci/pci.h +++ b/hw/pci/pci.h @@ -187,6 +187,9 @@ typedef void (*PCIINTxRoutingNotifier)(PCIDevice *dev); typedef int (*MSIVectorUseNotifier)(PCIDevice *dev, unsigned int vector, MSIMessage msg); typedef void (*MSIVectorReleaseNotifier)(PCIDevice *dev, unsigned int vector); +typedef void (*MSIVectorPollNotifier)(PCIDevice *dev, + unsigned int vector_start, + unsigned int vector_end); struct PCIDevice { DeviceState qdev; @@ -271,6 +274,7 @@ struct PCIDevice { /* MSI-X notifiers */ MSIVectorUseNotifier msix_vector_use_notifier; MSIVectorReleaseNotifier msix_vector_release_notifier; + MSIVectorPollNotifier msix_vector_poll_notifier; }; void pci_register_bar(PCIDevice *pci_dev, int region_num, diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c index 41fb7ad1de..28c83031d0 100644 --- a/hw/vfio_pci.c +++ b/hw/vfio_pci.c @@ -698,7 +698,7 @@ static void vfio_enable_msix(VFIODevice *vdev) vdev->interrupt = VFIO_INT_MSIX; if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use, - vfio_msix_vector_release)) { + vfio_msix_vector_release, NULL)) { error_report("vfio: msix_set_vector_notifiers failed\n"); } diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 1f1a285ce8..37e8b2d255 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -637,7 +637,8 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) msix_nr_vectors_allocated(&proxy->pci_dev)); r = msix_set_vector_notifiers(&proxy->pci_dev, kvm_virtio_pci_vector_use, - kvm_virtio_pci_vector_release); + kvm_virtio_pci_vector_release, + NULL); if (r < 0) { goto assign_error; }