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