diff options
-rw-r--r-- | lib/ioctl_wrappers.c | 33 | ||||
-rw-r--r-- | lib/ioctl_wrappers.h | 4 | ||||
-rw-r--r-- | tests/gem_userptr_blits.c | 77 |
3 files changed, 100 insertions, 14 deletions
diff --git a/lib/ioctl_wrappers.c b/lib/ioctl_wrappers.c index 32cb0f36..4d30443f 100644 --- a/lib/ioctl_wrappers.c +++ b/lib/ioctl_wrappers.c @@ -403,29 +403,38 @@ void gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t leng igt_assert_eq(__gem_read(fd, handle, offset, buf, length), 0); } +int __gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write) +{ + struct drm_i915_gem_set_domain set_domain; + int err; + + memset(&set_domain, 0, sizeof(set_domain)); + set_domain.handle = handle; + set_domain.read_domains = read; + set_domain.write_domain = write; + + err = 0; + if (igt_ioctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) + err = -errno; + + return err; +} + /** * gem_set_domain: * @fd: open i915 drm file descriptor * @handle: gem buffer object handle - * @read_domains: gem domain bits for read access - * @write_domain: gem domain bit for write access + * @read: gem domain bits for read access + * @write: gem domain bit for write access * * This wraps the SET_DOMAIN ioctl, which is used to control the coherency of * the gem buffer object between the cpu and gtt mappings. It is also use to * synchronize with outstanding rendering in general, but for that use-case * please have a look at gem_sync(). */ -void gem_set_domain(int fd, uint32_t handle, - uint32_t read_domains, uint32_t write_domain) +void gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write) { - struct drm_i915_gem_set_domain set_domain; - - memset(&set_domain, 0, sizeof(set_domain)); - set_domain.handle = handle; - set_domain.read_domains = read_domains; - set_domain.write_domain = write_domain; - - do_ioctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); + igt_assert_eq(__gem_set_domain(fd, handle, read, write), 0); } /** diff --git a/lib/ioctl_wrappers.h b/lib/ioctl_wrappers.h index af061ef3..56c5d14c 100644 --- a/lib/ioctl_wrappers.h +++ b/lib/ioctl_wrappers.h @@ -65,8 +65,8 @@ void gem_close(int fd, uint32_t handle); int __gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint64_t length); void gem_write(int fd, uint32_t handle, uint64_t offset, const void *buf, uint64_t length); void gem_read(int fd, uint32_t handle, uint64_t offset, void *buf, uint64_t length); -void gem_set_domain(int fd, uint32_t handle, - uint32_t read_domains, uint32_t write_domain); +int __gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write); +void gem_set_domain(int fd, uint32_t handle, uint32_t read, uint32_t write); int gem_wait(int fd, uint32_t handle, int64_t *timeout_ns); void gem_sync(int fd, uint32_t handle); bool gem_create__has_stolen_support(int fd); diff --git a/tests/gem_userptr_blits.c b/tests/gem_userptr_blits.c index 0df53105..49a7f2f4 100644 --- a/tests/gem_userptr_blits.c +++ b/tests/gem_userptr_blits.c @@ -614,6 +614,74 @@ static void test_forked_access(int fd) free(ptr2); } +#define MAP_FIXED_INVALIDATE_OVERLAP (1<<0) +#define MAP_FIXED_INVALIDATE_BUSY (1<<1) +#define MAP_FIXED_INVALIDATE_GET_PAGES (1<<2) +#define ALL_MAP_FIXED_INVALIDATE (MAP_FIXED_INVALIDATE_OVERLAP | \ + MAP_FIXED_INVALIDATE_BUSY | \ + MAP_FIXED_INVALIDATE_GET_PAGES) + +static int test_map_fixed_invalidate(int fd, uint32_t flags) +{ + const size_t ptr_size = sizeof(linear) + 2*PAGE_SIZE; + const int num_handles = (flags & MAP_FIXED_INVALIDATE_OVERLAP) ? 2 : 1; + uint32_t handle[num_handles]; + uint32_t *ptr; + + ptr = mmap(NULL, ptr_size, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, + -1, 0); + igt_assert(ptr != MAP_FAILED); + + for (int i = 0; i < num_handles; i++) + handle[i] = create_userptr(fd, 0, ptr + PAGE_SIZE/sizeof(*ptr)); + + for (char *fixed = (char *)ptr, *end = fixed + ptr_size; + fixed + 2*PAGE_SIZE <= end; + fixed += PAGE_SIZE) { + struct drm_i915_gem_mmap_gtt mmap_gtt; + char *map; + + ptr = mmap(ptr, ptr_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS | MAP_FIXED, + -1, 0); + + memset(&mmap_gtt, 0, sizeof(mmap_gtt)); + mmap_gtt.handle = gem_create(fd, 2*PAGE_SIZE); + do_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_gtt); + + if (flags & MAP_FIXED_INVALIDATE_BUSY) + copy(fd, handle[0], handle[num_handles-1], 0); + + map = mmap(fixed, 2*PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_FIXED, + fd, mmap_gtt.offset); + igt_assert(map == fixed); + + gem_set_tiling(fd, mmap_gtt.handle, I915_TILING_NONE, 0); + *(uint32_t*)map = 0xdead; + + if (flags & MAP_FIXED_INVALIDATE_GET_PAGES) + igt_assert_eq(__gem_set_domain(fd, handle[0], + I915_GEM_DOMAIN_GTT, + I915_GEM_DOMAIN_GTT), + -EFAULT); + + gem_set_tiling(fd, mmap_gtt.handle, I915_TILING_Y, 512 * 4); + *(uint32_t*)map = 0xbeef; + + gem_close(fd, mmap_gtt.handle); + } + + for (int i = 0; i < num_handles; i++) + gem_close(fd, handle[i]); + munmap(ptr, ptr_size); + + return 0; +} + static int test_forbidden_ops(int fd) { struct drm_i915_gem_pread gem_pread; @@ -1504,6 +1572,15 @@ int main(int argc, char **argv) igt_subtest("stress-mm-invalidate-close-overlap") test_invalidate_close_race(fd, true); + for (unsigned flags = 0; flags < ALL_MAP_FIXED_INVALIDATE + 1; flags++) { + igt_subtest_f("map-fixed-invalidate%s%s%s", + flags & MAP_FIXED_INVALIDATE_OVERLAP ? "-overlap" : "", + flags & MAP_FIXED_INVALIDATE_BUSY ? "-busy" : "", + flags & MAP_FIXED_INVALIDATE_GET_PAGES ? "-gup" : "") { + test_map_fixed_invalidate(fd, flags); + } + } + igt_subtest("coherency-sync") test_coherency(fd, count); |