These paths hold onto the struct mutex whilst accessing pages. In order, to prevent a recursive dead-lock should we fault-in a GTT mapped page we need to return -EFAULT and fallback to the slow path.
Lockdep has complained before about the potential dead-lock, but rvis is the first application found to sufficiently abuse the API to trigger it. Cursory performance regression testing on a 1GiB PineView system using x11perf, cairo-perf-trace, glxgears and a few game benchmarks suggested no large regressions with just a 2% slowdown for firefox. The caveat is that this was an otherwise idle system and that for 32-bit systems io_mapping_map_atomic_wc() already disabled page-faults. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=38115 Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk> --- drivers/gpu/drm/i915/i915_gem.c | 22 ++++++++++++++++++++-- 1 files changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2fce620..ecb27fd 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -365,9 +365,15 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, return PTR_ERR(page); vaddr = kmap_atomic(page); + /* We have to disable faulting here in case the user address + * is really a GTT mapping and so we can not enter + * i915_gem_fault() whilst already holding struct_mutex. + */ + pagefault_disable(); ret = __copy_to_user_inatomic(user_data, vaddr + page_offset, page_length); + pagefault_enable(); kunmap_atomic(vaddr); mark_page_accessed(page); @@ -593,8 +599,14 @@ fast_user_write(struct io_mapping *mapping, unsigned long unwritten; vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base); + /* We have to disable faulting here in case the user address + * is really a GTT mapping and so we can not enter + * i915_gem_fault() whilst already holding struct_mutex. + */ + pagefault_disable(); unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, user_data, length); + pagefault_enable(); io_mapping_unmap_atomic(vaddr_atomic); return unwritten; } @@ -812,11 +824,17 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, if (IS_ERR(page)) return PTR_ERR(page); - vaddr = kmap_atomic(page, KM_USER0); + vaddr = kmap_atomic(page); + /* We have to disable faulting here in case the user address + * is really a GTT mapping and so we can not enter + * i915_gem_fault() whilst already holding struct_mutex. + */ + pagefault_disable(); ret = __copy_from_user_inatomic(vaddr + page_offset, user_data, page_length); - kunmap_atomic(vaddr, KM_USER0); + pagefault_enable(); + kunmap_atomic(vaddr); set_page_dirty(page); mark_page_accessed(page); -- 1.7.5.4 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/intel-gfx