2 * Copyright © 2009-2014 Intel Corporation
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:
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
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
24 * Eric Anholt <eric@anholt.net>
25 * Chris Wilson <chris@chris-wilson.co.uk>
26 * Tvrtko Ursulin <tvrtko.ursulin@intel.com>
30 /** @file gem_userptr_blits.c
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
36 * The goal is to simply ensure the basics work.
55 #include "intel_bufmgr.h"
56 #include "intel_batchbuffer.h"
57 #include "intel_chipset.h"
58 #include "ioctl_wrappers.h"
60 #include "eviction_common.c"
63 #define PAGE_SIZE 4096
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 {
72 #define LOCAL_I915_USERPTR_READ_ONLY (1<<0)
73 #define LOCAL_I915_USERPTR_UNSYNCHRONIZED (1<<31)
77 static uint32_t userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED;
82 static uint32_t linear[WIDTH*HEIGHT];
84 static void gem_userptr_test_unsynchronized(void)
86 userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED;
89 static void gem_userptr_test_synchronized(void)
94 static int gem_userptr(int fd, void *ptr, int size, int read_only, uint32_t *handle)
96 struct local_i915_gem_userptr userptr;
99 userptr.user_ptr = (uintptr_t)ptr;
100 userptr.user_size = size;
101 userptr.flags = userptr_flags;
103 userptr.flags |= LOCAL_I915_USERPTR_READ_ONLY;
105 ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
108 igt_skip_on_f(ret == ENODEV &&
109 (userptr_flags & LOCAL_I915_USERPTR_UNSYNCHRONIZED) == 0 &&
111 "Skipping, synchronized mappings with no kernel CONFIG_MMU_NOTIFIER?");
113 *handle = userptr.handle;
119 static void gem_userptr_sync(int fd, uint32_t handle)
121 gem_set_domain(fd, handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
125 copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
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;
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)
142 batch[i++] = (3 << 24) | /* 32 bits */
143 (0xcc << 16) | /* copy ROP */
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)
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)
155 batch[i++] = MI_BATCH_BUFFER_END;
156 batch[i++] = MI_NOOP;
158 handle = gem_create(fd, 4096);
159 gem_write(fd, handle, 0, batch, sizeof(batch));
161 reloc[0].target_handle = dst;
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;
168 reloc[1].target_handle = src;
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;
178 obj[0].relocation_count = 0;
179 obj[0].relocs_ptr = 0;
180 obj[0].alignment = 0;
187 obj[1].relocation_count = 0;
188 obj[1].relocs_ptr = 0;
189 obj[1].alignment = 0;
195 obj[2].handle = handle;
196 obj[2].relocation_count = 2;
197 obj[2].relocs_ptr = (uintptr_t)reloc;
198 obj[2].alignment = 0;
201 obj[2].rsvd1 = obj[2].rsvd2 = 0;
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);
214 ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
219 igt_assert(ret != 0);
221 igt_assert(ret == error);
223 gem_close(fd, handle);
227 blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo)
230 struct drm_i915_gem_relocation_entry reloc[2];
231 struct drm_i915_gem_exec_object2 *obj;
232 struct drm_i915_gem_execbuffer2 exec;
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)
243 batch[i++] = (3 << 24) | /* 32 bits */
244 (0xcc << 16) | /* copy ROP */
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)
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)
256 batch[i++] = MI_BATCH_BUFFER_END;
257 batch[i++] = MI_NOOP;
259 handle = gem_create(fd, 4096);
260 gem_write(fd, handle, 0, batch, sizeof(batch));
262 reloc[0].target_handle = dst;
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;
269 reloc[1].target_handle = src;
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;
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;
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);
296 ret = drmIoctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &exec);
300 gem_close(fd, handle);
307 create_userptr(int fd, uint32_t val, uint32_t *ptr)
312 ret = gem_userptr(fd, ptr, sizeof(linear), 0, &handle);
313 igt_assert(ret == 0);
314 igt_assert(handle != 0);
316 /* Fill the BO with dwords starting at val */
317 for (i = 0; i < WIDTH*HEIGHT; i++)
323 static void **handle_ptr_map;
324 static int *handle_size_map;
325 static unsigned int num_handle_map;
327 static void reset_handle_ptr(void)
329 free(handle_ptr_map);
330 free(handle_size_map);
334 static void add_handle_ptr(uint32_t handle, void *ptr, int size)
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);
341 handle_size_map = realloc(handle_size_map,
342 (handle + 1000) * sizeof(int));
343 igt_assert(handle_size_map);
345 num_handle_map = handle + 1000;
348 handle_ptr_map[handle] = ptr;
349 handle_size_map[handle] = size;
352 static void *get_handle_ptr(uint32_t handle)
354 return handle_ptr_map[handle];
357 static void free_handle_ptr(uint32_t handle)
359 igt_assert(handle < num_handle_map);
360 igt_assert(handle_ptr_map[handle]);
362 munmap(handle_ptr_map[handle], handle_size_map[handle]);
363 handle_ptr_map[handle] = NULL;
366 static uint32_t create_userptr_bo(int fd, int size)
372 ptr = mmap(NULL, size,
373 PROT_READ | PROT_WRITE,
374 MAP_ANONYMOUS | MAP_SHARED,
376 igt_assert(ptr != MAP_FAILED);
378 ret = gem_userptr(fd, (uint32_t *)ptr, size, 0, &handle);
379 igt_assert(ret == 0);
380 add_handle_ptr(handle, ptr, size);
385 static void clear(int fd, uint32_t handle, int size)
387 void *ptr = get_handle_ptr(handle);
389 igt_assert(ptr != NULL);
391 memset(ptr, 0, size);
394 static void free_userptr_bo(int fd, uint32_t handle)
396 gem_close(fd, handle);
397 free_handle_ptr(handle);
401 create_bo(int fd, uint32_t val)
406 handle = gem_create(fd, sizeof(linear));
408 /* Fill the BO with dwords starting at val */
409 for (i = 0; i < WIDTH*HEIGHT; i++)
411 gem_write(fd, handle, 0, linear, sizeof(linear));
417 check_cpu(uint32_t *ptr, uint32_t val)
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",
431 check_gpu(int fd, uint32_t handle, uint32_t val)
433 gem_read(fd, handle, 0, linear, sizeof(linear));
434 check_cpu(linear, val);
437 static int has_userptr(int fd)
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;
454 gem_close(fd, handle);
460 static int test_input_checking(int fd)
462 struct local_i915_gem_userptr userptr;
466 userptr.user_ptr = 0;
467 userptr.user_size = 0;
469 ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
470 igt_assert(ret != 0);
473 userptr.user_ptr = 0;
474 userptr.user_size = ~0;
476 ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
477 igt_assert(ret != 0);
480 userptr.user_ptr = 0;
481 userptr.user_size = ~0;
483 ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
484 igt_assert(ret != 0);
489 static int test_access_control(int fd)
498 /* CAP_SYS_ADMIN is needed for UNSYNCHRONIZED mappings. */
499 gem_userptr_test_unsynchronized();
501 igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
503 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
505 gem_close(fd, handle);
507 igt_assert(ret == EPERM);
515 static int test_invalid_mapping(int fd)
518 uint32_t handle, handle2;
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);
528 handle = create_bo(fd, 0);
529 ptr = gem_mmap__gtt(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE);
531 gem_close(fd, handle);
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);
545 static void test_forked_access(int fd)
547 uint32_t handle1, handle2;
551 ret = posix_memalign(&ptr1, PAGE_SIZE, PAGE_SIZE);
552 igt_assert(ret == 0);
554 ret = madvise(ptr1, PAGE_SIZE, MADV_DONTFORK);
555 igt_assert(ret == 0);
557 ret = gem_userptr(fd, ptr1, PAGE_SIZE, 0, &handle1);
558 igt_assert(ret == 0);
560 ret = posix_memalign(&ptr2, PAGE_SIZE, PAGE_SIZE);
561 igt_assert(ret == 0);
563 ret = madvise(ptr2, PAGE_SIZE, MADV_DONTFORK);
564 igt_assert(ret == 0);
566 ret = gem_userptr(fd, ptr2, PAGE_SIZE, 0, &handle2);
567 igt_assert(ret == 0);
569 memset(ptr1, 0x1, PAGE_SIZE);
570 memset(ptr2, 0x2, PAGE_SIZE);
573 copy(fd, handle1, handle2, 0);
577 gem_userptr_sync(fd, handle1);
578 gem_userptr_sync(fd, handle2);
580 gem_close(fd, handle1);
581 gem_close(fd, handle2);
583 igt_assert(memcmp(ptr1, ptr2, PAGE_SIZE) == 0);
585 ret = madvise(ptr1, PAGE_SIZE, MADV_DOFORK);
586 igt_assert(ret == 0);
589 ret = madvise(ptr2, PAGE_SIZE, MADV_DOFORK);
590 igt_assert(ret == 0);
594 static int test_forbidden_ops(int fd)
600 struct drm_i915_gem_pread gem_pread;
601 struct drm_i915_gem_pwrite gem_pwrite;
603 assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
605 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
606 igt_assert(ret == 0);
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);
614 gem_close(fd, handle);
617 igt_assert(ret != 0);
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);
625 gem_close(fd, handle);
628 igt_assert(ret != 0);
630 gem_close(fd, handle);
638 static void (*orig_sigbus)(int sig, siginfo_t *info, void *param);
639 static unsigned long sigbus_start;
640 static long sigbus_cnt = -1;
643 check_bo(int fd1, uint32_t handle1, int is_userptr, int fd2, uint32_t handle2)
647 unsigned long size = sizeof(linear);
650 ptr1 = get_handle_ptr(handle1);
652 ptr1 = gem_mmap(fd1, handle1, sizeof(linear), PROT_READ | PROT_WRITE);
654 ptr2 = gem_mmap(fd2, handle2, sizeof(linear), PROT_READ | PROT_WRITE);
659 sigbus_start = (unsigned long)ptr2;
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);
673 memset(ptr1, counter, size);
674 igt_assert(memcmp(ptr1, ptr2, size) == 0);
678 munmap(ptr1, sizeof(linear));
679 munmap(ptr2, sizeof(linear));
682 static int export_handle(int fd, uint32_t handle, int *outfd)
684 struct drm_prime_handle args;
687 args.handle = handle;
688 args.flags = DRM_CLOEXEC;
691 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
699 static void sigbus(int sig, siginfo_t *info, void *param)
701 unsigned long ptr = (unsigned long)info->si_addr;
704 if (ptr >= sigbus_start &&
705 ptr <= (sigbus_start + sizeof(linear))) {
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));
717 orig_sigbus(sig, info, param);
721 static int test_dmabuf(void)
724 uint32_t handle, handle_import1, handle_import2, handle_selfimport;
727 struct sigaction sigact, orig_sigact;
729 fd1 = drm_open_any();
730 fd2 = drm_open_any();
732 handle = create_userptr_bo(fd1, sizeof(linear));
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);
741 igt_assert(ret == 0);
742 igt_assert(dma_buf_fd >= 0);
744 handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
745 check_bo(fd1, handle, 1, fd2, handle_import1);
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);
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);
756 /* close dma_buf, check whether nothing disappears. */
758 check_bo(fd1, handle, 1, fd2, handle_import1);
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);
766 orig_sigbus = orig_sigact.sa_sigaction;
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);
775 gem_close(fd2, handle_import1);
784 static int test_usage_restrictions(int fd)
790 assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE * 2) == 0);
792 /* Address not aligned. */
793 ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE, 0, &handle);
794 igt_assert(ret != 0);
796 /* Size not rounded to page size. */
797 ret = gem_userptr(fd, ptr, PAGE_SIZE - 1, 0, &handle);
798 igt_assert(ret != 0);
801 ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE - 1, 0, &handle);
802 igt_assert(ret != 0);
804 /* Read-only not supported. */
805 ret = gem_userptr(fd, (char *)ptr, PAGE_SIZE, 1, &handle);
806 igt_assert(ret != 0);
813 static int test_create_destroy(int fd)
819 igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
821 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
822 igt_assert(ret == 0);
824 gem_close(fd, handle);
830 static int test_coherency(int fd, int count)
833 uint32_t *cpu, *cpu_val;
834 uint32_t *gpu, *gpu_val;
838 igt_info("Using 2x%d 1MiB buffers\n", count);
840 ret = posix_memalign((void **)&memory, PAGE_SIZE, count*sizeof(linear));
841 igt_assert(ret == 0 && memory);
843 gpu = malloc(sizeof(uint32_t)*count*4);
844 gpu_val = gpu + count;
845 cpu = gpu_val + count;
846 cpu_val = cpu + count;
848 for (i = 0; i < count; i++) {
849 gpu[i] = create_bo(fd, start);
851 start += WIDTH*HEIGHT;
854 for (i = 0; i < count; i++) {
855 cpu[i] = create_userptr(fd, start, memory+i*WIDTH*HEIGHT);
857 start += WIDTH*HEIGHT;
860 igt_info("Verifying initialisation...\n");
861 for (i = 0; i < count; i++) {
862 check_gpu(fd, gpu[i], gpu_val[i]);
863 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
866 igt_info("Cyclic blits cpu->gpu, forward...\n");
867 for (i = 0; i < count * 4; i++) {
869 int dst = (i + 1) % count;
871 copy(fd, gpu[dst], cpu[src], 0);
872 gpu_val[dst] = cpu_val[src];
874 for (i = 0; i < count; i++)
875 check_gpu(fd, gpu[i], gpu_val[i]);
877 igt_info("Cyclic blits gpu->cpu, backward...\n");
878 for (i = 0; i < count * 4; i++) {
879 int src = (i + 1) % count;
882 copy(fd, cpu[dst], gpu[src], 0);
883 cpu_val[dst] = gpu_val[src];
885 for (i = 0; i < count; i++) {
886 gem_userptr_sync(fd, cpu[i]);
887 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
890 igt_info("Random blits...\n");
891 for (i = 0; i < count * 4; i++) {
892 int src = random() % count;
893 int dst = random() % count;
896 copy(fd, gpu[dst], cpu[src], 0);
897 gpu_val[dst] = cpu_val[src];
899 copy(fd, cpu[dst], gpu[src], 0);
900 cpu_val[dst] = gpu_val[src];
903 for (i = 0; i < count; i++) {
904 check_gpu(fd, gpu[i], gpu_val[i]);
905 gem_close(fd, gpu[i]);
907 gem_userptr_sync(fd, cpu[i]);
908 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
909 gem_close(fd, cpu[i]);
918 static struct igt_eviction_test_ops fault_ops = {
919 .create = create_userptr_bo,
920 .close = free_userptr_bo,
925 static int can_swap(void)
927 unsigned long as, ram;
929 /* Cannot swap if not enough address space */
931 /* FIXME: Improve check criteria. */
932 if (sizeof(void*) < 8)
935 as = 256 * 1024; /* Just a big number */
937 ram = intel_get_total_ram_mb();
939 if ((as - 128) < (ram - 256))
945 #define min(a, b) ((a) < (b) ? (a) : (b))
947 static void test_forking_evictions(int fd, int size, int count,
953 trash_count = intel_get_total_ram_mb() * 11 / 10;
954 /* Use the fact test will spawn a number of child
955 * processes meaning swapping will be triggered system
956 * wide even if one process on it's own can't do it.
958 num_threads = min(sysconf(_SC_NPROCESSORS_ONLN) * 4, 12);
959 trash_count /= num_threads;
960 if (count > trash_count)
963 forking_evictions(fd, &fault_ops, size, count, trash_count, flags);
966 static void test_swapping_evictions(int fd, int size, int count)
970 igt_skip_on_f(!can_swap(),
971 "Not enough process address space for swapping tests.\n");
973 trash_count = intel_get_total_ram_mb() * 11 / 10;
975 swapping_evictions(fd, &fault_ops, size, count, trash_count);
978 static void test_minor_evictions(int fd, int size, int count)
980 minor_evictions(fd, &fault_ops, size, count);
983 static void test_major_evictions(int fd, int size, int count)
985 major_evictions(fd, &fault_ops, size, count);
988 static int test_overlap(int fd, int expected)
992 uint32_t handle, handle2;
994 igt_assert(posix_memalign((void *)&ptr, PAGE_SIZE, PAGE_SIZE * 3) == 0);
996 ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE, 0, &handle);
997 igt_assert(ret == 0);
999 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle2);
1000 igt_assert(ret == 0);
1001 gem_close(fd, handle2);
1003 ret = gem_userptr(fd, ptr + PAGE_SIZE * 2, PAGE_SIZE, 0, &handle2);
1004 igt_assert(ret == 0);
1005 gem_close(fd, handle2);
1007 ret = gem_userptr(fd, ptr, PAGE_SIZE * 2, 0, &handle2);
1008 igt_assert(ret == expected);
1010 gem_close(fd, handle2);
1012 ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE * 2, 0, &handle2);
1013 igt_assert(ret == expected);
1015 gem_close(fd, handle2);
1017 ret = gem_userptr(fd, ptr, PAGE_SIZE * 3, 0, &handle2);
1018 igt_assert(ret == expected);
1020 gem_close(fd, handle2);
1022 gem_close(fd, handle);
1028 static int test_unmap(int fd, int expected)
1031 const unsigned int num_obj = 3;
1033 uint32_t bo[num_obj + 1];
1034 size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
1037 ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
1038 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1039 assert(ptr != MAP_FAILED);
1041 bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
1043 for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) {
1044 ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]);
1045 igt_assert(ret == 0);
1048 bo[num_obj] = create_bo(fd, 0);
1050 for (i = 0; i < num_obj; i++)
1051 copy(fd, bo[num_obj], bo[i], 0);
1053 ret = munmap(ptr, map_size);
1056 for (i = 0; i < num_obj; i++)
1057 copy(fd, bo[num_obj], bo[i], expected);
1059 for (i = 0; i < (num_obj + 1); i++)
1060 gem_close(fd, bo[i]);
1065 static int test_unmap_after_close(int fd)
1068 const unsigned int num_obj = 3;
1070 uint32_t bo[num_obj + 1];
1071 size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
1074 ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
1075 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1076 assert(ptr != MAP_FAILED);
1078 bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
1080 for (i = 0; i < num_obj; i++, bo_ptr += sizeof(linear)) {
1081 ret = gem_userptr(fd, bo_ptr, sizeof(linear), 0, &bo[i]);
1082 igt_assert(ret == 0);
1085 bo[num_obj] = create_bo(fd, 0);
1087 for (i = 0; i < num_obj; i++)
1088 copy(fd, bo[num_obj], bo[i], 0);
1090 for (i = 0; i < (num_obj + 1); i++)
1091 gem_close(fd, bo[i]);
1093 ret = munmap(ptr, map_size);
1099 static int test_unmap_cycles(int fd, int expected)
1103 for (i = 0; i < 1000; i++)
1104 test_unmap(fd, expected);
1109 unsigned int total_ram;
1110 uint64_t aperture_size;
1114 int main(int argc, char **argv)
1116 int size = sizeof(linear);
1118 igt_skip_on_simulation();
1120 igt_subtest_init(argc, argv);
1125 fd = drm_open_any();
1126 igt_assert(fd >= 0);
1128 ret = has_userptr(fd);
1129 igt_skip_on_f(ret == 0, "No userptr support - %s (%d)\n",
1130 strerror(errno), ret);
1132 size = sizeof(linear);
1134 aperture_size = gem_aperture_size(fd);
1135 igt_info("Aperture size is %lu MiB\n", (long)(aperture_size / (1024*1024)));
1138 count = atoi(argv[1]);
1140 count = 2 * aperture_size / (1024*1024) / 3;
1142 total_ram = intel_get_total_ram_mb();
1143 igt_info("Total RAM is %u MiB\n", total_ram);
1145 if (count > total_ram * 3 / 4) {
1146 count = intel_get_total_ram_mb() * 3 / 4;
1147 igt_info("Not enough RAM to run test, reducing buffer count.\n");
1151 igt_subtest("input-checking")
1152 test_input_checking(fd);
1154 igt_subtest("usage-restrictions")
1155 test_usage_restrictions(fd);
1157 igt_subtest("invalid-mapping")
1158 test_invalid_mapping(fd);
1160 igt_subtest("forked-access")
1161 test_forked_access(fd);
1163 igt_subtest("forbidden-operations")
1164 test_forbidden_ops(fd);
1166 igt_info("Testing unsynchronized mappings...\n");
1167 gem_userptr_test_unsynchronized();
1169 igt_subtest("create-destroy-unsync")
1170 test_create_destroy(fd);
1172 igt_subtest("unsync-overlap")
1173 test_overlap(fd, 0);
1175 igt_subtest("unsync-unmap")
1178 igt_subtest("unsync-unmap-cycles")
1179 test_unmap_cycles(fd, 0);
1181 igt_subtest("unsync-unmap-after-close")
1182 test_unmap_after_close(fd);
1184 igt_subtest("coherency-unsync")
1185 test_coherency(fd, count);
1187 igt_subtest("dmabuf-unsync")
1190 for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) {
1191 igt_subtest_f("forked-unsync%s%s%s-%s",
1192 flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "",
1193 flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "",
1194 flags & FORKING_EVICTIONS_MEMORY_PRESSURE ?
1195 "-mempressure" : "",
1196 flags & FORKING_EVICTIONS_INTERRUPTIBLE ?
1197 "interruptible" : "normal") {
1198 test_forking_evictions(fd, size, count, flags);
1202 igt_subtest("swapping-unsync-normal")
1203 test_swapping_evictions(fd, size, count);
1205 igt_subtest("minor-unsync-normal")
1206 test_minor_evictions(fd, size, count);
1208 igt_subtest("major-unsync-normal") {
1209 size = 200 * 1024 * 1024;
1210 count = (gem_aperture_size(fd) / size) + 2;
1211 test_major_evictions(fd, size, count);
1215 size = sizeof(linear);
1216 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1217 if (count > total_ram * 3 / 4)
1218 count = intel_get_total_ram_mb() * 3 / 4;
1221 igt_fork_signal_helper();
1223 igt_subtest("swapping-unsync-interruptible")
1224 test_swapping_evictions(fd, size, count);
1226 igt_subtest("minor-unsync-interruptible")
1227 test_minor_evictions(fd, size, count);
1229 igt_subtest("major-unsync-interruptible") {
1230 size = 200 * 1024 * 1024;
1231 count = (gem_aperture_size(fd) / size) + 2;
1232 test_major_evictions(fd, size, count);
1235 igt_stop_signal_helper();
1237 igt_info("Testing synchronized mappings...\n");
1240 size = sizeof(linear);
1241 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1242 if (count > total_ram * 3 / 4)
1243 count = intel_get_total_ram_mb() * 3 / 4;
1246 gem_userptr_test_synchronized();
1248 igt_subtest("create-destroy-sync")
1249 test_create_destroy(fd);
1251 igt_subtest("sync-overlap")
1252 test_overlap(fd, EINVAL);
1254 igt_subtest("sync-unmap")
1255 test_unmap(fd, EFAULT);
1257 igt_subtest("sync-unmap-cycles")
1258 test_unmap_cycles(fd, EFAULT);
1260 igt_subtest("sync-unmap-after-close")
1261 test_unmap_after_close(fd);
1263 igt_subtest("coherency-sync")
1264 test_coherency(fd, count);
1266 igt_subtest("dmabuf-sync")
1269 for (unsigned flags = 0; flags < ALL_FORKING_EVICTIONS + 1; flags++) {
1270 igt_subtest_f("forked-sync%s%s%s-%s",
1271 flags & FORKING_EVICTIONS_SWAPPING ? "-swapping" : "",
1272 flags & FORKING_EVICTIONS_DUP_DRMFD ? "-multifd" : "",
1273 flags & FORKING_EVICTIONS_MEMORY_PRESSURE ?
1274 "-mempressure" : "",
1275 flags & FORKING_EVICTIONS_INTERRUPTIBLE ?
1276 "interruptible" : "normal") {
1277 test_forking_evictions(fd, size, count, flags);
1281 igt_subtest("swapping-normal-sync")
1282 test_swapping_evictions(fd, size, count);
1284 igt_subtest("minor-normal-sync")
1285 test_minor_evictions(fd, size, count);
1287 igt_subtest("major-normal-sync") {
1288 size = 200 * 1024 * 1024;
1289 count = (gem_aperture_size(fd) / size) + 2;
1290 test_major_evictions(fd, size, count);
1295 count = 2 * gem_aperture_size(fd) / (1024*1024) / 3;
1296 if (count > total_ram * 3 / 4)
1297 count = intel_get_total_ram_mb() * 3 / 4;
1300 igt_fork_signal_helper();
1302 igt_subtest("swapping-sync-interruptible")
1303 test_swapping_evictions(fd, size, count);
1305 igt_subtest("minor-sync-interruptible")
1306 test_minor_evictions(fd, size, count);
1308 igt_subtest("major-sync-interruptible") {
1309 size = 200 * 1024 * 1024;
1310 count = (gem_aperture_size(fd) / size) + 2;
1311 test_major_evictions(fd, size, count);
1314 igt_stop_signal_helper();
1316 igt_subtest("access-control")
1317 test_access_control(fd);