---
hw/virtio/virtio-pci.c | 45 ++++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 2fe5b1f5aa..fe06847b62 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -710,6 +710,28 @@ static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy
*proxy,
ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, n, irqfd->virq);
assert(ret == 0);
}
+static int virtio_pci_get_notifier(VirtIOPCIProxy *proxy, int queue_no,
+ EventNotifier **n, unsigned int *vector)
+{
+ PCIDevice *dev = &proxy->pci_dev;
+ VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
+ VirtQueue *vq;
+
+ if (queue_no == VIRTIO_CONFIG_IRQ_IDX) {
+ return -1;
+ } else {
+ if (!virtio_queue_get_num(vdev, queue_no)) {
+ return -1;
+ }
+ *vector = virtio_queue_vector(vdev, queue_no);
+ vq = virtio_get_queue(vdev, queue_no);
+ *n = virtio_queue_get_guest_notifier(vq);
+ }
+ if (*vector >= msix_nr_vectors_allocated(dev)) {
+ return -1;
+ }
+ return 0;
+}
static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
{
@@ -718,13 +740,15 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy
*proxy, int nvqs)
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
unsigned int vector;
int ret, queue_no;
- VirtQueue *vq;
EventNotifier *n;
for (queue_no = 0; queue_no < nvqs; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) {
break;
}
- vector = virtio_queue_vector(vdev, queue_no);
+ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector);
+ if (ret < 0) {
+ break;
+ }
if (vector >= msix_nr_vectors_allocated(dev)) {
continue;
}
@@ -736,8 +760,6 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy,
int nvqs)
* Otherwise, delay until unmasked in the frontend.
*/
if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
- vq = virtio_get_queue(vdev, queue_no);
- n = virtio_queue_get_guest_notifier(vq);
ret = kvm_virtio_pci_irqfd_use(proxy, n, vector);
if (ret < 0) {
kvm_virtio_pci_vq_vector_release(proxy, vector);
@@ -754,8 +776,10 @@ undo:
continue;
}
if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
- vq = virtio_get_queue(vdev, queue_no);
- n = virtio_queue_get_guest_notifier(vq);
+ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector);
+ if (ret < 0) {
+ break;
+ }
kvm_virtio_pci_irqfd_release(proxy, n, vector);
}
kvm_virtio_pci_vq_vector_release(proxy, vector);
@@ -770,13 +794,16 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy
*proxy, int nvqs)
unsigned int vector;
int queue_no;
VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
- VirtQueue *vq;
EventNotifier *n;
+ int ret ;
for (queue_no = 0; queue_no < nvqs; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) {
break;
}
- vector = virtio_queue_vector(vdev, queue_no);
+ ret = virtio_pci_get_notifier(proxy, queue_no, &n, &vector);
+ if (ret < 0) {
+ break;
+ }
if (vector >= msix_nr_vectors_allocated(dev)) {
continue;
}
@@ -784,8 +811,6 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy
*proxy, int nvqs)
* Otherwise, it was cleaned when masked in the frontend.
*/
if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) {
- vq = virtio_get_queue(vdev, queue_no);
- n = virtio_queue_get_guest_notifier(vq);
kvm_virtio_pci_irqfd_release(proxy, n, vector);
}
kvm_virtio_pci_vq_vector_release(proxy, vector);