Skip to content

Commit

Permalink
drm/i915: don't clobber userspace memory before commiting to the pread
Browse files Browse the repository at this point in the history
The pagemap.h prefault helpers do the prefaulting by simply writing
some data into every page. Hence we should not prefault when we're not
yet commited to to actually writing data to userspace. The problem is
now that
- we can't prefault while holding dev->struct_mutex for we could
  deadlock with our own pagefault handler
- we need to grab dev->struct_mutex before copying to sync up with any
  outsanding gpu writes.

Therefore only prefault when we're dropping the lock the first time in
the pread slowpath - at that point we're committed to the write, don't
wait on the gpu anymore and hence won't return early (with e.g.
-EINTR).

Tested-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Daniel Vetter committed Mar 27, 2012
1 parent 935aaa6 commit 96d79b5
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ i915_gem_shmem_pread(struct drm_device *dev,
int shmem_page_offset, page_length, ret = 0;
int obj_do_bit17_swizzling, page_do_bit17_swizzling;
int hit_slowpath = 0;
int prefaulted = 0;
int needs_clflush = 0;
int release_page;

Expand Down Expand Up @@ -368,6 +369,16 @@ i915_gem_shmem_pread(struct drm_device *dev,
page_cache_get(page);
mutex_unlock(&dev->struct_mutex);

if (!prefaulted) {
ret = fault_in_pages_writeable(user_data, remain);
/* Userspace is tricking us, but we've already clobbered
* its pages with the prefault and promised to write the
* data up to the first fault. Hence ignore any errors
* and just continue. */
(void)ret;
prefaulted = 1;
}

vaddr = kmap(page);
if (needs_clflush)
drm_clflush_virt_range(vaddr + shmem_page_offset,
Expand Down Expand Up @@ -431,11 +442,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
args->size))
return -EFAULT;

ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr,
args->size);
if (ret)
return -EFAULT;

ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
Expand Down

0 comments on commit 96d79b5

Please sign in to comment.