Merge branch 'drm-next-3.10' of git://people.freedesktop.org/~agd5f/linux into drm...
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / drm / i915 / i915_gem_execbuffer.c
index 3b11ab0fbc960ab1ff58fd842a2d51ff10ca15db..117ce38136812d1689ecc4b65ffe743a5e86a71c 100644 (file)
@@ -57,7 +57,7 @@ eb_create(struct drm_i915_gem_execbuffer2 *args)
        if (eb == NULL) {
                int size = args->buffer_count;
                int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
-               BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
+               BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
                while (count > 2*size)
                        count >>= 1;
                eb = kzalloc(count*sizeof(struct hlist_head) +
@@ -305,7 +305,7 @@ i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
        struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
        int remain, ret;
 
-       user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
+       user_relocs = to_user_ptr(entry->relocs_ptr);
 
        remain = entry->relocation_count;
        while (remain) {
@@ -359,8 +359,7 @@ i915_gem_execbuffer_relocate_object_slow(struct drm_i915_gem_object *obj,
 }
 
 static int
-i915_gem_execbuffer_relocate(struct drm_device *dev,
-                            struct eb_objects *eb)
+i915_gem_execbuffer_relocate(struct eb_objects *eb)
 {
        struct drm_i915_gem_object *obj;
        int ret = 0;
@@ -475,7 +474,6 @@ i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
 
 static int
 i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,
-                           struct drm_file *file,
                            struct list_head *objects,
                            bool *need_relocs)
 {
@@ -618,7 +616,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                u64 invalid_offset = (u64)-1;
                int j;
 
-               user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
+               user_relocs = to_user_ptr(exec[i].relocs_ptr);
 
                if (copy_from_user(reloc+total, user_relocs,
                                   exec[i].relocation_count * sizeof(*reloc))) {
@@ -663,7 +661,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
                goto err;
 
        need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-       ret = i915_gem_execbuffer_reserve(ring, file, &eb->objects, &need_relocs);
+       ret = i915_gem_execbuffer_reserve(ring, &eb->objects, &need_relocs);
        if (ret)
                goto err;
 
@@ -736,7 +734,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
        int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
 
        for (i = 0; i < count; i++) {
-               char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
+               char __user *ptr = to_user_ptr(exec[i].relocs_ptr);
                int length; /* limited by fault_in_pages_readable() */
 
                if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS)
@@ -752,7 +750,11 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
 
                length = exec[i].relocation_count *
                        sizeof(struct drm_i915_gem_relocation_entry);
-               /* we may also need to update the presumed offsets */
+               /*
+                * We must check that the entire relocation array is safe
+                * to read, but since we may need to update the presumed
+                * offsets during execution, check for full write access.
+                */
                if (!access_ok(VERIFY_WRITE, ptr, length))
                        return -EFAULT;
 
@@ -949,9 +951,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
                }
 
                if (copy_from_user(cliprects,
-                                    (struct drm_clip_rect __user *)(uintptr_t)
-                                    args->cliprects_ptr,
-                                    sizeof(*cliprects)*args->num_cliprects)) {
+                                  to_user_ptr(args->cliprects_ptr),
+                                  sizeof(*cliprects)*args->num_cliprects)) {
                        ret = -EFAULT;
                        goto pre_mutex_err;
                }
@@ -986,13 +987,13 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 
        /* Move the objects en-masse into the GTT, evicting if necessary. */
        need_relocs = (args->flags & I915_EXEC_NO_RELOC) == 0;
-       ret = i915_gem_execbuffer_reserve(ring, file, &eb->objects, &need_relocs);
+       ret = i915_gem_execbuffer_reserve(ring, &eb->objects, &need_relocs);
        if (ret)
                goto err;
 
        /* The objects are in their final locations, apply the relocations. */
        if (need_relocs)
-               ret = i915_gem_execbuffer_relocate(dev, eb);
+               ret = i915_gem_execbuffer_relocate(eb);
        if (ret) {
                if (ret == -EFAULT) {
                        ret = i915_gem_execbuffer_relocate_slow(dev, args, file, ring,
@@ -1115,7 +1116,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                return -ENOMEM;
        }
        ret = copy_from_user(exec_list,
-                            (void __user *)(uintptr_t)args->buffers_ptr,
+                            to_user_ptr(args->buffers_ptr),
                             sizeof(*exec_list) * args->buffer_count);
        if (ret != 0) {
                DRM_DEBUG("copy %d exec entries failed %d\n",
@@ -1154,7 +1155,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                for (i = 0; i < args->buffer_count; i++)
                        exec_list[i].offset = exec2_list[i].offset;
                /* ... and back out to userspace */
-               ret = copy_to_user((void __user *)(uintptr_t)args->buffers_ptr,
+               ret = copy_to_user(to_user_ptr(args->buffers_ptr),
                                   exec_list,
                                   sizeof(*exec_list) * args->buffer_count);
                if (ret) {
@@ -1195,8 +1196,7 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
                return -ENOMEM;
        }
        ret = copy_from_user(exec2_list,
-                            (struct drm_i915_relocation_entry __user *)
-                            (uintptr_t) args->buffers_ptr,
+                            to_user_ptr(args->buffers_ptr),
                             sizeof(*exec2_list) * args->buffer_count);
        if (ret != 0) {
                DRM_DEBUG("copy %d exec entries failed %d\n",
@@ -1208,7 +1208,7 @@ 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. */
-               ret = copy_to_user((void __user *)(uintptr_t)args->buffers_ptr,
+               ret = copy_to_user(to_user_ptr(args->buffers_ptr),
                                   exec2_list,
                                   sizeof(*exec2_list) * args->buffer_count);
                if (ret) {