mbox series

[RFC,v2,0/3] Add packed virtqueue to shadow virtqueue

Message ID 20240726095822.104017-1-sahilcdq@proton.me
Headers show
Series Add packed virtqueue to shadow virtqueue | expand

Message

Sahil July 26, 2024, 9:58 a.m. UTC
Hi,

I have made some progress in this project and thought I would
send these changes first before continuing. I split patch v1 [1]
into two commits (#1 and #2) to make it easy to review. There are
very few changes in the first commit. The second commit has not
changes.

There are a few things that I am not entirely sure of in commit #3.

Q1.
In virtio_ring.h [2], new aliases with memory alignment enforcement
such as "vring_desc_t" have been created. I am not sure if this
is required for the packed vq descriptor ring (vring_packed_desc)
as well. I don't see a type alias that enforces memory alignment
for "vring_packed_desc" in the linux kernel. I haven't used any
alias either.

Q2.
I see that parts of the "vhost-vdpa" implementation is based on
the assumption that SVQ uses the split vq format. For example,
"vhost_vdpa_svq_map_rings" [3], calls "vhost_svq_device_area_size"
which is specific to split vqs. The "vhost_vring_addr" [4] struct
is also specific to split vqs.

My idea is to have a generic "vhost_vring_addr" structure that
wraps around split and packed vq specific structures, rather
than using them directly in if-else conditions wherever the
vhost-vdpa functions require their usage. However, this will
involve checking their impact in several other places where this
struct is currently being used (eg.: "vhost-user", "vhost-backend",
"libvhost-user").

Is this approach alright or is there a better alternative? I would
like to get your thoughts on this before working on this portion of
the project.

Thanks,
Sahil

[1] https://lists.nongnu.org/archive/html/qemu-devel/2024-06/msg03417.html
[2] https://gitlab.com/qemu-project/qemu/-/blob/master/include/standard-headers/linux/virtio_ring.h#L149
[3] https://gitlab.com/qemu-project/qemu/-/blob/master/hw/virtio/vhost-vdpa.c#L1178
[4] https://gitlab.com/qemu-project/qemu/-/blob/master/include/standard-headers/linux/vhost_types.h#L30

Changes v1 -> v2:
* Split commit from RFC v1 into two commits.
* vhost-shadow-virtqueue.c
  (vhost_svq_add_packed):
  - Merge with "vhost_svq_vring_write_descs_packed()"
  - Remove "num == 0" check
  (vhost_svq_add): Use "is_packed" to check vq format.
  (vhost_svq_get_vring_addr): Rename function.
  (vhost_svq_get_vring_addr_packed): New function but is yet to be implemented.
  (vhost_svq_memory_packed): New function.
  (vhost_svq_start): Support packed vq format.
* vhost-shadow-virtqueue.h
  (struct VhostShadowVirtqueue): New member "is_packed"
  (vhost_svq_get_vring_addr): Renamed function.
  (vhost_svq_get_vring_addr_packed): New function.
  (vhost_svq_memory_packed): Likewise.
* vhost-vdpa.c
  (vhost_svq_get_vring_addr): Rename function.

Sahil Siddiq (3):
  vhost: Introduce packed vq and add buffer elements
  vhost: Data structure changes to support packed vqs
  vhost: Allocate memory for packed vring.

 hw/virtio/vhost-shadow-virtqueue.c | 161 ++++++++++++++++++++++++++---
 hw/virtio/vhost-shadow-virtqueue.h |  76 +++++++++-----
 hw/virtio/vhost-vdpa.c             |   4 +-
 3 files changed, 198 insertions(+), 43 deletions(-)

Comments

Eugenio Pérez July 26, 2024, 1:40 p.m. UTC | #1
On Fri, Jul 26, 2024 at 11:58 AM Sahil Siddiq <icegambit91@gmail.com> wrote:
>
> Hi,
>
> I have made some progress in this project and thought I would
> send these changes first before continuing. I split patch v1 [1]
> into two commits (#1 and #2) to make it easy to review. There are
> very few changes in the first commit. The second commit has not
> changes.
>
> There are a few things that I am not entirely sure of in commit #3.
>
> Q1.
> In virtio_ring.h [2], new aliases with memory alignment enforcement
> such as "vring_desc_t" have been created. I am not sure if this
> is required for the packed vq descriptor ring (vring_packed_desc)
> as well. I don't see a type alias that enforces memory alignment
> for "vring_packed_desc" in the linux kernel. I haven't used any
> alias either.
>

The alignment is required to be 16 for the descriptor ring and 4 for
the device and driver ares by the standard [1]. In QEMU, this is
solved by calling mmap, which always returns page-aligned addresses.

> Q2.
> I see that parts of the "vhost-vdpa" implementation is based on
> the assumption that SVQ uses the split vq format. For example,
> "vhost_vdpa_svq_map_rings" [3], calls "vhost_svq_device_area_size"
> which is specific to split vqs. The "vhost_vring_addr" [4] struct
> is also specific to split vqs.
>
> My idea is to have a generic "vhost_vring_addr" structure that
> wraps around split and packed vq specific structures, rather
> than using them directly in if-else conditions wherever the
> vhost-vdpa functions require their usage. However, this will
> involve checking their impact in several other places where this
> struct is currently being used (eg.: "vhost-user", "vhost-backend",
> "libvhost-user").
>

Ok I've just found this is under-documented actually :).

As you mention, vhost-user is already using this same struct for
packed vqs [2], just translating the driver area from the avail vring
and the device area from the used vring. So the best option is to
stick with that, unless I'm missing something.

> Is this approach alright or is there a better alternative? I would
> like to get your thoughts on this before working on this portion of
> the project.
>
> Thanks,
> Sahil
>

[1] https://docs.oasis-open.org/virtio/virtio/v1.3/virtio-v1.3.html
[2] https://github.com/DPDK/dpdk/blob/82c47f005b9a0a1e3a649664b7713443d18abe43/lib/vhost/vhost_user.c#L841C1-L841C25
Sahil July 26, 2024, 5:11 p.m. UTC | #2
Hi,

On Friday, July 26, 2024 7:10:24 PM GMT+5:30 Eugenio Perez Martin wrote:
> On Fri, Jul 26, 2024 at 11:58 AM Sahil Siddiq <icegambit91@gmail.com> wrote:
> > [...]
> > Q1.
> > In virtio_ring.h [2], new aliases with memory alignment enforcement
> > such as "vring_desc_t" have been created. I am not sure if this
> > is required for the packed vq descriptor ring (vring_packed_desc)
> > as well. I don't see a type alias that enforces memory alignment
> > for "vring_packed_desc" in the linux kernel. I haven't used any
> > alias either.
> 
> The alignment is required to be 16 for the descriptor ring and 4 for
> the device and driver ares by the standard [1]. In QEMU, this is
> solved by calling mmap, which always returns page-aligned addresses.

Ok, I understand this now.

> > Q2.
> > I see that parts of the "vhost-vdpa" implementation is based on
> > the assumption that SVQ uses the split vq format. For example,
> > "vhost_vdpa_svq_map_rings" [3], calls "vhost_svq_device_area_size"
> > which is specific to split vqs. The "vhost_vring_addr" [4] struct
> > is also specific to split vqs.
> > 
> > My idea is to have a generic "vhost_vring_addr" structure that
> > wraps around split and packed vq specific structures, rather
> > than using them directly in if-else conditions wherever the
> > vhost-vdpa functions require their usage. However, this will
> > involve checking their impact in several other places where this
> > struct is currently being used (eg.: "vhost-user", "vhost-backend",
> > "libvhost-user").
> 
> Ok I've just found this is under-documented actually :).
> 
> As you mention, vhost-user is already using this same struct for
> packed vqs [2], just translating the driver area from the avail vring
> and the device area from the used vring. So the best option is to
> stick with that, unless I'm missing something.
> 
> 
> [1] https://docs.oasis-open.org/virtio/virtio/v1.3/virtio-v1.3.html
> [2]
> https://github.com/DPDK/dpdk/blob/82c47f005b9a0a1e3a649664b7713443d18abe43/
> lib/vhost/vhost_user.c#L841C1-L841C25

Sorry, I am a little confused here. I was referring to QEMU's vhost-user
implementation here.

Based on what I have understood, "vhost_vring_addr" is only being used
for split vqs in QEMU's vhost-user and in other places too. The implementation
does not take into account packed vqs.

I was going through DPDK's source. In DPDK's implementation of vhost-user [1],
the same struct (vhost_virtqueue) is being used for split vqs and packed vqs. This
is possible since "vhost_virtqueue" [2] uses a union to wrap around the split and
packed versions of the vq.

> > My idea is to have a generic "vhost_vring_addr" structure that
> > wraps around split and packed vq specific structures, rather
> > than using them directly in if-else conditions wherever the
> > vhost-vdpa functions require their usage. However, this will
> > involve checking their impact in several other places where this
> > struct is currently being used (eg.: "vhost-user", "vhost-backend",
> > "libvhost-user").

I was referring to something similar by this. The current "vhost_vring_addr"
can be renamed to "vhost_vring_addr_split" for example, and a new struct
"vhost_vring_addr" can wrap around this and "vhost_vring_addr_packed"
using a union.

I liked the idea of using three unions for each member in the virtqueue format
instead of having one union for the whole format. I didn't think of this. I think
by having three unions the "vhost_svq_get_vring_addr" [3] function won't have
to be split into two new functions to handle split and packed formats separately.
I am not sure if this is what you were referring to.

Thanks,
Sahil

[1] https://github.com/DPDK/dpdk/blob/82c47f005b9a0a1e3a649664b7713443d18abe43/lib/vhost/vhost_user.c#L861
[2] https://github.com/DPDK/dpdk/blob/82c47f005b9a0a1e3a649664b7713443d18abe43/lib/vhost/vhost.h#L275
[3] https://gitlab.com/qemu-project/qemu/-/blob/master/hw/virtio/vhost-shadow-virtqueue.c#L595
Eugenio Pérez July 26, 2024, 6:25 p.m. UTC | #3
On Fri, Jul 26, 2024 at 7:11 PM Sahil <icegambit91@gmail.com> wrote:
>
> Hi,
>
> On Friday, July 26, 2024 7:10:24 PM GMT+5:30 Eugenio Perez Martin wrote:
> > On Fri, Jul 26, 2024 at 11:58 AM Sahil Siddiq <icegambit91@gmail.com> wrote:
> > > [...]
> > > Q1.
> > > In virtio_ring.h [2], new aliases with memory alignment enforcement
> > > such as "vring_desc_t" have been created. I am not sure if this
> > > is required for the packed vq descriptor ring (vring_packed_desc)
> > > as well. I don't see a type alias that enforces memory alignment
> > > for "vring_packed_desc" in the linux kernel. I haven't used any
> > > alias either.
> >
> > The alignment is required to be 16 for the descriptor ring and 4 for
> > the device and driver ares by the standard [1]. In QEMU, this is
> > solved by calling mmap, which always returns page-aligned addresses.
>
> Ok, I understand this now.
>
> > > Q2.
> > > I see that parts of the "vhost-vdpa" implementation is based on
> > > the assumption that SVQ uses the split vq format. For example,
> > > "vhost_vdpa_svq_map_rings" [3], calls "vhost_svq_device_area_size"
> > > which is specific to split vqs. The "vhost_vring_addr" [4] struct
> > > is also specific to split vqs.
> > >
> > > My idea is to have a generic "vhost_vring_addr" structure that
> > > wraps around split and packed vq specific structures, rather
> > > than using them directly in if-else conditions wherever the
> > > vhost-vdpa functions require their usage. However, this will
> > > involve checking their impact in several other places where this
> > > struct is currently being used (eg.: "vhost-user", "vhost-backend",
> > > "libvhost-user").
> >
> > Ok I've just found this is under-documented actually :).
> >
> > As you mention, vhost-user is already using this same struct for
> > packed vqs [2], just translating the driver area from the avail vring
> > and the device area from the used vring. So the best option is to
> > stick with that, unless I'm missing something.
> >
> >
> > [1] https://docs.oasis-open.org/virtio/virtio/v1.3/virtio-v1.3.html
> > [2]
> > https://github.com/DPDK/dpdk/blob/82c47f005b9a0a1e3a649664b7713443d18abe43/
> > lib/vhost/vhost_user.c#L841C1-L841C25
>
> Sorry, I am a little confused here. I was referring to QEMU's vhost-user
> implementation here.
>
> Based on what I have understood, "vhost_vring_addr" is only being used
> for split vqs in QEMU's vhost-user and in other places too. The implementation
> does not take into account packed vqs.
>
> I was going through DPDK's source. In DPDK's implementation of vhost-user [1],
> the same struct (vhost_virtqueue) is being used for split vqs and packed vqs. This
> is possible since "vhost_virtqueue" [2] uses a union to wrap around the split and
> packed versions of the vq.
>

Ok, now I get you better. Let me start again from a different angle :).

vhost_vring_addr is already part of the API that QEMU uses between
itself and vhost devices, all vhost-kernel, vhost-user and vhost-vdpa.
To make non-backward compatible changes to it is impossible, as it
involves changes in all of these elements.

QEMU and DPDK, using vhost-user, already send and receive packed
virtqueues addresses using the current structure layout. QEMU's
hw/virtio/vhost.c:vhost_virtqueue_set_addr already sets vq->desc,
vq->avail and vq->user, which has the values of the desc, driver and
device. In that sense, I recommend not to modify it.

On the other hand, DPDK's vhost_virtqueue is not the same struct as
vhost_vring_addr. It is internal to DPDK so it can be modified. We
need to do something similar for the SVQ, yes.

To do that union trick piece by piece in VhostShadowVirtqueue is
possible, but it requires modifying all the usages of the current
vring. I think it is easier for us to follow the kernel's
virtio_ring.c model, as it is a driver too, and create a vring_packed.
We can create an anonymous union and suffix all members with a _packed
so we don't need to modify current split usage.

Let me know what you think.

> > > My idea is to have a generic "vhost_vring_addr" structure that
> > > wraps around split and packed vq specific structures, rather
> > > than using them directly in if-else conditions wherever the
> > > vhost-vdpa functions require their usage. However, this will
> > > involve checking their impact in several other places where this
> > > struct is currently being used (eg.: "vhost-user", "vhost-backend",
> > > "libvhost-user").
>
> I was referring to something similar by this. The current "vhost_vring_addr"
> can be renamed to "vhost_vring_addr_split" for example, and a new struct
> "vhost_vring_addr" can wrap around this and "vhost_vring_addr_packed"
> using a union.
>
> I liked the idea of using three unions for each member in the virtqueue format
> instead of having one union for the whole format. I didn't think of this. I think
> by having three unions the "vhost_svq_get_vring_addr" [3] function won't have
> to be split into two new functions to handle split and packed formats separately.
> I am not sure if this is what you were referring to.
>

But you need the if/else anyway, as the members are not vring_desc_t
but vring_packed_desc, and same with vring_avail_t and vring_used_t
with struct vring_packed_desc_event. Or am I missing something?

Thanks!
Sahil July 28, 2024, 4:42 p.m. UTC | #4
Hi,

On Friday, July 26, 2024 11:55:14 PM GMT+5:30 Eugenio Perez Martin wrote:
> On Fri, Jul 26, 2024 at 7:11 PM Sahil <icegambit91@gmail.com> wrote:
> > [...]
> > > > Q2.
> > > > I see that parts of the "vhost-vdpa" implementation is based on
> > > > the assumption that SVQ uses the split vq format. For example,
> > > > "vhost_vdpa_svq_map_rings" [3], calls "vhost_svq_device_area_size"
> > > > which is specific to split vqs. The "vhost_vring_addr" [4] struct
> > > > is also specific to split vqs.
> > > > 
> > > > My idea is to have a generic "vhost_vring_addr" structure that
> > > > wraps around split and packed vq specific structures, rather
> > > > than using them directly in if-else conditions wherever the
> > > > vhost-vdpa functions require their usage. However, this will
> > > > involve checking their impact in several other places where this
> > > > struct is currently being used (eg.: "vhost-user", "vhost-backend",
> > > > "libvhost-user").
> > > 
> > > Ok I've just found this is under-documented actually :).
> > > 
> > > As you mention, vhost-user is already using this same struct for
> > > packed vqs [2], just translating the driver area from the avail vring
> > > and the device area from the used vring. So the best option is to
> > > stick with that, unless I'm missing something.
> > > 
> > > 
> > > [1] https://docs.oasis-open.org/virtio/virtio/v1.3/virtio-v1.3.html
> > > [2]
> > > https://github.com/DPDK/dpdk/blob/82c47f005b9a0a1e3a649664b7713443d18abe
> > > 43/
> > > lib/vhost/vhost_user.c#L841C1-L841C25
> > 
> > Sorry, I am a little confused here. I was referring to QEMU's vhost-user
> > implementation here.
> > 
> > Based on what I have understood, "vhost_vring_addr" is only being used
> > for split vqs in QEMU's vhost-user and in other places too. The
> > implementation does not take into account packed vqs.
> > 
> > I was going through DPDK's source. In DPDK's implementation of vhost-user
> > [1], the same struct (vhost_virtqueue) is being used for split vqs and
> > packed vqs. This is possible since "vhost_virtqueue" [2] uses a union to
> > wrap around the split and packed versions of the vq.
> 
> Ok, now I get you better. Let me start again from a different angle :).
> 
> vhost_vring_addr is already part of the API that QEMU uses between
> itself and vhost devices, all vhost-kernel, vhost-user and vhost-vdpa.
> To make non-backward compatible changes to it is impossible, as it
> involves changes in all of these elements.
> 
> QEMU and DPDK, using vhost-user, already send and receive packed
> virtqueues addresses using the current structure layout. QEMU's
> hw/virtio/vhost.c:vhost_virtqueue_set_addr already sets vq->desc,
> vq->avail and vq->user, which has the values of the desc, driver and
> device. In that sense, I recommend not to modify it.
> 
> On the other hand, DPDK's vhost_virtqueue is not the same struct as
> vhost_vring_addr. It is internal to DPDK so it can be modified. We
> need to do something similar for the SVQ, yes.
> 
> To do that union trick piece by piece in VhostShadowVirtqueue is
> possible, but it requires modifying all the usages of the current
> vring. I think it is easier for us to follow the kernel's
> virtio_ring.c model, as it is a driver too, and create a vring_packed.
> We can create an anonymous union and suffix all members with a _packed
> so we don't need to modify current split usage.
> 
> Let me know what you think.

Thank you for the detailed explanation. This makes sense to me now.
Since the three *_addr members (not counting log_guest_addr) in
"vhost_vring_addr" simply store addresses, a union is not required
here and these members can be reused in the case of packed format
as well.

> > > > My idea is to have a generic "vhost_vring_addr" structure that
> > > > wraps around split and packed vq specific structures, rather
> > > > than using them directly in if-else conditions wherever the
> > > > vhost-vdpa functions require their usage. However, this will
> > > > involve checking their impact in several other places where this
> > > > struct is currently being used (eg.: "vhost-user", "vhost-backend",
> > > > "libvhost-user").
> > 
> > I was referring to something similar by this. The current
> > "vhost_vring_addr" can be renamed to "vhost_vring_addr_split" for
> > example, and a new struct "vhost_vring_addr" can wrap around this and
> > "vhost_vring_addr_packed" using a union.
> > 
> > I liked the idea of using three unions for each member in the virtqueue
> > format instead of having one union for the whole format. I didn't think
> > of this. I think by having three unions the "vhost_svq_get_vring_addr"
> > [3] function won't have to be split into two new functions to handle
> > split and packed formats separately. I am not sure if this is what you
> > were referring to.
> 
> But you need the if/else anyway, as the members are not vring_desc_t
> but vring_packed_desc, and same with vring_avail_t and vring_used_t
> with struct vring_packed_desc_event. Or am I missing something?

I was referring to having a union for each member in "vhost_vring_addr".
But based on your explanation above I don't think this would be required
either.

Thanks,
Sahil