test: Fixup for the previous patch
[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                 if (ptr[i] != val) {
405                         fprintf(stderr, "Expected 0x%08x, found 0x%08x "
406                                 "at offset 0x%08x\n",
407                                 val, ptr[i], i * 4);
408                         abort();
409                 }
410                 val++;
411         }
412 }
413
414 static void
415 check_gpu(int fd, uint32_t handle, uint32_t val)
416 {
417         gem_read(fd, handle, 0, linear, sizeof(linear));
418         check_cpu(linear, val);
419 }
420
421 static int has_userptr(int fd)
422 {
423         uint32_t handle = 0;
424         void *ptr;
425         uint32_t oldflags;
426         int ret;
427
428         assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
429         oldflags = userptr_flags;
430         gem_userptr_test_unsynchronized();
431         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
432         userptr_flags = oldflags;
433         if (ret != 0) {
434                 free(ptr);
435                 return 0;
436         }
437
438         gem_close(fd, handle);
439         free(ptr);
440
441         return handle != 0;
442 }
443
444 static int test_input_checking(int fd)
445 {
446         struct local_i915_gem_userptr userptr;
447         int ret;
448
449         /* Invalid flags. */
450         userptr.user_ptr = 0;
451         userptr.user_size = 0;
452         userptr.flags = ~0;
453         ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
454         igt_assert(ret != 0);
455
456         /* Too big. */
457         userptr.user_ptr = 0;
458         userptr.user_size = ~0;
459         userptr.flags = 0;
460         ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
461         igt_assert(ret != 0);
462
463         /* Both wrong. */
464         userptr.user_ptr = 0;
465         userptr.user_size = ~0;
466         userptr.flags = ~0;
467         ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
468         igt_assert(ret != 0);
469
470         return 0;
471 }
472
473 static int test_access_control(int fd)
474 {
475         igt_fork(child, 1) {
476                 void *ptr;
477                 int ret;
478                 uint32_t handle;
479
480                 igt_drop_root();
481
482                 /* CAP_SYS_ADMIN is needed for UNSYNCHRONIZED mappings. */
483                 gem_userptr_test_unsynchronized();
484
485                 igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
486
487                 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
488                 if (ret == 0)
489                         gem_close(fd, handle);
490                 free(ptr);
491                 igt_assert(ret == EPERM);
492         }
493
494         igt_waitchildren();
495
496         return 0;
497 }
498
499 static int test_invalid_mapping(int fd)
500 {
501         int ret;
502         uint32_t handle, handle2;
503         void *ptr;
504
505         /* NULL pointer. */
506         ret = gem_userptr(fd, NULL, PAGE_SIZE, 0, &handle);
507         igt_assert(ret == 0);
508         copy(fd, handle, handle, ~0); /* QQQ Precise errno? */
509         gem_close(fd, handle);
510
511         /* GTT mapping */
512         handle = create_bo(fd, 0);
513         ptr = gem_mmap__gtt(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE);
514         if (ptr == NULL)
515                 gem_close(fd, handle);
516         assert(ptr != NULL);
517         assert(((unsigned long)ptr & (PAGE_SIZE - 1)) == 0);
518         assert((sizeof(linear) & (PAGE_SIZE - 1)) == 0);
519         ret = gem_userptr(fd, ptr, sizeof(linear), 0, &handle2);
520         igt_assert(ret == 0);
521         copy(fd, handle, handle, ~0); /* QQQ Precise errno? */
522         gem_close(fd, handle2);
523         munmap(ptr, sizeof(linear));
524         gem_close(fd, handle);
525
526         return 0;
527 }
528
529 static int test_forbidden_ops(int fd)
530 {
531         void *ptr;
532         int ret;
533         uint32_t handle;
534         char buf[PAGE_SIZE];
535         struct drm_i915_gem_pread gem_pread;
536         struct drm_i915_gem_pwrite gem_pwrite;
537
538         assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
539
540         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
541         igt_assert(ret == 0);
542
543         gem_pread.handle = handle;
544         gem_pread.offset = 0;
545         gem_pread.size = PAGE_SIZE;
546         gem_pread.data_ptr = (uintptr_t)buf;
547         ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PREAD, &gem_pread);
548         if (ret == 0) {
549                 gem_close(fd, handle);
550                 free(ptr);
551         }
552         igt_assert(ret != 0);
553
554         gem_pwrite.handle = handle;
555         gem_pwrite.offset = 0;
556         gem_pwrite.size = PAGE_SIZE;
557         gem_pwrite.data_ptr = (uintptr_t)buf;
558         ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_PWRITE, &gem_pwrite);
559         if (ret == 0) {
560                 gem_close(fd, handle);
561                 free(ptr);
562         }
563         igt_assert(ret != 0);
564
565         gem_close(fd, handle);
566         free(ptr);
567
568         return 0;
569 }
570
571 static char counter;
572
573 static void (*orig_sigbus)(int sig, siginfo_t *info, void *param);
574 static unsigned long sigbus_start;
575 static long sigbus_cnt = -1;
576
577 static void
578 check_bo(int fd1, uint32_t handle1, int is_userptr, int fd2, uint32_t handle2)
579 {
580         char *ptr1, *ptr2;
581         int i;
582         unsigned long size = sizeof(linear);
583
584         if (is_userptr)
585                 ptr1 = get_handle_ptr(handle1);
586         else
587                 ptr1 = gem_mmap(fd1, handle1, sizeof(linear), PROT_READ | PROT_WRITE);
588
589         ptr2 = gem_mmap(fd2, handle2, sizeof(linear), PROT_READ | PROT_WRITE);
590
591         igt_assert(ptr1);
592         igt_assert(ptr2);
593
594         sigbus_start = (unsigned long)ptr2;
595
596         if (sigbus_cnt == 0)
597                 size = 1;
598
599         /* check whether it's still our old object first. */
600         for (i = 0; i < size; i++) {
601                 igt_assert(ptr1[i] == counter);
602                 igt_assert(ptr2[i] == counter);
603         }
604
605         counter++;
606
607         if (size > 1) {
608                 memset(ptr1, counter, size);
609                 igt_assert(memcmp(ptr1, ptr2, size) == 0);
610         }
611
612         if (!is_userptr)
613                 munmap(ptr1, sizeof(linear));
614         munmap(ptr2, sizeof(linear));
615 }
616
617 static int export_handle(int fd, uint32_t handle, int *outfd)
618 {
619         struct drm_prime_handle args;
620         int ret;
621
622         args.handle = handle;
623         args.flags = DRM_CLOEXEC;
624         args.fd = -1;
625
626         ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
627         if (ret)
628                 ret = errno;
629         *outfd = args.fd;
630
631         return ret;
632 }
633
634 static void sigbus(int sig, siginfo_t *info, void *param)
635 {
636         unsigned long ptr = (unsigned long)info->si_addr;
637         void *addr;
638
639         if (ptr >= sigbus_start &&
640             ptr <= (sigbus_start + sizeof(linear))) {
641                 sigbus_cnt++;
642                 addr = mmap((void *)ptr, sizeof(linear), PROT_READ | PROT_WRITE,
643                                 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
644                 if ((unsigned long)addr == ptr) {
645                         memset(addr, counter, sizeof(linear));
646                         return;
647                 }
648         }
649
650         if (orig_sigbus)
651                 orig_sigbus(sig, info, param);
652         assert(0);
653 }
654
655 static int test_dmabuf(void)
656 {
657         int fd1, fd2;
658         uint32_t handle, handle_import1, handle_import2, handle_selfimport;
659         int dma_buf_fd = -1;
660         int ret;
661         struct sigaction sigact, orig_sigact;
662
663         fd1 = drm_open_any();
664         fd2 = drm_open_any();
665
666         handle = create_userptr_bo(fd1, sizeof(linear));
667
668         ret = export_handle(fd1, handle, &dma_buf_fd);
669         if (userptr_flags & LOCAL_I915_USERPTR_UNSYNCHRONIZED) {
670                 igt_assert(ret == EINVAL);
671                 free_userptr_bo(fd1, handle);
672
673                 return 0;
674         } else {
675                 igt_assert(ret == 0);
676                 igt_assert(dma_buf_fd >= 0);
677         }
678         handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
679         check_bo(fd1, handle, 1, fd2, handle_import1);
680
681         /* reimport should give us the same handle so that userspace can check
682          * whether it has that bo already somewhere. */
683         handle_import2 = prime_fd_to_handle(fd2, dma_buf_fd);
684         igt_assert(handle_import1 == handle_import2);
685
686         /* Same for re-importing on the exporting fd. */
687         handle_selfimport = prime_fd_to_handle(fd1, dma_buf_fd);
688         igt_assert(handle == handle_selfimport);
689
690         /* close dma_buf, check whether nothing disappears. */
691         close(dma_buf_fd);
692         check_bo(fd1, handle, 1, fd2, handle_import1);
693
694         /* destroy userptr object and expect SIGBUS */
695         free_userptr_bo(fd1, handle);
696         sigact.sa_sigaction = sigbus;
697         sigact.sa_flags = SA_SIGINFO;
698         ret = sigaction(SIGBUS, &sigact, &orig_sigact);
699         assert(ret == 0);
700         orig_sigbus = orig_sigact.sa_sigaction;
701         sigbus_cnt = 0;
702         check_bo(fd2, handle_import1, 0, fd2, handle_import1);
703         assert(sigbus_cnt > 0);
704         sigact.sa_sigaction = orig_sigbus;
705         sigact.sa_flags = SA_SIGINFO;
706         ret = sigaction(SIGBUS, &sigact, &orig_sigact);
707         assert(ret == 0);
708
709         gem_close(fd2, handle_import1);
710         close(fd1);
711         close(fd2);
712
713         return 0;
714 }
715
716 static int test_usage_restrictions(int fd)
717 {
718         void *ptr;
719         int ret;
720         uint32_t handle;
721
722         assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE * 2) == 0);
723
724         /* Address not aligned. */
725         ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE, 0, &handle);
726         igt_assert(ret != 0);
727
728         /* Size not rounded to page size. */
729         ret = gem_userptr(fd, ptr, PAGE_SIZE - 1, 0, &handle);
730         igt_assert(ret != 0);
731
732         /* Both wrong. */
733         ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE - 1, 0, &handle);
734         igt_assert(ret != 0);
735
736         /* Read-only not supported. */
737         ret = gem_userptr(fd, (char *)ptr, PAGE_SIZE, 1, &handle);
738         igt_assert(ret != 0);
739
740         free(ptr);
741
742         return 0;
743 }
744
745 static int test_create_destroy(int fd)
746 {
747         void *ptr;
748         int ret;
749         uint32_t handle;
750
751         igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
752
753         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
754         igt_assert(ret == 0);
755
756         gem_close(fd, handle);
757         free(ptr);
758
759         return 0;
760 }
761
762 static int test_coherency(int fd, int count)
763 {
764         uint32_t *memory;
765         uint32_t *cpu, *cpu_val;
766         uint32_t *gpu, *gpu_val;
767         uint32_t start = 0;
768         int i, ret;
769
770         printf("Using 2x%d 1MiB buffers\n", count);
771
772         ret = posix_memalign((void **)&memory, PAGE_SIZE, count*sizeof(linear));
773         if (ret != 0 || memory == NULL) {
774                 fprintf(stderr, "Unable to allocate %lld bytes\n",
775                         (long long)count*sizeof(linear));
776                 return 1;
777         }
778
779         gpu = malloc(sizeof(uint32_t)*count*4);
780         gpu_val = gpu + count;
781         cpu = gpu_val + count;
782         cpu_val = cpu + count;
783
784         for (i = 0; i < count; i++) {
785                 gpu[i] = create_bo(fd, start);
786                 gpu_val[i] = start;
787                 start += WIDTH*HEIGHT;
788         }
789
790         for (i = 0; i < count; i++) {
791                 cpu[i] = create_userptr(fd, start, memory+i*WIDTH*HEIGHT);
792                 cpu_val[i] = start;
793                 start += WIDTH*HEIGHT;
794         }
795
796         printf("Verifying initialisation...\n");
797         for (i = 0; i < count; i++) {
798                 check_gpu(fd, gpu[i], gpu_val[i]);
799                 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
800         }
801
802         printf("Cyclic blits cpu->gpu, forward...\n");
803         for (i = 0; i < count * 4; i++) {
804                 int src = i % count;
805                 int dst = (i + 1) % count;
806
807                 copy(fd, gpu[dst], cpu[src], 0);
808                 gpu_val[dst] = cpu_val[src];
809         }
810         for (i = 0; i < count; i++)
811                 check_gpu(fd, gpu[i], gpu_val[i]);
812
813         printf("Cyclic blits gpu->cpu, backward...\n");
814         for (i = 0; i < count * 4; i++) {
815                 int src = (i + 1) % count;
816                 int dst = i % count;
817
818                 copy(fd, cpu[dst], gpu[src], 0);
819                 cpu_val[dst] = gpu_val[src];
820         }
821         for (i = 0; i < count; i++) {
822                 gem_userptr_sync(fd, cpu[i]);
823                 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
824         }
825
826         printf("Random blits...\n");
827         for (i = 0; i < count * 4; i++) {
828                 int src = random() % count;
829                 int dst = random() % count;
830
831                 if (random() & 1) {
832                         copy(fd, gpu[dst], cpu[src], 0);
833                         gpu_val[dst] = cpu_val[src];
834                 } else {
835                         copy(fd, cpu[dst], gpu[src], 0);
836                         cpu_val[dst] = gpu_val[src];
837                 }
838         }
839         for (i = 0; i < count; i++) {
840                 check_gpu(fd, gpu[i], gpu_val[i]);
841                 gem_close(fd, gpu[i]);
842
843                 gem_userptr_sync(fd, cpu[i]);
844                 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
845                 gem_close(fd, cpu[i]);
846         }
847
848         free(gpu);
849         free(memory);
850
851         return 0;
852 }
853
854 static struct igt_eviction_test_ops fault_ops = {
855         .create = create_userptr_bo,
856         .close = free_userptr_bo,
857         .copy = blit,
858         .clear = clear,
859 };
860
861 static int can_swap(void)
862 {
863         unsigned long as, ram;
864
865         /* Cannot swap if not enough address space */
866
867         /* FIXME: Improve check criteria. */
868         if (sizeof(void*) < 8)
869                 as = 3 * 1024;
870         else
871                 as = 256 * 1024; /* Just a big number */
872
873         ram = intel_get_total_ram_mb();
874
875         if ((as - 128) < (ram - 256))
876                 return 0;
877
878         return 1;
879 }
880
881 #define min(a, b) ((a) < (b) ? (a) : (b))
882
883 static void test_forking_evictions(int fd, int size, int count,
884                              unsigned flags)
885 {
886         int trash_count;
887         int num_threads;
888
889         trash_count = intel_get_total_ram_mb() * 11 / 10;
890         /* Use the fact test will spawn a number of child
891          * processes meaning swapping will be triggered system
892          * wide even if one process on it's own can't do it.
893          */
894         num_threads = min(sysconf(_SC_NPROCESSORS_ONLN) * 4, 12);
895         trash_count /= num_threads;
896         if (count > trash_count)
897                 count = trash_count;
898
899         forking_evictions(fd, &fault_ops, size, count, trash_count, flags);
900 }
901
902 static void test_swapping_evictions(int fd, int size, int count)
903 {
904         int trash_count;
905
906         igt_skip_on_f(!can_swap(),
907                 "Not enough process address space for swapping tests.\n");
908
909         trash_count = intel_get_total_ram_mb() * 11 / 10;
910
911         swapping_evictions(fd, &fault_ops, size, count, trash_count);
912 }
913
914 static void test_minor_evictions(int fd, int size, int count)
915 {
916         minor_evictions(fd, &fault_ops, size, count);
917 }
918
919 static void test_major_evictions(int fd, int size, int count)
920 {
921         major_evictions(fd, &fault_ops, size, count);
922 }
923
924 static int test_overlap(int fd, int expected)
925 {
926         char *ptr;
927         int ret;
928         uint32_t handle, handle2;
929
930         igt_assert(posix_memalign((void *)&ptr, PAGE_SIZE, PAGE_SIZE * 3) == 0);
931
932         ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE, 0, &handle);
933         igt_assert(ret == 0);
934
935         ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle2);
936         igt_assert(ret == 0);
937         gem_close(fd, handle2);
938
939         ret = gem_userptr(fd, ptr + PAGE_SIZE * 2, PAGE_SIZE, 0, &handle2);
940         igt_assert(ret == 0);
941         gem_close(fd, handle2);
942
943         ret = gem_userptr(fd, ptr, PAGE_SIZE * 2, 0, &handle2);
944         igt_assert(ret == expected);
945         if (ret == 0)
946                 gem_close(fd, handle2);
947
948         ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE * 2, 0, &handle2);
949         igt_assert(ret == expected);
950         if (ret == 0)
951                 gem_close(fd, handle2);
952
953         ret = gem_userptr(fd, ptr, PAGE_SIZE * 3, 0, &handle2);
954         igt_assert(ret == expected);
955         if (ret == 0)
956                 gem_close(fd, handle2);
957
958         gem_close(fd, handle);
959         free(ptr);
960
961         return 0;
962 }
963
964 static int test_unmap(int fd, int expected)
965 {
966         char *ptr, *bo_ptr;
967         const unsigned int num_obj = 3;
968         unsigned int i;
969         uint32_t bo[num_obj + 1];
970         size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
971         int ret;
972
973         ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
974                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
975         assert(ptr != MAP_FAILED);
976
977         bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
978
979         for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) {
980                 ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]);
981                 igt_assert(ret == 0);
982         }
983
984         bo[num_obj] = create_bo(fd, 0);
985
986         for (i = 0; i < num_obj; i++)
987                 copy(fd, bo[num_obj], bo[i], 0);
988
989         ret = munmap(ptr, map_size);
990         assert(ret == 0);
991
992         for (i = 0; i < num_obj; i++)
993                 copy(fd, bo[num_obj], bo[i], expected);
994
995         for (i = 0; i < (num_obj + 1); i++)
996                 gem_close(fd, bo[i]);
997
998         return 0;
999 }
1000
1001 static int test_unmap_after_close(int fd)
1002 {
1003         char *ptr, *bo_ptr;
1004         const unsigned int num_obj = 3;
1005         unsigned int i;
1006         uint32_t bo[num_obj + 1];
1007         size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
1008         int ret;
1009
1010         ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
1011                                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1012         assert(ptr != MAP_FAILED);
1013
1014         bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
1015
1016         for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) {
1017                 ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]);
1018                 igt_assert(ret == 0);
1019         }
1020
1021         bo[num_obj] = create_bo(fd, 0);
1022
1023         for (i = 0; i < num_obj; i++)
1024                 copy(fd, bo[num_obj], bo[i], 0);
1025
1026         for (i = 0; i < (num_obj + 1); i++)
1027                 gem_close(fd, bo[i]);
1028
1029         ret = munmap(ptr, map_size);
1030         assert(ret == 0);
1031
1032         return 0;
1033 }
1034
1035 static int test_unmap_cycles(int fd, int expected)
1036 {
1037         int i;
1038
1039         for (i = 0; i < 1000; i++)
1040                 test_unmap(fd, expected);
1041
1042         return 0;
1043 }
1044
1045 unsigned int total_ram;
1046 uint64_t aperture_size;
1047 int fd, count;
1048
1049
1050 int main(int argc, char **argv)
1051 {
1052         int size = sizeof(linear);
1053
1054         igt_skip_on_simulation();
1055
1056         igt_subtest_init(argc, argv);
1057
1058         igt_fixture {
1059                 int ret;
1060
1061                 fd = drm_open_any();
1062                 igt_assert(fd >= 0);
1063
1064                 ret = has_userptr(fd);
1065                 igt_skip_on_f(ret == 0, "No userptr support - %s (%d)\n",
1066                               strerror(errno), ret);
1067
1068                 size = sizeof(linear);
1069
1070                 aperture_size = gem_aperture_size(fd);
1071                 printf("Aperture size is %lu MiB\n", (long)(aperture_size / (1024*1024)));
1072
1073                 if (argc > 1)
1074                         count = atoi(argv[1]);
1075                 if (count == 0)
1076                         count = 2 * aperture_size / (1024*1024) / 3;
1077
1078                 total_ram = intel_get_total_ram_mb();
1079                 printf("Total RAM is %u MiB\n", total_ram);
1080
1081                 if (count > total_ram * 3 / 4) {
1082                         count = intel_get_total_ram_mb() * 3 / 4;
1083                         printf("Not enough RAM to run test, reducing buffer count.\n");
1084                 }
1085         }
1086
1087         igt_subtest("input-checking")
1088                 test_input_checking(fd);
1089
1090         igt_subtest("usage-restrictions")
1091                 test_usage_restrictions(fd);
1092
1093         igt_subtest("invalid-mapping")
1094                 test_invalid_mapping(fd);
1095
1096         igt_subtest("forbidden-operations")
1097                 test_forbidden_ops(fd);
1098
1099         printf("Testing unsynchronized mappings...\n");
1100         gem_userptr_test_unsynchronized();
1101
1102         igt_subtest("create-destroy-unsync")
1103                 test_create_destroy(fd);
1104
1105         igt_subtest("unsync-overlap")
1106                 test_overlap(fd, 0);
1107
1108         igt_subtest("unsync-unmap")
1109                 test_unmap(fd, 0);
1110
1111         igt_subtest("unsync-unmap-cycles")
1112                 test_unmap_cycles(fd, 0);
1113
1114         igt_subtest("unsync-unmap-after-close")
1115                 test_unmap_after_close(fd);
1116
1117         igt_subtest("coherency-unsync")
1118                 test_coherency(fd, count);
1119
1120         igt_subtest("dmabuf-unsync")
1121                 test_dmabuf();
1122
1123         for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) {
1124                 igt_subtest_f("forked-unsync%s%s%s-%s",
1125                     flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "",
1126                     flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "",
1127                     flags & FORKING_EVICTIONS_MEMORY_PRESSURE ?
1128                                 "-mempressure" : "",
1129                     flags & FORKING_EVICTIONS_INTERRUPTIBLE ?
1130                                 "interruptible" : "normal") {
1131                         test_forking_evictions(fd, size, count, flags);
1132                 }
1133         }
1134
1135         igt_subtest("swapping-unsync-normal")
1136                 test_swapping_evictions(fd, size, count);
1137
1138         igt_subtest("minor-unsync-normal")
1139                 test_minor_evictions(fd, size, count);
1140
1141         igt_subtest("major-unsync-normal") {
1142                 size = 200 * 1024 * 1024;
1143                 count = (gem_aperture_size(fd) / size) + 2;
1144                 test_major_evictions(fd, size, count);
1145         }
1146
1147         igt_fixture {
1148                 size = sizeof(linear);
1149                 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1150                 if (count > total_ram * 3 / 4)
1151                         count = intel_get_total_ram_mb() * 3 / 4;
1152         }
1153
1154         igt_fork_signal_helper();
1155
1156         igt_subtest("swapping-unsync-interruptible")
1157                 test_swapping_evictions(fd, size, count);
1158
1159         igt_subtest("minor-unsync-interruptible")
1160                 test_minor_evictions(fd, size, count);
1161
1162         igt_subtest("major-unsync-interruptible") {
1163                 size = 200 * 1024 * 1024;
1164                 count = (gem_aperture_size(fd) / size) + 2;
1165                 test_major_evictions(fd, size, count);
1166         }
1167
1168         igt_stop_signal_helper();
1169
1170         printf("Testing synchronized mappings...\n");
1171
1172         igt_fixture {
1173                 size = sizeof(linear);
1174                 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1175                 if (count > total_ram * 3 / 4)
1176                         count = intel_get_total_ram_mb() * 3 / 4;
1177         }
1178
1179         gem_userptr_test_synchronized();
1180
1181         igt_subtest("create-destroy-sync")
1182                 test_create_destroy(fd);
1183
1184         igt_subtest("sync-overlap")
1185                 test_overlap(fd, EINVAL);
1186
1187         igt_subtest("sync-unmap")
1188                 test_unmap(fd, EFAULT);
1189
1190         igt_subtest("sync-unmap-cycles")
1191                 test_unmap_cycles(fd, EFAULT);
1192
1193         igt_subtest("sync-unmap-after-close")
1194                 test_unmap_after_close(fd);
1195
1196         igt_subtest("coherency-sync")
1197                 test_coherency(fd, count);
1198
1199         igt_subtest("dmabuf-sync")
1200                 test_dmabuf();
1201
1202         for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) {
1203                 igt_subtest_f("forked-sync%s%s%s-%s",
1204                     flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "",
1205                     flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "",
1206                     flags & FORKING_EVICTIONS_MEMORY_PRESSURE ?
1207                                 "-mempressure" : "",
1208                     flags & FORKING_EVICTIONS_INTERRUPTIBLE ?
1209                                 "interruptible" : "normal") {
1210                         test_forking_evictions(fd, size, count, flags);
1211                 }
1212         }
1213
1214         igt_subtest("swapping-normal-sync")
1215                 test_swapping_evictions(fd, size, count);
1216
1217         igt_subtest("minor-normal-sync")
1218                 test_minor_evictions(fd, size, count);
1219
1220         igt_subtest("major-normal-sync") {
1221                 size = 200 * 1024 * 1024;
1222                 count = (gem_aperture_size(fd) / size) + 2;
1223                 test_major_evictions(fd, size, count);
1224         }
1225
1226         igt_fixture {
1227                 size = 1024 * 1024;
1228                 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1229                 if (count > total_ram * 3 / 4)
1230                         count = intel_get_total_ram_mb() * 3 / 4;
1231         }
1232
1233         igt_fork_signal_helper();
1234
1235         igt_subtest("swapping-sync-interruptible")
1236                 test_swapping_evictions(fd, size, count);
1237
1238         igt_subtest("minor-sync-interruptible")
1239                 test_minor_evictions(fd, size, count);
1240
1241         igt_subtest("major-sync-interruptible") {
1242                 size = 200 * 1024 * 1024;
1243                 count = (gem_aperture_size(fd) / size) + 2;
1244                 test_major_evictions(fd, size, count);
1245         }
1246
1247         igt_stop_signal_helper();
1248
1249         igt_subtest("access-control")
1250         test_access_control(fd);
1251
1252         igt_exit();
1253
1254         return 0;
1255 }