diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 5d01ea6..c906232 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -249,6 +249,25 @@ static inline int use_cpu_reloc(struct drm_i915_gem_object *obj)
 		obj->cache_level != I915_CACHE_NONE);
 }
 
+/* Used to convert any address to canonical form.
+ * Starting from gen8, some commands (e.g. STATE_BASE_ADDRESS,
+ * MI_LOAD_REGISTER_MEM and others, see Broadwell PRM Vol2a) require the
+ * addresses to be in a canonical form:
+ * "GraphicsAddress[63:48] are ignored by the HW and assumed to be in correct
+ * canonical form [63:48] == [47]."
+ */
+static inline uint64_t gen8_canonical_addr(uint64_t address)
+{
+	return ((int64_t)address << 16) >> 16;
+}
+
+static inline uint64_t
+relocation_target(struct drm_i915_gem_relocation_entry *reloc,
+		  uint64_t target_offset)
+{
+	return gen8_canonical_addr((int)reloc->delta + target_offset);
+}
+
 static int
 relocate_entry_cpu(struct drm_i915_gem_object *obj,
 		   struct drm_i915_gem_relocation_entry *reloc,
@@ -256,7 +275,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj,
 {
 	struct drm_device *dev = obj->base.dev;
 	uint32_t page_offset = offset_in_page(reloc->offset);
-	uint64_t delta = reloc->delta + target_offset;
+	uint64_t delta = relocation_target(reloc, target_offset);
 	char *vaddr;
 	int ret;
 
@@ -292,7 +311,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint64_t delta = reloc->delta + target_offset;
+	uint64_t delta = relocation_target(reloc, target_offset);
 	uint64_t offset;
 	void __iomem *reloc_page;
 	int ret;
@@ -347,7 +366,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj,
 {
 	struct drm_device *dev = obj->base.dev;
 	uint32_t page_offset = offset_in_page(reloc->offset);
-	uint64_t delta = (int)reloc->delta + target_offset;
+	uint64_t delta = relocation_target(reloc, target_offset);
 	char *vaddr;
 	int ret;
 
@@ -395,7 +414,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,
 	target_i915_obj = target_vma->obj;
 	target_obj = &target_vma->obj->base;
 
-	target_offset = target_vma->node.start;
+	target_offset = gen8_canonical_addr(target_vma->node.start);
 
 	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and
 	 * pipe_control writes because the gpu doesn't properly redirect them
@@ -994,6 +1013,18 @@ validate_exec_list(struct drm_device *dev,
 		if (exec[i].flags & invalid_flags)
 			return -EINVAL;
 
+		/* Offset can be used as input (EXEC_OBJECT_PINNED), since
+		 * userspace has to use canonical format, we need to reject all
+		 * non-canonical addresses.
+		 */
+		if (exec[i].offset != gen8_canonical_addr(exec[i].offset))
+			return -EINVAL;
+
+		/* On the other hand, from drm_mm perspective address space is
+		 * continuous, so we're converting to non-canonical form
+		 */
+		exec[i].offset &= (1ULL << 48) - 1;
+
 		if (exec[i].alignment && !is_power_of_2(exec[i].alignment))
 			return -EINVAL;
 
@@ -1617,6 +1648,29 @@ pre_mutex_err:
 	return ret;
 }
 
+static inline int
+__i915_gem_execlist_copy_to_user(struct drm_i915_gem_execbuffer2 *args,
+				 struct drm_i915_gem_exec_object2 *exec2_list)
+{
+	struct drm_i915_gem_exec_object2 __user *user_exec_list =
+			   to_user_ptr(args->buffers_ptr);
+	int i;
+
+	for (i = 0; i < args->buffer_count; i++) {
+		/* Userspace uses addresses in canonical form */
+		exec2_list[i].offset = gen8_canonical_addr(exec2_list[i].offset);
+		if (__copy_to_user(&user_exec_list[i].offset,
+				   &exec2_list[i].offset,
+				   sizeof(user_exec_list[i].offset))) {
+			DRM_DEBUG("failed to copy %d exec entries back to user\n",
+				  args->buffer_count);
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+
 /*
  * Legacy execbuffer just creates an exec2 list from the original exec object
  * list array and passes it to the real function.
@@ -1681,24 +1735,10 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 	i915_execbuffer2_set_context_id(exec2, 0);
 
 	ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
-	if (!ret) {
-		struct drm_i915_gem_exec_object __user *user_exec_list =
-			to_user_ptr(args->buffers_ptr);
-
-		/* Copy the new buffer offsets back to the user's exec list. */
-		for (i = 0; i < args->buffer_count; i++) {
-			ret = __copy_to_user(&user_exec_list[i].offset,
-					     &exec2_list[i].offset,
-					     sizeof(user_exec_list[i].offset));
-			if (ret) {
-				ret = -EFAULT;
-				DRM_DEBUG("failed to copy %d exec entries "
-					  "back to user (%d)\n",
-					  args->buffer_count, ret);
-				break;
-			}
-		}
-	}
+
+	/* Copy the new buffer offsets back to the user's exec list. */
+	if (!ret)
+		ret = __i915_gem_execlist_copy_to_user(&exec2, exec2_list);
 
 	drm_free_large(exec_list);
 	drm_free_large(exec2_list);
@@ -1745,25 +1785,10 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
 	}
 
 	ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
-	if (!ret) {
-		/* Copy the new buffer offsets back to the user's exec list. */
-		struct drm_i915_gem_exec_object2 __user *user_exec_list =
-				   to_user_ptr(args->buffers_ptr);
-		int i;
-
-		for (i = 0; i < args->buffer_count; i++) {
-			ret = __copy_to_user(&user_exec_list[i].offset,
-					     &exec2_list[i].offset,
-					     sizeof(user_exec_list[i].offset));
-			if (ret) {
-				ret = -EFAULT;
-				DRM_DEBUG("failed to copy %d exec entries "
-					  "back to user\n",
-					  args->buffer_count);
-				break;
-			}
-		}
-	}
+
+	/* Copy the new buffer offsets back to the user's exec list. */
+	if (!ret)
+		ret = __i915_gem_execlist_copy_to_user(args, exec2_list);
 
 	drm_free_large(exec2_list);
 	return ret;
