summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMika Kuoppala <mika.kuoppala@intel.com>2014-11-17 15:38:08 +0200
committerMika Kuoppala <mika.kuoppala@intel.com>2014-12-05 15:30:59 +0200
commit83b1bdd45d8b744e89086621c08709ccc4cc319c (patch)
tree0a16a0de939883e68c8336d2c3b74943e049d5c4
parentb64704673e2a4d891386a1200150e679216b6d60 (diff)
tests/gem_userptr_blits: add test to check blit aligns79053
Copy a block into a destination object with varying base offset into the destination and source. Put guard area before and after the blit target to see that it didn't touch memory out of blit boundaries. References: https://bugs.freedesktop.org/show_bug.cgi?id=79053 Cc: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Mika Kuoppala <mika.kuoppala@intel.com>
-rw-r--r--tests/gem_userptr_blits.c275
1 files changed, 268 insertions, 7 deletions
diff --git a/tests/gem_userptr_blits.c b/tests/gem_userptr_blits.c
index d641c120..b945b48d 100644
--- a/tests/gem_userptr_blits.c
+++ b/tests/gem_userptr_blits.c
@@ -81,6 +81,7 @@ static uint32_t userptr_flags = LOCAL_I915_USERPTR_UNSYNCHRONIZED;
#define HEIGHT 512
static uint32_t linear[WIDTH*HEIGHT];
+static uint32_t gen;
static void gem_userptr_test_unsynchronized(void)
{
@@ -136,7 +137,7 @@ copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
batch[i++] = XY_SRC_COPY_BLT_CMD |
XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB;
- if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ if (gen >= 8)
batch[i - 1] |= 8;
else
batch[i - 1] |= 6;
@@ -147,12 +148,12 @@ copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
batch[i++] = 0; /* dst x1,y1 */
batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
batch[i++] = 0; /* dst reloc */
- if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ if (gen >= 8)
batch[i++] = 0;
batch[i++] = 0; /* src x1,y1 */
batch[i++] = WIDTH*4;
batch[i++] = 0; /* src reloc */
- if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ if (gen >= 8)
batch[i++] = 0;
batch[i++] = MI_BATCH_BUFFER_END;
batch[i++] = MI_NOOP;
@@ -170,7 +171,7 @@ copy(int fd, uint32_t dst, uint32_t src, unsigned int error)
reloc[1].target_handle = src;
reloc[1].delta = 0;
reloc[1].offset = 7 * sizeof(batch[0]);
- if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ if (gen >= 8)
reloc[1].offset += sizeof(batch[0]);
reloc[1].presumed_offset = 0;
reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
@@ -221,7 +222,7 @@ blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo)
batch[i++] = XY_SRC_COPY_BLT_CMD |
XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB;
- if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ if (gen >= 8)
batch[i - 1] |= 8;
else
batch[i - 1] |= 6;
@@ -231,7 +232,7 @@ blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo)
batch[i++] = 0; /* dst x1,y1 */
batch[i++] = (HEIGHT << 16) | WIDTH; /* dst x2,y2 */
batch[i++] = 0; /* dst reloc */
- if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ if (gen >= 8)
batch[i++] = 0;
batch[i++] = 0; /* src x1,y1 */
batch[i++] = WIDTH*4;
@@ -254,7 +255,7 @@ blit(int fd, uint32_t dst, uint32_t src, uint32_t *all_bo, int n_bo)
reloc[1].target_handle = src;
reloc[1].delta = 0;
reloc[1].offset = 7 * sizeof(batch[0]);
- if (intel_gen(intel_get_drm_devid(fd)) >= 8)
+ if (gen >= 8)
reloc[1].offset += sizeof(batch[0]);
reloc[1].presumed_offset = 0;
reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
@@ -972,6 +973,258 @@ static int test_coherency(int fd, int count)
return 0;
}
+static uint32_t lb[12];
+
+static void
+copy_align(int fd,
+ uint32_t dst, uint32_t dst_offset,
+ uint32_t src, uint32_t src_offset,
+ uint32_t w, uint32_t h)
+{
+ uint32_t batch[12];
+ struct drm_i915_gem_relocation_entry reloc[2];
+ struct drm_i915_gem_exec_object2 obj[3];
+ struct drm_i915_gem_execbuffer2 exec;
+ uint32_t handle;
+ int i=0;
+
+ batch[i++] = XY_SRC_COPY_BLT_CMD |
+ XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB;
+ if (gen >= 8)
+ batch[i - 1] |= 8;
+ else
+ batch[i - 1] |= 6;
+
+ batch[i++] = (3 << 24) | /* 32 bits */
+ (0xcc << 16) | /* copy ROP */
+ w * 4;
+
+ batch[i++] = 0; /* dst, x1,y2 */
+ batch[i++] = ((h) << 16) | (w); /* dst x2,y2 */
+ batch[i++] = dst_offset * 4; /* dst reloc */
+ if (gen >= 8)
+ batch[i++] = 0;
+ batch[i++] = 0; /* src x1,y1 */
+ batch[i++] = w * 4;
+
+ if ((w * 4) % 8)
+ igt_warn("src pitch NOT aligned to quad\n");
+
+ batch[i++] = src_offset * 4; /* src reloc */
+ if (gen >= 8)
+ batch[i++] = 0;
+ batch[i++] = MI_BATCH_BUFFER_END;
+ batch[i++] = MI_NOOP;
+
+ handle = gem_create(fd, 4096);
+ gem_write(fd, handle, 0, batch, sizeof(batch));
+
+ reloc[0].target_handle = dst;
+ reloc[0].delta = dst_offset * 4;
+ reloc[0].offset = 4 * sizeof(batch[0]);
+ reloc[0].presumed_offset = 0;
+ reloc[0].read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc[0].write_domain = I915_GEM_DOMAIN_RENDER;
+
+ reloc[1].target_handle = src;
+ reloc[1].delta = src_offset * 4;
+ reloc[1].offset = 7 * sizeof(batch[0]);
+ if (gen >= 8)
+ reloc[1].offset += sizeof(batch[0]);
+ reloc[1].presumed_offset = 0;
+ reloc[1].read_domains = I915_GEM_DOMAIN_RENDER;
+ reloc[1].write_domain = 0;
+
+ memset(obj, 0, sizeof(obj));
+ exec.buffer_count = 0;
+ obj[exec.buffer_count++].handle = dst;
+ if (src != dst)
+ obj[exec.buffer_count++].handle = src;
+ obj[exec.buffer_count].handle = handle;
+ obj[exec.buffer_count].relocation_count = 2;
+ obj[exec.buffer_count].relocs_ptr = (uintptr_t)reloc;
+ exec.buffer_count++;
+ exec.buffers_ptr = (uintptr_t)obj;
+
+ exec.batch_start_offset = 0;
+ exec.batch_len = i * 4;
+ exec.DR1 = exec.DR4 = 0;
+ exec.num_cliprects = 0;
+ exec.cliprects_ptr = 0;
+ exec.flags = HAS_BLT_RING(intel_get_drm_devid(fd)) ? I915_EXEC_BLT : 0;
+ i915_execbuffer2_set_context_id(exec, 0);
+ exec.rsvd2 = 0;
+
+ gem_execbuf(fd, &exec);
+
+ memcpy(lb, batch, sizeof(batch));
+
+ gem_sync(fd, handle);
+ gem_close(fd, handle);
+}
+
+static unsigned long verify_guard_area(uint32_t *p,
+ const int size,
+ const uint32_t sval)
+{
+ int i;
+ unsigned long count = 0;
+
+ for (i = 0; i < size; i++) {
+ if (p[i] != i + sval) {
+ igt_warn("guard at index %d is 0x%08x, should be 0x%08x\n",
+ i, p[i], i + sval);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static unsigned long verify_destination_area(uint32_t *p, const int size, const int sval)
+{
+ int i;
+ unsigned long count = 0;
+
+ for (i = 0; i < size; i++) {
+ if (p[i] != i + sval) {
+ igt_warn("dest data at index %d 0x%08x, should be 0x%08x\n",
+ i, p[i], i + sval);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static int
+_test_destination_align(int fd, const uint32_t dst_align,
+ const uint32_t src_align,
+ const uint32_t w,
+ const uint32_t h,
+ const bool userptr)
+{
+ const uint32_t size = sizeof(linear) / 4;
+ const uint32_t guard_val = 0xdeadf00d;
+ uint32_t *p;
+ uint32_t h_dst;
+ uint32_t h_src;
+ int i, ret;
+ bool failed = false;
+ const int dwords = w*h;
+
+ igt_assert(dwords < size);
+
+ if (userptr) {
+ ret = posix_memalign((void **)&p, PAGE_SIZE, size * 4);
+ igt_assert(ret == 0 && p);
+
+ ret = gem_userptr(fd, p, size * 4, 0, &h_dst);
+ igt_assert(ret == 0);
+ } else {
+ h_dst = gem_create(fd, size * 4);
+ p = linear;
+ }
+
+ igt_assert(h_dst != 0);
+
+ h_src = create_bo(fd, 0);
+ check_gpu(fd, h_src, 0);
+
+ for (i = 0; i < size; i++)
+ p[i] = guard_val + i;
+
+ if (!userptr) {
+ gem_write(fd, h_dst, 0, p, size * 4);
+ gem_read(fd, h_dst, 0, p, size * 4);
+ }
+
+ igt_assert(verify_guard_area(p, size, guard_val) == 0);
+
+ copy_align(fd, h_dst, dst_align, h_src, src_align, w, h);
+
+ if (!userptr)
+ gem_read(fd, h_dst, 0, p, size * 4);
+
+ if (verify_guard_area(p, dst_align, guard_val)) {
+ failed = true;
+ igt_warn("corrupted before blit target, align (%d:%d) dwords\n",
+ dst_align, src_align);
+ }
+
+ if (verify_destination_area(p + dst_align, dwords, src_align)) {
+ failed = true;
+ igt_warn("blit src not copied correctly, align (%d:%d) dwords\n",
+ dst_align, src_align);
+ }
+
+ if (verify_guard_area(p + dwords + dst_align,
+ size - dwords - dst_align,
+ guard_val + dwords + dst_align)) {
+ failed = true;
+ igt_warn("corrupted after blit target, align (%d:%d) dwords\n",
+ dst_align, src_align);
+ }
+
+ gem_close(fd, h_src);
+ gem_close(fd, h_dst);
+
+ if (userptr)
+ free(p);
+
+ if (failed) {
+ igt_warn("failed batch:\n");
+ for(i = 0; i < 12; i++)
+ igt_warn("0x%04x: 0x%08x\n", i, lb[i]);
+ }
+
+ return failed ? 1 : 0;
+}
+
+static bool assumed_fail(int dst_align, int w, int h)
+{
+ if (h == 1 || gen < 8)
+ return false;
+
+ if ((w % 8) == 2 && h != 2)
+ return ((dst_align % 8) + (w % 8)) >= 4;
+
+ return (dst_align % 8) + (w % 8) >= 8;
+}
+
+static void test_destination_align(int fd, bool userptr, int dst_align, int src_align, int max_w,
+ int max_h)
+{
+ int i, j, w, h;
+ bool failed = false;
+ int res;
+
+ for (i = 0; i <= src_align; i++) {
+ for (j = 0; j <= dst_align; j++) {
+ for (h = 2; h <= max_h; h += 2) {
+ for (w = 2; w <= max_w; w += 2) {
+ res = _test_destination_align(fd, j, i, w, h, userptr);
+ if (res)
+ igt_warn("BLT %s: from 0x%08x to 0x%08x %d:%d (%d) dwords\n",
+ res ? "FAIL" : "OK",
+ i * 4, j * 4, w, h, w * h);
+
+ if (assumed_fail(j, w, h) != res) {
+ igt_warn("not expected dst blt result %s, %d:%d to 0x%08x, pitch 0x%08x\n",
+ res ? "FAIL" : "OK", w, h, j * 4, w * 4);
+ }
+
+ if (res)
+ failed = true;
+ }
+ }
+ }
+ }
+
+ igt_assert(failed == false);
+}
+
static struct igt_eviction_test_ops fault_ops = {
.create = create_userptr_bo,
.flink = flink_userptr_bo,
@@ -1248,6 +1501,8 @@ int main(int argc, char **argv)
fd = drm_open_any();
igt_assert(fd >= 0);
+ gen = intel_gen(intel_get_drm_devid(fd));
+
ret = has_userptr(fd);
igt_skip_on_f(ret == 0, "No userptr support - %s (%d)\n",
strerror(errno), ret);
@@ -1457,5 +1712,11 @@ int main(int argc, char **argv)
igt_subtest("access-control")
test_access_control(fd);
+ igt_subtest("destination-bo-align")
+ test_destination_align(fd, false, 16, 0, 16, 16);
+
+ igt_subtest("destination-userptr-align")
+ test_destination_align(fd, true, 16, 0, 16, 16);
+
igt_exit();
}