Skip to content

Commit

Permalink
virtio: use shadow_avail_idx while checking number of heads
Browse files Browse the repository at this point in the history
We do not need the most up to date number of heads, we only want to
know if there is at least one.

Use shadow variable as long as it is not equal to the last available
index checked.  This avoids expensive qatomic dereference of the
RCU-protected memory region cache as well as the memory access itself.

The change improves performance of the af-xdp network backend by 2-3%.

Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
Message-Id: <20230927135157.2316982-1-i.maximets@ovn.org>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
  • Loading branch information
igsilya authored and mstsirkin committed Oct 4, 2023
1 parent a252fa3 commit 6bc83c6
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions hw/virtio/virtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -997,16 +997,28 @@ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
/* Called within rcu_read_lock(). */
static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
{
uint16_t num_heads = vring_avail_idx(vq) - idx;
uint16_t avail_idx, num_heads;

/* Use shadow index whenever possible. */
avail_idx = (vq->shadow_avail_idx != idx) ? vq->shadow_avail_idx
: vring_avail_idx(vq);
num_heads = avail_idx - idx;

/* Check it isn't doing very strange things with descriptor numbers. */
if (num_heads > vq->vring.num) {
virtio_error(vq->vdev, "Guest moved used index from %u to %u",
idx, vq->shadow_avail_idx);
return -EINVAL;
}
/* On success, callers read a descriptor at vq->last_avail_idx.
* Make sure descriptor read does not bypass avail index read. */
/*
* On success, callers read a descriptor at vq->last_avail_idx.
* Make sure descriptor read does not bypass avail index read.
*
* This is necessary even if we are using a shadow index, since
* the shadow index could have been initialized by calling
* vring_avail_idx() outside of this function, i.e., by a guest
* memory read not accompanied by a barrier.
*/
if (num_heads) {
smp_rmb();
}
Expand Down

0 comments on commit 6bc83c6

Please sign in to comment.