drm/i915: rewrite shmem_pwrite_slow to use copy_from_user
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 14 Dec 2011 12:57:31 +0000 (13:57 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 30 Jan 2012 22:34:21 +0000 (23:34 +0100)
commit8c59967c448af5d77fe5189d0e73f32cd3dbe439
tree18b3a88249e8f87a517df421c17d0eca5c3bfeb7
parent5c0480f21f9896c443b0e65d779c8e09a695da7b
drm/i915: rewrite shmem_pwrite_slow to use copy_from_user

... instead of get_user_pages, because that fails on non page-backed
user addresses like e.g. a gtt mapping of a bo.

To get there essentially copy the vfs read path into pagecache. We
can't call that right away because we have to take care of bit17
swizzling. To not deadlock with our own pagefault handler we need
to completely drop struct_mutex, reducing the atomicty-guarantees
of our userspace abi. Implications for racing with other gem ioctl:

- execbuf, pwrite, pread: Due to -EFAULT fallback to slow paths there's
  already the risk of the pwrite call not being atomic, no degration.
- read/write access to mmaps: already fully racy, no degration.
- set_tiling: Calling set_tiling while reading/writing is already
  pretty much undefined, now it just got a bit worse. set_tiling is
  only called by libdrm on unused/new bos, so no problem.
- set_domain: When changing to the gtt domain while copying (without any
  read/write access, e.g. for synchronization), we might leave unflushed
  data in the cpu caches. The clflush_object at the end of pwrite_slow
  takes care of this problem.
- truncating of purgeable objects: the shmem_read_mapping_page call could
  reinstate backing storage for truncated objects. The check at the end
  of pwrite_slow takes care of this.

v2:
- add missing intel_gtt_chipset_flush
- add __ to copy_from_user_swizzled as suggest by Chris Wilson.

v3: Fixup bit17 swizzling, it swizzled the wrong pages.

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_gem.c