diff --git a/tests/gem_userptr_blits.c b/tests/gem_userptr_blits.c
index d641c12..b945b48 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();
 }
