Hi Michael,

> > -struct vring_used_elem *vring_add_used_user(struct vring_host *vh,
> > -                                unsigned int head, int len)
> > +
> > +static inline struct vring_used_elem *_vring_add_used(struct vring_host
> *vh,
> > +                                                 u32 head, u32 len,
> > +                                                 bool (*cpy)(void *dst,
> > +                                                             void *src,
> > +                                                             size_t s),
> > +                                                 void (*wbarrier)(void))
> >  {
> >     struct vring_used_elem  *used;
> > +   u16 last_used;
> >
> >     /* The virtqueue contains a ring of used buffers.  Get a pointer to the
> >      * next entry in that used ring. */
> > -   used = &vh->vr.used->ring[vh->last_used_idx % vh->vr.num];
> > -   if (__put_user(head, &used->id)) {
> > -           pr_debug("Failed to write used id");
> > +   used = &vh->vr.used->ring[vh->last_used_idx & (vh->vr.num - 1)];
> > +   if (!cpy(&used->id, &head, sizeof(used->id)) ||
> > +       !cpy(&used->len, &len, sizeof(used->len)))
> >             return NULL;
> > -   }
> > -   if (__put_user(len, &used->len)) {
> > -           pr_debug("Failed to write used len");
> > +   wbarrier();
> > +   last_used = vh->last_used_idx + 1;
> > +   if (!cpy(&vh->vr.used->idx, &last_used, sizeof(vh->vr.used->idx)))
> >             return NULL;
> 
> I think this is broken: we need a 16 bit access, this is
> doing a memcpy which is byte by byte.

I have played around with gcc and -O2 option, and it seems to me
that GCC is smart enough to optimize the use of sizeof and memcpy
into MOV operations. But my assembly knowledge is very rusty,
so a second opinion on this would be good.

> > -   }
> > -   /* Make sure buffer is written before we update index. */
> > -   smp_wmb();
> > -   if (__put_user(vh->last_used_idx + 1, &vh->vr.used->idx)) {
> > -           pr_debug("Failed to increment used idx");
> > -           return NULL;
> > -   }
> > -   vh->last_used_idx++;
> > +   vh->last_used_idx = last_used;
> >     return used;
> >  }
> > -EXPORT_SYMBOL(vring_add_used_user);

Thanks,
Sjur
_______________________________________________
Virtualization mailing list
[email protected]
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

Reply via email to