[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 5/8] virtio: backend virtqueue notifier masking
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] [PATCH 5/8] virtio: backend virtqueue notifier masking |
Date: |
Wed, 26 Dec 2012 12:52:32 +0200 |
some backends (notably vhost) can mask events
at their source in a way that is more efficient
than masking through kvm.
Specifically
- masking in kvm uses rcu write side so it has high latency
- in kvm on unmask we always send an interrupt
masking at source does not have these issues.
Add such support in virtio.h and use in virtio-pci.
Signed-off-by: Michael S. Tsirkin <address@hidden>
---
hw/virtio-pci.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
hw/virtio.h | 13 ++++++++++
2 files changed, 83 insertions(+), 9 deletions(-)
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 1d77146..aad9d6d 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -510,6 +510,31 @@ static void
kvm_virtio_pci_vq_vector_release(VirtIOPCIProxy *proxy,
}
}
+static int kvm_virtio_pci_irqfd_use(VirtIOPCIProxy *proxy,
+ unsigned int queue_no,
+ unsigned int vector)
+{
+ VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
+ VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ EventNotifier *n = virtio_queue_get_guest_notifier(vq);
+ int ret;
+ ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
+ return ret;
+}
+
+static void kvm_virtio_pci_irqfd_release(VirtIOPCIProxy *proxy,
+ unsigned int queue_no,
+ unsigned int vector)
+{
+ VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
+ EventNotifier *n = virtio_queue_get_guest_notifier(vq);
+ VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
+ int ret;
+
+ ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq);
+ assert(ret == 0);
+}
+
static int kvm_virtio_pci_vector_use(VirtIOPCIProxy *proxy, int nvqs)
{
PCIDevice *dev = &proxy->pci_dev;
@@ -531,6 +556,16 @@ static int kvm_virtio_pci_vector_use(VirtIOPCIProxy
*proxy, int nvqs)
if (ret < 0) {
goto undo;
}
+ /* If guest supports masking, set up irqfd now.
+ * Otherwise, delay until unmasked in the frontend.
+ */
+ if (proxy->vdev->guest_notifier_mask) {
+ ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
+ if (ret < 0) {
+ kvm_virtio_pci_vq_vector_release(proxy, vector);
+ goto undo;
+ }
+ }
}
return 0;
@@ -540,6 +575,9 @@ undo:
if (vector >= msix_nr_vectors_allocated(dev)) {
continue;
}
+ if (proxy->vdev->guest_notifier_mask) {
+ kvm_virtio_pci_irqfd_release(proxy, vector, queue_no);
+ }
kvm_virtio_pci_vq_vector_release(proxy, vector);
}
return ret;
@@ -560,6 +598,12 @@ static void kvm_virtio_pci_vector_release(VirtIOPCIProxy
*proxy, int nvqs)
if (vector >= msix_nr_vectors_allocated(dev)) {
continue;
}
+ /* If guest supports masking, clean up irqfd now.
+ * Otherwise, it was cleaned when masked in the frontend.
+ */
+ if (proxy->vdev->guest_notifier_mask) {
+ kvm_virtio_pci_irqfd_release(proxy, vector, queue_no);
+ }
kvm_virtio_pci_vq_vector_release(proxy, vector);
}
}
@@ -581,7 +625,19 @@ static int kvm_virtio_pci_vq_vector_unmask(VirtIOPCIProxy
*proxy,
}
}
- ret = kvm_irqchip_add_irqfd_notifier(kvm_state, n, irqfd->virq);
+ /* If guest supports masking, irqfd is already setup, unmask it.
+ * Otherwise, set it up now.
+ */
+ if (proxy->vdev->guest_notifier_mask) {
+ proxy->vdev->guest_notifier_mask(proxy->vdev, queue_no, false);
+ /* Test after unmasking to avoid losing events. */
+ if (proxy->vdev->guest_notifier_pending &&
+ proxy->vdev->guest_notifier_pending(proxy->vdev, queue_no)) {
+ event_notifier_set(n);
+ }
+ } else {
+ ret = kvm_virtio_pci_irqfd_use(proxy, queue_no, vector);
+ }
return ret;
}
@@ -589,13 +645,14 @@ static void kvm_virtio_pci_vq_vector_mask(VirtIOPCIProxy
*proxy,
unsigned int queue_no,
unsigned int vector)
{
- VirtQueue *vq = virtio_get_queue(proxy->vdev, queue_no);
- EventNotifier *n = virtio_queue_get_guest_notifier(vq);
- VirtIOIRQFD *irqfd = &proxy->vector_irqfd[vector];
- int ret;
-
- ret = kvm_irqchip_remove_irqfd_notifier(kvm_state, n, irqfd->virq);
- assert(ret == 0);
+ /* If guest supports masking, keep irqfd but mask it.
+ * Otherwise, clean it up now.
+ */
+ if (proxy->vdev->guest_notifier_mask) {
+ proxy->vdev->guest_notifier_mask(proxy->vdev, queue_no, true);
+ } else {
+ kvm_virtio_pci_irqfd_release(proxy, vector, queue_no);
+ }
}
static int kvm_virtio_pci_vector_unmask(PCIDevice *dev, unsigned vector,
@@ -668,7 +725,11 @@ static void kvm_virtio_pci_vector_poll(PCIDevice *dev,
}
vq = virtio_get_queue(vdev, queue_no);
notifier = virtio_queue_get_guest_notifier(vq);
- if (event_notifier_test_and_clear(notifier)) {
+ if (vdev->guest_notifier_pending) {
+ if (vdev->guest_notifier_pending(vdev, queue_no)) {
+ msix_set_pending(dev, vector);
+ }
+ } else if (event_notifier_test_and_clear(notifier)) {
msix_set_pending(dev, vector);
}
}
diff --git a/hw/virtio.h b/hw/virtio.h
index 329b426..b9f1873 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -126,6 +126,19 @@ struct VirtIODevice
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
void (*reset)(VirtIODevice *vdev);
void (*set_status)(VirtIODevice *vdev, uint8_t val);
+ /* Test and clear event pending status.
+ * Should be called after unmask to avoid losing events.
+ * If backend does not support masking,
+ * must check in frontend instead.
+ */
+ bool (*guest_notifier_pending)(VirtIODevice *vdev, int n);
+ /* Mask/unmask events from this vq. Any events reported
+ * while masked will become pending.
+ * If backend does not support masking,
+ * must mask in frontend instead.
+ */
+ void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask);
+
VirtQueue *vq;
const VirtIOBindings *binding;
DeviceState *binding_opaque;
--
MST
- [Qemu-devel] [PATCH 0/8] virtio-pci: msix masking optimizations, Michael S. Tsirkin, 2012/12/26
- [Qemu-devel] [PATCH 1/8] virtio: don't waste irqfds on control vqs, Michael S. Tsirkin, 2012/12/26
- [Qemu-devel] [PATCH 2/8] msix: add api to access msix message, Michael S. Tsirkin, 2012/12/26
- [Qemu-devel] [PATCH 4/8] virtio-pci: cache msix messages, Michael S. Tsirkin, 2012/12/26
- [Qemu-devel] [PATCH 3/8] kvm: add stub for update msi route, Michael S. Tsirkin, 2012/12/26
- [Qemu-devel] [PATCH 5/8] virtio: backend virtqueue notifier masking,
Michael S. Tsirkin <=
- [Qemu-devel] [PATCH 8/8] vhost: backend masking support, Michael S. Tsirkin, 2012/12/26
- [Qemu-devel] [PATCH 6/8] virtio-net: set/clear vhost_started in reverse order, Michael S. Tsirkin, 2012/12/26
- [Qemu-devel] [PATCH 7/8] vhost: set started flag while start is in progress, Michael S. Tsirkin, 2012/12/26