[PATCH] pathological

Matthew Auld matthew.auld at intel.com
Tue Oct 29 22:36:50 UTC 2019


Signed-off-by: Matthew Auld <matthew.auld at intel.com>
---
 .../gpu/drm/i915/gem/selftests/huge_pages.c   | 157 ++++++++++++++++++
 drivers/gpu/drm/i915/i915_pci.c               |   3 +-
 2 files changed, 159 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index 688c49a24f32..53a2bb8bb8f7 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -4,10 +4,12 @@
  * Copyright © 2017 Intel Corporation
  */
 
+#include <linux/sort.h>
 #include <linux/prime_numbers.h>
 
 #include "i915_selftest.h"
 
+#include "gem/i915_gem_object_blt.h"
 #include "gem/i915_gem_region.h"
 #include "gem/i915_gem_lmem.h"
 #include "gem/i915_gem_pm.h"
@@ -1550,6 +1552,160 @@ static int igt_ppgtt_sanity_check(void *arg)
 	return err;
 }
 
+static int wrap_ktime_compare(const void *A, const void *B)
+{
+	const ktime_t *a = A, *b = B;
+
+	return ktime_compare(*a, *b);
+}
+
+static int perf_pathological_alignment(void *arg)
+{
+	struct i915_gem_context *ctx = arg;
+	struct drm_i915_private *i915 = ctx->i915;
+	struct drm_i915_gem_object *normal;
+	struct drm_i915_gem_object *obj;
+	const unsigned int n_pages = 32;
+	struct intel_context *ce;
+	struct scatterlist *sg;
+	struct sg_table *old_st;
+	struct sg_table *st;
+	unsigned long i;
+	ktime_t t[5];
+	int err;
+
+	if (!HAS_PAGE_SIZES(i915, SZ_2M))
+		return 0;
+
+	normal = huge_pages_object(i915, n_pages * SZ_2M, SZ_4K);
+	if (IS_ERR(normal))
+		return PTR_ERR(normal);
+
+	err = i915_gem_object_pin_pages(normal);
+	if (err)
+		goto out_put;
+
+	normal->mm.page_sizes.sg = SZ_4K;
+
+	obj = huge_pages_object(i915, n_pages * SZ_2M, SZ_2M);
+	if (IS_ERR(obj))
+		return PTR_ERR(obj);
+
+	err = i915_gem_object_pin_pages(obj);
+	if (err)
+		goto out_put;
+
+	GEM_BUG_ON(obj->mm.page_sizes.sg < SZ_2M);
+	obj->mm.page_sizes.sg = SZ_4K;
+
+	st = kmalloc(sizeof(*st), GFP_KERNEL);
+	if (!st) {
+		err = -ENOMEM;
+		goto out_unpin;
+	}
+
+	if (sg_alloc_table(st, obj->base.size >> PAGE_SHIFT, GFP_KERNEL)) {
+		err = -ENOMEM;
+		goto out_free;
+	}
+
+	sg = st->sgl;
+	st->nents = 0;
+
+	for (i = 0; i < obj->base.size >> PAGE_SHIFT; ++i) {
+		unsigned long idx = (SZ_2M * (i % n_pages)) >> PAGE_SHIFT;
+		dma_addr_t daddr = i915_gem_object_get_dma_address(obj, idx);
+
+		if (!IS_ALIGNED(daddr, SZ_2M)) {
+			pr_info("%s dma-mapper screwed us over, skipping\n",
+				__func__);
+			goto out_reset;
+		}
+
+		sg_dma_address(sg) = daddr;
+		sg_dma_len(sg) = PAGE_SIZE;
+
+		sg->length = PAGE_SIZE;
+
+		st->nents++;
+
+		sg = __sg_next(sg);
+	}
+
+	old_st = obj->mm.pages;
+	obj->mm.pages = st;
+
+	ce = i915->engine[BCS0]->kernel_context;
+
+	for (i = 0; i < ARRAY_SIZE(t); ++i) {
+		ktime_t t0, t1;
+
+		t0 = ktime_get();
+
+		err = i915_gem_object_fill_blt(obj, ce, 0);
+		if (err)
+			goto out_reset;
+
+		err = i915_gem_object_wait(obj,
+				I915_WAIT_ALL,
+				MAX_SCHEDULE_TIMEOUT);
+		if (err)
+			goto out_reset;
+
+		t1 = ktime_get();
+		t[i] = ktime_sub(t1, t0);
+	}
+
+	/* XXX: forgive me for i have sinned */
+	i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE);
+
+	sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL);
+	pr_info("SLOW %zd KiB fill: %lld MiB/s\n",
+		obj->base.size >> 10,
+		div64_u64(mul_u32_u32(4 * obj->base.size,
+				      1000 * 1000 * 1000),
+			  t[1] + 2 * t[2] + t[3]) >> 20);
+
+	for (i = 0; i < ARRAY_SIZE(t); ++i) {
+		ktime_t t0, t1;
+
+		t0 = ktime_get();
+
+		err = i915_gem_object_fill_blt(normal, ce, 0);
+		if (err)
+			goto out_reset;
+
+		err = i915_gem_object_wait(normal,
+				I915_WAIT_ALL,
+				MAX_SCHEDULE_TIMEOUT);
+		if (err)
+			goto out_reset;
+
+		t1 = ktime_get();
+		t[i] = ktime_sub(t1, t0);
+	}
+
+	sort(t, ARRAY_SIZE(t), sizeof(*t), wrap_ktime_compare, NULL);
+	pr_info("FAST %zd KiB fill: %lld MiB/s\n",
+		normal->base.size >> 10,
+		div64_u64(mul_u32_u32(4 * normal->base.size,
+				      1000 * 1000 * 1000),
+			  t[1] + 2 * t[2] + t[3]) >> 20);
+
+out_reset:
+	obj->mm.pages = old_st;
+	sg_free_table(st);
+out_free:
+	kfree(st);
+out_unpin:
+	i915_gem_object_unpin_pages(normal);
+	i915_gem_object_unpin_pages(obj);
+out_put:
+	i915_gem_object_put(normal);
+	i915_gem_object_put(obj);
+	return err;
+}
+
 static int igt_ppgtt_pin_update(void *arg)
 {
 	struct i915_gem_context *ctx = arg;
@@ -1911,6 +2067,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915)
 		SUBTEST(igt_ppgtt_exhaust_huge),
 		SUBTEST(igt_ppgtt_smoke_huge),
 		SUBTEST(igt_ppgtt_sanity_check),
+		SUBTEST(perf_pathological_alignment),
 	};
 	struct drm_file *file;
 	struct i915_gem_context *ctx;
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index 1bb701d32a5d..87e9e3887da3 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -603,7 +603,8 @@ static const struct intel_device_info intel_cherryview_info = {
 
 #define GEN9_DEFAULT_PAGE_SIZES \
 	.page_sizes = I915_GTT_PAGE_SIZE_4K | \
-		      I915_GTT_PAGE_SIZE_64K
+		      I915_GTT_PAGE_SIZE_64K | \
+		      I915_GTT_PAGE_SIZE_2M
 
 #define GEN9_FEATURES \
 	GEN8_FEATURES, \
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list