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 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 {
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, int error)
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 igt_assert(ret == error);
302 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 unsigned int num_handle_ptr_map;
326 static void add_handle_ptr(uint32_t handle, void *ptr)
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;
334 handle_ptr_map[handle] = ptr;
337 static void *get_handle_ptr(uint32_t handle)
339 return handle_ptr_map[handle];
342 static void free_handle_ptr(uint32_t handle)
344 igt_assert(handle < num_handle_ptr_map);
345 igt_assert(handle_ptr_map[handle]);
347 free(handle_ptr_map[handle]);
348 handle_ptr_map[handle] = NULL;
351 static uint32_t create_userptr_bo(int fd, int size)
357 ret = posix_memalign(&ptr, PAGE_SIZE, size);
358 igt_assert(ret == 0);
360 ret = gem_userptr(fd, (uint32_t *)ptr, size, 0, &handle);
361 igt_assert(ret == 0);
362 add_handle_ptr(handle, ptr);
367 static void clear(int fd, uint32_t handle, int size)
369 void *ptr = get_handle_ptr(handle);
371 igt_assert(ptr != NULL);
373 memset(ptr, 0, size);
376 static void free_userptr_bo(int fd, uint32_t handle)
378 gem_close(fd, handle);
379 free_handle_ptr(handle);
383 create_bo(int fd, uint32_t val)
388 handle = gem_create(fd, sizeof(linear));
390 /* Fill the BO with dwords starting at val */
391 for (i = 0; i < WIDTH*HEIGHT; i++)
393 gem_write(fd, handle, 0, linear, sizeof(linear));
399 check_cpu(uint32_t *ptr, uint32_t val)
403 for (i = 0; i < WIDTH*HEIGHT; i++) {
405 fprintf(stderr, "Expected 0x%08x, found 0x%08x "
406 "at offset 0x%08x\n",
415 check_gpu(int fd, uint32_t handle, uint32_t val)
417 gem_read(fd, handle, 0, linear, sizeof(linear));
418 check_cpu(linear, val);
421 static int has_userptr(int fd)
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;
438 gem_close(fd, handle);
444 static int test_input_checking(int fd)
446 struct local_i915_gem_userptr userptr;
450 userptr.user_ptr = 0;
451 userptr.user_size = 0;
453 ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
454 igt_assert(ret != 0);
457 userptr.user_ptr = 0;
458 userptr.user_size = ~0;
460 ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
461 igt_assert(ret != 0);
464 userptr.user_ptr = 0;
465 userptr.user_size = ~0;
467 ret = drmIoctl(fd, LOCAL_IOCTL_I915_GEM_USERPTR, &userptr);
468 igt_assert(ret != 0);
473 static int test_access_control(int fd)
482 /* CAP_SYS_ADMIN is needed for UNSYNCHRONIZED mappings. */
483 gem_userptr_test_unsynchronized();
485 igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
487 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
489 gem_close(fd, handle);
491 igt_assert(ret == EPERM);
499 static int test_invalid_mapping(int fd)
502 uint32_t handle, handle2;
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);
512 handle = create_bo(fd, 0);
513 ptr = gem_mmap__gtt(fd, handle, sizeof(linear), PROT_READ | PROT_WRITE);
515 gem_close(fd, handle);
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);
529 static int test_forbidden_ops(int fd)
535 struct drm_i915_gem_pread gem_pread;
536 struct drm_i915_gem_pwrite gem_pwrite;
538 assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
540 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
541 igt_assert(ret == 0);
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);
549 gem_close(fd, handle);
552 igt_assert(ret != 0);
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);
560 gem_close(fd, handle);
563 igt_assert(ret != 0);
565 gem_close(fd, handle);
573 static void (*orig_sigbus)(int sig, siginfo_t *info, void *param);
574 static unsigned long sigbus_start;
575 static long sigbus_cnt = -1;
578 check_bo(int fd1, uint32_t handle1, int is_userptr, int fd2, uint32_t handle2)
582 unsigned long size = sizeof(linear);
585 ptr1 = get_handle_ptr(handle1);
587 ptr1 = gem_mmap(fd1, handle1, sizeof(linear), PROT_READ | PROT_WRITE);
589 ptr2 = gem_mmap(fd2, handle2, sizeof(linear), PROT_READ | PROT_WRITE);
594 sigbus_start = (unsigned long)ptr2;
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);
608 memset(ptr1, counter, size);
609 igt_assert(memcmp(ptr1, ptr2, size) == 0);
613 munmap(ptr1, sizeof(linear));
614 munmap(ptr2, sizeof(linear));
617 static int export_handle(int fd, uint32_t handle, int *outfd)
619 struct drm_prime_handle args;
622 args.handle = handle;
623 args.flags = DRM_CLOEXEC;
626 ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
634 static void sigbus(int sig, siginfo_t *info, void *param)
636 unsigned long ptr = (unsigned long)info->si_addr;
639 if (ptr >= sigbus_start &&
640 ptr <= (sigbus_start + sizeof(linear))) {
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));
651 orig_sigbus(sig, info, param);
655 static int test_dmabuf(void)
658 uint32_t handle, handle_import1, handle_import2, handle_selfimport;
661 struct sigaction sigact, orig_sigact;
663 fd1 = drm_open_any();
664 fd2 = drm_open_any();
666 handle = create_userptr_bo(fd1, sizeof(linear));
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);
675 igt_assert(ret == 0);
676 igt_assert(dma_buf_fd >= 0);
678 handle_import1 = prime_fd_to_handle(fd2, dma_buf_fd);
679 check_bo(fd1, handle, 1, fd2, handle_import1);
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);
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);
690 /* close dma_buf, check whether nothing disappears. */
692 check_bo(fd1, handle, 1, fd2, handle_import1);
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);
700 orig_sigbus = orig_sigact.sa_sigaction;
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);
709 gem_close(fd2, handle_import1);
716 static int test_usage_restrictions(int fd)
722 assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE * 2) == 0);
724 /* Address not aligned. */
725 ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE, 0, &handle);
726 igt_assert(ret != 0);
728 /* Size not rounded to page size. */
729 ret = gem_userptr(fd, ptr, PAGE_SIZE - 1, 0, &handle);
730 igt_assert(ret != 0);
733 ret = gem_userptr(fd, (char *)ptr + 1, PAGE_SIZE - 1, 0, &handle);
734 igt_assert(ret != 0);
736 /* Read-only not supported. */
737 ret = gem_userptr(fd, (char *)ptr, PAGE_SIZE, 1, &handle);
738 igt_assert(ret != 0);
745 static int test_create_destroy(int fd)
751 igt_assert(posix_memalign(&ptr, PAGE_SIZE, PAGE_SIZE) == 0);
753 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle);
754 igt_assert(ret == 0);
756 gem_close(fd, handle);
762 static int test_coherency(int fd, int count)
765 uint32_t *cpu, *cpu_val;
766 uint32_t *gpu, *gpu_val;
770 printf("Using 2x%d 1MiB buffers\n", count);
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));
779 gpu = malloc(sizeof(uint32_t)*count*4);
780 gpu_val = gpu + count;
781 cpu = gpu_val + count;
782 cpu_val = cpu + count;
784 for (i = 0; i < count; i++) {
785 gpu[i] = create_bo(fd, start);
787 start += WIDTH*HEIGHT;
790 for (i = 0; i < count; i++) {
791 cpu[i] = create_userptr(fd, start, memory+i*WIDTH*HEIGHT);
793 start += WIDTH*HEIGHT;
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]);
802 printf("Cyclic blits cpu->gpu, forward...\n");
803 for (i = 0; i < count * 4; i++) {
805 int dst = (i + 1) % count;
807 copy(fd, gpu[dst], cpu[src], 0);
808 gpu_val[dst] = cpu_val[src];
810 for (i = 0; i < count; i++)
811 check_gpu(fd, gpu[i], gpu_val[i]);
813 printf("Cyclic blits gpu->cpu, backward...\n");
814 for (i = 0; i < count * 4; i++) {
815 int src = (i + 1) % count;
818 copy(fd, cpu[dst], gpu[src], 0);
819 cpu_val[dst] = gpu_val[src];
821 for (i = 0; i < count; i++) {
822 gem_userptr_sync(fd, cpu[i]);
823 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
826 printf("Random blits...\n");
827 for (i = 0; i < count * 4; i++) {
828 int src = random() % count;
829 int dst = random() % count;
832 copy(fd, gpu[dst], cpu[src], 0);
833 gpu_val[dst] = cpu_val[src];
835 copy(fd, cpu[dst], gpu[src], 0);
836 cpu_val[dst] = gpu_val[src];
839 for (i = 0; i < count; i++) {
840 check_gpu(fd, gpu[i], gpu_val[i]);
841 gem_close(fd, gpu[i]);
843 gem_userptr_sync(fd, cpu[i]);
844 check_cpu(memory+i*WIDTH*HEIGHT, cpu_val[i]);
845 gem_close(fd, cpu[i]);
854 static struct igt_eviction_test_ops fault_ops = {
855 .create = create_userptr_bo,
856 .close = free_userptr_bo,
861 static int can_swap(void)
863 unsigned long as, ram;
865 /* Cannot swap if not enough address space */
867 /* FIXME: Improve check criteria. */
868 if (sizeof(void*) < 8)
871 as = 256 * 1024; /* Just a big number */
873 ram = intel_get_total_ram_mb();
875 if ((as - 128) < (ram - 256))
881 #define min(a, b) ((a) < (b) ? (a) : (b))
883 static void test_forking_evictions(int fd, int size, int count,
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.
894 num_threads = min(sysconf(_SC_NPROCESSORS_ONLN) * 4, 12);
895 trash_count /= num_threads;
896 if (count > trash_count)
899 forking_evictions(fd, &fault_ops, size, count, trash_count, flags);
902 static void test_swapping_evictions(int fd, int size, int count)
906 igt_skip_on_f(!can_swap(),
907 "Not enough process address space for swapping tests.\n");
909 trash_count = intel_get_total_ram_mb() * 11 / 10;
911 swapping_evictions(fd, &fault_ops, size, count, trash_count);
914 static void test_minor_evictions(int fd, int size, int count)
916 minor_evictions(fd, &fault_ops, size, count);
919 static void test_major_evictions(int fd, int size, int count)
921 major_evictions(fd, &fault_ops, size, count);
924 static int test_overlap(int fd, int expected)
928 uint32_t handle, handle2;
930 igt_assert(posix_memalign((void *)&ptr, PAGE_SIZE, PAGE_SIZE * 3) == 0);
932 ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE, 0, &handle);
933 igt_assert(ret == 0);
935 ret = gem_userptr(fd, ptr, PAGE_SIZE, 0, &handle2);
936 igt_assert(ret == 0);
937 gem_close(fd, handle2);
939 ret = gem_userptr(fd, ptr + PAGE_SIZE * 2, PAGE_SIZE, 0, &handle2);
940 igt_assert(ret == 0);
941 gem_close(fd, handle2);
943 ret = gem_userptr(fd, ptr, PAGE_SIZE * 2, 0, &handle2);
944 igt_assert(ret == expected);
946 gem_close(fd, handle2);
948 ret = gem_userptr(fd, ptr + PAGE_SIZE, PAGE_SIZE * 2, 0, &handle2);
949 igt_assert(ret == expected);
951 gem_close(fd, handle2);
953 ret = gem_userptr(fd, ptr, PAGE_SIZE * 3, 0, &handle2);
954 igt_assert(ret == expected);
956 gem_close(fd, handle2);
958 gem_close(fd, handle);
964 static int test_unmap(int fd, int expected)
967 const unsigned int num_obj = 3;
969 uint32_t bo[num_obj + 1];
970 size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
973 ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
974 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
975 assert(ptr != MAP_FAILED);
977 bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
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);
984 bo[num_obj] = create_bo(fd, 0);
986 for (i = 0; i < num_obj; i++)
987 copy(fd, bo[num_obj], bo[i], 0);
989 ret = munmap(ptr, map_size);
992 for (i = 0; i < num_obj; i++)
993 copy(fd, bo[num_obj], bo[i], expected);
995 for (i = 0; i < (num_obj + 1); i++)
996 gem_close(fd, bo[i]);
1001 static int test_unmap_after_close(int fd)
1004 const unsigned int num_obj = 3;
1006 uint32_t bo[num_obj + 1];
1007 size_t map_size = sizeof(linear) * num_obj + (PAGE_SIZE - 1);
1010 ptr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
1011 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1012 assert(ptr != MAP_FAILED);
1014 bo_ptr = (char *)ALIGN((unsigned long)ptr, PAGE_SIZE);
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);
1021 bo[num_obj] = create_bo(fd, 0);
1023 for (i = 0; i < num_obj; i++)
1024 copy(fd, bo[num_obj], bo[i], 0);
1026 for (i = 0; i < (num_obj + 1); i++)
1027 gem_close(fd, bo[i]);
1029 ret = munmap(ptr, map_size);
1035 static int test_unmap_cycles(int fd, int expected)
1039 for (i = 0; i < 1000; i++)
1040 test_unmap(fd, expected);
1045 unsigned int total_ram;
1046 uint64_t aperture_size;
1050 int main(int argc, char **argv)
1052 int size = sizeof(linear);
1054 igt_skip_on_simulation();
1056 igt_subtest_init(argc, argv);
1061 fd = drm_open_any();
1062 igt_assert(fd >= 0);
1064 ret = has_userptr(fd);
1065 igt_skip_on_f(ret == 0, "No userptr support - %s (%d)\n",
1066 strerror(errno), ret);
1068 size = sizeof(linear);
1070 aperture_size = gem_aperture_size(fd);
1071 printf("Aperture size is %lu MiB\n", (long)(aperture_size / (1024*1024)));
1074 count = atoi(argv[1]);
1076 count = 2 * aperture_size / (1024*1024) / 3;
1078 total_ram = intel_get_total_ram_mb();
1079 printf("Total RAM is %u MiB\n", total_ram);
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");
1087 igt_subtest("input-checking")
1088 test_input_checking(fd);
1090 igt_subtest("usage-restrictions")
1091 test_usage_restrictions(fd);
1093 igt_subtest("invalid-mapping")
1094 test_invalid_mapping(fd);
1096 igt_subtest("forbidden-operations")
1097 test_forbidden_ops(fd);
1099 printf("Testing unsynchronized mappings...\n");
1100 gem_userptr_test_unsynchronized();
1102 igt_subtest("create-destroy-unsync")
1103 test_create_destroy(fd);
1105 igt_subtest("unsync-overlap")
1106 test_overlap(fd, 0);
1108 igt_subtest("unsync-unmap")
1111 igt_subtest("unsync-unmap-cycles")
1112 test_unmap_cycles(fd, 0);
1114 igt_subtest("unsync-unmap-after-close")
1115 test_unmap_after_close(fd);
1117 igt_subtest("coherency-unsync")
1118 test_coherency(fd, count);
1120 igt_subtest("dmabuf-unsync")
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);
1135 igt_subtest("swapping-unsync-normal")
1136 test_swapping_evictions(fd, size, count);
1138 igt_subtest("minor-unsync-normal")
1139 test_minor_evictions(fd, size, count);
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);
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;
1154 igt_fork_signal_helper();
1156 igt_subtest("swapping-unsync-interruptible")
1157 test_swapping_evictions(fd, size, count);
1159 igt_subtest("minor-unsync-interruptible")
1160 test_minor_evictions(fd, size, count);
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);
1168 igt_stop_signal_helper();
1170 printf("Testing synchronized mappings...\n");
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;
1179 gem_userptr_test_synchronized();
1181 igt_subtest("create-destroy-sync")
1182 test_create_destroy(fd);
1184 igt_subtest("sync-overlap")
1185 test_overlap(fd, EINVAL);
1187 igt_subtest("sync-unmap")
1188 test_unmap(fd, EFAULT);
1190 igt_subtest("sync-unmap-cycles")
1191 test_unmap_cycles(fd, EFAULT);
1193 igt_subtest("sync-unmap-after-close")
1194 test_unmap_after_close(fd);
1196 igt_subtest("coherency-sync")
1197 test_coherency(fd, count);
1199 igt_subtest("dmabuf-sync")
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);
1214 igt_subtest("swapping-normal-sync")
1215 test_swapping_evictions(fd, size, count);
1217 igt_subtest("minor-normal-sync")
1218 test_minor_evictions(fd, size, count);
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);
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;
1233 igt_fork_signal_helper();
1235 igt_subtest("swapping-sync-interruptible")
1236 test_swapping_evictions(fd, size, count);
1238 igt_subtest("minor-sync-interruptible")
1239 test_minor_evictions(fd, size, count);
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);
1247 igt_stop_signal_helper();
1249 igt_subtest("access-control")
1250 test_access_control(fd);