xref: /aosp_15_r20/external/igt-gpu-tools/tests/prime_mmap.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1*d83cc019SAndroid Build Coastguard Worker /*
2*d83cc019SAndroid Build Coastguard Worker  * Copyright © 2014 Intel Corporation
3*d83cc019SAndroid Build Coastguard Worker  *
4*d83cc019SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
5*d83cc019SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
6*d83cc019SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
7*d83cc019SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*d83cc019SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
9*d83cc019SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
10*d83cc019SAndroid Build Coastguard Worker  *
11*d83cc019SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*d83cc019SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*d83cc019SAndroid Build Coastguard Worker  * Software.
14*d83cc019SAndroid Build Coastguard Worker  *
15*d83cc019SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*d83cc019SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*d83cc019SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*d83cc019SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*d83cc019SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*d83cc019SAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21*d83cc019SAndroid Build Coastguard Worker  * IN THE SOFTWARE.
22*d83cc019SAndroid Build Coastguard Worker  *
23*d83cc019SAndroid Build Coastguard Worker  * Authors:
24*d83cc019SAndroid Build Coastguard Worker  *    Rob Bradford <rob at linux.intel.com>
25*d83cc019SAndroid Build Coastguard Worker  *    Tiago Vignatti <tiago.vignatti at intel.com>
26*d83cc019SAndroid Build Coastguard Worker  *
27*d83cc019SAndroid Build Coastguard Worker  */
28*d83cc019SAndroid Build Coastguard Worker 
29*d83cc019SAndroid Build Coastguard Worker /*
30*d83cc019SAndroid Build Coastguard Worker  * Testcase: Check whether mmap()ing dma-buf works
31*d83cc019SAndroid Build Coastguard Worker  */
32*d83cc019SAndroid Build Coastguard Worker #include <unistd.h>
33*d83cc019SAndroid Build Coastguard Worker #include <stdlib.h>
34*d83cc019SAndroid Build Coastguard Worker #include <stdio.h>
35*d83cc019SAndroid Build Coastguard Worker #include <string.h>
36*d83cc019SAndroid Build Coastguard Worker #include <fcntl.h>
37*d83cc019SAndroid Build Coastguard Worker #include <inttypes.h>
38*d83cc019SAndroid Build Coastguard Worker #include <errno.h>
39*d83cc019SAndroid Build Coastguard Worker #include <sys/stat.h>
40*d83cc019SAndroid Build Coastguard Worker #include <sys/ioctl.h>
41*d83cc019SAndroid Build Coastguard Worker #include <pthread.h>
42*d83cc019SAndroid Build Coastguard Worker 
43*d83cc019SAndroid Build Coastguard Worker #include "drm.h"
44*d83cc019SAndroid Build Coastguard Worker #include "i915_drm.h"
45*d83cc019SAndroid Build Coastguard Worker #include "drmtest.h"
46*d83cc019SAndroid Build Coastguard Worker #include "igt_debugfs.h"
47*d83cc019SAndroid Build Coastguard Worker #include "ioctl_wrappers.h"
48*d83cc019SAndroid Build Coastguard Worker #include "i915/gem_mman.h"
49*d83cc019SAndroid Build Coastguard Worker 
50*d83cc019SAndroid Build Coastguard Worker #define BO_SIZE (16*1024)
51*d83cc019SAndroid Build Coastguard Worker 
52*d83cc019SAndroid Build Coastguard Worker static int fd;
53*d83cc019SAndroid Build Coastguard Worker 
54*d83cc019SAndroid Build Coastguard Worker char pattern[] = {0xff, 0x00, 0x00, 0x00,
55*d83cc019SAndroid Build Coastguard Worker 	0x00, 0xff, 0x00, 0x00,
56*d83cc019SAndroid Build Coastguard Worker 	0x00, 0x00, 0xff, 0x00,
57*d83cc019SAndroid Build Coastguard Worker 	0x00, 0x00, 0x00, 0xff};
58*d83cc019SAndroid Build Coastguard Worker 
59*d83cc019SAndroid Build Coastguard Worker static void
fill_bo(uint32_t handle,size_t size)60*d83cc019SAndroid Build Coastguard Worker fill_bo(uint32_t handle, size_t size)
61*d83cc019SAndroid Build Coastguard Worker {
62*d83cc019SAndroid Build Coastguard Worker 	off_t i;
63*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < size; i+=sizeof(pattern))
64*d83cc019SAndroid Build Coastguard Worker 	{
65*d83cc019SAndroid Build Coastguard Worker 		gem_write(fd, handle, i, pattern, sizeof(pattern));
66*d83cc019SAndroid Build Coastguard Worker 	}
67*d83cc019SAndroid Build Coastguard Worker }
68*d83cc019SAndroid Build Coastguard Worker 
69*d83cc019SAndroid Build Coastguard Worker static void
fill_bo_cpu(char * ptr)70*d83cc019SAndroid Build Coastguard Worker fill_bo_cpu(char *ptr)
71*d83cc019SAndroid Build Coastguard Worker {
72*d83cc019SAndroid Build Coastguard Worker 	memcpy(ptr, pattern, sizeof(pattern));
73*d83cc019SAndroid Build Coastguard Worker }
74*d83cc019SAndroid Build Coastguard Worker 
75*d83cc019SAndroid Build Coastguard Worker static void
test_correct(void)76*d83cc019SAndroid Build Coastguard Worker test_correct(void)
77*d83cc019SAndroid Build Coastguard Worker {
78*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
79*d83cc019SAndroid Build Coastguard Worker 	char *ptr1, *ptr2;
80*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
81*d83cc019SAndroid Build Coastguard Worker 
82*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
83*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
84*d83cc019SAndroid Build Coastguard Worker 
85*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
86*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
87*d83cc019SAndroid Build Coastguard Worker 
88*d83cc019SAndroid Build Coastguard Worker 	/* Check correctness vs GEM_MMAP_GTT */
89*d83cc019SAndroid Build Coastguard Worker 	ptr1 = gem_mmap__gtt(fd, handle, BO_SIZE, PROT_READ);
90*d83cc019SAndroid Build Coastguard Worker 	ptr2 = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
91*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr1 != MAP_FAILED);
92*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr2 != MAP_FAILED);
93*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
94*d83cc019SAndroid Build Coastguard Worker 
95*d83cc019SAndroid Build Coastguard Worker 	/* Check pattern correctness */
96*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr2, pattern, sizeof(pattern)) == 0);
97*d83cc019SAndroid Build Coastguard Worker 
98*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr1, BO_SIZE);
99*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr2, BO_SIZE);
100*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
101*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
102*d83cc019SAndroid Build Coastguard Worker }
103*d83cc019SAndroid Build Coastguard Worker 
104*d83cc019SAndroid Build Coastguard Worker static void
test_map_unmap(void)105*d83cc019SAndroid Build Coastguard Worker test_map_unmap(void)
106*d83cc019SAndroid Build Coastguard Worker {
107*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
108*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
109*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
110*d83cc019SAndroid Build Coastguard Worker 
111*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
112*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
113*d83cc019SAndroid Build Coastguard Worker 
114*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
115*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
116*d83cc019SAndroid Build Coastguard Worker 
117*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
118*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
119*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
120*d83cc019SAndroid Build Coastguard Worker 
121*d83cc019SAndroid Build Coastguard Worker 	/* Unmap and remap */
122*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
123*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
124*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
125*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
126*d83cc019SAndroid Build Coastguard Worker 
127*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
128*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
129*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
130*d83cc019SAndroid Build Coastguard Worker }
131*d83cc019SAndroid Build Coastguard Worker 
132*d83cc019SAndroid Build Coastguard Worker /* prime and then unprime and then prime again the same handle */
133*d83cc019SAndroid Build Coastguard Worker static void
test_reprime(void)134*d83cc019SAndroid Build Coastguard Worker test_reprime(void)
135*d83cc019SAndroid Build Coastguard Worker {
136*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
137*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
138*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
139*d83cc019SAndroid Build Coastguard Worker 
140*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
141*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
142*d83cc019SAndroid Build Coastguard Worker 
143*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
144*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
145*d83cc019SAndroid Build Coastguard Worker 
146*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
147*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
148*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
149*d83cc019SAndroid Build Coastguard Worker 
150*d83cc019SAndroid Build Coastguard Worker 	close (dma_buf_fd);
151*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
152*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
153*d83cc019SAndroid Build Coastguard Worker 
154*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
155*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
156*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
157*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
158*d83cc019SAndroid Build Coastguard Worker 
159*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
160*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
161*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
162*d83cc019SAndroid Build Coastguard Worker }
163*d83cc019SAndroid Build Coastguard Worker 
164*d83cc019SAndroid Build Coastguard Worker /* map from another process */
165*d83cc019SAndroid Build Coastguard Worker static void
test_forked(void)166*d83cc019SAndroid Build Coastguard Worker test_forked(void)
167*d83cc019SAndroid Build Coastguard Worker {
168*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
169*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
170*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
171*d83cc019SAndroid Build Coastguard Worker 
172*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
173*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
174*d83cc019SAndroid Build Coastguard Worker 
175*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
176*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
177*d83cc019SAndroid Build Coastguard Worker 
178*d83cc019SAndroid Build Coastguard Worker 	igt_fork(childno, 1) {
179*d83cc019SAndroid Build Coastguard Worker 		ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
180*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ptr != MAP_FAILED);
181*d83cc019SAndroid Build Coastguard Worker 		igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
182*d83cc019SAndroid Build Coastguard Worker 		munmap(ptr, BO_SIZE);
183*d83cc019SAndroid Build Coastguard Worker 		close(dma_buf_fd);
184*d83cc019SAndroid Build Coastguard Worker 	}
185*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
186*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren();
187*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
188*d83cc019SAndroid Build Coastguard Worker }
189*d83cc019SAndroid Build Coastguard Worker 
190*d83cc019SAndroid Build Coastguard Worker /* test simple CPU write */
191*d83cc019SAndroid Build Coastguard Worker static void
test_correct_cpu_write(void)192*d83cc019SAndroid Build Coastguard Worker test_correct_cpu_write(void)
193*d83cc019SAndroid Build Coastguard Worker {
194*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
195*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
196*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
197*d83cc019SAndroid Build Coastguard Worker 
198*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
199*d83cc019SAndroid Build Coastguard Worker 
200*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd_for_mmap(fd, handle);
201*d83cc019SAndroid Build Coastguard Worker 
202*d83cc019SAndroid Build Coastguard Worker 	/* Skip if DRM_RDWR is not supported */
203*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(errno == EINVAL);
204*d83cc019SAndroid Build Coastguard Worker 
205*d83cc019SAndroid Build Coastguard Worker 	/* Check correctness of map using write protection (PROT_WRITE) */
206*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd, 0);
207*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
208*d83cc019SAndroid Build Coastguard Worker 
209*d83cc019SAndroid Build Coastguard Worker 	/* Fill bo using CPU */
210*d83cc019SAndroid Build Coastguard Worker 	fill_bo_cpu(ptr);
211*d83cc019SAndroid Build Coastguard Worker 
212*d83cc019SAndroid Build Coastguard Worker 	/* Check pattern correctness */
213*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
214*d83cc019SAndroid Build Coastguard Worker 
215*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
216*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
217*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
218*d83cc019SAndroid Build Coastguard Worker }
219*d83cc019SAndroid Build Coastguard Worker 
220*d83cc019SAndroid Build Coastguard Worker /* map from another process and then write using CPU */
221*d83cc019SAndroid Build Coastguard Worker static void
test_forked_cpu_write(void)222*d83cc019SAndroid Build Coastguard Worker test_forked_cpu_write(void)
223*d83cc019SAndroid Build Coastguard Worker {
224*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
225*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
226*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
227*d83cc019SAndroid Build Coastguard Worker 
228*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
229*d83cc019SAndroid Build Coastguard Worker 
230*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd_for_mmap(fd, handle);
231*d83cc019SAndroid Build Coastguard Worker 
232*d83cc019SAndroid Build Coastguard Worker 	/* Skip if DRM_RDWR is not supported */
233*d83cc019SAndroid Build Coastguard Worker 	igt_skip_on(errno == EINVAL);
234*d83cc019SAndroid Build Coastguard Worker 
235*d83cc019SAndroid Build Coastguard Worker 	igt_fork(childno, 1) {
236*d83cc019SAndroid Build Coastguard Worker 		ptr = mmap(NULL, BO_SIZE, PROT_READ | PROT_WRITE , MAP_SHARED, dma_buf_fd, 0);
237*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ptr != MAP_FAILED);
238*d83cc019SAndroid Build Coastguard Worker 		fill_bo_cpu(ptr);
239*d83cc019SAndroid Build Coastguard Worker 
240*d83cc019SAndroid Build Coastguard Worker 		igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
241*d83cc019SAndroid Build Coastguard Worker 		munmap(ptr, BO_SIZE);
242*d83cc019SAndroid Build Coastguard Worker 		close(dma_buf_fd);
243*d83cc019SAndroid Build Coastguard Worker 	}
244*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
245*d83cc019SAndroid Build Coastguard Worker 	igt_waitchildren();
246*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
247*d83cc019SAndroid Build Coastguard Worker }
248*d83cc019SAndroid Build Coastguard Worker 
249*d83cc019SAndroid Build Coastguard Worker static void
test_refcounting(void)250*d83cc019SAndroid Build Coastguard Worker test_refcounting(void)
251*d83cc019SAndroid Build Coastguard Worker {
252*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
253*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
254*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
255*d83cc019SAndroid Build Coastguard Worker 
256*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
257*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
258*d83cc019SAndroid Build Coastguard Worker 
259*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
260*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
261*d83cc019SAndroid Build Coastguard Worker 	/* Close gem object before mapping */
262*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
263*d83cc019SAndroid Build Coastguard Worker 
264*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
265*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
266*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
267*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
268*d83cc019SAndroid Build Coastguard Worker 	close (dma_buf_fd);
269*d83cc019SAndroid Build Coastguard Worker }
270*d83cc019SAndroid Build Coastguard Worker 
271*d83cc019SAndroid Build Coastguard Worker /* dup before mmap */
272*d83cc019SAndroid Build Coastguard Worker static void
test_dup(void)273*d83cc019SAndroid Build Coastguard Worker test_dup(void)
274*d83cc019SAndroid Build Coastguard Worker {
275*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
276*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
277*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
278*d83cc019SAndroid Build Coastguard Worker 
279*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
280*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
281*d83cc019SAndroid Build Coastguard Worker 
282*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = dup(prime_handle_to_fd(fd, handle));
283*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
284*d83cc019SAndroid Build Coastguard Worker 
285*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
286*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr != MAP_FAILED);
287*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
288*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
289*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
290*d83cc019SAndroid Build Coastguard Worker 	close (dma_buf_fd);
291*d83cc019SAndroid Build Coastguard Worker }
292*d83cc019SAndroid Build Coastguard Worker 
293*d83cc019SAndroid Build Coastguard Worker /* Used for error case testing to avoid wrapper */
prime_handle_to_fd_no_assert(uint32_t handle,int flags,int * fd_out)294*d83cc019SAndroid Build Coastguard Worker static int prime_handle_to_fd_no_assert(uint32_t handle, int flags, int *fd_out)
295*d83cc019SAndroid Build Coastguard Worker {
296*d83cc019SAndroid Build Coastguard Worker 	struct drm_prime_handle args;
297*d83cc019SAndroid Build Coastguard Worker 	int ret;
298*d83cc019SAndroid Build Coastguard Worker 
299*d83cc019SAndroid Build Coastguard Worker 	args.handle = handle;
300*d83cc019SAndroid Build Coastguard Worker 	args.flags = flags;
301*d83cc019SAndroid Build Coastguard Worker 	args.fd = -1;
302*d83cc019SAndroid Build Coastguard Worker 
303*d83cc019SAndroid Build Coastguard Worker 	ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
304*d83cc019SAndroid Build Coastguard Worker 	if (ret)
305*d83cc019SAndroid Build Coastguard Worker 		ret = errno;
306*d83cc019SAndroid Build Coastguard Worker 	*fd_out = args.fd;
307*d83cc019SAndroid Build Coastguard Worker 
308*d83cc019SAndroid Build Coastguard Worker 	return ret;
309*d83cc019SAndroid Build Coastguard Worker }
310*d83cc019SAndroid Build Coastguard Worker 
has_userptr(void)311*d83cc019SAndroid Build Coastguard Worker static bool has_userptr(void)
312*d83cc019SAndroid Build Coastguard Worker {
313*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle = 0;
314*d83cc019SAndroid Build Coastguard Worker 	void *ptr;
315*d83cc019SAndroid Build Coastguard Worker 
316*d83cc019SAndroid Build Coastguard Worker 	igt_assert(posix_memalign(&ptr, 4096, 4096) == 0);
317*d83cc019SAndroid Build Coastguard Worker 	if ( __gem_userptr(fd, ptr, 4096, 0, 0, &handle) == 0)
318*d83cc019SAndroid Build Coastguard Worker 		gem_close(fd, handle);
319*d83cc019SAndroid Build Coastguard Worker 	free(ptr);
320*d83cc019SAndroid Build Coastguard Worker 
321*d83cc019SAndroid Build Coastguard Worker 	return handle;
322*d83cc019SAndroid Build Coastguard Worker }
323*d83cc019SAndroid Build Coastguard Worker 
324*d83cc019SAndroid Build Coastguard Worker /* test for mmap(dma_buf_export(userptr)) */
325*d83cc019SAndroid Build Coastguard Worker static void
test_userptr(void)326*d83cc019SAndroid Build Coastguard Worker test_userptr(void)
327*d83cc019SAndroid Build Coastguard Worker {
328*d83cc019SAndroid Build Coastguard Worker 	int ret, dma_buf_fd;
329*d83cc019SAndroid Build Coastguard Worker 	void *ptr;
330*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
331*d83cc019SAndroid Build Coastguard Worker 
332*d83cc019SAndroid Build Coastguard Worker 	igt_require(has_userptr());
333*d83cc019SAndroid Build Coastguard Worker 
334*d83cc019SAndroid Build Coastguard Worker 	/* create userptr bo */
335*d83cc019SAndroid Build Coastguard Worker 	ret = posix_memalign(&ptr, 4096, BO_SIZE);
336*d83cc019SAndroid Build Coastguard Worker 	igt_assert_eq(ret, 0);
337*d83cc019SAndroid Build Coastguard Worker 
338*d83cc019SAndroid Build Coastguard Worker 	/* we are not allowed to export unsynchronized userptr. Just create a normal
339*d83cc019SAndroid Build Coastguard Worker 	 * one */
340*d83cc019SAndroid Build Coastguard Worker 	gem_userptr(fd, (uint32_t *)ptr, BO_SIZE, 0, 0, &handle);
341*d83cc019SAndroid Build Coastguard Worker 
342*d83cc019SAndroid Build Coastguard Worker 	/* export userptr */
343*d83cc019SAndroid Build Coastguard Worker 	ret = prime_handle_to_fd_no_assert(handle, DRM_CLOEXEC, &dma_buf_fd);
344*d83cc019SAndroid Build Coastguard Worker 	if (ret) {
345*d83cc019SAndroid Build Coastguard Worker 		igt_assert(ret == EINVAL || ret == ENODEV);
346*d83cc019SAndroid Build Coastguard Worker 		goto free_userptr;
347*d83cc019SAndroid Build Coastguard Worker 	} else {
348*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(ret, 0);
349*d83cc019SAndroid Build Coastguard Worker 		igt_assert_lte(0, dma_buf_fd);
350*d83cc019SAndroid Build Coastguard Worker 	}
351*d83cc019SAndroid Build Coastguard Worker 
352*d83cc019SAndroid Build Coastguard Worker 	/* a userptr doesn't have the obj->base.filp, but can be exported via
353*d83cc019SAndroid Build Coastguard Worker 	 * dma-buf, so make sure it fails here */
354*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
355*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr == MAP_FAILED && errno == ENODEV);
356*d83cc019SAndroid Build Coastguard Worker free_userptr:
357*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
358*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
359*d83cc019SAndroid Build Coastguard Worker }
360*d83cc019SAndroid Build Coastguard Worker 
361*d83cc019SAndroid Build Coastguard Worker static void
test_errors(void)362*d83cc019SAndroid Build Coastguard Worker test_errors(void)
363*d83cc019SAndroid Build Coastguard Worker {
364*d83cc019SAndroid Build Coastguard Worker 	int i, dma_buf_fd;
365*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
366*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
367*d83cc019SAndroid Build Coastguard Worker 	int invalid_flags[] = {DRM_CLOEXEC - 1, DRM_CLOEXEC + 1,
368*d83cc019SAndroid Build Coastguard Worker 	                       DRM_RDWR - 1, DRM_RDWR + 1};
369*d83cc019SAndroid Build Coastguard Worker 
370*d83cc019SAndroid Build Coastguard Worker 	/* Test for invalid flags */
371*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
372*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(invalid_flags) / sizeof(invalid_flags[0]); i++) {
373*d83cc019SAndroid Build Coastguard Worker 		prime_handle_to_fd_no_assert(handle, invalid_flags[i], &dma_buf_fd);
374*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(errno, EINVAL);
375*d83cc019SAndroid Build Coastguard Worker 		errno = 0;
376*d83cc019SAndroid Build Coastguard Worker 	}
377*d83cc019SAndroid Build Coastguard Worker 
378*d83cc019SAndroid Build Coastguard Worker 	/* Close gem object before priming */
379*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
380*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
381*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
382*d83cc019SAndroid Build Coastguard Worker 	prime_handle_to_fd_no_assert(handle, DRM_CLOEXEC, &dma_buf_fd);
383*d83cc019SAndroid Build Coastguard Worker 	igt_assert(dma_buf_fd == -1 && errno == ENOENT);
384*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
385*d83cc019SAndroid Build Coastguard Worker 
386*d83cc019SAndroid Build Coastguard Worker 	/* close fd before mapping */
387*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
388*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
389*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
390*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
391*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
392*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
393*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr == MAP_FAILED && errno == EBADF);
394*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
395*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
396*d83cc019SAndroid Build Coastguard Worker 
397*d83cc019SAndroid Build Coastguard Worker 	/* Map too big */
398*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
399*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle, BO_SIZE);
400*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
401*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
402*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE * 2, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
403*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr == MAP_FAILED && errno == EINVAL);
404*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
405*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
406*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
407*d83cc019SAndroid Build Coastguard Worker 
408*d83cc019SAndroid Build Coastguard Worker 	/* Overlapping the end of the buffer */
409*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
410*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
411*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
412*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, BO_SIZE / 2);
413*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr == MAP_FAILED && errno == EINVAL);
414*d83cc019SAndroid Build Coastguard Worker 	errno = 0;
415*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
416*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
417*d83cc019SAndroid Build Coastguard Worker }
418*d83cc019SAndroid Build Coastguard Worker 
419*d83cc019SAndroid Build Coastguard Worker /* Test for invalid flags on sync ioctl */
420*d83cc019SAndroid Build Coastguard Worker static void
test_invalid_sync_flags(void)421*d83cc019SAndroid Build Coastguard Worker test_invalid_sync_flags(void)
422*d83cc019SAndroid Build Coastguard Worker {
423*d83cc019SAndroid Build Coastguard Worker 	int i, dma_buf_fd;
424*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
425*d83cc019SAndroid Build Coastguard Worker 	struct local_dma_buf_sync sync;
426*d83cc019SAndroid Build Coastguard Worker 	int invalid_flags[] = {-1,
427*d83cc019SAndroid Build Coastguard Worker 	                       0x00,
428*d83cc019SAndroid Build Coastguard Worker 	                       LOCAL_DMA_BUF_SYNC_RW + 1,
429*d83cc019SAndroid Build Coastguard Worker 	                       LOCAL_DMA_BUF_SYNC_VALID_FLAGS_MASK + 1};
430*d83cc019SAndroid Build Coastguard Worker 
431*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
432*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
433*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < sizeof(invalid_flags) / sizeof(invalid_flags[0]); i++) {
434*d83cc019SAndroid Build Coastguard Worker 		memset(&sync, 0, sizeof(sync));
435*d83cc019SAndroid Build Coastguard Worker 		sync.flags = invalid_flags[i];
436*d83cc019SAndroid Build Coastguard Worker 
437*d83cc019SAndroid Build Coastguard Worker 		drmIoctl(dma_buf_fd, LOCAL_DMA_BUF_IOCTL_SYNC, &sync);
438*d83cc019SAndroid Build Coastguard Worker 		igt_assert_eq(errno, EINVAL);
439*d83cc019SAndroid Build Coastguard Worker 		errno = 0;
440*d83cc019SAndroid Build Coastguard Worker 	}
441*d83cc019SAndroid Build Coastguard Worker }
442*d83cc019SAndroid Build Coastguard Worker 
443*d83cc019SAndroid Build Coastguard Worker static void
test_aperture_limit(void)444*d83cc019SAndroid Build Coastguard Worker test_aperture_limit(void)
445*d83cc019SAndroid Build Coastguard Worker {
446*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd1, dma_buf_fd2;
447*d83cc019SAndroid Build Coastguard Worker 	char *ptr1, *ptr2;
448*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle1, handle2;
449*d83cc019SAndroid Build Coastguard Worker 	/* Two buffers the sum of which > mappable aperture */
450*d83cc019SAndroid Build Coastguard Worker 	uint64_t size1 = (gem_mappable_aperture_size() * 7) / 8;
451*d83cc019SAndroid Build Coastguard Worker 	uint64_t size2 = (gem_mappable_aperture_size() * 3) / 8;
452*d83cc019SAndroid Build Coastguard Worker 
453*d83cc019SAndroid Build Coastguard Worker 	handle1 = gem_create(fd, size1);
454*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle1, BO_SIZE);
455*d83cc019SAndroid Build Coastguard Worker 
456*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd1 = prime_handle_to_fd(fd, handle1);
457*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
458*d83cc019SAndroid Build Coastguard Worker 	ptr1 = mmap(NULL, size1, PROT_READ, MAP_SHARED, dma_buf_fd1, 0);
459*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr1 != MAP_FAILED);
460*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr1, pattern, sizeof(pattern)) == 0);
461*d83cc019SAndroid Build Coastguard Worker 
462*d83cc019SAndroid Build Coastguard Worker 	handle2 = gem_create(fd, size1);
463*d83cc019SAndroid Build Coastguard Worker 	fill_bo(handle2, BO_SIZE);
464*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd2 = prime_handle_to_fd(fd, handle2);
465*d83cc019SAndroid Build Coastguard Worker 	igt_assert(errno == 0);
466*d83cc019SAndroid Build Coastguard Worker 	ptr2 = mmap(NULL, size2, PROT_READ, MAP_SHARED, dma_buf_fd2, 0);
467*d83cc019SAndroid Build Coastguard Worker 	igt_assert(ptr2 != MAP_FAILED);
468*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr2, pattern, sizeof(pattern)) == 0);
469*d83cc019SAndroid Build Coastguard Worker 
470*d83cc019SAndroid Build Coastguard Worker 	igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
471*d83cc019SAndroid Build Coastguard Worker 
472*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr1, size1);
473*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr2, size2);
474*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd1);
475*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd2);
476*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle1);
477*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle2);
478*d83cc019SAndroid Build Coastguard Worker }
479*d83cc019SAndroid Build Coastguard Worker 
480*d83cc019SAndroid Build Coastguard Worker static int
check_for_dma_buf_mmap(void)481*d83cc019SAndroid Build Coastguard Worker check_for_dma_buf_mmap(void)
482*d83cc019SAndroid Build Coastguard Worker {
483*d83cc019SAndroid Build Coastguard Worker 	int dma_buf_fd;
484*d83cc019SAndroid Build Coastguard Worker 	char *ptr;
485*d83cc019SAndroid Build Coastguard Worker 	uint32_t handle;
486*d83cc019SAndroid Build Coastguard Worker 	int ret = 1;
487*d83cc019SAndroid Build Coastguard Worker 
488*d83cc019SAndroid Build Coastguard Worker 	handle = gem_create(fd, BO_SIZE);
489*d83cc019SAndroid Build Coastguard Worker 	dma_buf_fd = prime_handle_to_fd(fd, handle);
490*d83cc019SAndroid Build Coastguard Worker 	ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
491*d83cc019SAndroid Build Coastguard Worker 	if (ptr != MAP_FAILED)
492*d83cc019SAndroid Build Coastguard Worker 		ret = 0;
493*d83cc019SAndroid Build Coastguard Worker 	munmap(ptr, BO_SIZE);
494*d83cc019SAndroid Build Coastguard Worker 	gem_close(fd, handle);
495*d83cc019SAndroid Build Coastguard Worker 	close(dma_buf_fd);
496*d83cc019SAndroid Build Coastguard Worker 	return ret;
497*d83cc019SAndroid Build Coastguard Worker }
498*d83cc019SAndroid Build Coastguard Worker 
499*d83cc019SAndroid Build Coastguard Worker igt_main
500*d83cc019SAndroid Build Coastguard Worker {
501*d83cc019SAndroid Build Coastguard Worker 	struct {
502*d83cc019SAndroid Build Coastguard Worker 		const char *name;
503*d83cc019SAndroid Build Coastguard Worker 		void (*fn)(void);
504*d83cc019SAndroid Build Coastguard Worker 	} tests[] = {
505*d83cc019SAndroid Build Coastguard Worker 		{ "test_correct", test_correct },
506*d83cc019SAndroid Build Coastguard Worker 		{ "test_map_unmap", test_map_unmap },
507*d83cc019SAndroid Build Coastguard Worker 		{ "test_reprime", test_reprime },
508*d83cc019SAndroid Build Coastguard Worker 		{ "test_forked", test_forked },
509*d83cc019SAndroid Build Coastguard Worker 		{ "test_correct_cpu_write", test_correct_cpu_write },
510*d83cc019SAndroid Build Coastguard Worker 		{ "test_forked_cpu_write", test_forked_cpu_write },
511*d83cc019SAndroid Build Coastguard Worker 		{ "test_refcounting", test_refcounting },
512*d83cc019SAndroid Build Coastguard Worker 		{ "test_dup", test_dup },
513*d83cc019SAndroid Build Coastguard Worker 		{ "test_userptr", test_userptr },
514*d83cc019SAndroid Build Coastguard Worker 		{ "test_errors", test_errors },
515*d83cc019SAndroid Build Coastguard Worker 		{ "test_invalid_sync_flags", test_invalid_sync_flags },
516*d83cc019SAndroid Build Coastguard Worker 		{ "test_aperture_limit", test_aperture_limit },
517*d83cc019SAndroid Build Coastguard Worker 	};
518*d83cc019SAndroid Build Coastguard Worker 	int i;
519*d83cc019SAndroid Build Coastguard Worker 
520*d83cc019SAndroid Build Coastguard Worker 	igt_fixture {
521*d83cc019SAndroid Build Coastguard Worker 		fd = drm_open_driver(DRIVER_INTEL);
522*d83cc019SAndroid Build Coastguard Worker 		igt_skip_on((check_for_dma_buf_mmap() != 0));
523*d83cc019SAndroid Build Coastguard Worker 		errno = 0;
524*d83cc019SAndroid Build Coastguard Worker 	}
525*d83cc019SAndroid Build Coastguard Worker 
526*d83cc019SAndroid Build Coastguard Worker 
527*d83cc019SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(tests); i++) {
528*d83cc019SAndroid Build Coastguard Worker 		igt_subtest(tests[i].name)
529*d83cc019SAndroid Build Coastguard Worker 			tests[i].fn();
530*d83cc019SAndroid Build Coastguard Worker 	}
531*d83cc019SAndroid Build Coastguard Worker 
532*d83cc019SAndroid Build Coastguard Worker 	igt_fixture
533*d83cc019SAndroid Build Coastguard Worker 		close(fd);
534*d83cc019SAndroid Build Coastguard Worker }
535