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]
Date:   Fri, 10 Sep 2021 14:20:11 +0200
From:   Hans Verkuil <hverkuil-cisco@...all.nl>
To:     Sergey Senozhatsky <senozhatsky@...omium.org>
Cc:     Tomasz Figa <tfiga@...omium.org>,
        Ricardo Ribalda <ribalda@...omium.org>,
        linux-media@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] v4l-compliance: re-introduce NON_COHERENT and cache hints
 tests

Hi Sergey,

I've applied the "[PATCHv6 0/8] videobuf2: support new noncontiguous DMA API" series
to my kernel, and applied this patch to v4l-utils.

Running 'test-media vim2m' in contrib/test results in the following compliance failures:

Streaming ioctls:
        test read/write: OK (Not Supported)
        test blocking wait: OK
        Video Capture: Captured 8 buffers
        test MMAP (no poll): OK
        Video Capture: Captured 8 buffers
        test MMAP (select): OK
        Video Capture: Captured 8 buffers
        test MMAP (epoll): OK
        Video Capture: Captured 8 buffers
        test USERPTR (no poll): OK
        Video Capture: Captured 8 buffers
        test USERPTR (select): OK
                fail: v4l2-test-buffers.cpp(1869): !(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE)
                fail: v4l2-test-buffers.cpp(1932): setupDmaBuf(expbuf_node, node, q, exp_q)
        test DMABUF (no poll): FAIL
                fail: v4l2-test-buffers.cpp(1869): !(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE)
                fail: v4l2-test-buffers.cpp(1932): setupDmaBuf(expbuf_node, node, q, exp_q)
        test DMABUF (select): FAIL

The same happens with e.g. vivid, but vim2m is quicker to test.

I'm not sure whether this is a bug in this v4l2-compliance patch or whether it is
a bug in the v6 series, but it should be checked.

Regards,

	Hans

On 09/07/2021 11:22, Sergey Senozhatsky wrote:
> This returns back non-coherent (previously known as NON_COHERENT)
> memory flag and buffer cache management hints testing (for VB2_MEMORY_MMAP
> buffers).
> 
> Signed-off-by: Sergey Senozhatsky <senozhatsky@...omium.org>
> ---
>  utils/common/cv4l-helpers.h                 |  8 +--
>  utils/common/v4l-helpers.h                  |  8 ++-
>  utils/v4l2-compliance/v4l2-test-buffers.cpp | 65 ++++++++++++++++++---
>  3 files changed, 66 insertions(+), 15 deletions(-)
> 
> diff --git a/utils/common/cv4l-helpers.h b/utils/common/cv4l-helpers.h
> index 712efde6..3cee372b 100644
> --- a/utils/common/cv4l-helpers.h
> +++ b/utils/common/cv4l-helpers.h
> @@ -754,17 +754,17 @@ public:
>  	int g_fd(unsigned index, unsigned plane) const { return v4l_queue_g_fd(this, index, plane); }
>  	void s_fd(unsigned index, unsigned plane, int fd) { v4l_queue_s_fd(this, index, plane, fd); }
>  
> -	int reqbufs(cv4l_fd *fd, unsigned count = 0)
> +	int reqbufs(cv4l_fd *fd, unsigned count = 0, unsigned int flags = 0)
>  	{
> -		return v4l_queue_reqbufs(fd->g_v4l_fd(), this, count);
> +		return v4l_queue_reqbufs(fd->g_v4l_fd(), this, count, flags);
>  	}
>  	bool has_create_bufs(cv4l_fd *fd) const
>  	{
>  		return v4l_queue_has_create_bufs(fd->g_v4l_fd(), this);
>  	}
> -	int create_bufs(cv4l_fd *fd, unsigned count, const v4l2_format *fmt = NULL)
> +	int create_bufs(cv4l_fd *fd, unsigned count, const v4l2_format *fmt = NULL, unsigned int flags = 0)
>  	{
> -		return v4l_queue_create_bufs(fd->g_v4l_fd(), this, count, fmt);
> +		return v4l_queue_create_bufs(fd->g_v4l_fd(), this, count, fmt, flags);
>  	}
>  	int mmap_bufs(cv4l_fd *fd, unsigned from = 0)
>  	{
> diff --git a/utils/common/v4l-helpers.h b/utils/common/v4l-helpers.h
> index f96b3c38..c09cd987 100644
> --- a/utils/common/v4l-helpers.h
> +++ b/utils/common/v4l-helpers.h
> @@ -1515,7 +1515,7 @@ static inline int v4l_queue_querybufs(struct v4l_fd *f, struct v4l_queue *q, uns
>  }
>  
>  static inline int v4l_queue_reqbufs(struct v4l_fd *f,
> -		struct v4l_queue *q, unsigned count)
> +		struct v4l_queue *q, unsigned count, unsigned int flags = 0)
>  {
>  	struct v4l2_requestbuffers reqbufs;
>  	int ret;
> @@ -1523,6 +1523,7 @@ static inline int v4l_queue_reqbufs(struct v4l_fd *f,
>  	reqbufs.type = q->type;
>  	reqbufs.memory = q->memory;
>  	reqbufs.count = count;
> +	reqbufs.flags = flags;
>  	/*
>  	 * Problem: if REQBUFS returns an error, did it free any old
>  	 * buffers or not?
> @@ -1547,7 +1548,7 @@ static inline bool v4l_queue_has_create_bufs(struct v4l_fd *f, const struct v4l_
>  
>  static inline int v4l_queue_create_bufs(struct v4l_fd *f,
>  		struct v4l_queue *q, unsigned count,
> -		const struct v4l2_format *fmt)
> +		const struct v4l2_format *fmt, unsigned int flags = 0)
>  {
>  	struct v4l2_create_buffers createbufs;
>  	int ret;
> @@ -1555,6 +1556,7 @@ static inline int v4l_queue_create_bufs(struct v4l_fd *f,
>  	createbufs.format.type = q->type;
>  	createbufs.memory = q->memory;
>  	createbufs.count = count;
> +	createbufs.flags = flags;
>  	if (fmt) {
>  		createbufs.format = *fmt;
>  	} else {
> @@ -1733,7 +1735,7 @@ static inline void v4l_queue_free(struct v4l_fd *f, struct v4l_queue *q)
>  	v4l_ioctl(f, VIDIOC_STREAMOFF, &q->type);
>  	v4l_queue_release_bufs(f, q, 0);
>  	v4l_queue_close_exported_fds(q);
> -	v4l_queue_reqbufs(f, q, 0);
> +	v4l_queue_reqbufs(f, q, 0, 0);
>  }
>  
>  static inline void v4l_queue_buffer_update(const struct v4l_queue *q,
> diff --git a/utils/v4l2-compliance/v4l2-test-buffers.cpp b/utils/v4l2-compliance/v4l2-test-buffers.cpp
> index e40461bd..6997f40b 100644
> --- a/utils/v4l2-compliance/v4l2-test-buffers.cpp
> +++ b/utils/v4l2-compliance/v4l2-test-buffers.cpp
> @@ -663,6 +663,10 @@ int testReqBufs(struct node *node)
>  		fail_on_test(q.reqbufs(node, 0));
>  
>  		for (m = V4L2_MEMORY_MMAP; m <= V4L2_MEMORY_DMABUF; m++) {
> +			bool cache_hints_cap = false;
> +			bool coherent;
> +
> +			cache_hints_cap = q.g_capabilities() & V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS;
>  			if (!(node->valid_memorytype & (1 << m)))
>  				continue;
>  			cv4l_queue q2(i, m);
> @@ -678,8 +682,17 @@ int testReqBufs(struct node *node)
>  			reqbufs.count = 1;
>  			reqbufs.type = i;
>  			reqbufs.memory = m;
> +			reqbufs.flags = V4L2_MEMORY_FLAG_NON_COHERENT;
>  			fail_on_test(doioctl(node, VIDIOC_REQBUFS, &reqbufs));
> -			fail_on_test(check_0(reqbufs.reserved, sizeof(reqbufs.reserved)));
> +			coherent = reqbufs.flags & V4L2_MEMORY_FLAG_NON_COHERENT;
> +			if (!cache_hints_cap) {
> +				fail_on_test(coherent);
> +			} else {
> +				if (m == V4L2_MEMORY_MMAP)
> +					fail_on_test(!coherent);
> +				else
> +					fail_on_test(coherent);
> +			}
>  			q.reqbufs(node);
>  
>  			ret = q.create_bufs(node, 0);
> @@ -692,9 +705,32 @@ int testReqBufs(struct node *node)
>  			node->g_fmt(crbufs.format, i);
>  			crbufs.count = 1;
>  			crbufs.memory = m;
> +			crbufs.flags = V4L2_MEMORY_FLAG_NON_COHERENT;
>  			fail_on_test(doioctl(node, VIDIOC_CREATE_BUFS, &crbufs));
>  			fail_on_test(check_0(crbufs.reserved, sizeof(crbufs.reserved)));
>  			fail_on_test(crbufs.index != q.g_buffers());
> +
> +			coherent = crbufs.flags & V4L2_MEMORY_FLAG_NON_COHERENT;
> +			if (!cache_hints_cap) {
> +				fail_on_test(coherent);
> +			} else {
> +				if (m == V4L2_MEMORY_MMAP)
> +					fail_on_test(!coherent);
> +				else
> +					fail_on_test(coherent);
> +			}
> +
> +			if (cache_hints_cap) {
> +				/*
> +				 * Different memory consistency model. Should fail for MMAP
> +				 * queues which support cache hints.
> +				 */
> +				crbufs.flags = 0;
> +				if (m == V4L2_MEMORY_MMAP)
> +					fail_on_test(doioctl(node, VIDIOC_CREATE_BUFS, &crbufs) != EINVAL);
> +				else
> +					fail_on_test(doioctl(node, VIDIOC_CREATE_BUFS, &crbufs));
> +			}
>  			q.reqbufs(node);
>  
>  			fail_on_test(q.create_bufs(node, 1));
> @@ -1207,10 +1243,16 @@ static int setupMmap(struct node *node, cv4l_queue &q)
>  		fail_on_test(buf.querybuf(node, i));
>  		fail_on_test(buf.check(q, Unqueued, i));
>  
> -		flags = buf.g_flags();
> -		flags |= V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
> -		flags |= V4L2_BUF_FLAG_NO_CACHE_CLEAN;
> -		buf.s_flags(flags);
> +		/*
> +		 * Do not set cache hints for all the buffers, but only on
> +		 * some of them, so that we can test more cases.
> +		 */
> +		if (i == 0) {
> +			flags = buf.g_flags();
> +			flags |= V4L2_BUF_FLAG_NO_CACHE_INVALIDATE;
> +			flags |= V4L2_BUF_FLAG_NO_CACHE_CLEAN;
> +			buf.s_flags(flags);
> +		}
>  
>  		for (unsigned p = 0; p < buf.g_num_planes(); p++) {
>  			// Try a random offset
> @@ -1250,8 +1292,15 @@ static int setupMmap(struct node *node, cv4l_queue &q)
>  		}
>  		flags = buf.g_flags();
>  		if (cache_hints) {
> -			fail_on_test(!(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE));
> -			fail_on_test(!(flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN));
> +			if (i == 0) {
> +				/* We do expect cache hints on this buffer */
> +				fail_on_test(!(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE));
> +				fail_on_test(!(flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN));
> +			} else {
> +				/* We expect no cache hints on this buffer */
> +				fail_on_test(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE);
> +				fail_on_test(flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN);
> +			}
>  		} else if (node->might_support_cache_hints) {
>  			fail_on_test(flags & V4L2_BUF_FLAG_NO_CACHE_INVALIDATE);
>  			fail_on_test(flags & V4L2_BUF_FLAG_NO_CACHE_CLEAN);
> @@ -1341,7 +1390,7 @@ int testMmap(struct node *node, struct node *node_m2m_cap, unsigned frame_count,
>  			have_createbufs = false;
>  		if (have_createbufs) {
>  			q.reqbufs(node);
> -			q.create_bufs(node, 2, &cur_fmt);
> +			q.create_bufs(node, 2, &cur_fmt, V4L2_MEMORY_FLAG_NON_COHERENT);
>  			fail_on_test(setupMmap(node, q));
>  			q.munmap_bufs(node);
>  			q.reqbufs(node, 2);
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ