Skip to content

Commit

Permalink
vhost: support virtqueue interrupt/notification suppression
Browse files Browse the repository at this point in the history
The driver can suppress interrupt when VIRTIO_F_EVENT_IDX feature bit is
negotiated. The driver set vring flags to 0, and MAY use used_event in
available ring to advise device interrupt util reach an index specified
by used_event. The device ignore the lower bit of vring flags, and send
an interrupt when index reach used_event.

The device can suppress notification in a manner analogous to the ways
driver suppress interrupt. The device manipulates flags or avail_event in
the used ring in the same way the driver manipulates flags or used_event in
available ring.

Signed-off-by: Junjie Chen <junjie.j.chen@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Tested-by: Lei Yao <lei.a.yao@intel.com>
Acked-by: Yuanhan Liu <yliu@fridaylinux.org>
  • Loading branch information
Junjie Chen authored and Ferruh Yigit committed Jan 16, 2018
1 parent 6a59d64 commit e37ff95
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
2 changes: 1 addition & 1 deletion lib/librte_vhost/vhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ rte_vhost_vring_call(int vid, uint16_t vring_idx)
if (!vq)
return -1;

vhost_vring_call(vq);
vhost_vring_call(dev, vq);
return 0;
}

Expand Down
44 changes: 39 additions & 5 deletions lib/librte_vhost/vhost.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ struct vhost_virtqueue {

uint16_t last_avail_idx;
uint16_t last_used_idx;
/* Last used index we notify to front end. */
uint16_t signalled_used;
#define VIRTIO_INVALID_EVENTFD (-1)
#define VIRTIO_UNINITIALIZED_EVENTFD (-2)

Expand Down Expand Up @@ -185,6 +187,7 @@ struct vhost_msg {
(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
(1ULL << VIRTIO_NET_F_GUEST_UFO) | \
(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
(1ULL << VIRTIO_RING_F_EVENT_IDX) | \
(1ULL << VIRTIO_NET_F_MTU) | \
(1ULL << VIRTIO_F_IOMMU_PLATFORM))

Expand Down Expand Up @@ -370,16 +373,47 @@ vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,
return __vhost_iova_to_vva(dev, vq, iova, size, perm);
}

#define vhost_used_event(vr) \
(*(volatile uint16_t*)&(vr)->avail->ring[(vr)->size])

/*
* The following is used with VIRTIO_RING_F_EVENT_IDX.
* Assuming a given event_idx value from the other size, if we have
* just incremented index from old to new_idx, should we trigger an
* event?
*/
static __rte_always_inline int
vhost_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old)
{
return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old);
}

static __rte_always_inline void
vhost_vring_call(struct vhost_virtqueue *vq)
vhost_vring_call(struct virtio_net *dev, struct vhost_virtqueue *vq)
{
/* Flush used->idx update before we read avail->flags. */
rte_mb();

/* Kick the guest if necessary. */
if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
&& (vq->callfd >= 0))
eventfd_write(vq->callfd, (eventfd_t)1);
/* Don't kick guest if we don't reach index specified by guest. */
if (dev->features & (1ULL << VIRTIO_RING_F_EVENT_IDX)) {
uint16_t old = vq->signalled_used;
uint16_t new = vq->last_used_idx;

LOG_DEBUG(VHOST_DATA, "%s: used_event_idx=%d, old=%d, new=%d\n",
__func__,
vhost_used_event(vq),
old, new);
if (vhost_need_event(vhost_used_event(vq), new, old)
&& (vq->callfd >= 0)) {
vq->signalled_used = vq->last_used_idx;
eventfd_write(vq->callfd, (eventfd_t) 1);
}
} else {
/* Kick the guest if necessary. */
if (!(vq->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
&& (vq->callfd >= 0))
eventfd_write(vq->callfd, (eventfd_t)1);
}
}

#endif /* _VHOST_NET_CDEV_H_ */
6 changes: 3 additions & 3 deletions lib/librte_vhost/virtio_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ virtio_dev_rx(struct virtio_net *dev, uint16_t queue_id,
offsetof(struct vring_used, idx),
sizeof(vq->used->idx));

vhost_vring_call(vq);
vhost_vring_call(dev, vq);
out:
if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
vhost_user_iotlb_rd_unlock(vq);
Expand Down Expand Up @@ -671,7 +671,7 @@ virtio_dev_merge_rx(struct virtio_net *dev, uint16_t queue_id,

if (likely(vq->shadow_used_idx)) {
flush_shadow_used_ring(dev, vq);
vhost_vring_call(vq);
vhost_vring_call(dev, vq);
}

out:
Expand Down Expand Up @@ -1075,7 +1075,7 @@ update_used_idx(struct virtio_net *dev, struct vhost_virtqueue *vq,
vq->used->idx += count;
vhost_log_used_vring(dev, vq, offsetof(struct vring_used, idx),
sizeof(vq->used->idx));
vhost_vring_call(vq);
vhost_vring_call(dev, vq);
}

static __rte_always_inline struct zcopy_mbuf *
Expand Down

0 comments on commit e37ff95

Please sign in to comment.