* [PATCH v2] virtio: use shadow_avail_idx while checking number of heads
@ 2023-09-27 13:50 Ilya Maximets
2023-09-27 14:45 ` Stefan Hajnoczi
2023-10-08 5:17 ` Jason Wang
0 siblings, 2 replies; 3+ messages in thread
From: Ilya Maximets @ 2023-09-27 13:50 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Jason Wang, qemu-devel, Stefan Hajnoczi, Ilya Maximets
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>
---
Version 2:
- Changed to not skip error checks and a barrier.
- Added comments about the need for a barrier.
hw/virtio/virtio.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 4577f3f5b3..8a4c3e95d2 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -999,7 +999,12 @@ 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) {
@@ -1007,8 +1012,15 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
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();
}
--
2.41.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] virtio: use shadow_avail_idx while checking number of heads
2023-09-27 13:50 [PATCH v2] virtio: use shadow_avail_idx while checking number of heads Ilya Maximets
@ 2023-09-27 14:45 ` Stefan Hajnoczi
2023-10-08 5:17 ` Jason Wang
1 sibling, 0 replies; 3+ messages in thread
From: Stefan Hajnoczi @ 2023-09-27 14:45 UTC (permalink / raw)
To: Ilya Maximets; +Cc: Michael S. Tsirkin, Jason Wang, qemu-devel, Stefan Hajnoczi
On Wed, 27 Sept 2023 at 09:52, Ilya Maximets <i.maximets@ovn.org> wrote:
>
> 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>
> ---
>
> Version 2:
> - Changed to not skip error checks and a barrier.
> - Added comments about the need for a barrier.
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
>
> hw/virtio/virtio.c | 18 +++++++++++++++---
> 1 file changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 4577f3f5b3..8a4c3e95d2 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -999,7 +999,12 @@ 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) {
> @@ -1007,8 +1012,15 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
> 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();
> }
> --
> 2.41.0
>
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] virtio: use shadow_avail_idx while checking number of heads
2023-09-27 13:50 [PATCH v2] virtio: use shadow_avail_idx while checking number of heads Ilya Maximets
2023-09-27 14:45 ` Stefan Hajnoczi
@ 2023-10-08 5:17 ` Jason Wang
1 sibling, 0 replies; 3+ messages in thread
From: Jason Wang @ 2023-10-08 5:17 UTC (permalink / raw)
To: Ilya Maximets; +Cc: Michael S. Tsirkin, qemu-devel, Stefan Hajnoczi
On Wed, Sep 27, 2023 at 9:51 PM Ilya Maximets <i.maximets@ovn.org> wrote:
>
> 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>
Acked-by: Jason Wang <jasowang@redhat.com>
Thanks
> ---
>
> Version 2:
> - Changed to not skip error checks and a barrier.
> - Added comments about the need for a barrier.
>
> hw/virtio/virtio.c | 18 +++++++++++++++---
> 1 file changed, 15 insertions(+), 3 deletions(-)
>
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 4577f3f5b3..8a4c3e95d2 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -999,7 +999,12 @@ 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) {
> @@ -1007,8 +1012,15 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
> 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();
> }
> --
> 2.41.0
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-10-08 5:18 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-27 13:50 [PATCH v2] virtio: use shadow_avail_idx while checking number of heads Ilya Maximets
2023-09-27 14:45 ` Stefan Hajnoczi
2023-10-08 5:17 ` Jason Wang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).