[PATCH] drm/i915: Make sure we always have the vm mutex held when calling i915_vma_bind

Thomas Hellström thomas.hellstrom at linux.intel.com
Fri Nov 12 09:22:11 UTC 2021


In order to avoid special-casing for the async vma work we would like to
be able to assert that the vm mutex is always held when calling
i915_vma_bind.

This is complicated by the fact that we call i915_vma_bind from atomic
context in eb_relocate_entry, and at that point we're in atomic context
because we cache a kmap_atomic().

Replace kmap_atomic() and the io_mapping_map_atomic_wc with their
s/atomic/local/ counterparts and take the vm mutex around the call to
i915_vma_bind. When doing this also add a pagefault_disable() around the
__put_user in the relocation code since it will otherwise typically not
be called with pagefaults disabled anymore, which may trigger a deadlock
in certain situations.

Finally assert vm mutex held in i915_vma_bind.

Signed-off-by: Thomas Hellström <thomas.hellstrom at linux.intel.com>
---
 .../gpu/drm/i915/gem/i915_gem_execbuffer.c    | 26 ++++++++++++-------
 drivers/gpu/drm/i915/i915_vma.c               |  2 ++
 2 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index ea5b7b2a4d70..cc0d8b1f65dc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -1117,13 +1117,13 @@ static void reloc_cache_reset(struct reloc_cache *cache, struct i915_execbuffer
 		if (cache->vaddr & CLFLUSH_AFTER)
 			mb();
 
-		kunmap_atomic(vaddr);
+		kunmap_local(vaddr);
 		i915_gem_object_finish_access(obj);
 	} else {
 		struct i915_ggtt *ggtt = cache_to_ggtt(cache);
 
 		intel_gt_flush_ggtt_writes(ggtt->vm.gt);
-		io_mapping_unmap_atomic((void __iomem *)vaddr);
+		io_mapping_unmap_local((void __iomem *)vaddr);
 
 		if (drm_mm_node_allocated(&cache->node)) {
 			ggtt->vm.clear_range(&ggtt->vm,
@@ -1149,7 +1149,7 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj,
 	struct page *page;
 
 	if (cache->vaddr) {
-		kunmap_atomic(unmask_page(cache->vaddr));
+		kunmap_local(unmask_page(cache->vaddr));
 	} else {
 		unsigned int flushes;
 		int err;
@@ -1171,7 +1171,7 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj,
 	if (!obj->mm.dirty)
 		set_page_dirty(page);
 
-	vaddr = kmap_atomic(page);
+	vaddr = kmap_local_page(page);
 	cache->vaddr = unmask_flags(cache->vaddr) | (unsigned long)vaddr;
 	cache->page = pageno;
 
@@ -1189,7 +1189,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
 
 	if (cache->vaddr) {
 		intel_gt_flush_ggtt_writes(ggtt->vm.gt);
-		io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr));
+		io_mapping_unmap_local((void __force __iomem *)unmask_page(cache->vaddr));
 	} else {
 		struct i915_vma *vma;
 		int err;
@@ -1237,8 +1237,8 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj,
 		offset += page << PAGE_SHIFT;
 	}
 
-	vaddr = (void __force *)io_mapping_map_atomic_wc(&ggtt->iomap,
-							 offset);
+	vaddr = (void __force *)io_mapping_map_local_wc(&ggtt->iomap,
+							offset);
 	cache->page = page;
 	cache->vaddr = (unsigned long)vaddr;
 
@@ -1368,9 +1368,15 @@ eb_relocate_entry(struct i915_execbuffer *eb,
 		 */
 		if (reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION &&
 		    GRAPHICS_VER(eb->i915) == 6) {
-			err = i915_vma_bind(target->vma,
-					    target->vma->obj->cache_level,
+			struct i915_vma *vma = target->vma;
+
+			err = mutex_lock_interruptible(&vma->vm->mutex);
+			if (err)
+				return err;
+			err = i915_vma_bind(vma,
+					    vma->obj->cache_level,
 					    PIN_GLOBAL, NULL);
+			mutex_unlock(&vma->vm->mutex);
 			if (err)
 				return err;
 		}
@@ -1489,8 +1495,10 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev)
 				 * can read from this userspace address.
 				 */
 				offset = gen8_canonical_addr(offset & ~UPDATE);
+				pagefault_disable();
 				__put_user(offset,
 					   &urelocs[r - stack].presumed_offset);
+				pagefault_enable();
 			}
 		} while (r++, --count);
 		urelocs += ARRAY_SIZE(stack);
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index 8781c4f61952..2f3ce02d1242 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -376,6 +376,8 @@ int i915_vma_bind(struct i915_vma *vma,
 	u32 bind_flags;
 	u32 vma_flags;
 
+	lockdep_assert_held(&vma->vm->mutex);
+
 	GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
 	GEM_BUG_ON(vma->size > vma->node.size);
 
-- 
2.31.1



More information about the Intel-gfx-trybot mailing list