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