All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection
@ 2021-12-30 18:26 Zbigniew Kempczyński
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2021-12-30 18:26 UTC (permalink / raw)
  To: igt-dev

Add some universal code which tries to detect kernel offset capabilities.

v2: unify cache, fix start offset iteration
    run gem_softpin@safe-alignment also on integrated
v3: move cache entry out of mutex
v4: avoid assert and skip adding to cache if there's no memory
    rename to safe-start
    verify safe start offset on each engine

Zbigniew Kempczyński (3):
  lib/intel_memory_region: Add start offset and alignment detection
  tests/i915/gem_softpin: Add safe-start test
  tests/fast-feedback.testlist: Add gem_softpin@safe-start subtest

 lib/i915/intel_memory_region.c        | 371 ++++++++++++++++++++++++++
 lib/i915/intel_memory_region.h        |   5 +
 tests/i915/gem_softpin.c              |  87 ++++++
 tests/intel-ci/fast-feedback.testlist |   1 +
 4 files changed, 464 insertions(+)

-- 
2.32.0

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2021-12-30 18:26 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
@ 2021-12-30 18:26 ` Zbigniew Kempczyński
  2022-01-05  5:00   ` Dixit, Ashutosh
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 2/3] tests/i915/gem_softpin: Add safe-start test Zbigniew Kempczyński
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Zbigniew Kempczyński @ 2021-12-30 18:26 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

With era of new gens we're enforced to use no-reloc (softpin). This
brings few problems like vm range limitations which were well solved
by the kernel. This can be handled also in userspace code by adding
gen related conditionals or by trying to detect the constraints.

Lets try to do this dynamically and detect safe start offset and
alignment for each memory region we got. This should be universal solution
regardless hw limitations and bugs. As such detection is not lightweight
technique add also some caching structures to handle consequtive calls
about same data.

v2: unify cache
v3: move allocation of cache entry out of mutex
v4: remove assert on allocation newentry, just skip adding to cache

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 lib/i915/intel_memory_region.c | 371 +++++++++++++++++++++++++++++++++
 lib/i915/intel_memory_region.h |   5 +
 2 files changed, 376 insertions(+)

diff --git a/lib/i915/intel_memory_region.c b/lib/i915/intel_memory_region.c
index dfbb8acf0..a4431046f 100644
--- a/lib/i915/intel_memory_region.c
+++ b/lib/i915/intel_memory_region.c
@@ -28,11 +28,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <pthread.h>
 
 #include "i915/gem_create.h"
 #include "intel_reg.h"
 #include "drmtest.h"
 #include "ioctl_wrappers.h"
+#include "igt_aux.h"
 #include "igt_dummyload.h"
 #include "igt_gt.h"
 #include "igt_params.h"
@@ -40,6 +42,7 @@
 #include "intel_chipset.h"
 #include "igt_collection.h"
 #include "igt_device.h"
+#include "gem_mman.h"
 
 #include "i915/intel_memory_region.h"
 
@@ -480,3 +483,371 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 
 	return 0;
 }
+
+#define PAGE_SIZE 4096
+
+enum cache_entry_type {
+	MIN_START_OFFSET,
+	MIN_ALIGNMENT,
+	SAFE_START_OFFSET,
+	SAFE_ALIGNMENT,
+};
+
+struct cache_entry {
+	uint16_t devid;
+	enum cache_entry_type type;
+
+	union {
+		/* for MIN_START_OFFSET */
+		struct {
+			uint64_t offset;
+			uint32_t region;
+		} start;
+
+		/* for MIN_ALIGNMENT */
+		struct {
+			uint64_t alignment;
+			uint64_t region1;
+			uint64_t region2;
+		} minalign;
+
+		/* for SAFE_START_OFFSET */
+		uint64_t safe_start_offset;
+
+		/* for SAFE_ALIGNMENT */
+		uint64_t safe_alignment;
+	};
+	struct igt_list_head link;
+};
+
+static IGT_LIST_HEAD(cache);
+static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static struct cache_entry *find_entry_unlocked(enum cache_entry_type type,
+					       uint16_t devid,
+					       uint32_t region1,
+					       uint32_t region2)
+{
+	struct cache_entry *entry;
+
+	igt_list_for_each_entry(entry, &cache, link) {
+		if (entry->type != type || entry->devid != devid)
+			continue;
+
+		switch (entry->type) {
+		case MIN_START_OFFSET:
+			if (entry->start.region == region1)
+				return entry;
+			continue;
+
+		case MIN_ALIGNMENT:
+			if (entry->minalign.region1 == region1 &&
+			    entry->minalign.region2 == region2)
+				return entry;
+			continue;
+
+		case SAFE_START_OFFSET:
+		case SAFE_ALIGNMENT:
+			return entry;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * gem_detect_min_start_offset_for_region:
+ * @i915: drm fd
+ * @region: memory region
+ *
+ * Returns: minimum start offset at which kernel allows placing objects
+ *          for memory region.
+ */
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
+{
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t start_offset = 0;
+	uint64_t bb_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(&obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	eb.buffers_ptr = to_user_pointer(&obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj.handle, &bb_size, region) == 0);
+	obj.flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	while (1) {
+		obj.offset = start_offset;
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		if (start_offset)
+			start_offset <<= 1;
+		else
+			start_offset = PAGE_SIZE;
+
+		igt_assert(start_offset <= 1ull << 48);
+	}
+	gem_close(i915, obj.handle);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return start_offset;
+
+	/* Check does other thread did the job before */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_START_OFFSET;
+	entry->start.offset = start_offset;
+	entry->start.region = region;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->start.offset;
+}
+
+/**
+ * gem_detect_safe_start_offset:
+ * @i915: drm fd
+ *
+ * Returns: finds start offset which can be used as first one regardless
+ *          memory region. Useful if for some reason some regions don't allow
+ *          starting from 0x0 offset.
+ */
+uint64_t gem_detect_safe_start_offset(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint32_t region;
+	uint64_t offset = 0;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_combination(regions, 1, set) {
+		region = igt_collection_get_value(regions, 0);
+		offset = max(offset,
+			     gem_detect_min_start_offset_for_region(i915, region));
+	}
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return offset;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_START_OFFSET;
+	entry->safe_start_offset = offset;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->safe_start_offset;
+}
+
+/**
+ * gem_detect_min_alignment_for_regions:
+ * @i915: drm fd
+ * @region1: first region
+ * @region2: second region
+ *
+ * Returns: minimum alignment which must be used when objects from @region1 and
+ * @region2 are going to interact.
+ */
+uint64_t gem_detect_min_alignment_for_regions(int i915,
+					      uint32_t region1,
+					      uint32_t region2)
+{
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t min_alignment = PAGE_SIZE;
+	uint64_t bb_size = PAGE_SIZE, obj_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	/* Establish bb offset first */
+	eb.buffers_ptr = to_user_pointer(obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle,
+						  &bb_size, region1) == 0);
+	obj[0].flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size,
+					  PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
+
+	/* Find appropriate alignment of object */
+	eb.buffer_count = ARRAY_SIZE(obj);
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle,
+						  &obj_size, region2) == 0);
+	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region2);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	while (1) {
+		obj[1].offset = ALIGN(obj[0].offset + bb_size, min_alignment);
+		igt_assert(obj[1].offset <= 1ull << 32);
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		min_alignment <<= 1;
+	}
+
+	gem_close(i915, obj[0].handle);
+	gem_close(i915, obj[1].handle);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return min_alignment;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_ALIGNMENT;
+	entry->minalign.alignment = min_alignment;
+	entry->minalign.region1 = region1;
+	entry->minalign.region2 = region2;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
+
+/**
+ * gem_get_safe_alignment:
+ * @i915: drm fd
+ *
+ * Returns: safe alignment for all memory regions on @i915 device.
+ * Safe in this case means max() from all minimum alignment for each
+ * region.
+ */
+uint64_t gem_detect_safe_alignment(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint64_t default_alignment = 0;
+	uint32_t region_bb, region_obj;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	/* non-discrete uses 4K page size */
+	if (!gem_has_lmem(i915))
+		return PAGE_SIZE;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_variation_r(regions, 2, set) {
+		uint64_t alignment;
+
+		region_bb = igt_collection_get_value(regions, 0);
+		region_obj = igt_collection_get_value(regions, 1);
+
+		/* We're interested in triangular matrix */
+		if (region_bb > region_obj)
+			continue;
+
+		alignment = gem_detect_min_alignment_for_regions(i915,
+								 region_bb,
+								 region_obj);
+		if (default_alignment < alignment)
+			default_alignment = alignment;
+	}
+
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return default_alignment;
+
+	/* Try again, check does we have cache updated in the meantime. */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid,  0, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_ALIGNMENT;
+	entry->safe_alignment = default_alignment;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
diff --git a/lib/i915/intel_memory_region.h b/lib/i915/intel_memory_region.h
index 8b427b7e7..936e7d1c8 100644
--- a/lib/i915/intel_memory_region.h
+++ b/lib/i915/intel_memory_region.h
@@ -129,4 +129,9 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 				      uint16_t memory_class,
 				      uint16_t memory_instance);
 
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region);
+uint64_t gem_detect_safe_start_offset(int i915);
+uint64_t gem_detect_min_alignment_for_regions(int i915, uint32_t region1, uint32_t region2);
+uint64_t gem_detect_safe_alignment(int i915);
+
 #endif /* INTEL_MEMORY_REGION_H */
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 2/3] tests/i915/gem_softpin: Add safe-start test
  2021-12-30 18:26 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
@ 2021-12-30 18:26 ` Zbigniew Kempczyński
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 3/3] tests/fast-feedback.testlist: Add gem_softpin@safe-start subtest Zbigniew Kempczyński
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2021-12-30 18:26 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

Exercise start offset and alignment detection when we start mixing
system and local memory.

v2: support integrated and check smem <-> smem alignment
v3: iterate over engines to verify safe start is correct everywhere

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 tests/i915/gem_softpin.c | 87 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 87 insertions(+)

diff --git a/tests/i915/gem_softpin.c b/tests/i915/gem_softpin.c
index d085dea34..7085605bc 100644
--- a/tests/i915/gem_softpin.c
+++ b/tests/i915/gem_softpin.c
@@ -1072,6 +1072,89 @@ static void test_allocator_evict(int fd, const intel_ctx_t *ctx,
 	igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0);
 }
 
+static void make_batch(int i915, uint32_t handle, uint64_t size)
+{
+	uint32_t *bb = gem_mmap__device_coherent(i915, handle, 0, size, PROT_WRITE);
+	*bb = MI_BATCH_BUFFER_END;
+	munmap(bb, size);
+}
+
+static void safe_start(int i915)
+{
+	struct drm_i915_gem_execbuffer2 execbuf = {};
+	struct drm_i915_gem_exec_object2 obj[2] = {};
+	uint32_t handle1, handle2, region1, region2;
+	uint64_t alignment, offset1, offset2, size1 = 4096, size2 = 4096;
+	const struct intel_execution_engine2 *e;
+	const intel_ctx_t *ctx;
+
+	region1 = REGION_SMEM;
+	region2 = gem_has_lmem(i915) ? REGION_LMEM(0) : REGION_SMEM;
+	igt_assert(__gem_create_in_memory_regions(i915, &handle1, &size1, region1) == 0);
+	igt_assert(handle1);
+	make_batch(i915, handle1, 4096);
+	igt_assert(__gem_create_in_memory_regions(i915, &handle2, &size2, region2) == 0);
+	igt_assert(handle2);
+	make_batch(i915, handle2, 4096);
+
+	offset1 = gem_detect_min_start_offset_for_region(i915, region1);
+	offset2 = gem_detect_min_start_offset_for_region(i915, region2);
+	alignment = gem_detect_safe_alignment(i915);
+	igt_debug("safe alignment: %llx\n", (long long) alignment);
+	igt_debug("safe start offset: %llx\n",
+		  (long long) gem_detect_safe_start_offset(i915));
+	igt_debug("minimum object1 start offset: %llx\n", (long long) offset1);
+	igt_debug("minimum object2 start offset: %llx\n", (long long) offset2);
+
+	execbuf.buffer_count = 2;
+	execbuf.buffers_ptr = to_user_pointer(obj);
+
+	obj[0].offset = offset1;
+	obj[0].flags = EXEC_OBJECT_PINNED;
+	obj[0].handle = handle1;
+	obj[1].offset = max(ALIGN(offset1 + size1, alignment), offset2);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	obj[1].handle = handle2;
+	igt_debug("obj[0].offset: %llx, handle: %u\n", obj[0].offset, obj[0].handle);
+	igt_debug("obj[1].offset: %llx, handle: %u\n", obj[1].offset, obj[1].handle);
+
+	gem_execbuf(i915, &execbuf);
+	execbuf.flags = I915_EXEC_BATCH_FIRST;
+	gem_execbuf(i915, &execbuf);
+
+	obj[0].offset = offset2;
+	obj[0].flags = EXEC_OBJECT_PINNED;
+	obj[0].handle = handle2;
+	obj[1].offset = max(ALIGN(offset2 + size2, alignment), offset1);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	obj[1].handle = handle1;
+	igt_debug("obj[0].offset: %llx, handle: %u\n", obj[0].offset, obj[0].handle);
+	igt_debug("obj[1].offset: %llx, handle: %u\n", obj[1].offset, obj[1].handle);
+
+	gem_execbuf(i915, &execbuf);
+	execbuf.flags = 0;
+	gem_execbuf(i915, &execbuf);
+	gem_sync(i915, handle1);
+
+	/* Last check, verify safe start for each engine */
+	ctx = intel_ctx_create_all_physical(i915);
+	execbuf.buffer_count = 1;
+	execbuf.rsvd1 = ctx->id;
+	obj[0].offset = gem_detect_safe_start_offset(i915);
+	for_each_ctx_engine(i915, ctx, e) {
+		execbuf.flags = e->flags;
+		obj[0].handle = handle1;
+		gem_execbuf(i915, &execbuf);
+		obj[0].handle = handle2;
+		gem_execbuf(i915, &execbuf);
+	}
+
+	gem_sync(i915, handle1);
+	gem_close(i915, handle1);
+	gem_close(i915, handle2);
+	intel_ctx_destroy(i915, ctx);
+}
+
 #define test_each_engine(T, i915, ctx, e) \
 	igt_subtest_with_dynamic(T) for_each_ctx_engine(i915, ctx, e) \
 		igt_dynamic_f("%s", e->name)
@@ -1133,6 +1216,10 @@ igt_main
 			test_allocator_evict(fd, ctx, ALL_ENGINES, 20);
 	}
 
+	igt_describe("Check start offset and alignment detection");
+	igt_subtest("safe-start")
+		safe_start(fd);
+
 	igt_subtest("softpin")
 		test_softpin(fd);
 	igt_subtest("overlap")
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 3/3] tests/fast-feedback.testlist: Add gem_softpin@safe-start subtest
  2021-12-30 18:26 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 2/3] tests/i915/gem_softpin: Add safe-start test Zbigniew Kempczyński
@ 2021-12-30 18:26 ` Zbigniew Kempczyński
  2022-01-04  4:41   ` Petri Latvala
  2022-01-03 22:56 ` [igt-dev] ✗ GitLab.Pipeline: warning for Add start offset and alignment detection (rev5) Patchwork
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Zbigniew Kempczyński @ 2021-12-30 18:26 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

This test takes up to few hundred of milliseconds and exercises
detecting of safe starting offset and alignment to use on discrete
where memory regions constraints could differ on different gens.

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 tests/intel-ci/fast-feedback.testlist | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist
index de1c6cb46..38a90ceb6 100644
--- a/tests/intel-ci/fast-feedback.testlist
+++ b/tests/intel-ci/fast-feedback.testlist
@@ -45,6 +45,7 @@ igt@gem_render_tiled_blits@basic
 igt@gem_ringfill@basic-all
 igt@gem_softpin@allocator-basic
 igt@gem_softpin@allocator-basic-reserve
+igt@gem_softpin@safe-start
 igt@gem_sync@basic-all
 igt@gem_sync@basic-each
 igt@gem_tiled_blits@basic
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [igt-dev] ✗ GitLab.Pipeline: warning for Add start offset and alignment detection (rev5)
  2021-12-30 18:26 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
                   ` (2 preceding siblings ...)
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 3/3] tests/fast-feedback.testlist: Add gem_softpin@safe-start subtest Zbigniew Kempczyński
@ 2022-01-03 22:56 ` Patchwork
  2022-01-03 23:00 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
  2022-01-04  0:11 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 0 replies; 17+ messages in thread
From: Patchwork @ 2022-01-03 22:56 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

== Series Details ==

Series: Add start offset and alignment detection (rev5)
URL   : https://patchwork.freedesktop.org/series/98402/
State : warning

== Summary ==

Pipeline status: FAILED.

see https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/-/pipelines/476576 for the overview.

build-containers:build-debian-arm64 has failed (https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/-/jobs/17223549):
  Authenticating with credentials from job payload (GitLab Registry)
  Pulling docker image registry.freedesktop.org/wayland/ci-templates/buildah:2019-08-13.0 ...
  Using docker image sha256:594aa868d31ee3304dee8cae8a3433c89a6fcfcf6c7d420c04cce22f60147176 for registry.freedesktop.org/wayland/ci-templates/buildah:2019-08-13.0 with digest registry.freedesktop.org/wayland/ci-templates/buildah@sha256:7dbcf22cd2c1c7d49db0dc7b4ab207c3d6a4a09bd81cc3b71a688d3727d8749f ...
  section_end:1641248749:prepare_executor
  section_start:1641248749:prepare_script
  Preparing environment
  Running on runner-zbmz6-qr-project-3185-concurrent-1 via fdo-packet-m1xl-1...
  section_end:1641248753:prepare_script
  section_start:1641248753:get_sources
  Getting source from Git repository
  $ eval "$CI_PRE_CLONE_SCRIPT"
  Fetching changes...
  Reinitialized existing Git repository in /builds/gfx-ci/igt-ci-tags/.git/
  fatal: unable to access 'https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags.git/': The requested URL returned error: 504
  section_end:1641250554:get_sources
  section_start:1641250554:cleanup_file_variables
  Cleaning up file based variables
  section_end:1641250555:cleanup_file_variables
  ERROR: Job failed: exit code 1
  

build-containers:build-debian-mips has failed (https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/-/jobs/17223550):
  Using Docker executor with image registry.freedesktop.org/wayland/ci-templates/buildah:2019-08-13.0 ...
  Authenticating with credentials from job payload (GitLab Registry)
  Pulling docker image registry.freedesktop.org/wayland/ci-templates/buildah:2019-08-13.0 ...
  Using docker image sha256:594aa868d31ee3304dee8cae8a3433c89a6fcfcf6c7d420c04cce22f60147176 for registry.freedesktop.org/wayland/ci-templates/buildah:2019-08-13.0 with digest registry.freedesktop.org/wayland/ci-templates/buildah@sha256:7dbcf22cd2c1c7d49db0dc7b4ab207c3d6a4a09bd81cc3b71a688d3727d8749f ...
  section_end:1641248750:prepare_executor
  section_start:1641248750:prepare_script
  Preparing environment
  Running on runner-ya9tm6yf-project-3185-concurrent-1 via fdo-packet-m1xl-2...
  section_end:1641248751:prepare_script
  section_start:1641248751:get_sources
  Getting source from Git repository
  $ eval "$CI_PRE_CLONE_SCRIPT"
  Fetching changes...
  Reinitialized existing Git repository in /builds/gfx-ci/igt-ci-tags/.git/
  fatal: unable to access 'https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags.git/': The requested URL returned error: 504
  section_end:1641250552:get_sources
  section_start:1641250552:cleanup_file_variables
  Cleaning up file based variables
  section_end:1641250553:cleanup_file_variables
  ERROR: Job failed: exit code 1

build-containers:build-fedora has failed (https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/-/jobs/17223551):
  Authenticating with credentials from job payload (GitLab Registry)
  Pulling docker image registry.freedesktop.org/wayland/ci-templates/buildah:2019-08-13.0 ...
  Using docker image sha256:594aa868d31ee3304dee8cae8a3433c89a6fcfcf6c7d420c04cce22f60147176 for registry.freedesktop.org/wayland/ci-templates/buildah:2019-08-13.0 with digest registry.freedesktop.org/wayland/ci-templates/buildah@sha256:7dbcf22cd2c1c7d49db0dc7b4ab207c3d6a4a09bd81cc3b71a688d3727d8749f ...
  section_end:1641248749:prepare_executor
  section_start:1641248749:prepare_script
  Preparing environment
  Running on runner-zbmz6-qr-project-3185-concurrent-2 via fdo-packet-m1xl-1...
  section_end:1641248753:prepare_script
  section_start:1641248753:get_sources
  Getting source from Git repository
  $ eval "$CI_PRE_CLONE_SCRIPT"
  Fetching changes...
  Reinitialized existing Git repository in /builds/gfx-ci/igt-ci-tags/.git/
  fatal: unable to access 'https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags.git/': The requested URL returned error: 504
  section_end:1641250554:get_sources
  section_start:1641250554:cleanup_file_variables
  Cleaning up file based variables
  section_end:1641250555:cleanup_file_variables
  ERROR: Job failed: exit code 1

== Logs ==

For more details see: https://gitlab.freedesktop.org/gfx-ci/igt-ci-tags/-/pipelines/476576

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for Add start offset and alignment detection (rev5)
  2021-12-30 18:26 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
                   ` (3 preceding siblings ...)
  2022-01-03 22:56 ` [igt-dev] ✗ GitLab.Pipeline: warning for Add start offset and alignment detection (rev5) Patchwork
@ 2022-01-03 23:00 ` Patchwork
  2022-01-04  0:11 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 0 replies; 17+ messages in thread
From: Patchwork @ 2022-01-03 23:00 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 6840 bytes --]

== Series Details ==

Series: Add start offset and alignment detection (rev5)
URL   : https://patchwork.freedesktop.org/series/98402/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11044 -> IGTPW_6529
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/index.html

Participating hosts (46 -> 36)
------------------------------

  Missing    (10): bat-dg1-6 bat-dg1-5 fi-icl-u2 fi-bsw-cyan bat-adlp-6 fi-pnv-d510 bat-rpls-1 fi-bdw-samus bat-jsl-2 bat-jsl-1 

New tests
---------

  New tests have been introduced between CI_DRM_11044 and IGTPW_6529:

### New IGT tests (1) ###

  * igt@gem_softpin@safe-start:
    - Statuses : 33 pass(s) 1 skip(s)
    - Exec time: [0.0, 0.10] s

  

Known issues
------------

  Here are the changes found in IGTPW_6529 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_basic@query-info:
    - fi-tgl-u2:          NOTRUN -> [SKIP][1] ([fdo#109315])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-tgl-u2/igt@amdgpu/amd_basic@query-info.html

  * igt@amdgpu/amd_basic@semaphore:
    - fi-bsw-nick:        NOTRUN -> [SKIP][2] ([fdo#109271]) +17 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-bsw-nick/igt@amdgpu/amd_basic@semaphore.html

  * igt@amdgpu/amd_cs_nop@fork-compute0:
    - fi-tgl-u2:          NOTRUN -> [SKIP][3] ([fdo#109315] / [i915#2575]) +16 similar issues
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-tgl-u2/igt@amdgpu/amd_cs_nop@fork-compute0.html

  * igt@amdgpu/amd_cs_nop@sync-fork-compute0:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][4] ([fdo#109271]) +7 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-kbl-soraka/igt@amdgpu/amd_cs_nop@sync-fork-compute0.html

  * igt@gem_flink_basic@bad-flink:
    - fi-skl-6600u:       [PASS][5] -> [FAIL][6] ([i915#4547])
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-skl-6600u/igt@gem_flink_basic@bad-flink.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-skl-6600u/igt@gem_flink_basic@bad-flink.html

  * {igt@gem_softpin@safe-start} (NEW):
    - fi-bwr-2160:        NOTRUN -> [SKIP][7] ([fdo#109271])
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-bwr-2160/igt@gem_softpin@safe-start.html

  * igt@i915_selftest@live@execlists:
    - fi-bsw-kefka:       [PASS][8] -> [INCOMPLETE][9] ([i915#2940])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-bsw-kefka/igt@i915_selftest@live@execlists.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-bsw-kefka/igt@i915_selftest@live@execlists.html

  * igt@i915_selftest@live@gt_heartbeat:
    - fi-cml-u2:          [PASS][10] -> [DMESG-FAIL][11] ([i915#541])
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-cml-u2/igt@i915_selftest@live@gt_heartbeat.html
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-cml-u2/igt@i915_selftest@live@gt_heartbeat.html

  * igt@i915_selftest@live@hangcheck:
    - fi-hsw-4770:        [PASS][12] -> [INCOMPLETE][13] ([i915#4785])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-hsw-4770/igt@i915_selftest@live@hangcheck.html

  * igt@runner@aborted:
    - fi-bsw-kefka:       NOTRUN -> [FAIL][14] ([fdo#109271] / [i915#1436] / [i915#3428] / [i915#4312])
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-bsw-kefka/igt@runner@aborted.html
    - fi-hsw-4770:        NOTRUN -> [FAIL][15] ([fdo#109271] / [i915#1436] / [i915#4312])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-hsw-4770/igt@runner@aborted.html

  
#### Possible fixes ####

  * igt@core_hotunplug@unbind-rebind:
    - fi-tgl-u2:          [INCOMPLETE][16] ([i915#4006]) -> [PASS][17]
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-tgl-u2/igt@core_hotunplug@unbind-rebind.html
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-tgl-u2/igt@core_hotunplug@unbind-rebind.html

  * igt@i915_selftest@live@uncore:
    - fi-bsw-nick:        [INCOMPLETE][18] -> [PASS][19]
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-bsw-nick/igt@i915_selftest@live@uncore.html
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-bsw-nick/igt@i915_selftest@live@uncore.html

  * igt@kms_frontbuffer_tracking@basic:
    - fi-cml-u2:          [DMESG-WARN][20] ([i915#4269]) -> [PASS][21]
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-cml-u2/igt@kms_frontbuffer_tracking@basic.html
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-cml-u2/igt@kms_frontbuffer_tracking@basic.html

  
#### Warnings ####

  * igt@runner@aborted:
    - fi-skl-6600u:       [FAIL][22] ([i915#2722] / [i915#4312]) -> [FAIL][23] ([i915#4312])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/fi-skl-6600u/igt@runner@aborted.html
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/fi-skl-6600u/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [i915#1436]: https://gitlab.freedesktop.org/drm/intel/issues/1436
  [i915#1886]: https://gitlab.freedesktop.org/drm/intel/issues/1886
  [i915#2575]: https://gitlab.freedesktop.org/drm/intel/issues/2575
  [i915#2722]: https://gitlab.freedesktop.org/drm/intel/issues/2722
  [i915#2940]: https://gitlab.freedesktop.org/drm/intel/issues/2940
  [i915#3428]: https://gitlab.freedesktop.org/drm/intel/issues/3428
  [i915#4006]: https://gitlab.freedesktop.org/drm/intel/issues/4006
  [i915#4269]: https://gitlab.freedesktop.org/drm/intel/issues/4269
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4547]: https://gitlab.freedesktop.org/drm/intel/issues/4547
  [i915#4785]: https://gitlab.freedesktop.org/drm/intel/issues/4785
  [i915#541]: https://gitlab.freedesktop.org/drm/intel/issues/541


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_6322 -> IGTPW_6529

  CI-20190529: 20190529
  CI_DRM_11044: 7b527a181f96f90a4c2f04d2705bdaffdd8168b6 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_6529: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/index.html
  IGT_6322: b0b7679b358b300b7b6bf42c6921d0aa1fc14388 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git



== Testlist changes ==

+igt@gem_softpin@safe-start

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/index.html

[-- Attachment #2: Type: text/html, Size: 8369 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [igt-dev] ✓ Fi.CI.IGT: success for Add start offset and alignment detection (rev5)
  2021-12-30 18:26 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
                   ` (4 preceding siblings ...)
  2022-01-03 23:00 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
@ 2022-01-04  0:11 ` Patchwork
  5 siblings, 0 replies; 17+ messages in thread
From: Patchwork @ 2022-01-04  0:11 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

[-- Attachment #1: Type: text/plain, Size: 27654 bytes --]

== Series Details ==

Series: Add start offset and alignment detection (rev5)
URL   : https://patchwork.freedesktop.org/series/98402/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_11044_full -> IGTPW_6529_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/index.html

Participating hosts (13 -> 7)
------------------------------

  Missing    (6): pig-kbl-iris shard-tglu pig-glk-j5005 pig-skl-6260u shard-rkl shard-dg1 

New tests
---------

  New tests have been introduced between CI_DRM_11044_full and IGTPW_6529_full:

### New IGT tests (4) ###

  * igt@gem_exec_async@forked-writes:
    - Statuses :
    - Exec time: [None] s

  * igt@gem_exec_create@legacy:
    - Statuses :
    - Exec time: [None] s

  * igt@gem_exec_fair@basic-flow@rcs0:
    - Statuses : 1 fail(s) 4 pass(s)
    - Exec time: [4.48, 5.96] s

  * igt@gem_softpin@safe-start:
    - Statuses : 6 pass(s)
    - Exec time: [0.01, 0.03] s

  

Known issues
------------

  Here are the changes found in IGTPW_6529_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@feature_discovery@psr2:
    - shard-iclb:         [PASS][1] -> [SKIP][2] ([i915#658])
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb2/igt@feature_discovery@psr2.html
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb5/igt@feature_discovery@psr2.html

  * igt@gem_create@create-massive:
    - shard-tglb:         NOTRUN -> [DMESG-WARN][3] ([i915#3002])
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb7/igt@gem_create@create-massive.html

  * igt@gem_exec_balancer@parallel-contexts:
    - shard-iclb:         [PASS][4] -> [SKIP][5] ([i915#4525]) +1 similar issue
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb2/igt@gem_exec_balancer@parallel-contexts.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb5/igt@gem_exec_balancer@parallel-contexts.html

  * igt@gem_exec_fair@basic-flow@rcs0 (NEW):
    - shard-tglb:         NOTRUN -> [FAIL][6] ([i915#2842])
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb7/igt@gem_exec_fair@basic-flow@rcs0.html

  * igt@gem_exec_fair@basic-pace@vecs0:
    - shard-kbl:          [PASS][7] -> [FAIL][8] ([i915#2842]) +1 similar issue
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-kbl7/igt@gem_exec_fair@basic-pace@vecs0.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl7/igt@gem_exec_fair@basic-pace@vecs0.html
    - shard-glk:          [PASS][9] -> [FAIL][10] ([i915#2842]) +1 similar issue
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk5/igt@gem_exec_fair@basic-pace@vecs0.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk4/igt@gem_exec_fair@basic-pace@vecs0.html

  * igt@gem_exec_whisper@basic-contexts:
    - shard-glk:          [PASS][11] -> [DMESG-WARN][12] ([i915#118]) +1 similar issue
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk2/igt@gem_exec_whisper@basic-contexts.html
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk4/igt@gem_exec_whisper@basic-contexts.html

  * igt@gem_exec_whisper@basic-fds-forked-all:
    - shard-glk:          NOTRUN -> [DMESG-WARN][13] ([i915#118])
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk4/igt@gem_exec_whisper@basic-fds-forked-all.html

  * igt@gem_lmem_swapping@random-engines:
    - shard-apl:          NOTRUN -> [SKIP][14] ([fdo#109271] / [i915#4613]) +1 similar issue
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl8/igt@gem_lmem_swapping@random-engines.html

  * igt@gem_lmem_swapping@verify-random:
    - shard-tglb:         NOTRUN -> [SKIP][15] ([i915#4613])
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb6/igt@gem_lmem_swapping@verify-random.html
    - shard-iclb:         NOTRUN -> [SKIP][16] ([i915#4613])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb3/igt@gem_lmem_swapping@verify-random.html
    - shard-glk:          NOTRUN -> [SKIP][17] ([fdo#109271] / [i915#4613])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk8/igt@gem_lmem_swapping@verify-random.html
    - shard-kbl:          NOTRUN -> [SKIP][18] ([fdo#109271] / [i915#4613])
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl3/igt@gem_lmem_swapping@verify-random.html

  * igt@gem_ppgtt@flink-and-close-vma-leak:
    - shard-glk:          [PASS][19] -> [FAIL][20] ([i915#644])
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk3/igt@gem_ppgtt@flink-and-close-vma-leak.html
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk7/igt@gem_ppgtt@flink-and-close-vma-leak.html

  * igt@gem_render_copy@x-tiled-to-vebox-yf-tiled:
    - shard-kbl:          NOTRUN -> [SKIP][21] ([fdo#109271]) +21 similar issues
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl1/igt@gem_render_copy@x-tiled-to-vebox-yf-tiled.html
    - shard-iclb:         NOTRUN -> [SKIP][22] ([i915#768])
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb4/igt@gem_render_copy@x-tiled-to-vebox-yf-tiled.html

  * igt@gen7_exec_parse@batch-without-end:
    - shard-iclb:         NOTRUN -> [SKIP][23] ([fdo#109289]) +1 similar issue
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb1/igt@gen7_exec_parse@batch-without-end.html
    - shard-tglb:         NOTRUN -> [SKIP][24] ([fdo#109289]) +1 similar issue
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb5/igt@gen7_exec_parse@batch-without-end.html

  * igt@gen9_exec_parse@bb-start-far:
    - shard-iclb:         NOTRUN -> [SKIP][25] ([i915#2856])
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb2/igt@gen9_exec_parse@bb-start-far.html
    - shard-tglb:         NOTRUN -> [SKIP][26] ([i915#2856])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb7/igt@gen9_exec_parse@bb-start-far.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-iclb:         [PASS][27] -> [FAIL][28] ([i915#454])
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb7/igt@i915_pm_dc@dc6-psr.html
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb1/igt@i915_pm_dc@dc6-psr.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip:
    - shard-apl:          NOTRUN -> [SKIP][29] ([fdo#109271] / [i915#3777])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl6/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html
    - shard-tglb:         NOTRUN -> [SKIP][30] ([fdo#111615])
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb7/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html
    - shard-kbl:          NOTRUN -> [SKIP][31] ([fdo#109271] / [i915#3777])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl4/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-0-hflip.html

  * igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc:
    - shard-apl:          NOTRUN -> [SKIP][32] ([fdo#109271] / [i915#3886]) +4 similar issues
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl8/igt@kms_ccs@pipe-a-crc-primary-rotation-180-y_tiled_gen12_rc_ccs_cc.html

  * igt@kms_ccs@pipe-c-bad-pixel-format-y_tiled_ccs:
    - shard-tglb:         NOTRUN -> [SKIP][33] ([i915#3689])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb7/igt@kms_ccs@pipe-c-bad-pixel-format-y_tiled_ccs.html

  * igt@kms_color_chamelium@pipe-a-ctm-0-5:
    - shard-apl:          NOTRUN -> [SKIP][34] ([fdo#109271] / [fdo#111827]) +6 similar issues
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl3/igt@kms_color_chamelium@pipe-a-ctm-0-5.html

  * igt@kms_content_protection@atomic:
    - shard-apl:          NOTRUN -> [FAIL][35] ([fdo#110321] / [fdo#110336])
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl8/igt@kms_content_protection@atomic.html

  * igt@kms_content_protection@atomic-dpms:
    - shard-apl:          NOTRUN -> [TIMEOUT][36] ([i915#1319])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl2/igt@kms_content_protection@atomic-dpms.html

  * igt@kms_cursor_crc@pipe-a-cursor-512x512-random:
    - shard-tglb:         NOTRUN -> [SKIP][37] ([fdo#109279] / [i915#3359]) +1 similar issue
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb7/igt@kms_cursor_crc@pipe-a-cursor-512x512-random.html

  * igt@kms_cursor_crc@pipe-c-cursor-512x170-sliding:
    - shard-iclb:         NOTRUN -> [SKIP][38] ([fdo#109278] / [fdo#109279]) +1 similar issue
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb7/igt@kms_cursor_crc@pipe-c-cursor-512x170-sliding.html

  * igt@kms_cursor_edge_walk@pipe-d-128x128-right-edge:
    - shard-snb:          NOTRUN -> [SKIP][39] ([fdo#109271]) +36 similar issues
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-snb5/igt@kms_cursor_edge_walk@pipe-d-128x128-right-edge.html
    - shard-iclb:         NOTRUN -> [SKIP][40] ([fdo#109278]) +1 similar issue
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb8/igt@kms_cursor_edge_walk@pipe-d-128x128-right-edge.html

  * igt@kms_cursor_legacy@cursorb-vs-flipa-atomic-transitions-varying-size:
    - shard-iclb:         NOTRUN -> [SKIP][41] ([fdo#109274] / [fdo#109278])
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb5/igt@kms_cursor_legacy@cursorb-vs-flipa-atomic-transitions-varying-size.html

  * igt@kms_draw_crc@draw-method-rgb565-mmap-cpu-ytiled:
    - shard-glk:          [PASS][42] -> [FAIL][43] ([i915#1888] / [i915#3451])
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk8/igt@kms_draw_crc@draw-method-rgb565-mmap-cpu-ytiled.html
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk4/igt@kms_draw_crc@draw-method-rgb565-mmap-cpu-ytiled.html

  * igt@kms_flip@2x-flip-vs-expired-vblank@ac-hdmi-a1-hdmi-a2:
    - shard-glk:          [PASS][44] -> [FAIL][45] ([i915#79])
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk2/igt@kms_flip@2x-flip-vs-expired-vblank@ac-hdmi-a1-hdmi-a2.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk9/igt@kms_flip@2x-flip-vs-expired-vblank@ac-hdmi-a1-hdmi-a2.html

  * igt@kms_flip@2x-plain-flip-ts-check-interruptible:
    - shard-iclb:         NOTRUN -> [SKIP][46] ([fdo#109274])
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb3/igt@kms_flip@2x-plain-flip-ts-check-interruptible.html

  * igt@kms_flip@flip-vs-suspend-interruptible@c-dp1:
    - shard-apl:          [PASS][47] -> [DMESG-WARN][48] ([i915#180]) +4 similar issues
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl6/igt@kms_flip@flip-vs-suspend-interruptible@c-dp1.html
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl1/igt@kms_flip@flip-vs-suspend-interruptible@c-dp1.html

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-msflip-blt:
    - shard-iclb:         NOTRUN -> [SKIP][49] ([fdo#109280]) +4 similar issues
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb5/igt@kms_frontbuffer_tracking@fbc-2p-primscrn-shrfb-msflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-cpu:
    - shard-glk:          NOTRUN -> [SKIP][50] ([fdo#109271]) +16 similar issues
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk4/igt@kms_frontbuffer_tracking@psr-1p-primscrn-pri-indfb-draw-mmap-cpu.html

  * igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-move:
    - shard-tglb:         NOTRUN -> [SKIP][51] ([fdo#111825]) +6 similar issues
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb8/igt@kms_frontbuffer_tracking@psr-2p-scndscrn-cur-indfb-move.html

  * igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area:
    - shard-apl:          NOTRUN -> [SKIP][52] ([fdo#109271] / [i915#658]) +1 similar issue
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl3/igt@kms_psr2_sf@overlay-primary-update-sf-dmg-area.html

  * igt@kms_psr@psr2_cursor_mmap_cpu:
    - shard-iclb:         NOTRUN -> [SKIP][53] ([fdo#109441])
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb1/igt@kms_psr@psr2_cursor_mmap_cpu.html
    - shard-tglb:         NOTRUN -> [FAIL][54] ([i915#132] / [i915#3467])
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb3/igt@kms_psr@psr2_cursor_mmap_cpu.html

  * igt@kms_psr@psr2_sprite_plane_move:
    - shard-iclb:         [PASS][55] -> [SKIP][56] ([fdo#109441]) +1 similar issue
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb2/igt@kms_psr@psr2_sprite_plane_move.html
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb5/igt@kms_psr@psr2_sprite_plane_move.html

  * igt@kms_vblank@pipe-a-ts-continuation-suspend:
    - shard-apl:          [PASS][57] -> [DMESG-WARN][58] ([i915#180] / [i915#295])
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl2/igt@kms_vblank@pipe-a-ts-continuation-suspend.html
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl7/igt@kms_vblank@pipe-a-ts-continuation-suspend.html

  * igt@kms_writeback@writeback-fb-id:
    - shard-apl:          NOTRUN -> [SKIP][59] ([fdo#109271] / [i915#2437])
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl6/igt@kms_writeback@writeback-fb-id.html

  * igt@nouveau_crc@pipe-b-ctx-flip-skip-current-frame:
    - shard-apl:          NOTRUN -> [SKIP][60] ([fdo#109271]) +95 similar issues
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl2/igt@nouveau_crc@pipe-b-ctx-flip-skip-current-frame.html
    - shard-tglb:         NOTRUN -> [SKIP][61] ([i915#2530])
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb6/igt@nouveau_crc@pipe-b-ctx-flip-skip-current-frame.html
    - shard-iclb:         NOTRUN -> [SKIP][62] ([i915#2530])
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb8/igt@nouveau_crc@pipe-b-ctx-flip-skip-current-frame.html

  * igt@perf@polling-parameterized:
    - shard-glk:          [PASS][63] -> [FAIL][64] ([i915#1542])
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk9/igt@perf@polling-parameterized.html
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk9/igt@perf@polling-parameterized.html

  * igt@prime_nv_pcopy@test2:
    - shard-iclb:         NOTRUN -> [SKIP][65] ([fdo#109291])
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb4/igt@prime_nv_pcopy@test2.html
    - shard-tglb:         NOTRUN -> [SKIP][66] ([fdo#109291])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-tglb8/igt@prime_nv_pcopy@test2.html

  * igt@sysfs_clients@split-50:
    - shard-apl:          NOTRUN -> [SKIP][67] ([fdo#109271] / [i915#2994])
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl4/igt@sysfs_clients@split-50.html

  
#### Possible fixes ####

  * igt@gem_eio@unwedge-stress:
    - shard-iclb:         [TIMEOUT][68] ([i915#2481] / [i915#3070]) -> [PASS][69]
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb7/igt@gem_eio@unwedge-stress.html
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb1/igt@gem_eio@unwedge-stress.html

  * igt@gem_exec_balancer@parallel-keep-submit-fence:
    - shard-iclb:         [SKIP][70] ([i915#4525]) -> [PASS][71] +1 similar issue
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb7/igt@gem_exec_balancer@parallel-keep-submit-fence.html
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb4/igt@gem_exec_balancer@parallel-keep-submit-fence.html

  * igt@gem_exec_fair@basic-deadline:
    - shard-kbl:          [FAIL][72] ([i915#2846]) -> [PASS][73]
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-kbl3/igt@gem_exec_fair@basic-deadline.html
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl3/igt@gem_exec_fair@basic-deadline.html

  * igt@gem_exec_fair@basic-none-share@rcs0:
    - shard-iclb:         [FAIL][74] ([i915#2842]) -> [PASS][75]
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb7/igt@gem_exec_fair@basic-none-share@rcs0.html
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb8/igt@gem_exec_fair@basic-none-share@rcs0.html

  * igt@gem_exec_fair@basic-none@rcs0:
    - shard-glk:          [FAIL][76] ([i915#2842]) -> [PASS][77] +1 similar issue
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk7/igt@gem_exec_fair@basic-none@rcs0.html
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk5/igt@gem_exec_fair@basic-none@rcs0.html

  * igt@gem_exec_fair@basic-none@vcs0:
    - shard-kbl:          [FAIL][78] ([i915#2842]) -> [PASS][79] +3 similar issues
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-kbl4/igt@gem_exec_fair@basic-none@vcs0.html
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl1/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_fair@basic-throttle@rcs0:
    - shard-iclb:         [FAIL][80] ([i915#2849]) -> [PASS][81]
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb5/igt@gem_exec_fair@basic-throttle@rcs0.html
   [81]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb6/igt@gem_exec_fair@basic-throttle@rcs0.html

  * igt@gem_workarounds@suspend-resume-context:
    - shard-apl:          [DMESG-WARN][82] ([i915#180]) -> [PASS][83] +1 similar issue
   [82]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl8/igt@gem_workarounds@suspend-resume-context.html
   [83]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl6/igt@gem_workarounds@suspend-resume-context.html

  * igt@kms_big_fb@linear-32bpp-rotate-0:
    - shard-glk:          [DMESG-WARN][84] ([i915#118]) -> [PASS][85]
   [84]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-glk5/igt@kms_big_fb@linear-32bpp-rotate-0.html
   [85]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-glk4/igt@kms_big_fb@linear-32bpp-rotate-0.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size:
    - shard-iclb:         [FAIL][86] ([i915#2346]) -> [PASS][87]
   [86]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb7/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html
   [87]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb3/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions-varying-size.html

  * igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling:
    - shard-iclb:         [SKIP][88] ([i915#3701]) -> [PASS][89]
   [88]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb2/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling.html
   [89]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb7/igt@kms_flip_scaled_crc@flip-64bpp-ytile-to-16bpp-ytile-downscaling.html

  * igt@kms_setmode@basic:
    - shard-apl:          [FAIL][90] ([i915#31]) -> [PASS][91]
   [90]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl1/igt@kms_setmode@basic.html
   [91]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl7/igt@kms_setmode@basic.html

  
#### Warnings ####

  * igt@i915_pm_rc6_residency@rc6-idle:
    - shard-iclb:         [WARN][92] ([i915#2684]) -> [WARN][93] ([i915#1804] / [i915#2684])
   [92]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb1/igt@i915_pm_rc6_residency@rc6-idle.html
   [93]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb3/igt@i915_pm_rc6_residency@rc6-idle.html

  * igt@kms_psr2_sf@cursor-plane-update-sf:
    - shard-iclb:         [SKIP][94] ([i915#2920]) -> [SKIP][95] ([fdo#111068] / [i915#658])
   [94]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb2/igt@kms_psr2_sf@cursor-plane-update-sf.html
   [95]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb6/igt@kms_psr2_sf@cursor-plane-update-sf.html

  * igt@kms_psr2_sf@plane-move-sf-dmg-area:
    - shard-iclb:         [SKIP][96] ([fdo#111068] / [i915#658]) -> [SKIP][97] ([i915#2920])
   [96]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb4/igt@kms_psr2_sf@plane-move-sf-dmg-area.html
   [97]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb2/igt@kms_psr2_sf@plane-move-sf-dmg-area.html

  * igt@kms_psr2_su@page_flip-p010:
    - shard-iclb:         [SKIP][98] ([fdo#111068] / [i915#658]) -> [FAIL][99] ([i915#4148])
   [98]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-iclb8/igt@kms_psr2_su@page_flip-p010.html
   [99]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-iclb2/igt@kms_psr2_su@page_flip-p010.html

  * igt@runner@aborted:
    - shard-kbl:          ([FAIL][100], [FAIL][101], [FAIL][102]) ([i915#180] / [i915#3002] / [i915#4312]) -> ([FAIL][103], [FAIL][104]) ([i915#3002] / [i915#4312])
   [100]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-kbl4/igt@runner@aborted.html
   [101]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-kbl4/igt@runner@aborted.html
   [102]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-kbl3/igt@runner@aborted.html
   [103]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl1/igt@runner@aborted.html
   [104]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-kbl7/igt@runner@aborted.html
    - shard-apl:          ([FAIL][105], [FAIL][106], [FAIL][107], [FAIL][108], [FAIL][109]) ([fdo#109271] / [i915#180] / [i915#3002] / [i915#4312]) -> ([FAIL][110], [FAIL][111], [FAIL][112], [FAIL][113], [FAIL][114], [FAIL][115], [FAIL][116], [FAIL][117], [FAIL][118]) ([fdo#109271] / [i915#180] / [i915#1814] / [i915#3002] / [i915#4312])
   [105]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl4/igt@runner@aborted.html
   [106]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl7/igt@runner@aborted.html
   [107]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl8/igt@runner@aborted.html
   [108]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl3/igt@runner@aborted.html
   [109]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_11044/shard-apl2/igt@runner@aborted.html
   [110]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl8/igt@runner@aborted.html
   [111]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl7/igt@runner@aborted.html
   [112]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl8/igt@runner@aborted.html
   [113]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl8/igt@runner@aborted.html
   [114]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl7/igt@runner@aborted.html
   [115]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl3/igt@runner@aborted.html
   [116]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl6/igt@runner@aborted.html
   [117]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl1/igt@runner@aborted.html
   [118]: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/shard-apl1/igt@runner@aborted.html

  
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109274]: https://bugs.freedesktop.org/show_bug.cgi?id=109274
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109279]: https://bugs.freedesktop.org/show_bug.cgi?id=109279
  [fdo#109280]: https://bugs.freedesktop.org/show_bug.cgi?id=109280
  [fdo#109289]: https://bugs.freedesktop.org/show_bug.cgi?id=109289
  [fdo#109291]: https://bugs.freedesktop.org/show_bug.cgi?id=109291
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#110321]: https://bugs.freedesktop.org/show_bug.cgi?id=110321
  [fdo#110336]: https://bugs.freedesktop.org/show_bug.cgi?id=110336
  [fdo#111068]: https://bugs.freedesktop.org/show_bug.cgi?id=111068
  [fdo#111615]: https://bugs.freedesktop.org/show_bug.cgi?id=111615
  [fdo#111825]: https://bugs.freedesktop.org/show_bug.cgi?id=111825
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#118]: https://gitlab.freedesktop.org/drm/intel/issues/118
  [i915#1319]: https://gitlab.freedesktop.org/drm/intel/issues/1319
  [i915#132]: https://gitlab.freedesktop.org/drm/intel/issues/132
  [i915#1542]: https://gitlab.freedesktop.org/drm/intel/issues/1542
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#1804]: https://gitlab.freedesktop.org/drm/intel/issues/1804
  [i915#1814]: https://gitlab.freedesktop.org/drm/intel/issues/1814
  [i915#1888]: https://gitlab.freedesktop.org/drm/intel/issues/1888
  [i915#2346]: https://gitlab.freedesktop.org/drm/intel/issues/2346
  [i915#2437]: https://gitlab.freedesktop.org/drm/intel/issues/2437
  [i915#2481]: https://gitlab.freedesktop.org/drm/intel/issues/2481
  [i915#2530]: https://gitlab.freedesktop.org/drm/intel/issues/2530
  [i915#2684]: https://gitlab.freedesktop.org/drm/intel/issues/2684
  [i915#2842]: https://gitlab.freedesktop.org/drm/intel/issues/2842
  [i915#2846]: https://gitlab.freedesktop.org/drm/intel/issues/2846
  [i915#2849]: https://gitlab.freedesktop.org/drm/intel/issues/2849
  [i915#2856]: https://gitlab.freedesktop.org/drm/intel/issues/2856
  [i915#2920]: https://gitlab.freedesktop.org/drm/intel/issues/2920
  [i915#295]: https://gitlab.freedesktop.org/drm/intel/issues/295
  [i915#2994]: https://gitlab.freedesktop.org/drm/intel/issues/2994
  [i915#3002]: https://gitlab.freedesktop.org/drm/intel/issues/3002
  [i915#3070]: https://gitlab.freedesktop.org/drm/intel/issues/3070
  [i915#31]: https://gitlab.freedesktop.org/drm/intel/issues/31
  [i915#3359]: https://gitlab.freedesktop.org/drm/intel/issues/3359
  [i915#3451]: https://gitlab.freedesktop.org/drm/intel/issues/3451
  [i915#3467]: https://gitlab.freedesktop.org/drm/intel/issues/3467
  [i915#3689]: https://gitlab.freedesktop.org/drm/intel/issues/3689
  [i915#3701]: https://gitlab.freedesktop.org/drm/intel/issues/3701
  [i915#3777]: https://gitlab.freedesktop.org/drm/intel/issues/3777
  [i915#3886]: https://gitlab.freedesktop.org/drm/intel/issues/3886
  [i915#4148]: https://gitlab.freedesktop.org/drm/intel/issues/4148
  [i915#4312]: https://gitlab.freedesktop.org/drm/intel/issues/4312
  [i915#4525]: https://gitlab.freedesktop.org/drm/intel/issues/4525
  [i915#454]: https://gitlab.freedesktop.org/drm/intel/issues/454
  [i915#4613]: https://gitlab.freedesktop.org/drm/intel/issues/4613
  [i915#644]: https://gitlab.freedesktop.org/drm/intel/issues/644
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#768]: https://gitlab.freedesktop.org/drm/intel/issues/768
  [i915#79]: https://gitlab.freedesktop.org/drm/intel/issues/79


Build changes
-------------

  * CI: CI-20190529 -> None
  * IGT: IGT_6322 -> IGTPW_6529
  * Piglit: piglit_4509 -> None

  CI-20190529: 20190529
  CI_DRM_11044: 7b527a181f96f90a4c2f04d2705bdaffdd8168b6 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_6529: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/index.html
  IGT_6322: b0b7679b358b300b7b6bf42c6921d0aa1fc14388 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_6529/index.html

[-- Attachment #2: Type: text/html, Size: 34278 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [igt-dev] [PATCH i-g-t 3/3] tests/fast-feedback.testlist: Add gem_softpin@safe-start subtest
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 3/3] tests/fast-feedback.testlist: Add gem_softpin@safe-start subtest Zbigniew Kempczyński
@ 2022-01-04  4:41   ` Petri Latvala
  0 siblings, 0 replies; 17+ messages in thread
From: Petri Latvala @ 2022-01-04  4:41 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev

On Thu, Dec 30, 2021 at 07:26:13PM +0100, Zbigniew Kempczyński wrote:
> This test takes up to few hundred of milliseconds and exercises
> detecting of safe starting offset and alignment to use on discrete
> where memory regions constraints could differ on different gens.
> 
> Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
> Cc: Petri Latvala <petri.latvala@intel.com>
> Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>

Acked-by: Petri Latvala <petri.latvala@intel.com>

> ---
>  tests/intel-ci/fast-feedback.testlist | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/tests/intel-ci/fast-feedback.testlist b/tests/intel-ci/fast-feedback.testlist
> index de1c6cb46..38a90ceb6 100644
> --- a/tests/intel-ci/fast-feedback.testlist
> +++ b/tests/intel-ci/fast-feedback.testlist
> @@ -45,6 +45,7 @@ igt@gem_render_tiled_blits@basic
>  igt@gem_ringfill@basic-all
>  igt@gem_softpin@allocator-basic
>  igt@gem_softpin@allocator-basic-reserve
> +igt@gem_softpin@safe-start
>  igt@gem_sync@basic-all
>  igt@gem_sync@basic-each
>  igt@gem_tiled_blits@basic
> -- 
> 2.32.0
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
@ 2022-01-05  5:00   ` Dixit, Ashutosh
  2022-01-05  6:44     ` Zbigniew Kempczyński
  0 siblings, 1 reply; 17+ messages in thread
From: Dixit, Ashutosh @ 2022-01-05  5:00 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev, Petri Latvala

On Thu, 30 Dec 2021 10:26:11 -0800, Zbigniew Kempczyński wrote:
>

I am still trying to understand this patch so just some questions/comments
for now.

I am not even looking at the caching part for now, it would have been
better to keep caching as a separate patch since that is performance
improvement but anyway leave as is. I will just review it later.

> With era of new gens we're enforced to use no-reloc (softpin). This
> brings few problems like vm range limitations which were well solved
> by the kernel. This can be handled also in userspace code by adding
> gen related conditionals or by trying to detect the constraints.

So why not just do this since the information is static and gen dependent?

Also what does this offset/alignment really depend on? Is it the minimum
page size supported by a particular gen for a region type? Or is there more
to it?

If we know the minimum page size for each region type per gen can we
compute the min/safe offset/alignemnt values below or do we still need this
dynamic detection?

Also, as far as I see, here we are calculating how generated offsets from
the allocator should be aligned. So rather than do this in the allocator
itself (i.e. introduce a 'region' argument to the allocator) we have these
functions to find the 'alignment' argument to allocator->alloc() function.

But it would be ok to do this inside the allocator itself and introduce a
region argument to the allocator, i.e. generate an offset for this region
or this set of regions? Anyway I see the allocator API at present takes the
alignment argument so it is probably ok as is too.

So at a high level do we need to add these functions here or should we add
them inside the allocator?

> +/**
> + * gem_detect_min_start_offset_for_region:
> + * @i915: drm fd
> + * @region: memory region
> + *
> + * Returns: minimum start offset at which kernel allows placing objects
> + *          for memory region.
> + */
> +uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)

Should this be static, that is should we only expose
gem_detect_safe_start_offset() to the tests? Is there any reason why any
test will call this directly?

Also I suggest:

s/detect/get/ since 'detect' is an implementation detail (and with the
cache we are not even detecting).

> +	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
> +	*batch = MI_BATCH_BUFFER_END;
> +	munmap(batch, bb_size);

I prefer gem_write() everywhere since it's a single statement but ok as is too.

> +
> +	while (1) {
> +		obj.offset = start_offset;
> +
> +		if (__gem_execbuf(i915, &eb) == 0)
> +			break;
> +
> +		if (start_offset)
> +			start_offset <<= 1;
> +		else
> +			start_offset = PAGE_SIZE;
> +
> +		igt_assert(start_offset <= 1ull << 48);

s/48/GEN8_GTT_ADDRESS_WIDTH/ or something like that?

> +/**
> + * gem_detect_safe_start_offset:
> + * @i915: drm fd
> + *
> + * Returns: finds start offset which can be used as first one regardless
> + *          memory region. Useful if for some reason some regions don't allow
> + *          starting from 0x0 offset.
> + */
> +uint64_t gem_detect_safe_start_offset(int i915)

Overall I am ok with gem_detect_safe_start_offset() and
gem_detect_min_start_offset_for_region() and understand that we need them.

> +/**
> + * gem_detect_min_alignment_for_regions:
> + * @i915: drm fd
> + * @region1: first region
> + * @region2: second region
> + *
> + * Returns: minimum alignment which must be used when objects from @region1 and
> + * @region2 are going to interact.
> + */
> +uint64_t gem_detect_min_alignment_for_regions(int i915,

Once again can this be static, that is we don't expose to the tests?

> +					      uint32_t region1,
> +					      uint32_t region2)

Also we can probably pass the list of all regions here (similar to what we
do for gem_create_in_memory_regions()) but probably ok as is too the way
it's done in gem_detect_safe_alignment().

> +	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
> +
> +	/* Find appropriate alignment of object */
> +	eb.buffer_count = ARRAY_SIZE(obj);
> +	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle,
> +						  &obj_size, region2) == 0);
> +	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region2);
> +	obj[1].flags = EXEC_OBJECT_PINNED;
> +	while (1) {
> +		obj[1].offset = ALIGN(obj[0].offset + bb_size, min_alignment);
> +		igt_assert(obj[1].offset <= 1ull << 32);
> +
> +		if (__gem_execbuf(i915, &eb) == 0)
> +			break;
> +
> +		min_alignment <<= 1;
> +	}

With this loop above I get very lost and don't clearly understand the
reason for it (taking the regions pairwise). Why do we need to do it this
way? Why is the value returned by gem_detect_safe_start_offset() (that is
the max offset over all regions) or even
gem_detect_min_start_offset_for_region() sufficient? Is this algorithm
above always guaranteed to return a value which will work?

Also, do we even need to expose gem_detect_safe_start_offset() to the tests
or all the tests will ever need to call is gem_detect_safe_alignment() so
everything else can be static?

> +/**
> + * gem_get_safe_alignment:

Comment mismatches function name below.

> + * @i915: drm fd
> + *
> + * Returns: safe alignment for all memory regions on @i915 device.
> + * Safe in this case means max() from all minimum alignment for each
> + * region.
> + */
> +uint64_t gem_detect_safe_alignment(int i915)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2022-01-05  5:00   ` Dixit, Ashutosh
@ 2022-01-05  6:44     ` Zbigniew Kempczyński
  0 siblings, 0 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2022-01-05  6:44 UTC (permalink / raw)
  To: Dixit, Ashutosh; +Cc: igt-dev, Petri Latvala

On Tue, Jan 04, 2022 at 09:00:50PM -0800, Dixit, Ashutosh wrote:
> On Thu, 30 Dec 2021 10:26:11 -0800, Zbigniew Kempczyński wrote:
> >
> 
> I am still trying to understand this patch so just some questions/comments
> for now.
> 
> I am not even looking at the caching part for now, it would have been
> better to keep caching as a separate patch since that is performance
> improvement but anyway leave as is. I will just review it later.
> 
> > With era of new gens we're enforced to use no-reloc (softpin). This
> > brings few problems like vm range limitations which were well solved
> > by the kernel. This can be handled also in userspace code by adding
> > gen related conditionals or by trying to detect the constraints.
> 
> So why not just do this since the information is static and gen dependent?

It may differ across gens/revisions regarding starting offset and alignment
between regions so I would like to detect is kernel supporting 64K or 2M or not.
Assuming it is constant from userspace is wrong - that's why detection code
here. Previously such adjustments were done in relocations, but we got single
system memory and world was a little bit simpler than now.

> 
> Also what does this offset/alignment really depend on? Is it the minimum
> page size supported by a particular gen for a region type? Or is there more
> to it?

No, on possible regions mixing within gtt as well as supporting grouping 
to 64K or 2M to decrease TLB eviction.

> 
> If we know the minimum page size for each region type per gen can we
> compute the min/safe offset/alignemnt values below or do we still need this
> dynamic detection?

See above, on ATS I'm not sure but starting offset can be 0x200000.

> 
> Also, as far as I see, here we are calculating how generated offsets from
> the allocator should be aligned. So rather than do this in the allocator
> itself (i.e. introduce a 'region' argument to the allocator) we have these
> functions to find the 'alignment' argument to allocator->alloc() function.

Objects within same region can be aligned to smaller alignment than max
of all regions. I would keep regioning away of allocator - it should just
do what you request of and nothing more.

On the very beginning Chris wanted to have "zones" within allocator but
I haven't decided to add this - adding allocator + fixing all tests were
time consuming and I skipped this request. Even now with single zone allocator
makes tests less readable. Introducing zones would introduce another layer
which at the moment we don't need to.

> 
> But it would be ok to do this inside the allocator itself and introduce a
> region argument to the allocator, i.e. generate an offset for this region
> or this set of regions? Anyway I see the allocator API at present takes the
> alignment argument so it is probably ok as is too.
> 
> So at a high level do we need to add these functions here or should we add
> them inside the allocator?

No, we should feed allocator with alignment we want. If you want to mix 
smem and lmem and you don't want to care of alignment between regions just
take "safe alignment". If you want to verify smem objects adhere with minimum
possible alignment use alignment for smem objects, same for lmem.

> 
> > +/**
> > + * gem_detect_min_start_offset_for_region:
> > + * @i915: drm fd
> > + * @region: memory region
> > + *
> > + * Returns: minimum start offset at which kernel allows placing objects
> > + *          for memory region.
> > + */
> > +uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
> 
> Should this be static, that is should we only expose
> gem_detect_safe_start_offset() to the tests? Is there any reason why any
> test will call this directly?

I think this should be exported if requester want to put object at minimum
possible offset for region. You don't need to use allocator if you have 
one or two objects and you're able to assign those offsets manually.
For PPGTT this is correct attitude and there're some tests which are 
already written this way.

> 
> Also I suggest:
> 
> s/detect/get/ since 'detect' is an implementation detail (and with the
> cache we are not even detecting).

I've discussed this and "detect" is correct word in this case. Get would be 
appropriate if we would be able to have static mapping.

> 
> > +	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
> > +	*batch = MI_BATCH_BUFFER_END;
> > +	munmap(batch, bb_size);
> 
> I prefer gem_write() everywhere since it's a single statement but ok as is too.
> 
> > +
> > +	while (1) {
> > +		obj.offset = start_offset;
> > +
> > +		if (__gem_execbuf(i915, &eb) == 0)
> > +			break;
> > +
> > +		if (start_offset)
> > +			start_offset <<= 1;
> > +		else
> > +			start_offset = PAGE_SIZE;
> > +
> > +		igt_assert(start_offset <= 1ull << 48);
> 
> s/48/GEN8_GTT_ADDRESS_WIDTH/ or something like that?

That value really doesn't matter if is big enough. If we're not be able to
place object up to 48bit I guess such HW won't work at all.

> 
> > +/**
> > + * gem_detect_safe_start_offset:
> > + * @i915: drm fd
> > + *
> > + * Returns: finds start offset which can be used as first one regardless
> > + *          memory region. Useful if for some reason some regions don't allow
> > + *          starting from 0x0 offset.
> > + */
> > +uint64_t gem_detect_safe_start_offset(int i915)
> 
> Overall I am ok with gem_detect_safe_start_offset() and
> gem_detect_min_start_offset_for_region() and understand that we need them.
> 
> > +/**
> > + * gem_detect_min_alignment_for_regions:
> > + * @i915: drm fd
> > + * @region1: first region
> > + * @region2: second region
> > + *
> > + * Returns: minimum alignment which must be used when objects from @region1 and
> > + * @region2 are going to interact.
> > + */
> > +uint64_t gem_detect_min_alignment_for_regions(int i915,
> 
> Once again can this be static, that is we don't expose to the tests?

Currently probably noone will use it, but discrete are on the way so some 
tests maybe will need it.

> 
> > +					      uint32_t region1,
> > +					      uint32_t region2)
> 
> Also we can probably pass the list of all regions here (similar to what we
> do for gem_create_in_memory_regions()) but probably ok as is too the way
> it's done in gem_detect_safe_alignment().

I decided to export this if test writer want to exercise exact interaction
between this two regions. I would extend this to region array if it will be
really needed. 

> 
> > +	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
> > +
> > +	/* Find appropriate alignment of object */
> > +	eb.buffer_count = ARRAY_SIZE(obj);
> > +	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle,
> > +						  &obj_size, region2) == 0);
> > +	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region2);
> > +	obj[1].flags = EXEC_OBJECT_PINNED;
> > +	while (1) {
> > +		obj[1].offset = ALIGN(obj[0].offset + bb_size, min_alignment);
> > +		igt_assert(obj[1].offset <= 1ull << 32);
> > +
> > +		if (__gem_execbuf(i915, &eb) == 0)
> > +			break;
> > +
> > +		min_alignment <<= 1;
> > +	}
> 
> With this loop above I get very lost and don't clearly understand the
> reason for it (taking the regions pairwise). Why do we need to do it this
> way? Why is the value returned by gem_detect_safe_start_offset() (that is
> the max offset over all regions) or even
> gem_detect_min_start_offset_for_region() sufficient? Is this algorithm
> above always guaranteed to return a value which will work?

If you're able to properly place two objects and kernel doesn't complain 
(-ENOSPC) yes, this guarantees you got alignment which you can use for 
both regions.

Loop exercises this with left shifting the alignment until it will hit
valid offset at which second (obj[1]) object can interact with first one.

> 
> Also, do we even need to expose gem_detect_safe_start_offset() to the tests
> or all the tests will ever need to call is gem_detect_safe_alignment() so
> everything else can be static?

Yes, think about ATS and first 2M which is not accessible if I good remember
(maybe something changed, but this limitation comes to my mind when I started
writing this patch).

> 
> > +/**
> > + * gem_get_safe_alignment:
> 
> Comment mismatches function name below.

Good catch, I thought I've fixed all issues before.

Thank you for the review.

--
Zbigniew

> 
> > + * @i915: drm fd
> > + *
> > + * Returns: safe alignment for all memory regions on @i915 device.
> > + * Safe in this case means max() from all minimum alignment for each
> > + * region.
> > + */
> > +uint64_t gem_detect_safe_alignment(int i915)

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2022-01-06 10:00 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
@ 2022-01-06 10:00 ` Zbigniew Kempczyński
  0 siblings, 0 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2022-01-06 10:00 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

With era of new gens we're enforced to use no-reloc (softpin). This
brings few problems like vm range limitations which were well solved
by the kernel. This can be handled also in userspace code by adding
gen related conditionals or by trying to detect the constraints.

Lets try to do this dynamically and detect safe start offset and
alignment for each memory region we got. This should be universal solution
regardless hw limitations and bugs. As such detection is not lightweight
technique add also some caching structures to handle consequtive calls
about same data.

v2: unify cache
v3: move allocation of cache entry out of mutex
v4: remove assert on allocation newentry, just skip adding to cache
v5: fix function documentation (Ashutosh)
v6: remove unnecessary buffers count initialization (Ashutosh)
    add 48b flag for pinning object

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 lib/i915/intel_memory_region.c | 373 +++++++++++++++++++++++++++++++++
 lib/i915/intel_memory_region.h |   5 +
 2 files changed, 378 insertions(+)

diff --git a/lib/i915/intel_memory_region.c b/lib/i915/intel_memory_region.c
index dfbb8acf0..a8759e069 100644
--- a/lib/i915/intel_memory_region.c
+++ b/lib/i915/intel_memory_region.c
@@ -28,11 +28,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <pthread.h>
 
 #include "i915/gem_create.h"
 #include "intel_reg.h"
 #include "drmtest.h"
 #include "ioctl_wrappers.h"
+#include "igt_aux.h"
 #include "igt_dummyload.h"
 #include "igt_gt.h"
 #include "igt_params.h"
@@ -40,6 +42,7 @@
 #include "intel_chipset.h"
 #include "igt_collection.h"
 #include "igt_device.h"
+#include "gem_mman.h"
 
 #include "i915/intel_memory_region.h"
 
@@ -480,3 +483,373 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 
 	return 0;
 }
+
+#define PAGE_SIZE 4096
+
+enum cache_entry_type {
+	MIN_START_OFFSET,
+	MIN_ALIGNMENT,
+	SAFE_START_OFFSET,
+	SAFE_ALIGNMENT,
+};
+
+struct cache_entry {
+	uint16_t devid;
+	enum cache_entry_type type;
+
+	union {
+		/* for MIN_START_OFFSET */
+		struct {
+			uint64_t offset;
+			uint32_t region;
+		} start;
+
+		/* for MIN_ALIGNMENT */
+		struct {
+			uint64_t alignment;
+			uint64_t region1;
+			uint64_t region2;
+		} minalign;
+
+		/* for SAFE_START_OFFSET */
+		uint64_t safe_start_offset;
+
+		/* for SAFE_ALIGNMENT */
+		uint64_t safe_alignment;
+	};
+	struct igt_list_head link;
+};
+
+static IGT_LIST_HEAD(cache);
+static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static struct cache_entry *find_entry_unlocked(enum cache_entry_type type,
+					       uint16_t devid,
+					       uint32_t region1,
+					       uint32_t region2)
+{
+	struct cache_entry *entry;
+
+	igt_list_for_each_entry(entry, &cache, link) {
+		if (entry->type != type || entry->devid != devid)
+			continue;
+
+		switch (entry->type) {
+		case MIN_START_OFFSET:
+			if (entry->start.region == region1)
+				return entry;
+			continue;
+
+		case MIN_ALIGNMENT:
+			if (entry->minalign.region1 == region1 &&
+			    entry->minalign.region2 == region2)
+				return entry;
+			continue;
+
+		case SAFE_START_OFFSET:
+		case SAFE_ALIGNMENT:
+			return entry;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * gem_detect_min_start_offset_for_region:
+ * @i915: drm fd
+ * @region: memory region
+ *
+ * Returns: minimum start offset at which kernel allows placing objects
+ *          for memory region.
+ */
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
+{
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t start_offset = 0;
+	uint64_t bb_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(&obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	eb.buffers_ptr = to_user_pointer(&obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj.handle, &bb_size, region) == 0);
+	obj.flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	while (1) {
+		obj.offset = start_offset;
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		if (start_offset)
+			start_offset <<= 1;
+		else
+			start_offset = PAGE_SIZE;
+
+		if (start_offset >= 1ull << 32)
+			obj.flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
+
+		igt_assert(start_offset <= 1ull << 48);
+	}
+	gem_close(i915, obj.handle);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return start_offset;
+
+	/* Check does other thread did the job before */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_START_OFFSET;
+	entry->start.offset = start_offset;
+	entry->start.region = region;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->start.offset;
+}
+
+/**
+ * gem_detect_safe_start_offset:
+ * @i915: drm fd
+ *
+ * Returns: finds start offset which can be used as first one regardless
+ *          memory region. Useful if for some reason some regions don't allow
+ *          starting from 0x0 offset.
+ */
+uint64_t gem_detect_safe_start_offset(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint32_t region;
+	uint64_t offset = 0;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_combination(regions, 1, set) {
+		region = igt_collection_get_value(regions, 0);
+		offset = max(offset,
+			     gem_detect_min_start_offset_for_region(i915, region));
+	}
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return offset;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_START_OFFSET;
+	entry->safe_start_offset = offset;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->safe_start_offset;
+}
+
+/**
+ * gem_detect_min_alignment_for_regions:
+ * @i915: drm fd
+ * @region1: first region
+ * @region2: second region
+ *
+ * Returns: minimum alignment which must be used when objects from @region1 and
+ * @region2 are going to interact.
+ */
+uint64_t gem_detect_min_alignment_for_regions(int i915,
+					      uint32_t region1,
+					      uint32_t region2)
+{
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t min_alignment = PAGE_SIZE;
+	uint64_t bb_size = PAGE_SIZE, obj_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	/* Establish bb offset first */
+	eb.buffers_ptr = to_user_pointer(obj);
+	eb.buffer_count = ARRAY_SIZE(obj);
+	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle,
+						  &bb_size, region1) == 0);
+
+	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size,
+					  PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	obj[0].flags = EXEC_OBJECT_PINNED;
+	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
+
+	/* Find appropriate alignment of object */
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle,
+						  &obj_size, region2) == 0);
+	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region2);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	while (1) {
+		obj[1].offset = ALIGN(obj[0].offset + bb_size, min_alignment);
+		igt_assert(obj[1].offset <= 1ull << 32);
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		min_alignment <<= 1;
+	}
+
+	gem_close(i915, obj[0].handle);
+	gem_close(i915, obj[1].handle);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return min_alignment;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_ALIGNMENT;
+	entry->minalign.alignment = min_alignment;
+	entry->minalign.region1 = region1;
+	entry->minalign.region2 = region2;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
+
+/**
+ * gem_detect_safe_alignment:
+ * @i915: drm fd
+ *
+ * Returns: safe alignment for all memory regions on @i915 device.
+ * Safe in this case means max() from all minimum alignments for each
+ * region.
+ */
+uint64_t gem_detect_safe_alignment(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint64_t default_alignment = 0;
+	uint32_t region_bb, region_obj;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	/* non-discrete uses 4K page size */
+	if (!gem_has_lmem(i915))
+		return PAGE_SIZE;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_variation_r(regions, 2, set) {
+		uint64_t alignment;
+
+		region_bb = igt_collection_get_value(regions, 0);
+		region_obj = igt_collection_get_value(regions, 1);
+
+		/* We're interested in triangular matrix */
+		if (region_bb > region_obj)
+			continue;
+
+		alignment = gem_detect_min_alignment_for_regions(i915,
+								 region_bb,
+								 region_obj);
+		if (default_alignment < alignment)
+			default_alignment = alignment;
+	}
+
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return default_alignment;
+
+	/* Try again, check does we have cache updated in the meantime. */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid,  0, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_ALIGNMENT;
+	entry->safe_alignment = default_alignment;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
diff --git a/lib/i915/intel_memory_region.h b/lib/i915/intel_memory_region.h
index 8b427b7e7..936e7d1c8 100644
--- a/lib/i915/intel_memory_region.h
+++ b/lib/i915/intel_memory_region.h
@@ -129,4 +129,9 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 				      uint16_t memory_class,
 				      uint16_t memory_instance);
 
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region);
+uint64_t gem_detect_safe_start_offset(int i915);
+uint64_t gem_detect_min_alignment_for_regions(int i915, uint32_t region1, uint32_t region2);
+uint64_t gem_detect_safe_alignment(int i915);
+
 #endif /* INTEL_MEMORY_REGION_H */
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2022-01-06  2:23   ` Dixit, Ashutosh
@ 2022-01-06  9:45     ` Zbigniew Kempczyński
  0 siblings, 0 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2022-01-06  9:45 UTC (permalink / raw)
  To: Dixit, Ashutosh; +Cc: igt-dev, Petri Latvala

On Wed, Jan 05, 2022 at 06:23:21PM -0800, Dixit, Ashutosh wrote:
> On Tue, 04 Jan 2022 22:49:43 -0800, Zbigniew Kempczyński wrote:
> >
> > With era of new gens we're enforced to use no-reloc (softpin). This
> > brings few problems like vm range limitations which were well solved
> > by the kernel. This can be handled also in userspace code by adding
> > gen related conditionals or by trying to detect the constraints.
> >
> > Lets try to do this dynamically and detect safe start offset and
> > alignment for each memory region we got. This should be universal solution
> > regardless hw limitations and bugs. As such detection is not lightweight
> > technique add also some caching structures to handle consequtive calls
> > about same data.
> 
> I have a few more comments and suggestions below. However, since these are
> non-blocking this patch is:
> 
> Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>

Thanks for the review.

> 
> > +static IGT_LIST_HEAD(cache);
> > +static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
> 
> The caching will help for multiple calls to the code within a single
> process, but in CI each process will still need to build up the cache.

Each code which will be called during single execution will need to build
the cache. That's the cost of softpinning and differences in hw / i915 paths.
Some panacea would be to expose some queries from i915 but this adds new uAPI
and requires to be handled forever. Detection generates few extra calls on the
very beginning where only one bb really touches hardware.

> 
> > +uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
> > +{
> > +	struct drm_i915_gem_exec_object2 obj;
> > +	struct drm_i915_gem_execbuffer2 eb;
> > +	uint64_t start_offset = 0;
> > +	uint64_t bb_size = PAGE_SIZE;
> > +	uint32_t *batch;
> > +	uint16_t devid = intel_get_drm_devid(i915);
> > +	struct cache_entry *entry, *newentry;
> > +
> > +	pthread_mutex_lock(&cache_mutex);
> > +	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
> > +	if (entry)
> > +		goto out;
> > +	pthread_mutex_unlock(&cache_mutex);
> 
> I think it would be better to add the locking to find_entry_unlocked(). And
> also add a list_add_entry() kind of function with the locking. This will
> associate the mutex directly with the list and get it out of the
> callers. The check if the entry has been previously added would also need
> to move to list_add_entry().
> 
> Anyway if this is complicated leave as is.

find_entry_unlocked() is used also in adding to cache path, where you need to
do following ops within single mutex locked:

1. mutex_lock()
2. find_entry_unlocked()
3. if found skip adding to cache (goto out)
4. add_to_cache_unlocked()
5. mutex_unlock()

That's why I couldn't add find()/add() functions to lock mutex themselves
because if I would drop mutex after find noone prevents for adding same
entry to cache twice (or more if there will be more threads).
 
> 
> > +	newentry = malloc(sizeof(*newentry));
> > +	if (!newentry)
> > +		return start_offset;
> 
> I'd suggest just do 'igt_assert(newentry)' in all these functions to keep
> things simple.

Primary code has assert here, but we don't need it. At least we won't 
expose memory problem here. I got heavy discussion about this on irc 
and I was convinced that if we got value already established we can
return it (in hope some memory can be reclaimed in the meantime).

> 
> > +/**
> > + * gem_detect_min_alignment_for_regions:
> > + * @i915: drm fd
> > + * @region1: first region
> > + * @region2: second region
> > + *
> > + * Returns: minimum alignment which must be used when objects from @region1 and
> > + * @region2 are going to interact.
> 
> Here actually it is not obvious why the code below in this function is
> needed. Page sizes for different memory regions can be different. From
> discussions with people here, it seems what happens is that different page
> sizes cannot be included as part of the same page table structure level (in
> the multi-level page table structure hierarchy). That is why offsets for
> memory regions with different page sizes cannot be adjacent.
> 
> Can we add some explanation of this sort here as a hint as to why the code
> below is needed?

I haven't found better idea how to properly align objects from different 
regions than use some detection on the very beginning. If you have better
idea how to solve this I won't insist to merge my code. 

> 
> There is still the question in my mind whether the situation is "dynamic"
> when a memory region has multiple page sizes, say 64 K and 2 MiB. In this
> case when we run the detection we get one safe alignemnt value which is
> cached, but "later" because of memory use, this cached value proves
> insufficient (so when we detect say we get 64 K but actually later the 2
> MiB value is needed). This could happen because of different code paths
> taken in the kernel.

If kernel will change alignment during runtime detection and caching is wrong
and almost all of that code should looks:

uint64_t gem_get_safe_alignment() {
	return SIZE_2M; /* or SIZE_1G */
}

Only start offset should be still detected as we've no idea what is first
offset we can use. I wondered to add same for end offset but it can be
tricky as if I good remember last page can be problematic but it is not
easily detectable and can depend on engine (likely there're problems on
rcs0 if my memory is not failing too much).

> 
> Any case, I think what we have is good enough for now and worth
> trying. Let's see if we hit this issue later.
> 
> > +	/* Establish bb offset first */
> > +	eb.buffers_ptr = to_user_pointer(obj);
> > +	eb.buffer_count = 1;
> 
> Looks like this line is not needed, eb.buffer_count is set again below.

Good catch. This is remnant where I've detected min start offset here.

If you think there's better way how to solve problems regarding alignment
/ start offset please propose. I focused on detecton but maybe there's 
different technique we can use for those problems.

Thank you for the comments and debug session :)
--
Zbigniew


> 
> > +	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
> > +	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle,
> > +						  &bb_size, region1) == 0);
> > +	obj[0].flags = EXEC_OBJECT_PINNED;
> > +
> > +	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size,
> > +					  PROT_WRITE);
> > +	*batch = MI_BATCH_BUFFER_END;
> > +	munmap(batch, bb_size);
> > +
> > +	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
> > +
> > +	/* Find appropriate alignment of object */
> > +	eb.buffer_count = ARRAY_SIZE(obj);

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2022-01-05  6:49 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
@ 2022-01-06  2:23   ` Dixit, Ashutosh
  2022-01-06  9:45     ` Zbigniew Kempczyński
  0 siblings, 1 reply; 17+ messages in thread
From: Dixit, Ashutosh @ 2022-01-06  2:23 UTC (permalink / raw)
  To: Zbigniew Kempczyński; +Cc: igt-dev, Petri Latvala

On Tue, 04 Jan 2022 22:49:43 -0800, Zbigniew Kempczyński wrote:
>
> With era of new gens we're enforced to use no-reloc (softpin). This
> brings few problems like vm range limitations which were well solved
> by the kernel. This can be handled also in userspace code by adding
> gen related conditionals or by trying to detect the constraints.
>
> Lets try to do this dynamically and detect safe start offset and
> alignment for each memory region we got. This should be universal solution
> regardless hw limitations and bugs. As such detection is not lightweight
> technique add also some caching structures to handle consequtive calls
> about same data.

I have a few more comments and suggestions below. However, since these are
non-blocking this patch is:

Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>

> +static IGT_LIST_HEAD(cache);
> +static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;

The caching will help for multiple calls to the code within a single
process, but in CI each process will still need to build up the cache.

> +uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
> +{
> +	struct drm_i915_gem_exec_object2 obj;
> +	struct drm_i915_gem_execbuffer2 eb;
> +	uint64_t start_offset = 0;
> +	uint64_t bb_size = PAGE_SIZE;
> +	uint32_t *batch;
> +	uint16_t devid = intel_get_drm_devid(i915);
> +	struct cache_entry *entry, *newentry;
> +
> +	pthread_mutex_lock(&cache_mutex);
> +	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
> +	if (entry)
> +		goto out;
> +	pthread_mutex_unlock(&cache_mutex);

I think it would be better to add the locking to find_entry_unlocked(). And
also add a list_add_entry() kind of function with the locking. This will
associate the mutex directly with the list and get it out of the
callers. The check if the entry has been previously added would also need
to move to list_add_entry().

Anyway if this is complicated leave as is.

> +	newentry = malloc(sizeof(*newentry));
> +	if (!newentry)
> +		return start_offset;

I'd suggest just do 'igt_assert(newentry)' in all these functions to keep
things simple.

> +/**
> + * gem_detect_min_alignment_for_regions:
> + * @i915: drm fd
> + * @region1: first region
> + * @region2: second region
> + *
> + * Returns: minimum alignment which must be used when objects from @region1 and
> + * @region2 are going to interact.

Here actually it is not obvious why the code below in this function is
needed. Page sizes for different memory regions can be different. From
discussions with people here, it seems what happens is that different page
sizes cannot be included as part of the same page table structure level (in
the multi-level page table structure hierarchy). That is why offsets for
memory regions with different page sizes cannot be adjacent.

Can we add some explanation of this sort here as a hint as to why the code
below is needed?

There is still the question in my mind whether the situation is "dynamic"
when a memory region has multiple page sizes, say 64 K and 2 MiB. In this
case when we run the detection we get one safe alignemnt value which is
cached, but "later" because of memory use, this cached value proves
insufficient (so when we detect say we get 64 K but actually later the 2
MiB value is needed). This could happen because of different code paths
taken in the kernel.

Any case, I think what we have is good enough for now and worth
trying. Let's see if we hit this issue later.

> +	/* Establish bb offset first */
> +	eb.buffers_ptr = to_user_pointer(obj);
> +	eb.buffer_count = 1;

Looks like this line is not needed, eb.buffer_count is set again below.

> +	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
> +	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle,
> +						  &bb_size, region1) == 0);
> +	obj[0].flags = EXEC_OBJECT_PINNED;
> +
> +	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size,
> +					  PROT_WRITE);
> +	*batch = MI_BATCH_BUFFER_END;
> +	munmap(batch, bb_size);
> +
> +	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
> +
> +	/* Find appropriate alignment of object */
> +	eb.buffer_count = ARRAY_SIZE(obj);

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2022-01-05  6:49 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
@ 2022-01-05  6:49 ` Zbigniew Kempczyński
  2022-01-06  2:23   ` Dixit, Ashutosh
  0 siblings, 1 reply; 17+ messages in thread
From: Zbigniew Kempczyński @ 2022-01-05  6:49 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

With era of new gens we're enforced to use no-reloc (softpin). This
brings few problems like vm range limitations which were well solved
by the kernel. This can be handled also in userspace code by adding
gen related conditionals or by trying to detect the constraints.

Lets try to do this dynamically and detect safe start offset and
alignment for each memory region we got. This should be universal solution
regardless hw limitations and bugs. As such detection is not lightweight
technique add also some caching structures to handle consequtive calls
about same data.

v2: unify cache
v3: move allocation of cache entry out of mutex
v4: remove assert on allocation newentry, just skip adding to cache
v5: fix function documentation (Ashutosh)

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 lib/i915/intel_memory_region.c | 371 +++++++++++++++++++++++++++++++++
 lib/i915/intel_memory_region.h |   5 +
 2 files changed, 376 insertions(+)

diff --git a/lib/i915/intel_memory_region.c b/lib/i915/intel_memory_region.c
index dfbb8acf0..c54dc03b1 100644
--- a/lib/i915/intel_memory_region.c
+++ b/lib/i915/intel_memory_region.c
@@ -28,11 +28,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <pthread.h>
 
 #include "i915/gem_create.h"
 #include "intel_reg.h"
 #include "drmtest.h"
 #include "ioctl_wrappers.h"
+#include "igt_aux.h"
 #include "igt_dummyload.h"
 #include "igt_gt.h"
 #include "igt_params.h"
@@ -40,6 +42,7 @@
 #include "intel_chipset.h"
 #include "igt_collection.h"
 #include "igt_device.h"
+#include "gem_mman.h"
 
 #include "i915/intel_memory_region.h"
 
@@ -480,3 +483,371 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 
 	return 0;
 }
+
+#define PAGE_SIZE 4096
+
+enum cache_entry_type {
+	MIN_START_OFFSET,
+	MIN_ALIGNMENT,
+	SAFE_START_OFFSET,
+	SAFE_ALIGNMENT,
+};
+
+struct cache_entry {
+	uint16_t devid;
+	enum cache_entry_type type;
+
+	union {
+		/* for MIN_START_OFFSET */
+		struct {
+			uint64_t offset;
+			uint32_t region;
+		} start;
+
+		/* for MIN_ALIGNMENT */
+		struct {
+			uint64_t alignment;
+			uint64_t region1;
+			uint64_t region2;
+		} minalign;
+
+		/* for SAFE_START_OFFSET */
+		uint64_t safe_start_offset;
+
+		/* for SAFE_ALIGNMENT */
+		uint64_t safe_alignment;
+	};
+	struct igt_list_head link;
+};
+
+static IGT_LIST_HEAD(cache);
+static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static struct cache_entry *find_entry_unlocked(enum cache_entry_type type,
+					       uint16_t devid,
+					       uint32_t region1,
+					       uint32_t region2)
+{
+	struct cache_entry *entry;
+
+	igt_list_for_each_entry(entry, &cache, link) {
+		if (entry->type != type || entry->devid != devid)
+			continue;
+
+		switch (entry->type) {
+		case MIN_START_OFFSET:
+			if (entry->start.region == region1)
+				return entry;
+			continue;
+
+		case MIN_ALIGNMENT:
+			if (entry->minalign.region1 == region1 &&
+			    entry->minalign.region2 == region2)
+				return entry;
+			continue;
+
+		case SAFE_START_OFFSET:
+		case SAFE_ALIGNMENT:
+			return entry;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * gem_detect_min_start_offset_for_region:
+ * @i915: drm fd
+ * @region: memory region
+ *
+ * Returns: minimum start offset at which kernel allows placing objects
+ *          for memory region.
+ */
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
+{
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t start_offset = 0;
+	uint64_t bb_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(&obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	eb.buffers_ptr = to_user_pointer(&obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj.handle, &bb_size, region) == 0);
+	obj.flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	while (1) {
+		obj.offset = start_offset;
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		if (start_offset)
+			start_offset <<= 1;
+		else
+			start_offset = PAGE_SIZE;
+
+		igt_assert(start_offset <= 1ull << 48);
+	}
+	gem_close(i915, obj.handle);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return start_offset;
+
+	/* Check does other thread did the job before */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_START_OFFSET;
+	entry->start.offset = start_offset;
+	entry->start.region = region;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->start.offset;
+}
+
+/**
+ * gem_detect_safe_start_offset:
+ * @i915: drm fd
+ *
+ * Returns: finds start offset which can be used as first one regardless
+ *          memory region. Useful if for some reason some regions don't allow
+ *          starting from 0x0 offset.
+ */
+uint64_t gem_detect_safe_start_offset(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint32_t region;
+	uint64_t offset = 0;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_combination(regions, 1, set) {
+		region = igt_collection_get_value(regions, 0);
+		offset = max(offset,
+			     gem_detect_min_start_offset_for_region(i915, region));
+	}
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return offset;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_START_OFFSET;
+	entry->safe_start_offset = offset;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->safe_start_offset;
+}
+
+/**
+ * gem_detect_min_alignment_for_regions:
+ * @i915: drm fd
+ * @region1: first region
+ * @region2: second region
+ *
+ * Returns: minimum alignment which must be used when objects from @region1 and
+ * @region2 are going to interact.
+ */
+uint64_t gem_detect_min_alignment_for_regions(int i915,
+					      uint32_t region1,
+					      uint32_t region2)
+{
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t min_alignment = PAGE_SIZE;
+	uint64_t bb_size = PAGE_SIZE, obj_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	/* Establish bb offset first */
+	eb.buffers_ptr = to_user_pointer(obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle,
+						  &bb_size, region1) == 0);
+	obj[0].flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size,
+					  PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
+
+	/* Find appropriate alignment of object */
+	eb.buffer_count = ARRAY_SIZE(obj);
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle,
+						  &obj_size, region2) == 0);
+	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region2);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	while (1) {
+		obj[1].offset = ALIGN(obj[0].offset + bb_size, min_alignment);
+		igt_assert(obj[1].offset <= 1ull << 32);
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		min_alignment <<= 1;
+	}
+
+	gem_close(i915, obj[0].handle);
+	gem_close(i915, obj[1].handle);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return min_alignment;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_ALIGNMENT;
+	entry->minalign.alignment = min_alignment;
+	entry->minalign.region1 = region1;
+	entry->minalign.region2 = region2;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
+
+/**
+ * gem_detect_safe_alignment:
+ * @i915: drm fd
+ *
+ * Returns: safe alignment for all memory regions on @i915 device.
+ * Safe in this case means max() from all minimum alignments for each
+ * region.
+ */
+uint64_t gem_detect_safe_alignment(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint64_t default_alignment = 0;
+	uint32_t region_bb, region_obj;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	/* non-discrete uses 4K page size */
+	if (!gem_has_lmem(i915))
+		return PAGE_SIZE;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_variation_r(regions, 2, set) {
+		uint64_t alignment;
+
+		region_bb = igt_collection_get_value(regions, 0);
+		region_obj = igt_collection_get_value(regions, 1);
+
+		/* We're interested in triangular matrix */
+		if (region_bb > region_obj)
+			continue;
+
+		alignment = gem_detect_min_alignment_for_regions(i915,
+								 region_bb,
+								 region_obj);
+		if (default_alignment < alignment)
+			default_alignment = alignment;
+	}
+
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	if (!newentry)
+		return default_alignment;
+
+	/* Try again, check does we have cache updated in the meantime. */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid,  0, 0);
+	if (entry)
+		goto out;
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_ALIGNMENT;
+	entry->safe_alignment = default_alignment;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
diff --git a/lib/i915/intel_memory_region.h b/lib/i915/intel_memory_region.h
index 8b427b7e7..936e7d1c8 100644
--- a/lib/i915/intel_memory_region.h
+++ b/lib/i915/intel_memory_region.h
@@ -129,4 +129,9 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 				      uint16_t memory_class,
 				      uint16_t memory_instance);
 
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region);
+uint64_t gem_detect_safe_start_offset(int i915);
+uint64_t gem_detect_min_alignment_for_regions(int i915, uint32_t region1, uint32_t region2);
+uint64_t gem_detect_safe_alignment(int i915);
+
 #endif /* INTEL_MEMORY_REGION_H */
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2021-12-30  8:14 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
@ 2021-12-30  8:14 ` Zbigniew Kempczyński
  0 siblings, 0 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2021-12-30  8:14 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

With era of new gens we're enforced to use no-reloc (softpin). This
brings few problems like vm range limitations which were well solved
by the kernel. This can be handled also in userspace code by adding
gen related conditionals or by trying to detect the constraints.

Lets try to do this dynamically and detect safe start offset and
alignment for each memory region we got. This should be universal solution
regardless hw limitations and bugs. As such detection is not lightweight
technique add also some caching structures to handle consequtive calls
about same data.

v2: unify cache
v3: move allocation of cache entry out of mutex

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 lib/i915/intel_memory_region.c | 375 +++++++++++++++++++++++++++++++++
 lib/i915/intel_memory_region.h |   5 +
 2 files changed, 380 insertions(+)

diff --git a/lib/i915/intel_memory_region.c b/lib/i915/intel_memory_region.c
index dfbb8acf0..60121a603 100644
--- a/lib/i915/intel_memory_region.c
+++ b/lib/i915/intel_memory_region.c
@@ -28,11 +28,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <pthread.h>
 
 #include "i915/gem_create.h"
 #include "intel_reg.h"
 #include "drmtest.h"
 #include "ioctl_wrappers.h"
+#include "igt_aux.h"
 #include "igt_dummyload.h"
 #include "igt_gt.h"
 #include "igt_params.h"
@@ -40,6 +42,7 @@
 #include "intel_chipset.h"
 #include "igt_collection.h"
 #include "igt_device.h"
+#include "gem_mman.h"
 
 #include "i915/intel_memory_region.h"
 
@@ -480,3 +483,375 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 
 	return 0;
 }
+
+#define PAGE_SIZE 4096
+
+enum cache_entry_type {
+	MIN_START_OFFSET,
+	MIN_ALIGNMENT,
+	SAFE_START_OFFSET,
+	SAFE_ALIGNMENT,
+};
+
+struct cache_entry {
+	uint16_t devid;
+	enum cache_entry_type type;
+
+	union {
+		/* for MIN_START_OFFSET */
+		struct {
+			uint64_t offset;
+			uint32_t region;
+		} start;
+
+		/* for MIN_ALIGNMENT */
+		struct {
+			uint64_t alignment;
+			uint64_t region1;
+			uint64_t region2;
+		} minalign;
+
+		/* for SAFE_START_OFFSET */
+		uint64_t safe_start_offset;
+
+		/* for SAFE_ALIGNMENT */
+		uint64_t safe_alignment;
+	};
+	struct igt_list_head link;
+};
+
+static IGT_LIST_HEAD(cache);
+static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static struct cache_entry *find_entry_unlocked(enum cache_entry_type type,
+					       uint16_t devid,
+					       uint32_t region1,
+					       uint32_t region2)
+{
+	struct cache_entry *entry;
+
+	igt_list_for_each_entry(entry, &cache, link) {
+		if (entry->type != type || entry->devid != devid)
+			continue;
+
+		switch (entry->type) {
+		case MIN_START_OFFSET:
+			if (entry->start.region == region1)
+				return entry;
+			continue;
+
+		case MIN_ALIGNMENT:
+			if (entry->minalign.region1 == region1 &&
+			    entry->minalign.region2 == region2)
+				return entry;
+			continue;
+
+		case SAFE_START_OFFSET:
+		case SAFE_ALIGNMENT:
+			return entry;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * gem_detect_min_start_offset_for_region:
+ * @i915: drm fd
+ * @region: memory region
+ *
+ * Returns: minimum start offset at which kernel allows placing objects
+ *          for memory region.
+ */
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
+{
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t start_offset = 0;
+	uint64_t bb_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(&obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	eb.buffers_ptr = to_user_pointer(&obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj.handle, &bb_size, region) == 0);
+	obj.flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	while (1) {
+		obj.offset = start_offset;
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		if (start_offset)
+			start_offset <<= 1;
+		else
+			start_offset = PAGE_SIZE;
+
+		igt_assert(start_offset <= 1ull << 32);
+	}
+	gem_close(i915, obj.handle);
+
+	newentry = malloc(sizeof(*newentry));
+	igt_assert(newentry);
+
+	/* Check does other thread did the job before */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry) {
+		free(newentry); /* extremely rare case */
+		goto out;
+	}
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_START_OFFSET;
+	entry->start.offset = start_offset;
+	entry->start.region = region;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->start.offset;
+}
+
+/**
+ * gem_detect_safe_start_offset:
+ * @i915: drm fd
+ *
+ * Returns: finds start offset which can be used as first one regardless
+ *          memory region. Useful if for some reason some regions don't allow
+ *          starting from 0x0 offset.
+ */
+uint64_t gem_detect_safe_start_offset(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint32_t region;
+	uint64_t offset = 0;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_combination(regions, 1, set) {
+		region = igt_collection_get_value(regions, 0);
+		offset = max(offset,
+			     gem_detect_min_start_offset_for_region(i915, region));
+	}
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	igt_assert(newentry);
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry) {
+		free(newentry);
+		goto out;
+	}
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_START_OFFSET;
+	entry->safe_start_offset = offset;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->safe_start_offset;
+}
+
+/**
+ * gem_detect_min_alignment_for_regions:
+ * @i915: drm fd
+ * @region1: first region
+ * @region2: second region
+ *
+ * Returns: minimum alignment which must be used when objects from @region1 and
+ * @region2 are going to interact.
+ */
+uint64_t gem_detect_min_alignment_for_regions(int i915,
+					      uint32_t region1,
+					      uint32_t region2)
+{
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t min_alignment = PAGE_SIZE;
+	uint64_t bb_size = PAGE_SIZE, obj_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	/* Establish bb offset first */
+	eb.buffers_ptr = to_user_pointer(obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle,
+						  &bb_size, region1) == 0);
+	obj[0].flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size,
+					  PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
+
+	/* Find appropriate alignment of object */
+	eb.buffer_count = ARRAY_SIZE(obj);
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle,
+						  &obj_size, region2) == 0);
+	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region2);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	while (1) {
+		obj[1].offset = ALIGN(obj[0].offset + bb_size, min_alignment);
+		igt_assert(obj[1].offset <= 1ull << 32);
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		min_alignment <<= 1;
+	}
+
+	gem_close(i915, obj[0].handle);
+	gem_close(i915, obj[1].handle);
+
+	newentry = malloc(sizeof(*newentry));
+	igt_assert(newentry);
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry) {
+		free(newentry);
+		goto out;
+	}
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = MIN_ALIGNMENT;
+	entry->minalign.alignment = min_alignment;
+	entry->minalign.region1 = region1;
+	entry->minalign.region2 = region2;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
+
+/**
+ * gem_get_safe_alignment:
+ * @i915: drm fd
+ *
+ * Returns: safe alignment for all memory regions on @i915 device.
+ * Safe in this case means max() from all minimum alignment for each
+ * region.
+ */
+uint64_t gem_detect_safe_alignment(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint64_t default_alignment = 0;
+	uint32_t region_bb, region_obj;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry, *newentry;
+
+	/* non-discrete uses 4K page size */
+	if (!gem_has_lmem(i915))
+		return PAGE_SIZE;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_variation_r(regions, 2, set) {
+		uint64_t alignment;
+
+		region_bb = igt_collection_get_value(regions, 0);
+		region_obj = igt_collection_get_value(regions, 1);
+
+		/* We're interested in triangular matrix */
+		if (region_bb > region_obj)
+			continue;
+
+		alignment = gem_detect_min_alignment_for_regions(i915,
+								 region_bb,
+								 region_obj);
+		if (default_alignment < alignment)
+			default_alignment = alignment;
+	}
+
+	free(query_info);
+	igt_collection_destroy(set);
+
+	newentry = malloc(sizeof(*newentry));
+	igt_assert(newentry);
+
+	/* Try again, check does we have cache updated in the meantime. */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid,  0, 0);
+	if (entry) {
+		free(newentry);
+		goto out;
+	}
+
+	entry = newentry;
+	entry->devid = devid;
+	entry->type = SAFE_ALIGNMENT;
+	entry->safe_alignment = default_alignment;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
diff --git a/lib/i915/intel_memory_region.h b/lib/i915/intel_memory_region.h
index 8b427b7e7..936e7d1c8 100644
--- a/lib/i915/intel_memory_region.h
+++ b/lib/i915/intel_memory_region.h
@@ -129,4 +129,9 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 				      uint16_t memory_class,
 				      uint16_t memory_instance);
 
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region);
+uint64_t gem_detect_safe_start_offset(int i915);
+uint64_t gem_detect_min_alignment_for_regions(int i915, uint32_t region1, uint32_t region2);
+uint64_t gem_detect_safe_alignment(int i915);
+
 #endif /* INTEL_MEMORY_REGION_H */
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2021-12-29 19:37 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
@ 2021-12-29 19:37 ` Zbigniew Kempczyński
  0 siblings, 0 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2021-12-29 19:37 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

With era of new gens we're enforced to use no-reloc (softpin). This
brings few problems like vm range limitations which were well solved
by the kernel. This can be handled also in userspace code by adding
gen related conditionals or by trying to detect the constraints.

Lets try to do this dynamically and detect safe start offset and
alignment for each memory region we got. This should be universal solution
regardless hw limitations and bugs. As such detection is not lightweight
technique add also some caching structures to handle consequtive calls
about same data.

v2: unify cache

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 lib/i915/intel_memory_region.c | 367 +++++++++++++++++++++++++++++++++
 lib/i915/intel_memory_region.h |   5 +
 2 files changed, 372 insertions(+)

diff --git a/lib/i915/intel_memory_region.c b/lib/i915/intel_memory_region.c
index dfbb8acf0..2db2774e3 100644
--- a/lib/i915/intel_memory_region.c
+++ b/lib/i915/intel_memory_region.c
@@ -28,11 +28,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <pthread.h>
 
 #include "i915/gem_create.h"
 #include "intel_reg.h"
 #include "drmtest.h"
 #include "ioctl_wrappers.h"
+#include "igt_aux.h"
 #include "igt_dummyload.h"
 #include "igt_gt.h"
 #include "igt_params.h"
@@ -40,6 +42,7 @@
 #include "intel_chipset.h"
 #include "igt_collection.h"
 #include "igt_device.h"
+#include "gem_mman.h"
 
 #include "i915/intel_memory_region.h"
 
@@ -480,3 +483,367 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 
 	return 0;
 }
+
+#define PAGE_SIZE 4096
+
+enum cache_entry_type {
+	MIN_START_OFFSET,
+	MIN_ALIGNMENT,
+	SAFE_START_OFFSET,
+	SAFE_ALIGNMENT,
+};
+
+struct cache_entry {
+	uint16_t devid;
+	enum cache_entry_type type;
+
+	union {
+		/* for MIN_START_OFFSET */
+		struct {
+			uint64_t offset;
+			uint32_t region;
+		} start;
+
+		/* for MIN_ALIGNMENT */
+		struct {
+			uint64_t alignment;
+			uint64_t region1;
+			uint64_t region2;
+		} minalign;
+
+		/* for SAFE_START_OFFSET */
+		uint64_t safe_start_offset;
+
+		/* for SAFE_ALIGNMENT */
+		uint64_t safe_alignment;
+	};
+	struct igt_list_head link;
+};
+
+static IGT_LIST_HEAD(cache);
+static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static struct cache_entry *find_entry_unlocked(enum cache_entry_type type,
+					       uint16_t devid,
+					       uint32_t region1,
+					       uint32_t region2)
+{
+	struct cache_entry *entry;
+
+	igt_list_for_each_entry(entry, &cache, link) {
+		if (entry->type != type || entry->devid != devid)
+			continue;
+
+		switch (entry->type) {
+		case MIN_START_OFFSET:
+			if (entry->start.region == region1)
+				return entry;
+			continue;
+
+		case MIN_ALIGNMENT:
+			if (entry->minalign.region1 == region1 &&
+			    entry->minalign.region2 == region2)
+				return entry;
+			continue;
+
+		case SAFE_START_OFFSET:
+		case SAFE_ALIGNMENT:
+			return entry;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * gem_detect_min_start_offset_for_region:
+ * @i915: drm fd
+ * @region: memory region
+ *
+ * Returns: minimum start offset at which kernel allows placing objects
+ *          for memory region.
+ */
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region)
+{
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t start_offset = 0;
+	uint64_t bb_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(&obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	eb.buffers_ptr = to_user_pointer(&obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj.handle, &bb_size, region) == 0);
+	obj.flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	while (1) {
+		obj.offset = start_offset;
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		if (start_offset)
+			start_offset <<= 1;
+		else
+			start_offset = PAGE_SIZE;
+
+		igt_assert(start_offset <= 1ull << 32);
+	}
+	gem_close(i915, obj.handle);
+
+	/* Check does other thread did the job before */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_START_OFFSET, devid, region, 0);
+	if (entry)
+		goto out;
+
+	entry = malloc(sizeof(*entry));
+	if (!entry)
+		pthread_mutex_unlock(&cache_mutex);
+	igt_assert(entry);
+	entry->devid = devid;
+	entry->type = MIN_START_OFFSET;
+	entry->start.offset = start_offset;
+	entry->start.region = region;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->start.offset;
+}
+
+/**
+ * gem_detect_safe_start_offset:
+ * @i915: drm fd
+ *
+ * Returns: finds start offset which can be used as first one regardless
+ *          memory region. Useful if for some reason some regions don't allow
+ *          starting from 0x0 offset.
+ */
+uint64_t gem_detect_safe_start_offset(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint32_t region;
+	uint64_t offset = 0;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_combination(regions, 1, set) {
+		region = igt_collection_get_value(regions, 0);
+		offset = max(offset,
+			     gem_detect_min_start_offset_for_region(i915, region));
+	}
+	free(query_info);
+	igt_collection_destroy(set);
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_START_OFFSET, devid, 0, 0);
+	if (entry)
+		goto out;
+
+	entry = malloc(sizeof(*entry));
+	if (!entry)
+		pthread_mutex_unlock(&cache_mutex);
+	igt_assert(entry);
+	entry->devid = devid;
+	entry->type = SAFE_START_OFFSET;
+	entry->safe_start_offset = offset;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->safe_start_offset;
+}
+
+/**
+ * gem_detect_min_alignment_for_regions:
+ * @i915: drm fd
+ * @region1: first region
+ * @region2: second region
+ *
+ * Returns: minimum alignment which must be used when objects from @region1 and
+ * @region2 are going to interact.
+ */
+uint64_t gem_detect_min_alignment_for_regions(int i915,
+					      uint32_t region1,
+					      uint32_t region2)
+{
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t min_alignment = PAGE_SIZE;
+	uint64_t bb_size = PAGE_SIZE, obj_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	memset(obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	/* Establish bb offset first */
+	eb.buffers_ptr = to_user_pointer(obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle,
+						  &bb_size, region1) == 0);
+	obj[0].flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size,
+					  PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	obj[0].offset = gem_detect_min_start_offset_for_region(i915, region1);
+
+	/* Find appropriate alignment of object */
+	eb.buffer_count = ARRAY_SIZE(obj);
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle,
+						  &obj_size, region2) == 0);
+	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region2);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	while (1) {
+		obj[1].offset = ALIGN(obj[0].offset + bb_size, min_alignment);
+		igt_assert(obj[1].offset <= 1ull << 32);
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		min_alignment <<= 1;
+	}
+
+	gem_close(i915, obj[0].handle);
+	gem_close(i915, obj[1].handle);
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(MIN_ALIGNMENT, devid, region1, region2);
+	if (entry)
+		goto out;
+
+	entry = malloc(sizeof(*entry));
+	if (!entry)
+		pthread_mutex_unlock(&cache_mutex);
+	igt_assert(entry);
+	entry->devid = devid;
+	entry->type = MIN_ALIGNMENT;
+	entry->minalign.alignment = min_alignment;
+	entry->minalign.region1 = region1;
+	entry->minalign.region2 = region2;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
+
+/**
+ * gem_get_safe_alignment:
+ * @i915: drm fd
+ *
+ * Returns: safe alignment for all memory regions on @i915 device.
+ * Safe in this case means max() from all minimum alignment for each
+ * region.
+ */
+uint64_t gem_detect_safe_alignment(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint64_t default_alignment = 0;
+	uint32_t region_bb, region_obj;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct cache_entry *entry;
+
+	/* non-discrete uses 4K page size */
+	if (!gem_has_lmem(i915))
+		return PAGE_SIZE;
+
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid, 0, 0);
+	if (entry)
+		goto out;
+	pthread_mutex_unlock(&cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_variation_r(regions, 2, set) {
+		uint64_t alignment;
+
+		region_bb = igt_collection_get_value(regions, 0);
+		region_obj = igt_collection_get_value(regions, 1);
+
+		/* We're interested in triangular matrix */
+		if (region_bb > region_obj)
+			continue;
+
+		alignment = gem_detect_min_alignment_for_regions(i915,
+								 region_bb,
+								 region_obj);
+		if (default_alignment < alignment)
+			default_alignment = alignment;
+	}
+
+	free(query_info);
+	igt_collection_destroy(set);
+
+	/* Try again, check does we have cache updated in the meantime. */
+	pthread_mutex_lock(&cache_mutex);
+	entry = find_entry_unlocked(SAFE_ALIGNMENT, devid,  0, 0);
+	if (entry)
+		goto out;
+
+	entry = malloc(sizeof(*entry));
+	if (!entry)
+		pthread_mutex_unlock(&cache_mutex);
+	igt_assert(entry);
+	entry->devid = devid;
+	entry->type = SAFE_ALIGNMENT;
+	entry->safe_alignment = default_alignment;
+	igt_list_add(&entry->link, &cache);
+
+out:
+	pthread_mutex_unlock(&cache_mutex);
+
+	return entry->minalign.alignment;
+}
diff --git a/lib/i915/intel_memory_region.h b/lib/i915/intel_memory_region.h
index 8b427b7e7..936e7d1c8 100644
--- a/lib/i915/intel_memory_region.h
+++ b/lib/i915/intel_memory_region.h
@@ -129,4 +129,9 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 				      uint16_t memory_class,
 				      uint16_t memory_instance);
 
+uint64_t gem_detect_min_start_offset_for_region(int i915, uint32_t region);
+uint64_t gem_detect_safe_start_offset(int i915);
+uint64_t gem_detect_min_alignment_for_regions(int i915, uint32_t region1, uint32_t region2);
+uint64_t gem_detect_safe_alignment(int i915);
+
 #endif /* INTEL_MEMORY_REGION_H */
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: Add start offset and alignment detection
  2021-12-29 13:57 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
@ 2021-12-29 13:57 ` Zbigniew Kempczyński
  0 siblings, 0 replies; 17+ messages in thread
From: Zbigniew Kempczyński @ 2021-12-29 13:57 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala

With era of new gens we're enforced to use no-reloc (softpin). This
brings few problems like vm range limitations which were well solved
by the kernel. This can be handled also in userspace code by adding
gen related conditionals or by trying to detect the constraints.

Lets try to do this dynamically and detect safe start offset and
alignment for each memory region we got. This should be universal solution
regardless hw limitations and bugs. As such detection is not lightweight
technique add also some caching structures to handle consequtive calls
about same data.

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Cc: Petri Latvala <petri.latvala@intel.com>
Cc: Ashutosh Dixit <ashutosh.dixit@intel.com>
---
 lib/i915/intel_memory_region.c | 269 +++++++++++++++++++++++++++++++++
 lib/i915/intel_memory_region.h |   5 +
 2 files changed, 274 insertions(+)

diff --git a/lib/i915/intel_memory_region.c b/lib/i915/intel_memory_region.c
index dfbb8acf0..4bf116dc9 100644
--- a/lib/i915/intel_memory_region.c
+++ b/lib/i915/intel_memory_region.c
@@ -28,11 +28,13 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <pthread.h>
 
 #include "i915/gem_create.h"
 #include "intel_reg.h"
 #include "drmtest.h"
 #include "ioctl_wrappers.h"
+#include "igt_aux.h"
 #include "igt_dummyload.h"
 #include "igt_gt.h"
 #include "igt_params.h"
@@ -40,6 +42,7 @@
 #include "intel_chipset.h"
 #include "igt_collection.h"
 #include "igt_device.h"
+#include "gem_mman.h"
 
 #include "i915/intel_memory_region.h"
 
@@ -480,3 +483,269 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 
 	return 0;
 }
+
+#define PAGE_SIZE 4096
+#define START_OFFSET PAGE_SIZE
+
+struct devid_start {
+	uint16_t devid;
+	uint64_t start;
+	uint32_t region;
+	struct igt_list_head link;
+};
+
+static IGT_LIST_HEAD(start_cache);
+static pthread_mutex_t start_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static uint64_t detect_start_offset(int i915, uint32_t region_bb)
+{
+	struct drm_i915_gem_exec_object2 obj;
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t start_offset = START_OFFSET;
+	uint64_t bb_size = PAGE_SIZE;
+	uint32_t *batch;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct devid_start *entry;
+
+	pthread_mutex_lock(&start_cache_mutex);
+	igt_list_for_each_entry(entry, &start_cache, link) {
+		if (entry->devid == devid && entry->region == region_bb)
+			goto out;
+	}
+	pthread_mutex_unlock(&start_cache_mutex);
+
+	memset(&obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	eb.buffers_ptr = to_user_pointer(&obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj.handle, &bb_size, region_bb) == 0);
+	obj.flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj.handle, 0, bb_size, PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	while (1) {
+		obj.offset = start_offset;
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		start_offset <<= 1;
+
+		igt_assert(start_offset <= 1ull << 32);
+	}
+	gem_close(i915, obj.handle);
+
+	/* Check does other thread did the job before */
+	pthread_mutex_lock(&start_cache_mutex);
+	igt_list_for_each_entry(entry, &start_cache, link) {
+		if (entry->devid == devid && entry->region == region_bb)
+			goto out;
+	}
+
+	entry = malloc(sizeof(*entry));
+	if (entry)
+		pthread_mutex_unlock(&start_cache_mutex);
+	igt_assert(entry);
+	entry->devid = devid;
+	entry->start = start_offset;
+	entry->region = region_bb;
+	igt_list_add(&entry->link, &start_cache);
+
+out:
+	pthread_mutex_unlock(&start_cache_mutex);
+
+	return entry->start;
+}
+
+/**
+ * gem_get_start_offset_for_region:
+ * @i915: drm fd
+ * @region: memory region
+ *
+ * Returns: start offset at which kernel allows placing objects for memory
+ *          region.
+ */
+uint64_t gem_get_start_offset_for_region(int i915, uint32_t region)
+{
+	return detect_start_offset(i915, region);
+}
+
+/**
+ * gem_get_safe_start_offset:
+ * @i915: drm fd
+ *
+ * Returns: finds start offset which can be used as first one regardless
+ *          memory region. Useful if for some reason some regions don't allow
+ *          starting from 0x0 offset.
+ */
+uint64_t gem_get_safe_start_offset(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint32_t region;
+	uint64_t offset = 0;
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_combination(regions, 1, set) {
+		region = igt_collection_get_value(regions, 0);
+		offset = max(offset, gem_get_start_offset_for_region(i915, region));
+	}
+	free(query_info);
+	igt_collection_destroy(set);
+
+	return offset;
+}
+
+static uint64_t detect_alignment(int i915, uint32_t region_bb, uint32_t region_obj)
+{
+	struct drm_i915_gem_exec_object2 obj[2];
+	struct drm_i915_gem_execbuffer2 eb;
+	uint64_t default_alignment = PAGE_SIZE;
+	uint64_t bb_size = PAGE_SIZE, obj_size = PAGE_SIZE;
+	uint32_t *batch;
+
+	memset(obj, 0, sizeof(obj));
+	memset(&eb, 0, sizeof(eb));
+
+	/* Establish bb offset first */
+	eb.buffers_ptr = to_user_pointer(obj);
+	eb.buffer_count = 1;
+	eb.flags = I915_EXEC_BATCH_FIRST | I915_EXEC_DEFAULT;
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[0].handle, &bb_size, region_bb) == 0);
+	obj[0].flags = EXEC_OBJECT_PINNED;
+
+	batch = gem_mmap__device_coherent(i915, obj[0].handle, 0, bb_size, PROT_WRITE);
+	*batch = MI_BATCH_BUFFER_END;
+	munmap(batch, bb_size);
+
+	obj[0].offset = detect_start_offset(i915, region_bb);
+
+	/* Find appropriate alignment of object */
+	eb.buffer_count = ARRAY_SIZE(obj);
+	igt_assert(__gem_create_in_memory_regions(i915, &obj[1].handle, &obj_size, region_obj) == 0);
+	obj[1].handle = gem_create_in_memory_regions(i915, PAGE_SIZE, region_obj);
+	obj[1].flags = EXEC_OBJECT_PINNED;
+	while (1) {
+		obj[1].offset = ALIGN(obj[0].offset + bb_size, default_alignment);
+		igt_assert(obj[1].offset <= 1ull << 32);
+
+		if (__gem_execbuf(i915, &eb) == 0)
+			break;
+
+		default_alignment <<= 1;
+	}
+
+	gem_close(i915, obj[0].handle);
+	gem_close(i915, obj[1].handle);
+
+	return default_alignment;
+}
+
+/**
+ * gem_get_alignment_for_regions:
+ * @i915: drm fd
+ * @region1: first region
+ * @region2: second region
+ *
+ * Returns: alignment which must be used when objects from @region1 and
+ * @region2 are going to interact.
+ */
+uint64_t gem_get_alignment_for_regions(int i915, uint32_t region1, uint32_t region2)
+{
+	return detect_alignment(i915, region1, region2);
+}
+
+struct devid_align {
+	uint16_t devid;
+	uint64_t alignment;
+	struct igt_list_head link;
+};
+
+static IGT_LIST_HEAD(alignment_cache);
+static pthread_mutex_t alignment_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/**
+ * gem_get_safe_alignment:
+ * @i915: drm fd
+ *
+ * Returns: safe (maximum) alignment for all memory regions on @i915 device.
+ */
+uint64_t gem_get_safe_alignment(int i915)
+{
+	struct drm_i915_query_memory_regions *query_info;
+	struct igt_collection *regions, *set;
+	uint64_t default_alignment = 0;
+	uint32_t region_bb, region_obj;
+	uint16_t devid = intel_get_drm_devid(i915);
+	struct devid_align *entry;
+
+	/* non-discrete uses 4K page size */
+	if (!gem_has_lmem(i915))
+		return PAGE_SIZE;
+
+	pthread_mutex_lock(&alignment_cache_mutex);
+	igt_list_for_each_entry(entry, &alignment_cache, link) {
+		if (entry->devid == devid)
+			goto out;
+	}
+	/*
+	 * Unlock mutex in hope parallel alignment detection will happen
+	 * on different devid-s.
+	 */
+	pthread_mutex_unlock(&alignment_cache_mutex);
+
+	query_info = gem_get_query_memory_regions(i915);
+	igt_assert(query_info);
+
+	set = get_memory_region_set(query_info,
+				    I915_SYSTEM_MEMORY,
+				    I915_DEVICE_MEMORY);
+
+	for_each_variation_r(regions, 2, set) {
+		uint64_t alignment;
+
+		region_bb = igt_collection_get_value(regions, 0);
+		region_obj = igt_collection_get_value(regions, 1);
+
+		/* We're interested in triangular matrix */
+		if (region_bb > region_obj)
+			continue;
+
+		alignment = detect_alignment(i915, region_bb, region_obj);
+		if (default_alignment < alignment)
+			default_alignment = alignment;
+	}
+
+	free(query_info);
+	igt_collection_destroy(set);
+
+	/* Try again, check does we have cache updated in the meantime. */
+	pthread_mutex_lock(&alignment_cache_mutex);
+	igt_list_for_each_entry(entry, &alignment_cache, link) {
+		if (entry->devid == devid)
+			goto out;
+	}
+
+	entry = malloc(sizeof(*entry));
+	if (!entry)
+		pthread_mutex_unlock(&alignment_cache_mutex);
+	igt_assert(entry);
+	entry->devid = devid;
+	entry->alignment = default_alignment;
+	igt_list_add(&entry->link, &alignment_cache);
+
+out:
+	pthread_mutex_unlock(&alignment_cache_mutex);
+
+	return entry->alignment;
+}
diff --git a/lib/i915/intel_memory_region.h b/lib/i915/intel_memory_region.h
index 8b427b7e7..4d994f1ad 100644
--- a/lib/i915/intel_memory_region.h
+++ b/lib/i915/intel_memory_region.h
@@ -129,4 +129,9 @@ uint64_t gpu_meminfo_region_available(const struct drm_i915_query_memory_regions
 				      uint16_t memory_class,
 				      uint16_t memory_instance);
 
+uint64_t gem_get_start_offset_for_region(int i915, uint32_t region);
+uint64_t gem_get_safe_start_offset(int i915);
+uint64_t gem_get_alignment_for_regions(int i915, uint32_t region1, uint32_t region2);
+uint64_t gem_get_safe_alignment(int i915);
+
 #endif /* INTEL_MEMORY_REGION_H */
-- 
2.32.0

^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-01-06 10:00 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-30 18:26 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
2022-01-05  5:00   ` Dixit, Ashutosh
2022-01-05  6:44     ` Zbigniew Kempczyński
2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 2/3] tests/i915/gem_softpin: Add safe-start test Zbigniew Kempczyński
2021-12-30 18:26 ` [igt-dev] [PATCH i-g-t 3/3] tests/fast-feedback.testlist: Add gem_softpin@safe-start subtest Zbigniew Kempczyński
2022-01-04  4:41   ` Petri Latvala
2022-01-03 22:56 ` [igt-dev] ✗ GitLab.Pipeline: warning for Add start offset and alignment detection (rev5) Patchwork
2022-01-03 23:00 ` [igt-dev] ✓ Fi.CI.BAT: success " Patchwork
2022-01-04  0:11 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2022-01-06 10:00 [igt-dev] [PATCH i-g-t 0/3] Add start offset and alignment detection Zbigniew Kempczyński
2022-01-06 10:00 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
2022-01-05  6:49 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
2022-01-05  6:49 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
2022-01-06  2:23   ` Dixit, Ashutosh
2022-01-06  9:45     ` Zbigniew Kempczyński
2021-12-30  8:14 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
2021-12-30  8:14 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
2021-12-29 19:37 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
2021-12-29 19:37 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński
2021-12-29 13:57 [igt-dev] [PATCH i-g-t 0/3] " Zbigniew Kempczyński
2021-12-29 13:57 ` [igt-dev] [PATCH i-g-t 1/3] lib/intel_memory_region: " Zbigniew Kempczyński

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.