[PATCH 50/54] fast-pwrite-ioctl

Chris Wilson chris at chris-wilson.co.uk
Sun Jun 4 12:08:33 UTC 2017


---
 drivers/gpu/drm/i915/i915_drv.c   |  2 +-
 drivers/gpu/drm/i915/i915_drv.h   |  5 ++--
 drivers/gpu/drm/i915/i915_gem.c   | 50 +++++++++++++++++++++++++--------------
 drivers/gpu/drm/i915/i915_utils.h |  2 +-
 4 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 4bd88294238d..cefc18785423 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -2557,7 +2557,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_GEM_LEAVEVT, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 	DRM_DRIVER_IOCTL_DEF(I915_GEM_CREATE, i915_gem_create_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_PREAD, i915_gem_pread_ioctl, DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF_DRV(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW),
+	DRM_DRIVER_IOCTL_DEF(I915_GEM_PWRITE, i915_gem_pwrite_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_MMAP, i915_gem_mmap_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_MMAP_GTT, i915_gem_mmap_gtt_ioctl, DRM_RENDER_ALLOW),
 	DRM_DRIVER_IOCTL_DEF(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW),
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 2cea49a69d1b..f970bbe608f6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3193,8 +3193,9 @@ long i915_gem_create_ioctl(struct file *filp,
 			   unsigned long data);
 int i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
-int i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv);
+long i915_gem_pwrite_ioctl(struct file *filp,
+			   unsigned int cmd,
+			   unsigned long data);
 int i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 int i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index cbf2f324a4c2..bd3b541fde06 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -619,8 +619,7 @@ i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
 
 static int
 i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
-		     struct drm_i915_gem_pwrite *args,
-		     struct drm_file *file)
+		     struct drm_i915_gem_pwrite *args)
 {
 	void *vaddr = obj->phys_handle->vaddr + args->offset;
 	char __user *user_data = u64_to_user_ptr(args->data_ptr);
@@ -1523,37 +1522,48 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
  *
  * On error, the contents of the buffer that were to be modified are undefined.
  */
-int
-i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
-		      struct drm_file *file)
+long
+i915_gem_pwrite_ioctl(struct file *filp,
+		      unsigned int cmd,
+		      unsigned long data)
 {
-	struct drm_i915_gem_pwrite *args = data;
+	struct drm_i915_gem_pwrite __user *user = (typeof(user))data;
+	struct drm_file *file = filp->private_data;
 	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_pwrite arg;
 	int ret;
 
-	if (args->size == 0)
+	if (unlikely(!access_ok(VERIFY_READ, user, sizeof(*user))))
+		return -EFAULT;
+
+	user_access_begin();
+	unsafe_get_user(arg.handle, &user->handle, err_user);
+	unsafe_get_user(arg.size, &user->size, err_user);
+	unsafe_get_user(arg.offset, &user->offset, err_user);
+	unsafe_get_user(arg.data_ptr, &user->data_ptr, err_user);
+	user_access_end();
+
+	if (arg.size == 0)
 		return 0;
 
-	if (!access_ok(VERIFY_READ,
-		       u64_to_user_ptr(args->data_ptr),
-		       args->size))
+	if (!access_ok(VERIFY_READ, u64_to_user_ptr(arg.data_ptr), arg.size))
 		return -EFAULT;
 
-	obj = i915_gem_object_lookup(file, args->handle);
-	if (!obj)
+	obj = i915_gem_object_lookup(file, arg.handle);
+	if (unlikely(!obj))
 		return -ENOENT;
 
 	/* Bounds check destination. */
-	if (range_overflows_t(u64, args->offset, args->size, obj->base.size)) {
+	if (range_overflows_t(u64, arg.offset, arg.size, obj->base.size)) {
 		ret = -EINVAL;
 		goto err;
 	}
 
-	trace_i915_gem_object_pwrite(obj, args->offset, args->size);
+	trace_i915_gem_object_pwrite(obj, arg.offset, arg.size);
 
 	ret = -ENODEV;
 	if (obj->ops->pwrite)
-		ret = obj->ops->pwrite(obj, args);
+		ret = obj->ops->pwrite(obj, &arg);
 	if (ret != -ENODEV)
 		goto err;
 
@@ -1582,19 +1592,23 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		 * pointers (e.g. gtt mappings when moving data between
 		 * textures). Fallback to the shmem path in that case.
 		 */
-		ret = i915_gem_gtt_pwrite_fast(obj, args);
+		ret = i915_gem_gtt_pwrite_fast(obj, &arg);
 
 	if (ret == -EFAULT || ret == -ENOSPC) {
 		if (obj->phys_handle)
-			ret = i915_gem_phys_pwrite(obj, args, file);
+			ret = i915_gem_phys_pwrite(obj, &arg);
 		else
-			ret = i915_gem_shmem_pwrite(obj, args);
+			ret = i915_gem_shmem_pwrite(obj, &arg);
 	}
 
 	i915_gem_object_unpin_pages(obj);
 err:
 	i915_gem_object_put(obj);
 	return ret;
+
+err_user:
+	user_access_end();
+	return -EFAULT;
 }
 
 static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj)
diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index 12fc250b47b9..b6ba7a09fe2a 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -60,7 +60,7 @@
 	typeof(max) max__ = (max); \
 	(void)(&start__ == &size__); \
 	(void)(&start__ == &max__); \
-	start__ > max__ || size__ > max__ - start__; \
+	unlikely(start__ > max__ || size__ > max__ - start__); \
 })
 
 #define range_overflows_t(type, start, size, max) \
-- 
2.11.0



More information about the Intel-gfx-trybot mailing list