diff mbox series

[v3,v4l-utils] common: Use posix_memalign for allocating userptr buffers

Message ID 20240625112425.37172-1-fusibrandon13@gmail.com (mailing list archive)
State New
Headers show
Series [v3,v4l-utils] common: Use posix_memalign for allocating userptr buffers | expand

Commit Message

Brandon Cheo Fusi June 25, 2024, 11:24 a.m. UTC
When dealing with a userptr pointing to a buffer in userspace,
videobuf2 swaps the corresponding physical pages with other pages
so we have a contiguous area of memory for DMA. This only works if
the userptr is page aligned.

The current way of allocating user buffers using malloc only
guarantees alignment up to `alignof(max_align_t)`, which is usually
16. So replace malloc with posix_memalign to ensure the returned
pointer is on a page boundary.

Signed-off-by: Brandon Cheo Fusi <fusibrandon13@gmail.com>
---
 utils/common/v4l-helpers.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

Comments

Hans Verkuil Oct. 17, 2024, 10:51 a.m. UTC | #1
Hi Brandon,

On 25/06/2024 13:24, Brandon Cheo Fusi wrote:
> When dealing with a userptr pointing to a buffer in userspace,
> videobuf2 swaps the corresponding physical pages with other pages
> so we have a contiguous area of memory for DMA. This only works if
> the userptr is page aligned.
> 
> The current way of allocating user buffers using malloc only
> guarantees alignment up to `alignof(max_align_t)`, which is usually
> 16. So replace malloc with posix_memalign to ensure the returned
> pointer is on a page boundary.

With which driver is this tested? USERPTR is really supposed to work
with malloc()ed memory.

There have been drivers in the past that used contiguous DMA but still
allowed USERPTR, but that was a hack and these days you would use DMABUF.

Regards,

	Hans

> 
> Signed-off-by: Brandon Cheo Fusi <fusibrandon13@gmail.com>
> ---
>  utils/common/v4l-helpers.h | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h
> index cf0e92d..aa9ee26 100644
> --- a/utils/common/v4l-helpers.h
> +++ b/utils/common/v4l-helpers.h
> @@ -1661,10 +1661,11 @@ static inline int v4l_queue_alloc_bufs(struct v4l_fd *f,
>  		return 0;
>  	for (b = from; b < v4l_queue_g_buffers(q); b++) {
>  		for (p = 0; p < v4l_queue_g_num_planes(q); p++) {
> -			void *m = malloc(v4l_queue_g_length(q, p));
> -
> -			if (m == NULL)
> -				return errno;
> +			void *m;
> +			int ret = posix_memalign(&m, getpagesize(),
> +						v4l_queue_g_length(q, p));
> +			if (ret)
> +				return ret;
>  			v4l_queue_s_userptr(q, b, p, m);
>  		}
>  	}
Tomasz Figa Oct. 22, 2024, 10:14 a.m. UTC | #2
On Thu, Oct 17, 2024 at 7:51 PM Hans Verkuil <hverkuil-cisco@xs4all.nl> wrote:
>
> Hi Brandon,
>
> On 25/06/2024 13:24, Brandon Cheo Fusi wrote:
> > When dealing with a userptr pointing to a buffer in userspace,
> > videobuf2 swaps the corresponding physical pages with other pages
> > so we have a contiguous area of memory for DMA. This only works if
> > the userptr is page aligned.
> >
> > The current way of allocating user buffers using malloc only
> > guarantees alignment up to `alignof(max_align_t)`, which is usually
> > 16. So replace malloc with posix_memalign to ensure the returned
> > pointer is on a page boundary.
>
> With which driver is this tested? USERPTR is really supposed to work
> with malloc()ed memory.

In theory yes, but the entire idea of USERPTR is shaky enough that
some hardware may not work if the pointer is not aligned enough.
Another aspect is security - IOMMUs can only work on page granularity,
so if the first page of the buffer is preceded (or last page followed)
by some other data, that data would be leaked to the hardware.

That said, that doesn't seem to be what the commit description refers
to and actually it's kind of wrong - videobuf2 doesn't do anything to
make the userptr memory contiguous. It's all down to the DMA mapping
ops of the device, and if it's behind an IOMMU, it should just work
regardless of the alignment, minus the user data leak caveat I
mentioned.

Besides that, any idea why this function actually even uses userptr?
(I assume this is libv4l?)

>
> There have been drivers in the past that used contiguous DMA but still
> allowed USERPTR, but that was a hack and these days you would use DMABUF.
>
> Regards,
>
>         Hans
>
> >
> > Signed-off-by: Brandon Cheo Fusi <fusibrandon13@gmail.com>
> > ---
> >  utils/common/v4l-helpers.h | 9 +++++----
> >  1 file changed, 5 insertions(+), 4 deletions(-)
> >
> > diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h
> > index cf0e92d..aa9ee26 100644
> > --- a/utils/common/v4l-helpers.h
> > +++ b/utils/common/v4l-helpers.h
> > @@ -1661,10 +1661,11 @@ static inline int v4l_queue_alloc_bufs(struct v4l_fd *f,
> >               return 0;
> >       for (b = from; b < v4l_queue_g_buffers(q); b++) {
> >               for (p = 0; p < v4l_queue_g_num_planes(q); p++) {
> > -                     void *m = malloc(v4l_queue_g_length(q, p));
> > -
> > -                     if (m == NULL)
> > -                             return errno;
> > +                     void *m;
> > +                     int ret = posix_memalign(&m, getpagesize(),
> > +                                             v4l_queue_g_length(q, p));
> > +                     if (ret)
> > +                             return ret;
> >                       v4l_queue_s_userptr(q, b, p, m);
> >               }
> >       }
>
diff mbox series

Patch

diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h
index cf0e92d..aa9ee26 100644
--- a/utils/common/v4l-helpers.h
+++ b/utils/common/v4l-helpers.h
@@ -1661,10 +1661,11 @@  static inline int v4l_queue_alloc_bufs(struct v4l_fd *f,
 		return 0;
 	for (b = from; b < v4l_queue_g_buffers(q); b++) {
 		for (p = 0; p < v4l_queue_g_num_planes(q); p++) {
-			void *m = malloc(v4l_queue_g_length(q, p));
-
-			if (m == NULL)
-				return errno;
+			void *m;
+			int ret = posix_memalign(&m, getpagesize(),
+						v4l_queue_g_length(q, p));
+			if (ret)
+				return ret;
 			v4l_queue_s_userptr(q, b, p, m);
 		}
 	}