virtio-pci: don't try to mask or unmask vqs without notifiers

We should validate the vq index against nvqs_with_notifiers. Otherwise we may
try to mask or unmask vector for vqs without notifiers (e.g control vq). This
will lead qemu abort on kvm_irqchip_commit_routes() when trying to boot win8.1
guest.

Fixes 851c2a75a6 ("virtio-pci: speedup MSI-X
masking and unmasking")

Reported-by: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Jason Wang 2015-05-27 16:26:07 +08:00 committed by Michael S. Tsirkin
parent 557772f26b
commit 6652d0811c

View File

@ -632,21 +632,26 @@ static int virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
if (!virtio_queue_get_num(vdev, index)) { if (!virtio_queue_get_num(vdev, index)) {
break; break;
} }
if (index < proxy->nvqs_with_notifiers) {
ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg); ret = virtio_pci_vq_vector_unmask(proxy, index, vector, msg);
if (ret < 0) { if (ret < 0) {
goto undo; goto undo;
} }
vq = virtio_vector_next_queue(vq);
++unmasked; ++unmasked;
} }
vq = virtio_vector_next_queue(vq);
}
return 0; return 0;
undo: undo:
vq = virtio_vector_first_queue(vdev, vector); vq = virtio_vector_first_queue(vdev, vector);
while (vq && --unmasked >= 0) { while (vq && unmasked >= 0) {
index = virtio_get_queue_index(vq); index = virtio_get_queue_index(vq);
if (index < proxy->nvqs_with_notifiers) {
virtio_pci_vq_vector_mask(proxy, index, vector); virtio_pci_vq_vector_mask(proxy, index, vector);
--unmasked;
}
vq = virtio_vector_next_queue(vq); vq = virtio_vector_next_queue(vq);
} }
return ret; return ret;
@ -664,7 +669,9 @@ static void virtio_pci_vector_mask(PCIDevice *dev, unsigned vector)
if (!virtio_queue_get_num(vdev, index)) { if (!virtio_queue_get_num(vdev, index)) {
break; break;
} }
if (index < proxy->nvqs_with_notifiers) {
virtio_pci_vq_vector_mask(proxy, index, vector); virtio_pci_vq_vector_mask(proxy, index, vector);
}
vq = virtio_vector_next_queue(vq); vq = virtio_vector_next_queue(vq);
} }
} }