lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CACGkMEt8djYRdSvwBK7QGoNV1iG-8nafOox0=pt6ix1m0NOZtA@mail.gmail.com>
Date: Thu, 23 Jan 2025 09:51:17 +0800
From: Jason Wang <jasowang@...hat.com>
To: Eugenio Pérez <eperezma@...hat.com>
Cc: linux-kernel@...r.kernel.org, mst@...hat.com, 
	Hanna Reitz <hreitz@...hat.com>, Stefano Garzarella <sgarzare@...hat.com>, 
	Xuan Zhuo <xuanzhuo@...ux.alibaba.com>, Vivek Goyal <vgoyal@...hat.com>, 
	Miklos Szeredi <miklos@...redi.hu>, German Maglione <gmaglione@...hat.com>, 
	Stefan Hajnoczi <stefanha@...hat.com>, virtualization@...ts.linux.dev
Subject: Re: [RFC 2/5] virtio_ring: introduce virtqueue_map/unmap_sgs()

On Thu, Jan 23, 2025 at 12:32 AM Eugenio Pérez <eperezma@...hat.com> wrote:
>
> From: Jason Wang <jasowang@...hat.com>
>
> Introduce new virtqueue DMA operations which allows the drivers that
> want to make use of the premapping API but operate at the sg level.
>
> Note that we still follow the assumtions if virtqueue_add() so
> dma_map_sg() is not used. This could be optimized in the future.
> Signed-off-by: Jason Wang <jasowang@...hat.com>
> Signed-off-by: Eugenio Pérez <eperezma@...hat.com>
> --
> Eugenio's changes: Remove blank
> TODO: Should we call directly dma_map instead of this? XDP do the direct
> call.

Note that we should have an indirection layer as the device is not
necessarily DMA capable.

And we probably need to rename the virtqueue_dma_map_XXX() to
virtqueue_map_XXX()

Thanks

> ---
>  drivers/virtio/virtio_ring.c | 128 +++++++++++++++++++++++++++++++----
>  include/linux/virtio.h       |  10 +++
>  2 files changed, 125 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index fdd2d2b07b5a..05729bc5cbb1 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -359,6 +359,26 @@ static struct device *vring_dma_dev(const struct vring_virtqueue *vq)
>         return vq->dma_dev;
>  }
>
> +static int __vring_map_one_sg(const struct vring_virtqueue *vq,
> +                             struct scatterlist *sg,
> +                             enum dma_data_direction direction,
> +                             dma_addr_t *addr)
> +{
> +       /*
> +        * We can't use dma_map_sg, because we don't use scatterlists in
> +        * the way it expects (we don't guarantee that the scatterlist
> +        * will exist for the lifetime of the mapping).
> +        */
> +       *addr = dma_map_page(vring_dma_dev(vq),
> +                           sg_page(sg), sg->offset, sg->length,
> +                           direction);
> +
> +       if (dma_mapping_error(vring_dma_dev(vq), *addr))
> +               return -ENOMEM;
> +
> +       return 0;
> +}
> +
>  /* Map one sg entry. */
>  static int vring_map_one_sg(const struct vring_virtqueue *vq, struct scatterlist *sg,
>                             enum dma_data_direction direction, dma_addr_t *addr,
> @@ -383,19 +403,7 @@ static int vring_map_one_sg(const struct vring_virtqueue *vq, struct scatterlist
>                 return 0;
>         }
>
> -       /*
> -        * We can't use dma_map_sg, because we don't use scatterlists in
> -        * the way it expects (we don't guarantee that the scatterlist
> -        * will exist for the lifetime of the mapping).
> -        */
> -       *addr = dma_map_page(vring_dma_dev(vq),
> -                           sg_page(sg), sg->offset, sg->length,
> -                           direction);
> -
> -       if (dma_mapping_error(vring_dma_dev(vq), *addr))
> -               return -ENOMEM;
> -
> -       return 0;
> +       return __vring_map_one_sg(vq, sg, direction, addr);
>  }
>
>  static dma_addr_t vring_map_single(const struct vring_virtqueue *vq,
> @@ -526,6 +534,100 @@ static inline unsigned int virtqueue_add_desc_split(struct virtqueue *vq,
>         return next;
>  }
>
> +void virtqueue_unmap_sgs(struct virtqueue *_vq,
> +                        struct scatterlist *sgs[],
> +                        unsigned int out_sgs,
> +                        unsigned int in_sgs)
> +{
> +       struct vring_virtqueue *vq = to_vvq(_vq);
> +       struct scatterlist *sg;
> +       int n;
> +
> +       for (n = 0; n < out_sgs; n++) {
> +               for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> +                       dma_unmap_page(vring_dma_dev(vq),
> +                                      sg_dma_address(sg),
> +                                      sg->length,
> +                                      DMA_TO_DEVICE);
> +               }
> +       }
> +
> +       for (; n < (out_sgs + in_sgs); n++) {
> +               for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> +                       dma_unmap_page(vring_dma_dev(vq),
> +                                      sg_dma_address(sg),
> +                                      sg->length,
> +                                      DMA_FROM_DEVICE);
> +               }
> +       }
> +}
> +EXPORT_SYMBOL_GPL(virtqueue_unmap_sgs);
> +
> +int virtqueue_map_sgs(struct virtqueue *_vq,
> +                     struct scatterlist *sgs[],
> +                     unsigned int out_sgs,
> +                     unsigned int in_sgs)
> +{
> +       struct vring_virtqueue *vq = to_vvq(_vq);
> +       int i, n, mapped_sg = 0;
> +       struct scatterlist *sg;
> +
> +       for (n = 0; n < out_sgs; n++) {
> +               for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> +                       dma_addr_t addr;
> +
> +                       if (__vring_map_one_sg(vq, sg, DMA_TO_DEVICE, &addr))
> +                               goto unmap_release;
> +
> +                       sg_dma_address(sg) = addr;
> +                       mapped_sg++;
> +               }
> +       }
> +
> +       for (; n < (out_sgs + in_sgs); n++) {
> +               for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> +                       dma_addr_t addr;
> +
> +                       if (__vring_map_one_sg(vq, sg, DMA_FROM_DEVICE, &addr))
> +                               goto unmap_release;
> +
> +                       sg_dma_address(sg) = addr;
> +                       mapped_sg++;
> +               }
> +       }
> +
> +       return 0;
> +
> +unmap_release:
> +       i = 0;
> +
> +       for (n = 0; n < out_sgs; n++) {
> +               for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> +                       if (i++ == mapped_sg)
> +                               goto out;
> +                       dma_unmap_page(vring_dma_dev(vq),
> +                                      sg_dma_address(sg),
> +                                      sg->length,
> +                                      DMA_TO_DEVICE);
> +               }
> +       }
> +
> +       for (; n < (out_sgs + in_sgs); n++) {
> +               for (sg = sgs[n]; sg; sg = sg_next(sg)) {
> +
> +                       if (i++ == mapped_sg)
> +                               goto out;
> +                       dma_unmap_page(vring_dma_dev(vq),
> +                                      sg_dma_address(sg),
> +                                      sg->length,
> +                                      DMA_FROM_DEVICE);
> +               }
> +       }
> +out:
> +       return -ENOMEM;
> +}
> +EXPORT_SYMBOL_GPL(virtqueue_map_sgs);
> +
>  static inline int virtqueue_add_split(struct virtqueue *_vq,
>                                       struct scatterlist *sgs[],
>                                       unsigned int total_sg,
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index dd88682e27e3..28db998d691e 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -67,6 +67,16 @@ int virtqueue_add_outbuf_premapped(struct virtqueue *vq,
>                                    void *data,
>                                    gfp_t gfp);
>
> +int virtqueue_map_sgs(struct virtqueue *_vq,
> +                     struct scatterlist *sgs[],
> +                     unsigned int out_sgs,
> +                     unsigned int in_sgs);
> +
> +void virtqueue_unmap_sgs(struct virtqueue *_vq,
> +                        struct scatterlist *sgs[],
> +                        unsigned int out_sgs,
> +                        unsigned int in_sgs);
> +
>  int virtqueue_add_sgs(struct virtqueue *vq,
>                       struct scatterlist *sgs[],
>                       unsigned int out_sgs,
> --
> 2.48.1
>


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ