tests: Use igt macros more
[platform/upstream/intel-gpu-tools.git] / tests / gem_userptr_blits.c
1 /*
2  * Copyright © 2009-2014 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Eric Anholt <eric@anholt.net>
25  *    Chris Wilson <chris@chris-wilson.co.uk>
26  *    Tvrtko Ursulin <tvrtko.ursulin@intel.com>
27  *
28  */
29
30 /** @file gem_userptr_blits.c
31  *
32  * This is a test of doing many blits using a mixture of normal system pages
33  * and uncached linear buffers, with a working set larger than the
34  * aperture size.
35  *
36  * The goal is to simply ensure the basics work.
37  */
38
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <fcntl.h>
43 #include <inttypes.h>
44 #include <errno.h>
45 #include <assert.h>
46 #include <sys/stat.h>
47 #include <sys/time.h>
48 #include <sys/mman.h>
49 #include <signal.h>
50
51 #include "drm.h"
52 #include "i915_drm.h"
53
54 #include "drmtest.h"
55 #include "intel_bufmgr.h"
56 #include "intel_batchbuffer.h"
57 #include "intel_chipset.h"
58 #include "ioctl_wrappers.h"
59
60 #include "eviction_common.c"
61
62 #ifndef PAGE_SIZE
63 #define PAGE_SIZE 4096
64 #endif
65
66 #define LOCAL_I915_GEM_USERPTR       0x34
67 #define LOCAL_IOCTL_I915_GEM_USERPTR DRM_IOWR (DRM_COMMAND_BASE + LOCAL_I915_GEM_USERPTR, struct local_i915_gem_userptr)
68 struct local_i915_gem_userptr {
69         uint64_t user_ptr;
70         uint64_t user_size;
71         uint32_t flags;
72 #define LOCAL_I915_USERPTR_READ_ONLY (1<<0)
73 #define LOCAL_I915_USERPTR_UNSYNCHRONIZED (1<<31)
74         uint32_t handle;
75 };
76
77 static uint32_t userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED;
78
79 #define WIDTH 512
80 #define HEIGHT 512
81
82 static uint32_t linear[WIDTH*HEIGHT];
83
84 static void gem_userptr_test_unsynchronized(void)
85 {
86         userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED;
87 }
88
89 static void gem_userptr_test_synchronized(void)
90 {
91         userptr_flags = 0;
92 }
93
94 static int gem_userptr(int fd, void *ptr, int size, int read_only, uint32_t *handle)
95 {
96         struct local_i915_gem_userptr userptr;
97         int ret;
98
99         userptr.user_ptr = (uintptr_t)ptr;
100         userptr.user_size = size;
101         userptr.flags = userptr_flags;
102         if (read_only)
103                 userptr.flags |= LOCAL_I915_USERPTR_READ_ONLY;
104
105         ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
106         if (ret)
107                 ret = errno;
108         igt_skip_on_f(ret == ENODEV &&
109                       (userptr_flags & LOCAL_I915_USERPTR_UNSYNCHRONIZED) == 0 &&
110                       !read_only,
111                       "Skipping, synchronized mappings with no kernel CONFIG_MMU_NOTIFIER?");
112         if (ret == 0)
113                 *handle = userptr.handle;
114
115         return ret;
116 }
117
118
119 static void gem_userptr_sync(int fd, uint32_t handle)
120 {
121         gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
122 }
123
124 static void
125 copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
126 {
127         uint32_t batch[12];
128         struct drm_i915_gem_relocation_entry reloc[2];
129         struct drm_i915_gem_exec_object2 obj[3];
130         struct drm_i915_gem_execbuffer2 exec;
131         uint32_t handle;
132         int ret, i=0;
133
134         batch[i++] = XY_SRC_COPY_BLT_CMD |
135                   XY_SRC_COPY_BLT_WRITE_ALPHA |
136                   XY_SRC_COPY_BLT_WRITE_RGB;
137         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
138                 batch[i - 1] |= 8;
139         else
140                 batch[i - 1] |= 6;
141
142         batch[i++] = (3 << 24) | /* 32 bits */
143                   (0xcc << 16) | /* copy ROP */
144                   WIDTH*4;
145         batch[i++] = 0; /* dst x1,y1 */
146         batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
147         batch[i++] = 0; /* dst reloc */
148         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
149                 batch[i++] = 0;
150         batch[i++] = 0; /* src x1,y1 */
151         batch[i++] = WIDTH*4;
152         batch[i++] = 0; /* src reloc */
153         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
154                 batch[i++] = 0;
155         batch[i++] = MI_BATCH_BUFFER_END;
156         batch[i++] = MI_NOOP;
157
158         handle = gem_create(fd, 4096);
159         gem_write(fd, handle, 0, batch, sizeof(batch));
160
161         reloc[0].target_handle = dst;
162         reloc[0].delta = 0;
163         reloc[0].offset = 4 * sizeof(batch[0]);
164         reloc[0].presumed_offset = 0;
165         reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;;
166         reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
167
168         reloc[1].target_handle = src;
169         reloc[1].delta = 0;
170         reloc[1].offset = 7 * sizeof(batch[0]);
171         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
172                 reloc[1].offset += sizeof(batch[0]);
173         reloc[1].presumed_offset = 0;
174         reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;;
175         reloc[1].write_domain = 0;
176
177         obj[0].handle = dst;
178         obj[0].relocation_count = 0;
179         obj[0].relocs_ptr = 0;
180         obj[0].alignment = 0;
181         obj[0].offset = 0;
182         obj[0].flags = 0;
183         obj[0].rsvd1 = 0;
184         obj[0].rsvd2 = 0;
185
186         obj[1].handle = src;
187         obj[1].relocation_count = 0;
188         obj[1].relocs_ptr = 0;
189         obj[1].alignment = 0;
190         obj[1].offset = 0;
191         obj[1].flags = 0;
192         obj[1].rsvd1 = 0;
193         obj[1].rsvd2 = 0;
194
195         obj[2].handle = handle;
196         obj[2].relocation_count = 2;
197         obj[2].relocs_ptr = (uintptr_t)reloc;
198         obj[2].alignment = 0;
199         obj[2].offset = 0;
200         obj[2].flags = 0;
201         obj[2].rsvd1 = obj[2].rsvd2 = 0;
202
203         exec.buffers_ptr = (uintptr_t)obj;
204         exec.buffer_count = 3;
205         exec.batch_start_offset = 0;
206         exec.batch_len = i * 4;
207         exec.DR1 = exec.DR4 = 0;
208         exec.num_cliprects = 0;
209         exec.cliprects_ptr = 0;
210         exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0;
211         i915_execbuffer2_set_context_id(exec, 0);
212         exec.rsvd2 = 0;
213
214         ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
215         if (ret)
216                 ret = errno;
217
218         if (error == ~0)
219                 igt_assert(ret != 0);
220         else
221                 igt_assert(ret == error);
222
223         gem_close(fd, handle);
224 }
225
226 static void
227 blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo, int error)
228 {
229         uint32_t batch[12];
230         struct drm_i915_gem_relocation_entry reloc[2];
231         struct drm_i915_gem_exec_object2 *obj;
232         struct drm_i915_gem_execbuffer2 exec;
233         uint32_t handle;
234         int n, ret, i=0;
235
236         batch[i++] = XY_SRC_COPY_BLT_CMD |
237                   XY_SRC_COPY_BLT_WRITE_ALPHA |
238                   XY_SRC_COPY_BLT_WRITE_RGB;
239         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
240                 batch[i - 1] |= 8;
241         else
242                 batch[i - 1] |= 6;
243         batch[i++] = (3 << 24) | /* 32 bits */
244                   (0xcc << 16) | /* copy ROP */
245                   WIDTH*4;
246         batch[i++] = 0; /* dst x1,y1 */
247         batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
248         batch[i++] = 0; /* dst reloc */
249         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
250                 batch[i++] = 0;
251         batch[i++] = 0; /* src x1,y1 */
252         batch[i++] = WIDTH*4;
253         batch[i++] = 0; /* src reloc */
254         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
255                 batch[i++] = 0;
256         batch[i++] = MI_BATCH_BUFFER_END;
257         batch[i++] = MI_NOOP;
258
259         handle = gem_create(fd, 4096);
260         gem_write(fd, handle, 0, batch, sizeof(batch));
261
262         reloc[0].target_handle = dst;
263         reloc[0].delta = 0;
264         reloc[0].offset = 4 * sizeof(batch[0]);
265         reloc[0].presumed_offset = 0;
266         reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
267         reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
268
269         reloc[1].target_handle = src;
270         reloc[1].delta = 0;
271         reloc[1].offset = 7 * sizeof(batch[0]);
272         if (intel_gen(intel_get_drm_devid(fd)) >= 8)
273                 reloc[1].offset += sizeof(batch[0]);
274         reloc[1].presumed_offset = 0;
275         reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
276         reloc[1].write_domain = 0;
277
278         obj = calloc(n_bo + 1, sizeof(*obj));
279         for (n = 0; n < n_bo; n++)
280                 obj[n].handle = all_bo[n];
281         obj[n].handle = handle;
282         obj[n].relocation_count = 2;
283         obj[n].relocs_ptr = (uintptr_t)reloc;
284
285         exec.buffers_ptr = (uintptr_t)obj;
286         exec.buffer_count = n_bo + 1;
287         exec.batch_start_offset = 0;
288         exec.batch_len = i * 4;
289         exec.DR1 = exec.DR4 = 0;
290         exec.num_cliprects = 0;
291         exec.cliprects_ptr = 0;
292         exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0;
293         i915_execbuffer2_set_context_id(exec, 0);
294         exec.rsvd2 = 0;
295
296         ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
297         if (ret)
298                 ret = errno;
299
300         igt_assert(ret == error);
301
302         gem_close(fd, handle);
303         free(obj);
304 }
305
306 static uint32_t
307 create_userptr(int fd, uint32_t val, uint32_t *ptr)
308 {
309         uint32_t handle;
310         int i, ret;
311
312         ret = gem_userptr(fd, ptr, sizeof(linear), 0, &handle);
313         igt_assert(ret == 0);
314         igt_assert(handle != 0);
315
316         /* Fill the BO with dwords starting at val */
317         for (i = 0; i < WIDTH*HEIGHT; i++)
318                 ptr[i] = val++;
319
320         return handle;
321 }
322
323 static void **handle_ptr_map;
324 static unsigned int num_handle_ptr_map;
325
326 static void add_handle_ptr(uint32_t handle, void *ptr)
327 {
328         if (handle >= num_handle_ptr_map) {
329                 handle_ptr_map = realloc(handle_ptr_map,
330                                          (handle + 1000) * sizeof(void*));
331                 num_handle_ptr_map = handle + 1000;
332         }
333
334         handle_ptr_map[handle] = ptr;
335 }
336
337 static void *get_handle_ptr(uint32_t handle)
338 {
339         return handle_ptr_map[handle];
340 }
341
342 static void free_handle_ptr(uint32_t handle)
343 {
344         igt_assert(handle < num_handle_ptr_map);
345         igt_assert(handle_ptr_map[handle]);
346
347         free(handle_ptr_map[handle]);
348         handle_ptr_map[handle] = NULL;
349 }
350
351 static uint32_t create_userptr_bo(int fd, int size)
352 {
353         void *ptr;
354         uint32_t handle;
355         int ret;
356
357         ret = posix_memalign(&ptr, PAGE_SIZE, size);
358         igt_assert(ret == 0);
359
360         ret = gem_userptr(fd, (uint32_t *)ptr, size, 0, &handle);
361         igt_assert(ret == 0);
362         add_handle_ptr(handle, ptr);
363
364         return handle;
365 }
366
367 static void clear(int fd, uint32_t handle, int size)
368 {
369         void *ptr = get_handle_ptr(handle);
370
371         igt_assert(ptr != NULL);
372
373         memset(ptr, 0, size);
374 }
375
376 static void free_userptr_bo(int fd, uint32_t handle)
377 {
378         gem_close(fd, handle);
379         free_handle_ptr(handle);
380 }
381
382 static uint32_t
383 create_bo(int fd, uint32_t val)
384 {
385         uint32_t handle;
386         int i;
387
388         handle = gem_create(fd, sizeof(linear));
389
390         /* Fill the BO with dwords starting at val */
391         for (i = 0; i < WIDTH*HEIGHT; i++)
392                 linear[i] = val++;
393         gem_write(fd, handle, 0, linear, sizeof(linear));
394
395         return handle;
396 }
397
398 static void
399 check_cpu(uint32_t *ptr, uint32_t val)
400 {
401         int i;
402
403         for (i = 0; i < WIDTH*HEIGHT; i++) {
404                 igt_assert_f(ptr[i] == val,
405                              "Expected 0x%08x, found 0x%08x "
406                              "at offset 0x%08x\n",
407                              val, ptr[i], i * 4);
408                 val++;
409         }
410 }
411
412 static void
413 check_gpu(int fd, uint32_t handle, uint32_t val)
414 {
415         gem_read(fd, handle, 0, linear, sizeof(linear));
416         check_cpu(linear, val);
417 }
418
419 static int has_userptr(int fd)
420 {
421         uint32_t handle = 0;
422         void *ptr;
423         uint32_t oldflags;
424         int ret;
425
426         assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
427         oldflags = userptr_flags;
428         gem_userptr_test_unsynchronized();
429         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
430         userptr_flags = oldflags;
431         if (ret != 0) {
432                 free(ptr);
433                 return 0;
434         }
435
436         gem_close(fd, handle);
437         free(ptr);
438
439         return handle != 0;
440 }
441
442 static int test_input_checking(int fd)
443 {
444         struct local_i915_gem_userptr userptr;
445         int ret;
446
447         /* Invalid flags. */
448         userptr.user_ptr = 0;
449         userptr.user_size = 0;
450         userptr.flags = ~0;
451         ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
452         igt_assert(ret != 0);
453
454         /* Too big. */
455         userptr.user_ptr = 0;
456         userptr.user_size = ~0;
457         userptr.flags = 0;
458         ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
459         igt_assert(ret != 0);
460
461         /* Both wrong. */
462         userptr.user_ptr = 0;
463         userptr.user_size = ~0;
464         userptr.flags = ~0;
465         ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
466         igt_assert(ret != 0);
467
468         return 0;
469 }
470
471 static int test_access_control(int fd)
472 {
473         igt_fork(child, 1) {
474                 void *ptr;
475                 int ret;
476                 uint32_t handle;
477
478                 igt_drop_root();
479
480                 /* CAP_SYS_ADMIN is needed for UNSYNCHRONIZED mappings. */
481                 gem_userptr_test_unsynchronized();
482
483                 igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
484
485                 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
486                 if (ret == 0)
487                         gem_close(fd, handle);
488                 free(ptr);
489                 igt_assert(ret == EPERM);
490         }
491
492         igt_waitchildren();
493
494         return 0;
495 }
496
497 static int test_invalid_mapping(int fd)
498 {
499         int ret;
500         uint32_t handle, handle2;
501         void *ptr;
502
503         /* NULL pointer. */
504         ret = gem_userptr(fd, NULL, PAGE_SIZE, 0, &handle);
505         igt_assert(ret == 0);
506         copy(fd, handle, handle, ~0); /* QQQ Precise errno? */
507         gem_close(fd, handle);
508
509         /* GTT mapping */
510         handle = create_bo(fd, 0);
511         ptr = gem_mmap__gtt(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE);
512         if (ptr == NULL)
513                 gem_close(fd, handle);
514         assert(ptr != NULL);
515         assert(((unsigned long)ptr & (PAGE_SIZE - 1)) == 0);
516         assert((sizeof(linear) & (PAGE_SIZE - 1)) == 0);
517         ret = gem_userptr(fd, ptr, sizeof(linear), 0, &handle2);
518         igt_assert(ret == 0);
519         copy(fd, handle, handle, ~0); /* QQQ Precise errno? */
520         gem_close(fd, handle2);
521         munmap(ptr, sizeof(linear));
522         gem_close(fd, handle);
523
524         return 0;
525 }
526
527 static int test_forbidden_ops(int fd)
528 {
529         void *ptr;
530         int ret;
531         uint32_t handle;
532         char buf[PAGE_SIZE];
533         struct drm_i915_gem_pread gem_pread;
534         struct drm_i915_gem_pwrite gem_pwrite;
535
536         assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
537
538         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
539         igt_assert(ret == 0);
540
541         gem_pread.handle = handle;
542         gem_pread.offset = 0;
543         gem_pread.size = PAGE_SIZE;
544         gem_pread.data_ptr = (uintptr_t)buf;
545         ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PREAD, &gem_pread);
546         if (ret == 0) {
547                 gem_close(fd, handle);
548                 free(ptr);
549         }
550         igt_assert(ret != 0);
551
552         gem_pwrite.handle = handle;
553         gem_pwrite.offset = 0;
554         gem_pwrite.size = PAGE_SIZE;
555         gem_pwrite.data_ptr = (uintptr_t)buf;
556         ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite);
557         if (ret == 0) {
558                 gem_close(fd, handle);
559                 free(ptr);
560         }
561         igt_assert(ret != 0);
562
563         gem_close(fd, handle);
564         free(ptr);
565
566         return 0;
567 }
568
569 static char counter;
570
571 static void (*orig_sigbus)(int sig, siginfo_t *info, void *param);
572 static unsigned long sigbus_start;
573 static long sigbus_cnt = -1;
574
575 static void
576 check_bo(int fd1, uint32_t handle1, int is_userptr, int fd2, uint32_t handle2)
577 {
578         char *ptr1, *ptr2;
579         int i;
580         unsigned long size = sizeof(linear);
581
582         if (is_userptr)
583                 ptr1 = get_handle_ptr(handle1);
584         else
585                 ptr1 = gem_mmap(fd1, handle1, sizeof(linear), PROT_READ | PROT_WRITE);
586
587         ptr2 = gem_mmap(fd2, handle2, sizeof(linear), PROT_READ | PROT_WRITE);
588
589         igt_assert(ptr1);
590         igt_assert(ptr2);
591
592         sigbus_start = (unsigned long)ptr2;
593
594         if (sigbus_cnt == 0)
595                 size = 1;
596
597         /* check whether it's still our old object first. */
598         for (i = 0; i < size; i++) {
599                 igt_assert(ptr1[i] == counter);
600                 igt_assert(ptr2[i] == counter);
601         }
602
603         counter++;
604
605         if (size > 1) {
606                 memset(ptr1, counter, size);
607                 igt_assert(memcmp(ptr1, ptr2, size) == 0);
608         }
609
610         if (!is_userptr)
611                 munmap(ptr1, sizeof(linear));
612         munmap(ptr2, sizeof(linear));
613 }
614
615 static int export_handle(int fd, uint32_t handle, int *outfd)
616 {
617         struct drm_prime_handle args;
618         int ret;
619
620         args.handle = handle;
621         args.flags = DRM_CLOEXEC;
622         args.fd = -1;
623
624         ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
625         if (ret)
626                 ret = errno;
627         *outfd = args.fd;
628
629         return ret;
630 }
631
632 static void sigbus(int sig, siginfo_t *info, void *param)
633 {
634         unsigned long ptr = (unsigned long)info->si_addr;
635         void *addr;
636
637         if (ptr >= sigbus_start &&
638             ptr <= (sigbus_start + sizeof(linear))) {
639                 sigbus_cnt++;
640                 addr = mmap((void *)ptr, sizeof(linear), PROT_READ | PROT_WRITE,
641                                 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
642                 if ((unsigned long)addr == ptr) {
643                         memset(addr, counter, sizeof(linear));
644                         return;
645                 }
646         }
647
648         if (orig_sigbus)
649                 orig_sigbus(sig, info, param);
650         assert(0);
651 }
652
653 static int test_dmabuf(void)
654 {
655         int fd1, fd2;
656         uint32_t handle, handle_import1, handle_import2, handle_selfimport;
657         int dma_buf_fd = -1;
658         int ret;
659         struct sigaction sigact, orig_sigact;
660
661         fd1 = drm_open_any();
662         fd2 = drm_open_any();
663
664         handle = create_userptr_bo(fd1, sizeof(linear));
665
666         ret = export_handle(fd1, handle, &dma_buf_fd);
667         if (userptr_flags & LOCAL_I915_USERPTR_UNSYNCHRONIZED) {
668                 igt_assert(ret == EINVAL);
669                 free_userptr_bo(fd1, handle);
670
671                 return 0;
672         } else {
673                 igt_assert(ret == 0);
674                 igt_assert(dma_buf_fd >= 0);
675         }
676         handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
677         check_bo(fd1, handle, 1, fd2, handle_import1);
678
679         /* reimport should give us the same handle so that userspace can check
680          * whether it has that bo already somewhere. */
681         handle_import2 = prime_fd_to_handle(fd2, dma_buf_fd);
682         igt_assert(handle_import1 == handle_import2);
683
684         /* Same for re-importing on the exporting fd. */
685         handle_selfimport = prime_fd_to_handle(fd1, dma_buf_fd);
686         igt_assert(handle == handle_selfimport);
687
688         /* close dma_buf, check whether nothing disappears. */
689         close(dma_buf_fd);
690         check_bo(fd1, handle, 1, fd2, handle_import1);
691
692         /* destroy userptr object and expect SIGBUS */
693         free_userptr_bo(fd1, handle);
694         sigact.sa_sigaction = sigbus;
695         sigact.sa_flags = SA_SIGINFO;
696         ret = sigaction(SIGBUS, &sigact, &orig_sigact);
697         assert(ret == 0);
698         orig_sigbus = orig_sigact.sa_sigaction;
699         sigbus_cnt = 0;
700         check_bo(fd2, handle_import1, 0, fd2, handle_import1);
701         assert(sigbus_cnt > 0);
702         sigact.sa_sigaction = orig_sigbus;
703         sigact.sa_flags = SA_SIGINFO;
704         ret = sigaction(SIGBUS, &sigact, &orig_sigact);
705         assert(ret == 0);
706
707         gem_close(fd2, handle_import1);
708         close(fd1);
709         close(fd2);
710
711         return 0;
712 }
713
714 static int test_usage_restrictions(int fd)
715 {
716         void *ptr;
717         int ret;
718         uint32_t handle;
719
720         assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE * 2) == 0);
721
722         /* Address not aligned. */
723         ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE, 0, &handle);
724         igt_assert(ret != 0);
725
726         /* Size not rounded to page size. */
727         ret = gem_userptr(fd, ptr, PAGE_SIZE - 1, 0, &handle);
728         igt_assert(ret != 0);
729
730         /* Both wrong. */
731         ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE - 1, 0, &handle);
732         igt_assert(ret != 0);
733
734         /* Read-only not supported. */
735         ret = gem_userptr(fd, (char *)ptr, PAGE_SIZE, 1, &handle);
736         igt_assert(ret != 0);
737
738         free(ptr);
739
740         return 0;
741 }
742
743 static int test_create_destroy(int fd)
744 {
745         void *ptr;
746         int ret;
747         uint32_t handle;
748
749         igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
750
751         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
752         igt_assert(ret == 0);
753
754         gem_close(fd, handle);
755         free(ptr);
756
757         return 0;
758 }
759
760 static int test_coherency(int fd, int count)
761 {
762         uint32_t *memory;
763         uint32_t *cpu, *cpu_val;
764         uint32_t *gpu, *gpu_val;
765         uint32_t start = 0;
766         int i, ret;
767
768         igt_info("Using 2x%d 1MiB buffers\n", count);
769
770         ret = posix_memalign((void **)&memory, PAGE_SIZE, count*sizeof(linear));
771         igt_assert(ret == 0 && memory);
772
773         gpu = malloc(sizeof(uint32_t)*count*4);
774         gpu_val = gpu + count;
775         cpu = gpu_val + count;
776         cpu_val = cpu + count;
777
778         for (i = 0; i < count; i++) {
779                 gpu[i] = create_bo(fd, start);
780                 gpu_val[i] = start;
781                 start += WIDTH*HEIGHT;
782         }
783
784         for (i = 0; i < count; i++) {
785                 cpu[i] = create_userptr(fd, start, memory+i*WIDTH*HEIGHT);
786                 cpu_val[i] = start;
787                 start += WIDTH*HEIGHT;
788         }
789
790         igt_info("Verifying initialisation...\n");
791         for (i = 0; i < count; i++) {
792                 check_gpu(fd, gpu[i], gpu_val[i]);
793                 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
794         }
795
796         igt_info("Cyclic blits cpu->gpu, forward...\n");
797         for (i = 0; i < count * 4; i++) {
798                 int src = i % count;
799                 int dst = (i + 1) % count;
800
801                 copy(fd, gpu[dst], cpu[src], 0);
802                 gpu_val[dst] = cpu_val[src];
803         }
804         for (i = 0; i < count; i++)
805                 check_gpu(fd, gpu[i], gpu_val[i]);
806
807         igt_info("Cyclic blits gpu->cpu, backward...\n");
808         for (i = 0; i < count * 4; i++) {
809                 int src = (i + 1) % count;
810                 int dst = i % count;
811
812                 copy(fd, cpu[dst], gpu[src], 0);
813                 cpu_val[dst] = gpu_val[src];
814         }
815         for (i = 0; i < count; i++) {
816                 gem_userptr_sync(fd, cpu[i]);
817                 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
818         }
819
820         igt_info("Random blits...\n");
821         for (i = 0; i < count * 4; i++) {
822                 int src = random() % count;
823                 int dst = random() % count;
824
825                 if (random() & 1) {
826                         copy(fd, gpu[dst], cpu[src], 0);
827                         gpu_val[dst] = cpu_val[src];
828                 } else {
829                         copy(fd, cpu[dst], gpu[src], 0);
830                         cpu_val[dst] = gpu_val[src];
831                 }
832         }
833         for (i = 0; i < count; i++) {
834                 check_gpu(fd, gpu[i], gpu_val[i]);
835                 gem_close(fd, gpu[i]);
836
837                 gem_userptr_sync(fd, cpu[i]);
838                 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
839                 gem_close(fd, cpu[i]);
840         }
841
842         free(gpu);
843         free(memory);
844
845         return 0;
846 }
847
848 static struct igt_eviction_test_ops fault_ops = {
849         .create = create_userptr_bo,
850         .close = free_userptr_bo,
851         .copy = blit,
852         .clear = clear,
853 };
854
855 static int can_swap(void)
856 {
857         unsigned long as, ram;
858
859         /* Cannot swap if not enough address space */
860
861         /* FIXME: Improve check criteria. */
862         if (sizeof(void*) < 8)
863                 as = 3 * 1024;
864         else
865                 as = 256 * 1024; /* Just a big number */
866
867         ram = intel_get_total_ram_mb();
868
869         if ((as - 128) < (ram - 256))
870                 return 0;
871
872         return 1;
873 }
874
875 #define min(a, b) ((a) < (b) ? (a) : (b))
876
877 static void test_forking_evictions(int fd, int size, int count,
878                              unsigned flags)
879 {
880         int trash_count;
881         int num_threads;
882
883         trash_count = intel_get_total_ram_mb() * 11 / 10;
884         /* Use the fact test will spawn a number of child
885          * processes meaning swapping will be triggered system
886          * wide even if one process on it's own can't do it.
887          */
888         num_threads = min(sysconf(_SC_NPROCESSORS_ONLN) * 4, 12);
889         trash_count /= num_threads;
890         if (count > trash_count)
891                 count = trash_count;
892
893         forking_evictions(fd, &fault_ops, size, count, trash_count, flags);
894 }
895
896 static void test_swapping_evictions(int fd, int size, int count)
897 {
898         int trash_count;
899
900         igt_skip_on_f(!can_swap(),
901                 "Not enough process address space for swapping tests.\n");
902
903         trash_count = intel_get_total_ram_mb() * 11 / 10;
904
905         swapping_evictions(fd, &fault_ops, size, count, trash_count);
906 }
907
908 static void test_minor_evictions(int fd, int size, int count)
909 {
910         minor_evictions(fd, &fault_ops, size, count);
911 }
912
913 static void test_major_evictions(int fd, int size, int count)
914 {
915         major_evictions(fd, &fault_ops, size, count);
916 }
917
918 static int test_overlap(int fd, int expected)
919 {
920         char *ptr;
921         int ret;
922         uint32_t handle, handle2;
923
924         igt_assert(posix_memalign((void *)&ptr, PAGE_SIZE, PAGE_SIZE * 3) == 0);
925
926         ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE, 0, &handle);
927         igt_assert(ret == 0);
928
929         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle2);
930         igt_assert(ret == 0);
931         gem_close(fd, handle2);
932
933         ret = gem_userptr(fd, ptr + PAGE_SIZE * 2, PAGE_SIZE, 0, &handle2);
934         igt_assert(ret == 0);
935         gem_close(fd, handle2);
936
937         ret = gem_userptr(fd, ptr, PAGE_SIZE * 2, 0, &handle2);
938         igt_assert(ret == expected);
939         if (ret == 0)
940                 gem_close(fd, handle2);
941
942         ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE * 2, 0, &handle2);
943         igt_assert(ret == expected);
944         if (ret == 0)
945                 gem_close(fd, handle2);
946
947         ret = gem_userptr(fd, ptr, PAGE_SIZE * 3, 0, &handle2);
948         igt_assert(ret == expected);
949         if (ret == 0)
950                 gem_close(fd, handle2);
951
952         gem_close(fd, handle);
953         free(ptr);
954
955         return 0;
956 }
957
958 static int test_unmap(int fd, int expected)
959 {
960         char *ptr, *bo_ptr;
961         const unsigned int num_obj = 3;
962         unsigned int i;
963         uint32_t bo[num_obj + 1];
964         size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
965         int ret;
966
967         ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
968                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
969         assert(ptr != MAP_FAILED);
970
971         bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
972
973         for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) {
974                 ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]);
975                 igt_assert(ret == 0);
976         }
977
978         bo[num_obj] = create_bo(fd, 0);
979
980         for (i = 0; i < num_obj; i++)
981                 copy(fd, bo[num_obj], bo[i], 0);
982
983         ret = munmap(ptr, map_size);
984         assert(ret == 0);
985
986         for (i = 0; i < num_obj; i++)
987                 copy(fd, bo[num_obj], bo[i], expected);
988
989         for (i = 0; i < (num_obj + 1); i++)
990                 gem_close(fd, bo[i]);
991
992         return 0;
993 }
994
995 static int test_unmap_after_close(int fd)
996 {
997         char *ptr, *bo_ptr;
998         const unsigned int num_obj = 3;
999         unsigned int i;
1000         uint32_t bo[num_obj + 1];
1001         size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
1002         int ret;
1003
1004         ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
1005                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1006         assert(ptr != MAP_FAILED);
1007
1008         bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
1009
1010         for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) {
1011                 ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]);
1012                 igt_assert(ret == 0);
1013         }
1014
1015         bo[num_obj] = create_bo(fd, 0);
1016
1017         for (i = 0; i < num_obj; i++)
1018                 copy(fd, bo[num_obj], bo[i], 0);
1019
1020         for (i = 0; i < (num_obj + 1); i++)
1021                 gem_close(fd, bo[i]);
1022
1023         ret = munmap(ptr, map_size);
1024         assert(ret == 0);
1025
1026         return 0;
1027 }
1028
1029 static int test_unmap_cycles(int fd, int expected)
1030 {
1031         int i;
1032
1033         for (i = 0; i < 1000; i++)
1034                 test_unmap(fd, expected);
1035
1036         return 0;
1037 }
1038
1039 unsigned int total_ram;
1040 uint64_t aperture_size;
1041 int fd, count;
1042
1043
1044 int main(int argc, char **argv)
1045 {
1046         int size = sizeof(linear);
1047
1048         igt_skip_on_simulation();
1049
1050         igt_subtest_init(argc, argv);
1051
1052         igt_fixture {
1053                 int ret;
1054
1055                 fd = drm_open_any();
1056                 igt_assert(fd >= 0);
1057
1058                 ret = has_userptr(fd);
1059                 igt_skip_on_f(ret == 0, "No userptr support - %s (%d)\n",
1060                               strerror(errno), ret);
1061
1062                 size = sizeof(linear);
1063
1064                 aperture_size = gem_aperture_size(fd);
1065                 igt_info("Aperture size is %lu MiB\n", (long)(aperture_size / (1024*1024)));
1066
1067                 if (argc > 1)
1068                         count = atoi(argv[1]);
1069                 if (count == 0)
1070                         count = 2 * aperture_size / (1024*1024) / 3;
1071
1072                 total_ram = intel_get_total_ram_mb();
1073                 igt_info("Total RAM is %u MiB\n", total_ram);
1074
1075                 if (count > total_ram * 3 / 4) {
1076                         count = intel_get_total_ram_mb() * 3 / 4;
1077                         igt_info("Not enough RAM to run test, reducing buffer count.\n");
1078                 }
1079         }
1080
1081         igt_subtest("input-checking")
1082                 test_input_checking(fd);
1083
1084         igt_subtest("usage-restrictions")
1085                 test_usage_restrictions(fd);
1086
1087         igt_subtest("invalid-mapping")
1088                 test_invalid_mapping(fd);
1089
1090         igt_subtest("forbidden-operations")
1091                 test_forbidden_ops(fd);
1092
1093         igt_info("Testing unsynchronized mappings...\n");
1094         gem_userptr_test_unsynchronized();
1095
1096         igt_subtest("create-destroy-unsync")
1097                 test_create_destroy(fd);
1098
1099         igt_subtest("unsync-overlap")
1100                 test_overlap(fd, 0);
1101
1102         igt_subtest("unsync-unmap")
1103                 test_unmap(fd, 0);
1104
1105         igt_subtest("unsync-unmap-cycles")
1106                 test_unmap_cycles(fd, 0);
1107
1108         igt_subtest("unsync-unmap-after-close")
1109                 test_unmap_after_close(fd);
1110
1111         igt_subtest("coherency-unsync")
1112                 test_coherency(fd, count);
1113
1114         igt_subtest("dmabuf-unsync")
1115                 test_dmabuf();
1116
1117         for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) {
1118                 igt_subtest_f("forked-unsync%s%s%s-%s",
1119                     flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "",
1120                     flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "",
1121                     flags & FORKING_EVICTIONS_MEMORY_PRESSURE ?
1122                                 "-mempressure" : "",
1123                     flags & FORKING_EVICTIONS_INTERRUPTIBLE ?
1124                                 "interruptible" : "normal") {
1125                         test_forking_evictions(fd, size, count, flags);
1126                 }
1127         }
1128
1129         igt_subtest("swapping-unsync-normal")
1130                 test_swapping_evictions(fd, size, count);
1131
1132         igt_subtest("minor-unsync-normal")
1133                 test_minor_evictions(fd, size, count);
1134
1135         igt_subtest("major-unsync-normal") {
1136                 size = 200 * 1024 * 1024;
1137                 count = (gem_aperture_size(fd) / size) + 2;
1138                 test_major_evictions(fd, size, count);
1139         }
1140
1141         igt_fixture {
1142                 size = sizeof(linear);
1143                 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1144                 if (count > total_ram * 3 / 4)
1145                         count = intel_get_total_ram_mb() * 3 / 4;
1146         }
1147
1148         igt_fork_signal_helper();
1149
1150         igt_subtest("swapping-unsync-interruptible")
1151                 test_swapping_evictions(fd, size, count);
1152
1153         igt_subtest("minor-unsync-interruptible")
1154                 test_minor_evictions(fd, size, count);
1155
1156         igt_subtest("major-unsync-interruptible") {
1157                 size = 200 * 1024 * 1024;
1158                 count = (gem_aperture_size(fd) / size) + 2;
1159                 test_major_evictions(fd, size, count);
1160         }
1161
1162         igt_stop_signal_helper();
1163
1164         igt_info("Testing synchronized mappings...\n");
1165
1166         igt_fixture {
1167                 size = sizeof(linear);
1168                 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1169                 if (count > total_ram * 3 / 4)
1170                         count = intel_get_total_ram_mb() * 3 / 4;
1171         }
1172
1173         gem_userptr_test_synchronized();
1174
1175         igt_subtest("create-destroy-sync")
1176                 test_create_destroy(fd);
1177
1178         igt_subtest("sync-overlap")
1179                 test_overlap(fd, EINVAL);
1180
1181         igt_subtest("sync-unmap")
1182                 test_unmap(fd, EFAULT);
1183
1184         igt_subtest("sync-unmap-cycles")
1185                 test_unmap_cycles(fd, EFAULT);
1186
1187         igt_subtest("sync-unmap-after-close")
1188                 test_unmap_after_close(fd);
1189
1190         igt_subtest("coherency-sync")
1191                 test_coherency(fd, count);
1192
1193         igt_subtest("dmabuf-sync")
1194                 test_dmabuf();
1195
1196         for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) {
1197                 igt_subtest_f("forked-sync%s%s%s-%s",
1198                     flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "",
1199                     flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "",
1200                     flags & FORKING_EVICTIONS_MEMORY_PRESSURE ?
1201                                 "-mempressure" : "",
1202                     flags & FORKING_EVICTIONS_INTERRUPTIBLE ?
1203                                 "interruptible" : "normal") {
1204                         test_forking_evictions(fd, size, count, flags);
1205                 }
1206         }
1207
1208         igt_subtest("swapping-normal-sync")
1209                 test_swapping_evictions(fd, size, count);
1210
1211         igt_subtest("minor-normal-sync")
1212                 test_minor_evictions(fd, size, count);
1213
1214         igt_subtest("major-normal-sync") {
1215                 size = 200 * 1024 * 1024;
1216                 count = (gem_aperture_size(fd) / size) + 2;
1217                 test_major_evictions(fd, size, count);
1218         }
1219
1220         igt_fixture {
1221                 size = 1024 * 1024;
1222                 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1223                 if (count > total_ram * 3 / 4)
1224                         count = intel_get_total_ram_mb() * 3 / 4;
1225         }
1226
1227         igt_fork_signal_helper();
1228
1229         igt_subtest("swapping-sync-interruptible")
1230                 test_swapping_evictions(fd, size, count);
1231
1232         igt_subtest("minor-sync-interruptible")
1233                 test_minor_evictions(fd, size, count);
1234
1235         igt_subtest("major-sync-interruptible") {
1236                 size = 200 * 1024 * 1024;
1237                 count = (gem_aperture_size(fd) / size) + 2;
1238                 test_major_evictions(fd, size, count);
1239         }
1240
1241         igt_stop_signal_helper();
1242
1243         igt_subtest("access-control")
1244         test_access_control(fd);
1245
1246         igt_exit();
1247
1248         return 0;
1249 }