On Mon, Mar 24, 2025 at 3:34 PM Sahil Siddiq <icegambi...@gmail.com> wrote:
>
> Hi,
>
> I had a few more queries here as well.
>
> On 3/24/25 7:29 PM, Sahil Siddiq wrote:
> > Detect when used descriptors are ready for consumption by the guest via
> > packed virtqueues and forward them from the device to the guest.
> >
> > Signed-off-by: Sahil Siddiq <sahil...@proton.me>
> > ---
> > Changes from v4 -> v5:
> > - New commit.
> > - vhost-shadow-virtqueue.c:
> >    (vhost_svq_more_used): Split into vhost_svq_more_used_split and
> >    vhost_svq_more_used_packed.
> >    (vhost_svq_enable_notification): Handle split and packed vqs.
> >    (vhost_svq_disable_notification): Likewise.
> >    (vhost_svq_get_buf): Split into vhost_svq_get_buf_split and
> >    vhost_svq_get_buf_packed.
> >    (vhost_svq_poll): Use new functions.
> >
> >   hw/virtio/vhost-shadow-virtqueue.c | 121 ++++++++++++++++++++++++++---
> >   1 file changed, 110 insertions(+), 11 deletions(-)
> >
> > diff --git a/hw/virtio/vhost-shadow-virtqueue.c 
> > b/hw/virtio/vhost-shadow-virtqueue.c
> > index 126957231d..8430b3c94a 100644
> > --- a/hw/virtio/vhost-shadow-virtqueue.c
> > +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > @@ -463,7 +463,7 @@ static void 
> > vhost_handle_guest_kick_notifier(EventNotifier *n)
> >       vhost_handle_guest_kick(svq);
> >   }
> >
> > -static bool vhost_svq_more_used(VhostShadowVirtqueue *svq)
> > +static bool vhost_svq_more_used_split(VhostShadowVirtqueue *svq)
> >   {
> >       uint16_t *used_idx = &svq->vring.used->idx;
> >       if (svq->last_used_idx != svq->shadow_used_idx) {
> > @@ -475,6 +475,22 @@ static bool vhost_svq_more_used(VhostShadowVirtqueue 
> > *svq)
> >       return svq->last_used_idx != svq->shadow_used_idx;
> >   }
> >
> > +static bool vhost_svq_more_used_packed(VhostShadowVirtqueue *svq)
> > +{
> > +    bool avail_flag, used_flag, used_wrap_counter;
> > +    uint16_t last_used_idx, last_used, flags;
> > +
> > +    last_used_idx = svq->last_used_idx;
> > +    last_used = last_used_idx & ~(1 << VRING_PACKED_EVENT_F_WRAP_CTR);
>
> In the linux kernel, last_used is calculated as:
>
> last_used_idx & ~(-(1 << VRING_PACKED_EVENT_F_WRAP_CTR))
>
> ...instead of...
>
> last_used_idx & ~(1 << VRING_PACKED_EVENT_F_WRAP_CTR)
>
> Isn't the second option good enough if last_used_idx is uint16_t
> and VRING_PACKED_EVENT_F_WRAP_CTR is defined as 15.
>

I think it is good enough with the u16 restrictions but it's just
defensive code.

> > +    used_wrap_counter = !!(last_used_idx & (1 << 
> > VRING_PACKED_EVENT_F_WRAP_CTR));
> > +
> > +    flags = le16_to_cpu(svq->vring_packed.vring.desc[last_used].flags);
> > +    avail_flag = !!(flags & (1 << VRING_PACKED_DESC_F_AVAIL));
> > +    used_flag = !!(flags & (1 << VRING_PACKED_DESC_F_USED));
> > +
> > +    return avail_flag == used_flag && used_flag == used_wrap_counter;
> > +}
> > +
>
> Also in the implementation of vhost_svq_more_used_split() [1], I haven't
> understood why the following condition:
>
> svq->last_used_idx != svq->shadow_used_idx
>
> is checked before updating the value of "svq->shadow_used_idx":
>
> svq->shadow_used_idx = le16_to_cpu(*(volatile uint16_t *)used_idx)
>

As far as I know this is used to avoid concurrent access to guest's
used_idx, avoiding cache sharing, the memory barrier, and the
potentially costly volatile access.


Reply via email to