[Intel-gfx] [PATCH v2 5/5] drm/i915: Use batch length instead of object size in command parser

bradley.d.volkin at intel.com bradley.d.volkin at intel.com
Wed Jul 9 00:26:40 CEST 2014


From: Brad Volkin <bradley.d.volkin at intel.com>

Previously we couldn't trust the user-supplied batch length because
it came directly from userspace (i.e. untrusted code). It would have
affected what commands software parsed without regard to what hardware
would actually execute, leaving a potential hole.

With the parser now copying the user supplied batch buffer and writing
MI_NOP commands to any space after the copied region, we can safely use
the batch length input. This should be a performance win as the actual
batch length is frequently much smaller than the allocated object size.

Signed-off-by: Brad Volkin <bradley.d.volkin at intel.com>
---
 drivers/gpu/drm/i915/i915_cmd_parser.c     | 20 +++++++++++---------
 drivers/gpu/drm/i915/i915_drv.h            |  1 +
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  1 +
 3 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c
index 18788df..2470d3b 100644
--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
+++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
@@ -833,7 +833,8 @@ finish:
 
 /* Returns a vmap'd pointer to dest_obj, which the caller must unmap */
 static u32 *copy_batch(struct drm_i915_gem_object *dest_obj,
-		       struct drm_i915_gem_object *src_obj)
+		       struct drm_i915_gem_object *src_obj,
+		       u32 batch_len)
 {
 	int ret = 0;
 	int needs_clflush = 0;
@@ -853,7 +854,7 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj,
 	}
 
 	if (needs_clflush)
-		drm_clflush_virt_range((char *)src_addr, src_obj->base.size);
+		drm_clflush_virt_range((char *)src_addr, batch_len);
 
 	ret = i915_gem_object_set_to_cpu_domain(dest_obj, true);
 	if (ret) {
@@ -868,10 +869,10 @@ static u32 *copy_batch(struct drm_i915_gem_object *dest_obj,
 		goto unmap_src;
 	}
 
-	memcpy(dest_addr, src_addr, src_obj->base.size);
-	if (dest_obj->base.size > src_obj->base.size)
-		memset((u8 *)dest_addr + src_obj->base.size, 0,
-		       dest_obj->base.size - src_obj->base.size);
+	memcpy(dest_addr, src_addr, batch_len);
+	if (dest_obj->base.size > batch_len)
+		memset((u8 *)dest_addr + batch_len, 0,
+		       dest_obj->base.size - batch_len);
 
 unmap_src:
 	vunmap(src_addr);
@@ -1015,6 +1016,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
 		    struct drm_i915_gem_object *batch_obj,
 		    struct drm_i915_gem_object *shadow_batch_obj,
 		    u32 batch_start_offset,
+		    u32 batch_len,
 		    bool is_master)
 {
 	int ret = 0;
@@ -1022,7 +1024,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
 	struct drm_i915_cmd_descriptor default_desc = { 0 };
 	bool oacontrol_set = false; /* OACONTROL tracking. See check_cmd() */
 
-	batch_base = copy_batch(shadow_batch_obj, batch_obj);
+	batch_base = copy_batch(shadow_batch_obj, batch_obj, batch_len);
 	if (IS_ERR(batch_base)) {
 		DRM_DEBUG_DRIVER("CMD: Failed to copy batch\n");
 		return PTR_ERR(batch_base);
@@ -1031,11 +1033,11 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
 	cmd = batch_base + (batch_start_offset / sizeof(*cmd));
 
 	/*
-	 * We use the source object's size because the shadow object is as
+	 * We use the batch length as size because the shadow object is as
 	 * large or larger and copy_batch() will write MI_NOPs to the extra
 	 * space. Parsing should be faster in some cases this way.
 	 */
-	batch_end = cmd + (batch_obj->base.size / sizeof(*batch_end));
+	batch_end = cmd + (batch_len / sizeof(*batch_end));
 
 	while (cmd < batch_end) {
 		const struct drm_i915_cmd_descriptor *desc;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a6b903d..49bcf79 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2627,6 +2627,7 @@ int i915_parse_cmds(struct intel_engine_cs *ring,
 		    struct drm_i915_gem_object *batch_obj,
 		    struct drm_i915_gem_object *shadow_batch_obj,
 		    u32 batch_start_offset,
+		    u32 batch_len,
 		    bool is_master);
 
 /* i915_suspend.c */
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 908cf48..69ce030 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1388,6 +1388,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 				      batch_obj,
 				      shadow_batch_obj,
 				      args->batch_start_offset,
+				      args->batch_len,
 				      file->is_master);
 		if (ret)
 			goto err;
-- 
1.8.3.2




More information about the Intel-gfx mailing list