aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem_execbuffer.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-05-23 05:45:52 -0400
committerJani Nikula <jani.nikula@intel.com>2014-05-27 04:18:39 -0400
commit9aab8bff7aa3bee567213ad3c1fdfb217bb980a2 (patch)
treea067229b1557076fc66d2d49e546c599ecc2052f /drivers/gpu/drm/i915/i915_gem_execbuffer.c
parent00731155a73020c8e3c215723be193f96b4fcb1f (diff)
drm/i915: Only copy back the modified fields to userspace from execbuffer
We only want to modifiy a single field in the userspace view of the execbuffer command buffer, so explicitly change that rather than copy everything back again. This serves two purposes: 1. The single fields are much cheaper to copy (constant size so the copy uses special case code) and much smaller than the whole array. 2. We modify the array for internal use that need to be masked from the user. Note: We need this backported since without it the next bugfix will blow up when userspace recycles batchbuffers and relocations. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem_execbuffer.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 2c9d9cbaf653..7aaf6390cfaf 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -773,9 +773,9 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
773 * relocations were valid. 773 * relocations were valid.
774 */ 774 */
775 for (j = 0; j < exec[i].relocation_count; j++) { 775 for (j = 0; j < exec[i].relocation_count; j++) {
776 if (copy_to_user(&user_relocs[j].presumed_offset, 776 if (__copy_to_user(&user_relocs[j].presumed_offset,
777 &invalid_offset, 777 &invalid_offset,
778 sizeof(invalid_offset))) { 778 sizeof(invalid_offset))) {
779 ret = -EFAULT; 779 ret = -EFAULT;
780 mutex_lock(&dev->struct_mutex); 780 mutex_lock(&dev->struct_mutex);
781 goto err; 781 goto err;
@@ -1355,18 +1355,21 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
1355 1355
1356 ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list); 1356 ret = i915_gem_do_execbuffer(dev, data, file, &exec2, exec2_list);
1357 if (!ret) { 1357 if (!ret) {
1358 struct drm_i915_gem_exec_object __user *user_exec_list =
1359 to_user_ptr(args->buffers_ptr);
1360
1358 /* Copy the new buffer offsets back to the user's exec list. */ 1361 /* Copy the new buffer offsets back to the user's exec list. */
1359 for (i = 0; i < args->buffer_count; i++) 1362 for (i = 0; i < args->buffer_count; i++) {
1360 exec_list[i].offset = exec2_list[i].offset; 1363 ret = __copy_to_user(&user_exec_list[i].offset,
1361 /* ... and back out to userspace */ 1364 &exec2_list[i].offset,
1362 ret = copy_to_user(to_user_ptr(args->buffers_ptr), 1365 sizeof(user_exec_list[i].offset));
1363 exec_list, 1366 if (ret) {
1364 sizeof(*exec_list) * args->buffer_count); 1367 ret = -EFAULT;
1365 if (ret) { 1368 DRM_DEBUG("failed to copy %d exec entries "
1366 ret = -EFAULT; 1369 "back to user (%d)\n",
1367 DRM_DEBUG("failed to copy %d exec entries " 1370 args->buffer_count, ret);
1368 "back to user (%d)\n", 1371 break;
1369 args->buffer_count, ret); 1372 }
1370 } 1373 }
1371 } 1374 }
1372 1375
@@ -1412,14 +1415,21 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
1412 ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list); 1415 ret = i915_gem_do_execbuffer(dev, data, file, args, exec2_list);
1413 if (!ret) { 1416 if (!ret) {
1414 /* Copy the new buffer offsets back to the user's exec list. */ 1417 /* Copy the new buffer offsets back to the user's exec list. */
1415 ret = copy_to_user(to_user_ptr(args->buffers_ptr), 1418 struct drm_i915_gem_exec_object2 *user_exec_list =
1416 exec2_list, 1419 to_user_ptr(args->buffers_ptr);
1417 sizeof(*exec2_list) * args->buffer_count); 1420 int i;
1418 if (ret) { 1421
1419 ret = -EFAULT; 1422 for (i = 0; i < args->buffer_count; i++) {
1420 DRM_DEBUG("failed to copy %d exec entries " 1423 ret = __copy_to_user(&user_exec_list[i].offset,
1421 "back to user (%d)\n", 1424 &exec2_list[i].offset,
1422 args->buffer_count, ret); 1425 sizeof(user_exec_list[i].offset));
1426 if (ret) {
1427 ret = -EFAULT;
1428 DRM_DEBUG("failed to copy %d exec entries "
1429 "back to user\n",
1430 args->buffer_count);
1431 break;
1432 }
1423 } 1433 }
1424 } 1434 }
1425 1435