提交 2d620f59 编写于 作者: M Michael S. Tsirkin

virtio: don't waste irqfds on control vqs

Pass nvqs to set_guest_notifiers. This makes it possible to
save on irqfds by not allocating one for the control vq
for virtio-net.
Signed-off-by: NMichael S. Tsirkin <mst@redhat.com>
上级 8e4a424b
...@@ -879,7 +879,9 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) ...@@ -879,7 +879,9 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
goto fail; goto fail;
} }
r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, true); r = vdev->binding->set_guest_notifiers(vdev->binding_opaque,
hdev->nvqs,
true);
if (r < 0) { if (r < 0) {
fprintf(stderr, "Error binding guest notifier: %d\n", -r); fprintf(stderr, "Error binding guest notifier: %d\n", -r);
goto fail_notifiers; goto fail_notifiers;
...@@ -929,7 +931,7 @@ fail_vq: ...@@ -929,7 +931,7 @@ fail_vq:
} }
fail_mem: fail_mem:
fail_features: fail_features:
vdev->binding->set_guest_notifiers(vdev->binding_opaque, false); vdev->binding->set_guest_notifiers(vdev->binding_opaque, hdev->nvqs, false);
fail_notifiers: fail_notifiers:
fail: fail:
return r; return r;
...@@ -950,7 +952,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) ...@@ -950,7 +952,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i], vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i],
0, (hwaddr)~0x0ull); 0, (hwaddr)~0x0ull);
} }
r = vdev->binding->set_guest_notifiers(vdev->binding_opaque, false); r = vdev->binding->set_guest_notifiers(vdev->binding_opaque,
hdev->nvqs,
false);
if (r < 0) { if (r < 0) {
fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r); fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
fflush(stderr); fflush(stderr);
......
...@@ -535,7 +535,7 @@ static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector, ...@@ -535,7 +535,7 @@ static int kvm_virtio_pci_vector_use(PCIDevice *dev, unsigned vector,
VirtIODevice *vdev = proxy->vdev; VirtIODevice *vdev = proxy->vdev;
int ret, queue_no; int ret, queue_no;
for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) { for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) { if (!virtio_queue_get_num(vdev, queue_no)) {
break; break;
} }
...@@ -565,7 +565,7 @@ static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector) ...@@ -565,7 +565,7 @@ static void kvm_virtio_pci_vector_release(PCIDevice *dev, unsigned vector)
VirtIODevice *vdev = proxy->vdev; VirtIODevice *vdev = proxy->vdev;
int queue_no; int queue_no;
for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) { for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) { if (!virtio_queue_get_num(vdev, queue_no)) {
break; break;
} }
...@@ -587,7 +587,7 @@ static void kvm_virtio_pci_vector_poll(PCIDevice *dev, ...@@ -587,7 +587,7 @@ static void kvm_virtio_pci_vector_poll(PCIDevice *dev,
EventNotifier *notifier; EventNotifier *notifier;
VirtQueue *vq; VirtQueue *vq;
for (queue_no = 0; queue_no < VIRTIO_PCI_QUEUE_MAX; queue_no++) { for (queue_no = 0; queue_no < proxy->nvqs_with_notifiers; queue_no++) {
if (!virtio_queue_get_num(vdev, queue_no)) { if (!virtio_queue_get_num(vdev, queue_no)) {
break; break;
} }
...@@ -631,7 +631,7 @@ static bool virtio_pci_query_guest_notifiers(DeviceState *d) ...@@ -631,7 +631,7 @@ static bool virtio_pci_query_guest_notifiers(DeviceState *d)
return msix_enabled(&proxy->pci_dev); return msix_enabled(&proxy->pci_dev);
} }
static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign)
{ {
VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d); VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
VirtIODevice *vdev = proxy->vdev; VirtIODevice *vdev = proxy->vdev;
...@@ -639,6 +639,15 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) ...@@ -639,6 +639,15 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign)
bool with_irqfd = msix_enabled(&proxy->pci_dev) && bool with_irqfd = msix_enabled(&proxy->pci_dev) &&
kvm_msi_via_irqfd_enabled(); kvm_msi_via_irqfd_enabled();
nvqs = MIN(nvqs, VIRTIO_PCI_QUEUE_MAX);
/* When deassigning, pass a consistent nvqs value
* to avoid leaking notifiers.
*/
assert(assign || nvqs == proxy->nvqs_with_notifiers);
proxy->nvqs_with_notifiers = nvqs;
/* Must unset vector notifier while guest notifier is still assigned */ /* Must unset vector notifier while guest notifier is still assigned */
if (proxy->vector_irqfd && !assign) { if (proxy->vector_irqfd && !assign) {
msix_unset_vector_notifiers(&proxy->pci_dev); msix_unset_vector_notifiers(&proxy->pci_dev);
...@@ -646,7 +655,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign) ...@@ -646,7 +655,7 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, bool assign)
proxy->vector_irqfd = NULL; proxy->vector_irqfd = NULL;
} }
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) { for (n = 0; n < nvqs; n++) {
if (!virtio_queue_get_num(vdev, n)) { if (!virtio_queue_get_num(vdev, n)) {
break; break;
} }
......
...@@ -51,6 +51,7 @@ typedef struct { ...@@ -51,6 +51,7 @@ typedef struct {
bool ioeventfd_disabled; bool ioeventfd_disabled;
bool ioeventfd_started; bool ioeventfd_started;
VirtIOIRQFD *vector_irqfd; VirtIOIRQFD *vector_irqfd;
int nvqs_with_notifiers;
} VirtIOPCIProxy; } VirtIOPCIProxy;
void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev); void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
......
...@@ -99,7 +99,7 @@ typedef struct { ...@@ -99,7 +99,7 @@ typedef struct {
int (*load_done)(DeviceState *d, QEMUFile *f); int (*load_done)(DeviceState *d, QEMUFile *f);
unsigned (*get_features)(DeviceState *d); unsigned (*get_features)(DeviceState *d);
bool (*query_guest_notifiers)(DeviceState *d); bool (*query_guest_notifiers)(DeviceState *d);
int (*set_guest_notifiers)(DeviceState *d, bool assigned); int (*set_guest_notifiers)(DeviceState *d, int nvqs, bool assigned);
int (*set_host_notifier)(DeviceState *d, int n, bool assigned); int (*set_host_notifier)(DeviceState *d, int n, bool assigned);
void (*vmstate_change)(DeviceState *d, bool running); void (*vmstate_change)(DeviceState *d, bool running);
} VirtIOBindings; } VirtIOBindings;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册