[igt-dev] [PATCH i-g-t] tests/prime_mmap: Add support for local memory
apoorva1.singh at intel.com
apoorva1.singh at intel.com
Wed Oct 6 11:06:43 UTC 2021
From: Andrzej Turko <andrzej.turko at linux.intel.com>
Add support for local memory region (Device memory)
Signed-off-by: Andrzej Turko <andrzej.turko at linux.intel.com>
Signed-off-by: Apoorva Singh <apoorva1.singh at intel.com>
Cc: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>
Cc: Thomas Hellström <thomas.hellstrom at linux.intel.com>
Cc: Melkaveri, Arjun <arjun.melkaveri at intel.com>
---
tests/prime_mmap.c | 259 +++++++++++++++++++++++++++------------------
1 file changed, 158 insertions(+), 101 deletions(-)
diff --git a/tests/prime_mmap.c b/tests/prime_mmap.c
index a4e4b4b6..9f3a1ad9 100644
--- a/tests/prime_mmap.c
+++ b/tests/prime_mmap.c
@@ -42,11 +42,14 @@
#include "drm.h"
#include "drmtest.h"
+#include "igt.h"
+#include "igt_collection.h"
#include "i915_drm.h"
#include "i915/gem_create.h"
#include "i915/gem_mman.h"
#include "igt_debugfs.h"
#include "ioctl_wrappers.h"
+#include "i915/intel_memory_region.h"
#define BO_SIZE (16*1024)
@@ -68,119 +71,123 @@ fill_bo(uint32_t handle, size_t size)
}
static void
-fill_bo_cpu(char *ptr)
+fill_bo_cpu(char *ptr, size_t size)
{
- memcpy(ptr, pattern, sizeof(pattern));
+ off_t i;
+ for (i = 0; i < size; i += sizeof(pattern))
+ {
+ memcpy(ptr + i, pattern, sizeof(pattern));
+ }
}
static void
-test_correct(void)
+test_correct(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr1, *ptr2;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
/* Check correctness vs GEM_MMAP */
- ptr1 = gem_mmap__device_coherent(fd, handle, 0, BO_SIZE, PROT_READ);
- ptr2 = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr1 = gem_mmap__device_coherent(fd, handle, 0, size, PROT_READ);
+ ptr2 = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr1 != MAP_FAILED);
igt_assert(ptr2 != MAP_FAILED);
- igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
+ igt_assert(memcmp(ptr1, ptr2, size) == 0);
/* Check pattern correctness */
igt_assert(memcmp(ptr2, pattern, sizeof(pattern)) == 0);
- munmap(ptr1, BO_SIZE);
- munmap(ptr2, BO_SIZE);
+ munmap(ptr1, size);
+ munmap(ptr2, size);
close(dma_buf_fd);
gem_close(fd, handle);
}
static void
-test_map_unmap(void)
+test_map_unmap(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
/* Unmap and remap */
- munmap(ptr, BO_SIZE);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ munmap(ptr, size);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
close(dma_buf_fd);
gem_close(fd, handle);
}
/* prime and then unprime and then prime again the same handle */
static void
-test_reprime(void)
+test_reprime(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
close (dma_buf_fd);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
close(dma_buf_fd);
gem_close(fd, handle);
}
/* map from another process */
static void
-test_forked(void)
+test_forked(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
igt_fork(childno, 1) {
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
close(dma_buf_fd);
}
close(dma_buf_fd);
@@ -190,13 +197,13 @@ test_forked(void)
/* test simple CPU write */
static void
-test_correct_cpu_write(void)
+test_correct_cpu_write(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
dma_buf_fd = prime_handle_to_fd_for_mmap(fd, handle);
@@ -204,29 +211,30 @@ test_correct_cpu_write(void)
igt_skip_on(errno == EINVAL);
/* Check correctness of map using write protection (PROT_WRITE) */
- ptr = mmap(NULL, BO_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd,
+ 0);
igt_assert(ptr != MAP_FAILED);
/* Fill bo using CPU */
- fill_bo_cpu(ptr);
+ fill_bo_cpu(ptr, BO_SIZE);
/* Check pattern correctness */
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
close(dma_buf_fd);
gem_close(fd, handle);
}
/* map from another process and then write using CPU */
static void
-test_forked_cpu_write(void)
+test_forked_cpu_write(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
dma_buf_fd = prime_handle_to_fd_for_mmap(fd, handle);
@@ -234,12 +242,13 @@ test_forked_cpu_write(void)
igt_skip_on(errno == EINVAL);
igt_fork(childno, 1) {
- ptr = mmap(NULL, BO_SIZE, PROT_READ | PROT_WRITE , MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ | PROT_WRITE , MAP_SHARED,
+ dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
- fill_bo_cpu(ptr);
+ fill_bo_cpu(ptr, BO_SIZE);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
close(dma_buf_fd);
}
close(dma_buf_fd);
@@ -248,45 +257,45 @@ test_forked_cpu_write(void)
}
static void
-test_refcounting(void)
+test_refcounting(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
/* Close gem object before mapping */
gem_close(fd, handle);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
close (dma_buf_fd);
}
/* dup before mmap */
static void
-test_dup(void)
+test_dup(uint32_t region, int size)
{
int dma_buf_fd;
char *ptr;
uint32_t handle;
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = dup(prime_handle_to_fd(fd, handle));
igt_assert(errno == 0);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr != MAP_FAILED);
igt_assert(memcmp(ptr, pattern, sizeof(pattern)) == 0);
- munmap(ptr, BO_SIZE);
+ munmap(ptr, size);
gem_close(fd, handle);
close (dma_buf_fd);
}
@@ -324,21 +333,21 @@ static bool has_userptr(void)
/* test for mmap(dma_buf_export(userptr)) */
static void
-test_userptr(void)
+test_userptr(uint32_t region, int size)
{
int ret, dma_buf_fd;
void *ptr;
uint32_t handle;
- igt_require(has_userptr());
-
/* create userptr bo */
- ret = posix_memalign(&ptr, 4096, BO_SIZE);
+ ret = posix_memalign(&ptr, 4096, size);
igt_assert_eq(ret, 0);
- /* we are not allowed to export unsynchronized userptr. Just create a normal
- * one */
- gem_userptr(fd, (uint32_t *)ptr, BO_SIZE, 0, 0, &handle);
+ /*
+ * we are not allowed to export unsynchronized userptr. Just create a
+ * normal one
+ */
+ gem_userptr(fd, (uint32_t *)ptr, size, 0, 0, &handle);
/* export userptr */
ret = prime_handle_to_fd_no_assert(handle, DRM_CLOEXEC, &dma_buf_fd);
@@ -352,7 +361,7 @@ test_userptr(void)
/* a userptr doesn't have the obj->base.filp, but can be exported via
* dma-buf, so make sure it fails here */
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr == MAP_FAILED && errno == ENODEV);
free_userptr:
gem_close(fd, handle);
@@ -360,7 +369,7 @@ free_userptr:
}
static void
-test_errors(void)
+test_errors(uint32_t region, int size)
{
int i, dma_buf_fd;
char *ptr;
@@ -369,48 +378,50 @@ test_errors(void)
DRM_RDWR - 1, DRM_RDWR + 1};
/* Test for invalid flags */
- handle = gem_create(fd, BO_SIZE);
- for (i = 0; i < sizeof(invalid_flags) / sizeof(invalid_flags[0]); i++) {
- prime_handle_to_fd_no_assert(handle, invalid_flags[i], &dma_buf_fd);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ for (i = 0; i < ARRAY_SIZE(invalid_flags); i++) {
+ prime_handle_to_fd_no_assert(handle, invalid_flags[i],
+ &dma_buf_fd);
igt_assert_eq(errno, EINVAL);
errno = 0;
}
+ gem_close(fd, handle);
/* Close gem object before priming */
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
gem_close(fd, handle);
prime_handle_to_fd_no_assert(handle, DRM_CLOEXEC, &dma_buf_fd);
igt_assert(dma_buf_fd == -1 && errno == ENOENT);
errno = 0;
/* close fd before mapping */
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
close(dma_buf_fd);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr == MAP_FAILED && errno == EBADF);
errno = 0;
gem_close(fd, handle);
/* Map too big */
- handle = gem_create(fd, BO_SIZE);
- fill_bo(handle, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
+ fill_bo(handle, size);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
- ptr = mmap(NULL, BO_SIZE * 2, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ ptr = mmap(NULL, size * 2, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
igt_assert(ptr == MAP_FAILED && errno == EINVAL);
errno = 0;
close(dma_buf_fd);
gem_close(fd, handle);
/* Overlapping the end of the buffer */
- handle = gem_create(fd, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
dma_buf_fd = prime_handle_to_fd(fd, handle);
igt_assert(errno == 0);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, BO_SIZE / 2);
+ ptr = mmap(NULL, size, PROT_READ, MAP_SHARED, dma_buf_fd, size / 2);
igt_assert(ptr == MAP_FAILED && errno == EINVAL);
errno = 0;
close(dma_buf_fd);
@@ -419,7 +430,7 @@ test_errors(void)
/* Test for invalid flags on sync ioctl */
static void
-test_invalid_sync_flags(void)
+test_invalid_sync_flags(uint32_t region, int size)
{
int i, dma_buf_fd;
uint32_t handle;
@@ -429,7 +440,7 @@ test_invalid_sync_flags(void)
LOCAL_DMA_BUF_SYNC_RW + 1,
LOCAL_DMA_BUF_SYNC_VALID_FLAGS_MASK + 1};
- handle = gem_create(fd, BO_SIZE);
+ handle = gem_create_in_memory_regions(fd, size, region);
dma_buf_fd = prime_handle_to_fd(fd, handle);
for (i = 0; i < sizeof(invalid_flags) / sizeof(invalid_flags[0]); i++) {
memset(&sync, 0, sizeof(sync));
@@ -442,7 +453,7 @@ test_invalid_sync_flags(void)
}
static void
-test_aperture_limit(void)
+test_aperture_limit(uint32_t region, int size)
{
int dma_buf_fd1, dma_buf_fd2;
char *ptr1, *ptr2;
@@ -452,23 +463,22 @@ test_aperture_limit(void)
uint64_t size2 = (gem_mappable_aperture_size(fd) * 3) / 8;
handle1 = gem_create(fd, size1);
- fill_bo(handle1, BO_SIZE);
-
- dma_buf_fd1 = prime_handle_to_fd(fd, handle1);
+ dma_buf_fd1 = prime_handle_to_fd_for_mmap(fd, handle1);
igt_assert(errno == 0);
- ptr1 = mmap(NULL, size1, PROT_READ, MAP_SHARED, dma_buf_fd1, 0);
+ ptr1 = mmap(NULL, size1, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd1, 0);
igt_assert(ptr1 != MAP_FAILED);
+ fill_bo_cpu(ptr1, size);
igt_assert(memcmp(ptr1, pattern, sizeof(pattern)) == 0);
handle2 = gem_create(fd, size1);
- fill_bo(handle2, BO_SIZE);
- dma_buf_fd2 = prime_handle_to_fd(fd, handle2);
+ dma_buf_fd2 = prime_handle_to_fd_for_mmap(fd, handle2);
igt_assert(errno == 0);
- ptr2 = mmap(NULL, size2, PROT_READ, MAP_SHARED, dma_buf_fd2, 0);
+ ptr2 = mmap(NULL, size2, PROT_READ | PROT_WRITE, MAP_SHARED, dma_buf_fd2, 0);
igt_assert(ptr2 != MAP_FAILED);
+ fill_bo_cpu(ptr2, size);
igt_assert(memcmp(ptr2, pattern, sizeof(pattern)) == 0);
- igt_assert(memcmp(ptr1, ptr2, BO_SIZE) == 0);
+ igt_assert(memcmp(ptr1, ptr2, size) == 0);
munmap(ptr1, size1);
munmap(ptr2, size2);
@@ -479,29 +489,55 @@ test_aperture_limit(void)
}
static int
-check_for_dma_buf_mmap(void)
+check_for_dma_buf_mmap(struct igt_collection *set)
{
+ struct igt_collection *region;
+ uint32_t reg;
int dma_buf_fd;
char *ptr;
uint32_t handle;
int ret = 1;
- handle = gem_create(fd, BO_SIZE);
- dma_buf_fd = prime_handle_to_fd(fd, handle);
- ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
- if (ptr != MAP_FAILED)
- ret = 0;
- munmap(ptr, BO_SIZE);
- gem_close(fd, handle);
- close(dma_buf_fd);
+ for_each_combination(region, 1, set) {
+ reg = igt_collection_get_value(region, 0);
+ handle = gem_create_in_memory_regions(fd, BO_SIZE, reg);
+
+ dma_buf_fd = prime_handle_to_fd(fd, handle);
+ ptr = mmap(NULL, BO_SIZE, PROT_READ, MAP_SHARED, dma_buf_fd, 0);
+ if (ptr != MAP_FAILED)
+ ret = 0;
+ munmap(ptr, BO_SIZE);
+ gem_close(fd, handle);
+ close(dma_buf_fd);
+ }
return ret;
}
+#define SKIP_LMEM (1 << 0)
+#define SKIP_USERPTR (1 << 1)
+
+/*
+ * true skips the test
+ */
+static bool check_skip(uint32_t skip, uint32_t region)
+{
+ if ((skip & SKIP_LMEM) && IS_DEVICE_MEMORY_REGION(region))
+ return true;
+
+ if (skip & SKIP_USERPTR)
+ return !has_userptr();
+
+ return false;
+}
+
igt_main
{
+ struct igt_collection *set, *regions;
+ struct drm_i915_query_memory_regions *query_info;
struct {
const char *name;
- void (*fn)(void);
+ void (*fn)(uint32_t, int);
+ uint32_t skip;
} tests[] = {
{ "test_correct", test_correct },
{ "test_map_unmap", test_map_unmap },
@@ -511,25 +547,46 @@ igt_main
{ "test_forked_cpu_write", test_forked_cpu_write },
{ "test_refcounting", test_refcounting },
{ "test_dup", test_dup },
- { "test_userptr", test_userptr },
+ { "test_userptr", test_userptr, SKIP_LMEM | SKIP_USERPTR },
{ "test_errors", test_errors },
{ "test_invalid_sync_flags", test_invalid_sync_flags },
- { "test_aperture_limit", test_aperture_limit },
+ { "test_aperture_limit", test_aperture_limit, SKIP_LMEM },
};
+ uint32_t region;
+ char *ext;
+ int size;
int i;
igt_fixture {
fd = drm_open_driver(DRIVER_INTEL);
- igt_skip_on((check_for_dma_buf_mmap() != 0));
- errno = 0;
- }
+ query_info = gem_get_query_memory_regions(fd);
+ igt_assert(query_info);
- for (i = 0; i < ARRAY_SIZE(tests); i++) {
- igt_subtest(tests[i].name)
- tests[i].fn();
+ set = get_memory_region_set(query_info, I915_SYSTEM_MEMORY,
+ I915_DEVICE_MEMORY);
+ igt_skip_on((check_for_dma_buf_mmap(set) != 0));
+ errno = 0;
}
- igt_fixture
+ for (i = 0; i < ARRAY_SIZE(tests); i++)
+ igt_subtest_with_dynamic(tests[i].name) {
+ for_each_combination(regions, 1, set) {
+ region = igt_collection_get_value(regions, 0);
+ size = gem_get_batch_size(fd, MEMORY_TYPE_FROM_REGION(region));
+ size = max(size, BO_SIZE);
+ if (check_skip(tests[i].skip, region))
+ continue;
+ ext = memregion_dynamic_subtest_name(regions);
+ igt_dynamic_f("%s-%s", tests[i].name, ext)
+ tests[i].fn(region, size);
+ free(ext);
+ }
+ }
+
+ igt_fixture {
+ free(query_info);
+ igt_collection_destroy(set);
close(fd);
+ }
}
--
2.25.1
More information about the igt-dev
mailing list