qemu/virtio: use last used index published by guest
RFC PATCH 1/1 qemu/virtio: use last used index published by guest
Reduces irq_window in guest by only injecting
an interrupt if guest has handled all buffers we
used so far.
Signed-off-by Michael S. Tsirkin <[email protected]>
---
This is the qemu part of the story.
hw/vhost_net.c | 6 ++++++ hw/virtio.c | 15 +++++++++++++++ hw/virtio.h | 4 ++++ 3 files changed, 25 insertions(+), 0 deletions(-)
hw/vhost_net.c +6 -0
@@ -51,6 +51,9 @@ unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)if (!(net->dev.features & (1 <<VIRTIO_RING_F_INDIRECT_DESC ))) { features &= ~(1 <<VIRTIO_RING_F_INDIRECT_DESC ); } +if (!(net->dev.features & (1 <<VIRTIO_RING_F_PUBLISH_USED ))) { + features &= ~(1 <<VIRTIO_RING_F_PUBLISH_USED ); + } features &= ~(1 <<VIRTIO_NET_F_MRG_RXBUF );return features; }
@@ -64,6 +67,9 @@ void vhost_net_ack_features(struct vhost_net *net, unsigned features)if (features & (1 <<VIRTIO_RING_F_INDIRECT_DESC )) { net->dev.acked_features |= (1 <<VIRTIO_RING_F_INDIRECT_DESC ); } +if (features & (1 <<VIRTIO_RING_F_PUBLISH_USED )) { + net->dev.acked_features |= (1 <<VIRTIO_RING_F_PUBLISH_USED ); + } }static int vhost_net_get_fd (VLANClientState *backend)
hw/virtio.c +15 -0
@@ -71,6 +71,7 @@ struct VirtQueuetarget_phys_addr_t pa;uint16_t last_avail_idx;int inuse; +int num_notify;uint16_t vector;void (*handle_output)(VirtIODevice *vdev,VirtQueue *vq);VirtIODevice *vdev;
@@ -139,6 +140,11 @@ static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)return lduw_phys (pa); } +static inline uint16_t vring_last_used_idx (VirtQueue *vq) +{ +return vring_avail_ring (vq, vq->vring.num); +} +static inline void vring_used_ring_id (VirtQueue *vq,int i,uint32_t val) {target_phys_addr_t pa;
@@ -234,6 +240,7 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count)wmb ();vring_used_idx_increment (vq, count); vq->inuse -= count; + vq->num_notify += count; } void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
@@ -603,6 +610,14 @@ void virtio_irq(VirtQueue *vq)void virtio_notify (VirtIODevice *vdev,VirtQueue *vq) { +/* Do not notify if guest did not yet see the last update. */ +if ((vdev->guest_features & (1 <<VIRTIO_RING_F_PUBLISH_USED )) && +vring_last_used_idx (vq) != + (uint16_t )(vring_used_idx (vq) + vq->num_notify)) +return ; + + vq->num_notify =0 ; +/* Always notify when queue is empty (when feature acknowledge) */ if ((vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT) && (!(vdev->guest_features & (1 << VIRTIO_F_NOTIFY_ON_EMPTY)) ||
hw/virtio.h +4 -0
@@ -43,6 +43,8 @@#define VIRTIO_F_NOTIFY_ON_EMPTY 24/* We support indirect buffer descriptors */ #define VIRTIO_RING_F_INDIRECT_DESC 28 +/* The Guest publishes last-seen used index at the end of the avail ring. */ +#define VIRTIO_RING_F_PUBLISH_USED 29/* A guest should never accept this. It implies negotiation is broken. */ #define VIRTIO_F_BAD_FEATURE 30
@@ -189,6 +191,8 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev);void virtio_net_exit (VirtIODevice *vdev);#define DEFINE_VIRTIO_COMMON_FEATURES (_state, _field) \ + DEFINE_PROP_BIT("publish_used", _state, _field, \ + VIRTIO_RING_F_PUBLISH_USED, true), \ DEFINE_PROP_BIT("indirect_desc", _state, _field, \ VIRTIO_RING_F_INDIRECT_DESC, true)
Signature · 1 line
1.7.1.12.g42b7f