All of lore.kernel.org
 help / color / mirror / Atom feed
* [FIXES 1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
@ 2019-11-11 13:32 ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 13:32 UTC (permalink / raw)
  To: intel-gfx
  Cc: tvrtko.ursulin, joonas.lahtinen, Chris Wilson, Lionel Landwerlin,
	Tvrtko Ursulin, stable

set_page_dirty says:

	For pages with a mapping this should be done under the page lock
	for the benefit of asynchronous memory errors who prefer a
	consistent dirty state. This rule can be broken in some special
	cases, but should be better not to.

Under those rules, it is only safe for us to use the plain set_page_dirty
calls for shmemfs/anonymous memory. Userptr may be used with real
mappings and so needs to use the locked version (set_page_dirty_lock).

However, following a try_to_unmap() we may want to remove the userptr and
so call put_pages(). However, try_to_unmap() acquires the page lock and
so we must avoid recursively locking the pages ourselves -- which means
that we cannot safely acquire the lock around set_page_dirty(). Since we
can't be sure of the lock, we have to risk skip dirtying the page, or
else risk calling set_page_dirty() without a lock and so risk fs
corruption.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203317
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112012
Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video m
References: cb6d7c7dc7ff ("drm/i915/userptr: Acquire the page lock around set_page_dirty()")
References: 505a8ec7e11a ("Revert "drm/i915/userptr: Acquire the page lock around set_page_dirty()"")
References: 6dcc693bc57f ("ext4: warn when page is dirtied without buffers")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: stable@vger.kernel.org
---
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 ++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index ee65c6acf0e2..dd104b0e2071 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -646,8 +646,28 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
 		obj->mm.dirty = false;
 
 	for_each_sgt_page(page, sgt_iter, pages) {
-		if (obj->mm.dirty)
+		if (obj->mm.dirty && trylock_page(page)) {
+			/*
+			 * As this may not be anonymous memory (e.g. shmem)
+			 * but exist on a real mapping, we have to lock
+			 * the page in order to dirty it -- holding
+			 * the page reference is not sufficient to
+			 * prevent the inode from being truncated.
+			 * Play safe and take the lock.
+			 *
+			 * However...!
+			 *
+			 * The mmu-notifier can be invalidated for a
+			 * migrate_page, that is alreadying holding the lock
+			 * on the page. Such a try_to_unmap() will result
+			 * in us calling put_pages() and so recursively try
+			 * to lock the page. We avoid that deadlock with
+			 * a trylock_page() and in exchange we risk missing
+			 * some page dirtying.
+			 */
 			set_page_dirty(page);
+			unlock_page(page);
+		}
 
 		mark_page_accessed(page);
 		put_page(page);
-- 
2.24.0


^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Intel-gfx] [FIXES 1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
@ 2019-11-11 13:32 ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 13:32 UTC (permalink / raw)
  To: intel-gfx; +Cc: stable

set_page_dirty says:

	For pages with a mapping this should be done under the page lock
	for the benefit of asynchronous memory errors who prefer a
	consistent dirty state. This rule can be broken in some special
	cases, but should be better not to.

Under those rules, it is only safe for us to use the plain set_page_dirty
calls for shmemfs/anonymous memory. Userptr may be used with real
mappings and so needs to use the locked version (set_page_dirty_lock).

However, following a try_to_unmap() we may want to remove the userptr and
so call put_pages(). However, try_to_unmap() acquires the page lock and
so we must avoid recursively locking the pages ourselves -- which means
that we cannot safely acquire the lock around set_page_dirty(). Since we
can't be sure of the lock, we have to risk skip dirtying the page, or
else risk calling set_page_dirty() without a lock and so risk fs
corruption.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203317
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112012
Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video m
References: cb6d7c7dc7ff ("drm/i915/userptr: Acquire the page lock around set_page_dirty()")
References: 505a8ec7e11a ("Revert "drm/i915/userptr: Acquire the page lock around set_page_dirty()"")
References: 6dcc693bc57f ("ext4: warn when page is dirtied without buffers")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: stable@vger.kernel.org
---
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 ++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index ee65c6acf0e2..dd104b0e2071 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -646,8 +646,28 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
 		obj->mm.dirty = false;
 
 	for_each_sgt_page(page, sgt_iter, pages) {
-		if (obj->mm.dirty)
+		if (obj->mm.dirty && trylock_page(page)) {
+			/*
+			 * As this may not be anonymous memory (e.g. shmem)
+			 * but exist on a real mapping, we have to lock
+			 * the page in order to dirty it -- holding
+			 * the page reference is not sufficient to
+			 * prevent the inode from being truncated.
+			 * Play safe and take the lock.
+			 *
+			 * However...!
+			 *
+			 * The mmu-notifier can be invalidated for a
+			 * migrate_page, that is alreadying holding the lock
+			 * on the page. Such a try_to_unmap() will result
+			 * in us calling put_pages() and so recursively try
+			 * to lock the page. We avoid that deadlock with
+			 * a trylock_page() and in exchange we risk missing
+			 * some page dirtying.
+			 */
 			set_page_dirty(page);
+			unlock_page(page);
+		}
 
 		mark_page_accessed(page);
 		put_page(page);
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 13:32   ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 13:32 UTC (permalink / raw)
  To: intel-gfx

Enable gup to retry and fault the pages outside of the mmap_sem lock in
our worker. As we are inside our worker, outside of any critical path,
we can allow the mmap_sem lock to be dropped in order to service a page
fault; this in turn allows the mm to populate the page using a slow
fault handler.

Testcase: igt/gem_userptr/userfault
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index dd104b0e2071..54ebc7ab71bc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -459,26 +459,31 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
 	if (pvec != NULL) {
 		struct mm_struct *mm = obj->userptr.mm->mm;
 		unsigned int flags = 0;
+		int locked = 0;
 
 		if (!i915_gem_object_is_readonly(obj))
 			flags |= FOLL_WRITE;
 
 		ret = -EFAULT;
 		if (mmget_not_zero(mm)) {
-			down_read(&mm->mmap_sem);
 			while (pinned < npages) {
+				if (!locked) {
+					down_read(&mm->mmap_sem);
+					locked = 1;
+				}
 				ret = get_user_pages_remote
 					(work->task, mm,
 					 obj->userptr.ptr + pinned * PAGE_SIZE,
 					 npages - pinned,
 					 flags,
-					 pvec + pinned, NULL, NULL);
+					 pvec + pinned, NULL, &locked);
 				if (ret < 0)
 					break;
 
 				pinned += ret;
 			}
-			up_read(&mm->mmap_sem);
+			if (locked)
+				up_read(&mm->mmap_sem);
 			mmput(mm);
 		}
 	}
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Intel-gfx] [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 13:32   ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 13:32 UTC (permalink / raw)
  To: intel-gfx

Enable gup to retry and fault the pages outside of the mmap_sem lock in
our worker. As we are inside our worker, outside of any critical path,
we can allow the mmap_sem lock to be dropped in order to service a page
fault; this in turn allows the mm to populate the page using a slow
fault handler.

Testcase: igt/gem_userptr/userfault
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index dd104b0e2071..54ebc7ab71bc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -459,26 +459,31 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
 	if (pvec != NULL) {
 		struct mm_struct *mm = obj->userptr.mm->mm;
 		unsigned int flags = 0;
+		int locked = 0;
 
 		if (!i915_gem_object_is_readonly(obj))
 			flags |= FOLL_WRITE;
 
 		ret = -EFAULT;
 		if (mmget_not_zero(mm)) {
-			down_read(&mm->mmap_sem);
 			while (pinned < npages) {
+				if (!locked) {
+					down_read(&mm->mmap_sem);
+					locked = 1;
+				}
 				ret = get_user_pages_remote
 					(work->task, mm,
 					 obj->userptr.ptr + pinned * PAGE_SIZE,
 					 npages - pinned,
 					 flags,
-					 pvec + pinned, NULL, NULL);
+					 pvec + pinned, NULL, &locked);
 				if (ret < 0)
 					break;
 
 				pinned += ret;
 			}
-			up_read(&mm->mmap_sem);
+			if (locked)
+				up_read(&mm->mmap_sem);
 			mmput(mm);
 		}
 	}
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [FIXES 3/3] drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
@ 2019-11-11 13:32   ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 13:32 UTC (permalink / raw)
  To: intel-gfx

The gem_ctx_persistence/smoketest was detecting an odd coherency issue
inside the LRC context image; that the address of the ring buffer did
not match our associated struct intel_ring. As we set the address into
the context image when we pin the ring buffer into place before the
context is active, that leaves the question of where did it get
overwritten. Either the HW context save occurred after our pin which
would imply that our idle barriers are broken, or we overwrote the
context image ourselves. It is only in reset_active() where we dabble
inside the context image outside of a serialised path from schedule-out;
but we could equally perform the operation inside schedule-in which is
then fully serialised with the context pin -- and remains serialised by
the engine pulse with kill_context(). (The only downside, aside from
doing more work inside the engine->active.lock, was the plan to merge
all the reset paths into doing their context scrubbing on schedule-out
needs more thought.)

Fixes: d12acee84ffb ("drm/i915/execlists: Cancel banned contexts on schedule-out")
Testcase: igt/gem_ctx_persistence/smoketest
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
---
 drivers/gpu/drm/i915/gt/intel_lrc.c | 114 ++++++++++++++--------------
 1 file changed, 57 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index e57345795c08..4b6d9e6b1bfd 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1042,6 +1042,59 @@ execlists_check_context(const struct intel_context *ce,
 	WARN_ONCE(!valid, "Invalid lrc state found before submission\n");
 }
 
+static void restore_default_state(struct intel_context *ce,
+				  struct intel_engine_cs *engine)
+{
+	u32 *regs = ce->lrc_reg_state;
+
+	if (engine->pinned_default_state)
+		memcpy(regs, /* skip restoring the vanilla PPHWSP */
+		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
+		       engine->context_size - PAGE_SIZE);
+
+	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
+}
+
+static void reset_active(struct i915_request *rq,
+			 struct intel_engine_cs *engine)
+{
+	struct intel_context * const ce = rq->hw_context;
+	u32 head;
+
+	/*
+	 * The executing context has been cancelled. We want to prevent
+	 * further execution along this context and propagate the error on
+	 * to anything depending on its results.
+	 *
+	 * In __i915_request_submit(), we apply the -EIO and remove the
+	 * requests' payloads for any banned requests. But first, we must
+	 * rewind the context back to the start of the incomplete request so
+	 * that we do not jump back into the middle of the batch.
+	 *
+	 * We preserve the breadcrumbs and semaphores of the incomplete
+	 * requests so that inter-timeline dependencies (i.e other timelines)
+	 * remain correctly ordered. And we defer to __i915_request_submit()
+	 * so that all asynchronous waits are correctly handled.
+	 */
+	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
+		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
+
+	/* On resubmission of the active request, payload will be scrubbed */
+	if (i915_request_completed(rq))
+		head = rq->tail;
+	else
+		head = active_request(ce->timeline, rq)->head;
+	ce->ring->head = intel_ring_wrap(ce->ring, head);
+	intel_ring_update_space(ce->ring);
+
+	/* Scrub the context image to prevent replaying the previous batch */
+	restore_default_state(ce, engine);
+	__execlists_update_reg_state(ce, engine);
+
+	/* We've switched away, so this should be a no-op, but intent matters */
+	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
+}
+
 static inline struct intel_engine_cs *
 __execlists_schedule_in(struct i915_request *rq)
 {
@@ -1050,8 +1103,11 @@ __execlists_schedule_in(struct i915_request *rq)
 
 	intel_context_get(ce);
 
+	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
+		reset_active(rq, engine);
+
 	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
-		execlists_check_context(ce, rq->engine);
+		execlists_check_context(ce, engine);
 
 	if (ce->tag) {
 		/* Use a fixed tag for OA and friends */
@@ -1102,59 +1158,6 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
 		tasklet_schedule(&ve->base.execlists.tasklet);
 }
 
-static void restore_default_state(struct intel_context *ce,
-				  struct intel_engine_cs *engine)
-{
-	u32 *regs = ce->lrc_reg_state;
-
-	if (engine->pinned_default_state)
-		memcpy(regs, /* skip restoring the vanilla PPHWSP */
-		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
-		       engine->context_size - PAGE_SIZE);
-
-	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
-}
-
-static void reset_active(struct i915_request *rq,
-			 struct intel_engine_cs *engine)
-{
-	struct intel_context * const ce = rq->hw_context;
-	u32 head;
-
-	/*
-	 * The executing context has been cancelled. We want to prevent
-	 * further execution along this context and propagate the error on
-	 * to anything depending on its results.
-	 *
-	 * In __i915_request_submit(), we apply the -EIO and remove the
-	 * requests' payloads for any banned requests. But first, we must
-	 * rewind the context back to the start of the incomplete request so
-	 * that we do not jump back into the middle of the batch.
-	 *
-	 * We preserve the breadcrumbs and semaphores of the incomplete
-	 * requests so that inter-timeline dependencies (i.e other timelines)
-	 * remain correctly ordered. And we defer to __i915_request_submit()
-	 * so that all asynchronous waits are correctly handled.
-	 */
-	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
-		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
-
-	/* On resubmission of the active request, payload will be scrubbed */
-	if (i915_request_completed(rq))
-		head = rq->tail;
-	else
-		head = active_request(ce->timeline, rq)->head;
-	ce->ring->head = intel_ring_wrap(ce->ring, head);
-	intel_ring_update_space(ce->ring);
-
-	/* Scrub the context image to prevent replaying the previous batch */
-	restore_default_state(ce, engine);
-	__execlists_update_reg_state(ce, engine);
-
-	/* We've switched away, so this should be a no-op, but intent matters */
-	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
-}
-
 static inline void
 __execlists_schedule_out(struct i915_request *rq,
 			 struct intel_engine_cs * const engine)
@@ -1165,9 +1168,6 @@ __execlists_schedule_out(struct i915_request *rq,
 	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
 	intel_gt_pm_put(engine->gt);
 
-	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
-		reset_active(rq, engine);
-
 	/*
 	 * If this is part of a virtual engine, its next request may
 	 * have been blocked waiting for access to the active context.
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* [Intel-gfx] [FIXES 3/3] drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
@ 2019-11-11 13:32   ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 13:32 UTC (permalink / raw)
  To: intel-gfx

The gem_ctx_persistence/smoketest was detecting an odd coherency issue
inside the LRC context image; that the address of the ring buffer did
not match our associated struct intel_ring. As we set the address into
the context image when we pin the ring buffer into place before the
context is active, that leaves the question of where did it get
overwritten. Either the HW context save occurred after our pin which
would imply that our idle barriers are broken, or we overwrote the
context image ourselves. It is only in reset_active() where we dabble
inside the context image outside of a serialised path from schedule-out;
but we could equally perform the operation inside schedule-in which is
then fully serialised with the context pin -- and remains serialised by
the engine pulse with kill_context(). (The only downside, aside from
doing more work inside the engine->active.lock, was the plan to merge
all the reset paths into doing their context scrubbing on schedule-out
needs more thought.)

Fixes: d12acee84ffb ("drm/i915/execlists: Cancel banned contexts on schedule-out")
Testcase: igt/gem_ctx_persistence/smoketest
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
---
 drivers/gpu/drm/i915/gt/intel_lrc.c | 114 ++++++++++++++--------------
 1 file changed, 57 insertions(+), 57 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index e57345795c08..4b6d9e6b1bfd 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1042,6 +1042,59 @@ execlists_check_context(const struct intel_context *ce,
 	WARN_ONCE(!valid, "Invalid lrc state found before submission\n");
 }
 
+static void restore_default_state(struct intel_context *ce,
+				  struct intel_engine_cs *engine)
+{
+	u32 *regs = ce->lrc_reg_state;
+
+	if (engine->pinned_default_state)
+		memcpy(regs, /* skip restoring the vanilla PPHWSP */
+		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
+		       engine->context_size - PAGE_SIZE);
+
+	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
+}
+
+static void reset_active(struct i915_request *rq,
+			 struct intel_engine_cs *engine)
+{
+	struct intel_context * const ce = rq->hw_context;
+	u32 head;
+
+	/*
+	 * The executing context has been cancelled. We want to prevent
+	 * further execution along this context and propagate the error on
+	 * to anything depending on its results.
+	 *
+	 * In __i915_request_submit(), we apply the -EIO and remove the
+	 * requests' payloads for any banned requests. But first, we must
+	 * rewind the context back to the start of the incomplete request so
+	 * that we do not jump back into the middle of the batch.
+	 *
+	 * We preserve the breadcrumbs and semaphores of the incomplete
+	 * requests so that inter-timeline dependencies (i.e other timelines)
+	 * remain correctly ordered. And we defer to __i915_request_submit()
+	 * so that all asynchronous waits are correctly handled.
+	 */
+	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
+		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
+
+	/* On resubmission of the active request, payload will be scrubbed */
+	if (i915_request_completed(rq))
+		head = rq->tail;
+	else
+		head = active_request(ce->timeline, rq)->head;
+	ce->ring->head = intel_ring_wrap(ce->ring, head);
+	intel_ring_update_space(ce->ring);
+
+	/* Scrub the context image to prevent replaying the previous batch */
+	restore_default_state(ce, engine);
+	__execlists_update_reg_state(ce, engine);
+
+	/* We've switched away, so this should be a no-op, but intent matters */
+	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
+}
+
 static inline struct intel_engine_cs *
 __execlists_schedule_in(struct i915_request *rq)
 {
@@ -1050,8 +1103,11 @@ __execlists_schedule_in(struct i915_request *rq)
 
 	intel_context_get(ce);
 
+	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
+		reset_active(rq, engine);
+
 	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
-		execlists_check_context(ce, rq->engine);
+		execlists_check_context(ce, engine);
 
 	if (ce->tag) {
 		/* Use a fixed tag for OA and friends */
@@ -1102,59 +1158,6 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
 		tasklet_schedule(&ve->base.execlists.tasklet);
 }
 
-static void restore_default_state(struct intel_context *ce,
-				  struct intel_engine_cs *engine)
-{
-	u32 *regs = ce->lrc_reg_state;
-
-	if (engine->pinned_default_state)
-		memcpy(regs, /* skip restoring the vanilla PPHWSP */
-		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
-		       engine->context_size - PAGE_SIZE);
-
-	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
-}
-
-static void reset_active(struct i915_request *rq,
-			 struct intel_engine_cs *engine)
-{
-	struct intel_context * const ce = rq->hw_context;
-	u32 head;
-
-	/*
-	 * The executing context has been cancelled. We want to prevent
-	 * further execution along this context and propagate the error on
-	 * to anything depending on its results.
-	 *
-	 * In __i915_request_submit(), we apply the -EIO and remove the
-	 * requests' payloads for any banned requests. But first, we must
-	 * rewind the context back to the start of the incomplete request so
-	 * that we do not jump back into the middle of the batch.
-	 *
-	 * We preserve the breadcrumbs and semaphores of the incomplete
-	 * requests so that inter-timeline dependencies (i.e other timelines)
-	 * remain correctly ordered. And we defer to __i915_request_submit()
-	 * so that all asynchronous waits are correctly handled.
-	 */
-	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
-		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
-
-	/* On resubmission of the active request, payload will be scrubbed */
-	if (i915_request_completed(rq))
-		head = rq->tail;
-	else
-		head = active_request(ce->timeline, rq)->head;
-	ce->ring->head = intel_ring_wrap(ce->ring, head);
-	intel_ring_update_space(ce->ring);
-
-	/* Scrub the context image to prevent replaying the previous batch */
-	restore_default_state(ce, engine);
-	__execlists_update_reg_state(ce, engine);
-
-	/* We've switched away, so this should be a no-op, but intent matters */
-	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
-}
-
 static inline void
 __execlists_schedule_out(struct i915_request *rq,
 			 struct intel_engine_cs * const engine)
@@ -1165,9 +1168,6 @@ __execlists_schedule_out(struct i915_request *rq,
 	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
 	intel_gt_pm_put(engine->gt);
 
-	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
-		reset_active(rq, engine);
-
 	/*
 	 * If this is part of a virtual engine, its next request may
 	 * have been blocked waiting for access to the active context.
-- 
2.24.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 22+ messages in thread

* Re: [FIXES 1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
@ 2019-11-11 14:12   ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 14:12 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx
  Cc: joonas.lahtinen, Lionel Landwerlin, Tvrtko Ursulin, stable


On 11/11/2019 13:32, Chris Wilson wrote:
> set_page_dirty says:
> 
> 	For pages with a mapping this should be done under the page lock
> 	for the benefit of asynchronous memory errors who prefer a
> 	consistent dirty state. This rule can be broken in some special
> 	cases, but should be better not to.
> 
> Under those rules, it is only safe for us to use the plain set_page_dirty
> calls for shmemfs/anonymous memory. Userptr may be used with real
> mappings and so needs to use the locked version (set_page_dirty_lock).
> 
> However, following a try_to_unmap() we may want to remove the userptr and
> so call put_pages(). However, try_to_unmap() acquires the page lock and
> so we must avoid recursively locking the pages ourselves -- which means
> that we cannot safely acquire the lock around set_page_dirty(). Since we
> can't be sure of the lock, we have to risk skip dirtying the page, or
> else risk calling set_page_dirty() without a lock and so risk fs
> corruption.
> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203317
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112012
> Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video m
> References: cb6d7c7dc7ff ("drm/i915/userptr: Acquire the page lock around set_page_dirty()")
> References: 505a8ec7e11a ("Revert "drm/i915/userptr: Acquire the page lock around set_page_dirty()"")
> References: 6dcc693bc57f ("ext4: warn when page is dirtied without buffers")
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Cc: stable@vger.kernel.org
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 ++++++++++++++++++++-
>   1 file changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> index ee65c6acf0e2..dd104b0e2071 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> @@ -646,8 +646,28 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
>   		obj->mm.dirty = false;
>   
>   	for_each_sgt_page(page, sgt_iter, pages) {
> -		if (obj->mm.dirty)
> +		if (obj->mm.dirty && trylock_page(page)) {
> +			/*
> +			 * As this may not be anonymous memory (e.g. shmem)
> +			 * but exist on a real mapping, we have to lock
> +			 * the page in order to dirty it -- holding
> +			 * the page reference is not sufficient to
> +			 * prevent the inode from being truncated.
> +			 * Play safe and take the lock.
> +			 *
> +			 * However...!
> +			 *
> +			 * The mmu-notifier can be invalidated for a
> +			 * migrate_page, that is alreadying holding the lock
> +			 * on the page. Such a try_to_unmap() will result
> +			 * in us calling put_pages() and so recursively try
> +			 * to lock the page. We avoid that deadlock with
> +			 * a trylock_page() and in exchange we risk missing
> +			 * some page dirtying.
> +			 */
>   			set_page_dirty(page);
> +			unlock_page(page);
> +		}
>   
>   		mark_page_accessed(page);
>   		put_page(page);
> 

It looks that the bug report could be about BUG_ON(PageWriteback(page)) 
in ext4/mpage_prepare_extent_to_map which would be somewhat consistent 
with not being allowed to call set_page_dirty on an unlocked page. So on 
the basis of that:

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Intel-gfx] [FIXES 1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
@ 2019-11-11 14:12   ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 14:12 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx; +Cc: stable


On 11/11/2019 13:32, Chris Wilson wrote:
> set_page_dirty says:
> 
> 	For pages with a mapping this should be done under the page lock
> 	for the benefit of asynchronous memory errors who prefer a
> 	consistent dirty state. This rule can be broken in some special
> 	cases, but should be better not to.
> 
> Under those rules, it is only safe for us to use the plain set_page_dirty
> calls for shmemfs/anonymous memory. Userptr may be used with real
> mappings and so needs to use the locked version (set_page_dirty_lock).
> 
> However, following a try_to_unmap() we may want to remove the userptr and
> so call put_pages(). However, try_to_unmap() acquires the page lock and
> so we must avoid recursively locking the pages ourselves -- which means
> that we cannot safely acquire the lock around set_page_dirty(). Since we
> can't be sure of the lock, we have to risk skip dirtying the page, or
> else risk calling set_page_dirty() without a lock and so risk fs
> corruption.
> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=203317
> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=112012
> Fixes: 5cc9ed4b9a7a ("drm/i915: Introduce mapping of user pages into video m
> References: cb6d7c7dc7ff ("drm/i915/userptr: Acquire the page lock around set_page_dirty()")
> References: 505a8ec7e11a ("Revert "drm/i915/userptr: Acquire the page lock around set_page_dirty()"")
> References: 6dcc693bc57f ("ext4: warn when page is dirtied without buffers")
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
> Cc: stable@vger.kernel.org
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 22 ++++++++++++++++++++-
>   1 file changed, 21 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> index ee65c6acf0e2..dd104b0e2071 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> @@ -646,8 +646,28 @@ i915_gem_userptr_put_pages(struct drm_i915_gem_object *obj,
>   		obj->mm.dirty = false;
>   
>   	for_each_sgt_page(page, sgt_iter, pages) {
> -		if (obj->mm.dirty)
> +		if (obj->mm.dirty && trylock_page(page)) {
> +			/*
> +			 * As this may not be anonymous memory (e.g. shmem)
> +			 * but exist on a real mapping, we have to lock
> +			 * the page in order to dirty it -- holding
> +			 * the page reference is not sufficient to
> +			 * prevent the inode from being truncated.
> +			 * Play safe and take the lock.
> +			 *
> +			 * However...!
> +			 *
> +			 * The mmu-notifier can be invalidated for a
> +			 * migrate_page, that is alreadying holding the lock
> +			 * on the page. Such a try_to_unmap() will result
> +			 * in us calling put_pages() and so recursively try
> +			 * to lock the page. We avoid that deadlock with
> +			 * a trylock_page() and in exchange we risk missing
> +			 * some page dirtying.
> +			 */
>   			set_page_dirty(page);
> +			unlock_page(page);
> +		}
>   
>   		mark_page_accessed(page);
>   		put_page(page);
> 

It looks that the bug report could be about BUG_ON(PageWriteback(page)) 
in ext4/mpage_prepare_extent_to_map which would be somewhat consistent 
with not being allowed to call set_page_dirty on an unlocked page. So on 
the basis of that:

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 14:19     ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 14:19 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 11/11/2019 13:32, Chris Wilson wrote:
> Enable gup to retry and fault the pages outside of the mmap_sem lock in
> our worker. As we are inside our worker, outside of any critical path,
> we can allow the mmap_sem lock to be dropped in order to service a page
> fault; this in turn allows the mm to populate the page using a slow
> fault handler.
> 
> Testcase: igt/gem_userptr/userfault

There are no references or explanation on what does this fix?

Regards,

Tvrtko

> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 11 ++++++++---
>   1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> index dd104b0e2071..54ebc7ab71bc 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> @@ -459,26 +459,31 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
>   	if (pvec != NULL) {
>   		struct mm_struct *mm = obj->userptr.mm->mm;
>   		unsigned int flags = 0;
> +		int locked = 0;
>   
>   		if (!i915_gem_object_is_readonly(obj))
>   			flags |= FOLL_WRITE;
>   
>   		ret = -EFAULT;
>   		if (mmget_not_zero(mm)) {
> -			down_read(&mm->mmap_sem);
>   			while (pinned < npages) {
> +				if (!locked) {
> +					down_read(&mm->mmap_sem);
> +					locked = 1;
> +				}
>   				ret = get_user_pages_remote
>   					(work->task, mm,
>   					 obj->userptr.ptr + pinned * PAGE_SIZE,
>   					 npages - pinned,
>   					 flags,
> -					 pvec + pinned, NULL, NULL);
> +					 pvec + pinned, NULL, &locked);
>   				if (ret < 0)
>   					break;
>   
>   				pinned += ret;
>   			}
> -			up_read(&mm->mmap_sem);
> +			if (locked)
> +				up_read(&mm->mmap_sem);
>   			mmput(mm);
>   		}
>   	}
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Intel-gfx] [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 14:19     ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 14:19 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 11/11/2019 13:32, Chris Wilson wrote:
> Enable gup to retry and fault the pages outside of the mmap_sem lock in
> our worker. As we are inside our worker, outside of any critical path,
> we can allow the mmap_sem lock to be dropped in order to service a page
> fault; this in turn allows the mm to populate the page using a slow
> fault handler.
> 
> Testcase: igt/gem_userptr/userfault

There are no references or explanation on what does this fix?

Regards,

Tvrtko

> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> ---
>   drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 11 ++++++++---
>   1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> index dd104b0e2071..54ebc7ab71bc 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
> @@ -459,26 +459,31 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
>   	if (pvec != NULL) {
>   		struct mm_struct *mm = obj->userptr.mm->mm;
>   		unsigned int flags = 0;
> +		int locked = 0;
>   
>   		if (!i915_gem_object_is_readonly(obj))
>   			flags |= FOLL_WRITE;
>   
>   		ret = -EFAULT;
>   		if (mmget_not_zero(mm)) {
> -			down_read(&mm->mmap_sem);
>   			while (pinned < npages) {
> +				if (!locked) {
> +					down_read(&mm->mmap_sem);
> +					locked = 1;
> +				}
>   				ret = get_user_pages_remote
>   					(work->task, mm,
>   					 obj->userptr.ptr + pinned * PAGE_SIZE,
>   					 npages - pinned,
>   					 flags,
> -					 pvec + pinned, NULL, NULL);
> +					 pvec + pinned, NULL, &locked);
>   				if (ret < 0)
>   					break;
>   
>   				pinned += ret;
>   			}
> -			up_read(&mm->mmap_sem);
> +			if (locked)
> +				up_read(&mm->mmap_sem);
>   			mmput(mm);
>   		}
>   	}
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 14:27       ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 14:27 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

Quoting Tvrtko Ursulin (2019-11-11 14:19:31)
> 
> On 11/11/2019 13:32, Chris Wilson wrote:
> > Enable gup to retry and fault the pages outside of the mmap_sem lock in
> > our worker. As we are inside our worker, outside of any critical path,
> > we can allow the mmap_sem lock to be dropped in order to service a page
> > fault; this in turn allows the mm to populate the page using a slow
> > fault handler.
> > 
> > Testcase: igt/gem_userptr/userfault
> 
> There are no references or explanation on what does this fix?

gup simply fails if it is not allowed to drop the lock for some faults,

__get_user_pages_locked:
                ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages,
                                       vmas, locked);
                if (!locked)
                        /* VM_FAULT_RETRY couldn't trigger, bypass */
                        return ret;

userfault being the first time I discovered this even existed. Since we
are only holding the mmap_sem for the gup (and not protecting anything
else) we can simply allow gup to drop the lock if it needs to.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Intel-gfx] [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 14:27       ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 14:27 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

Quoting Tvrtko Ursulin (2019-11-11 14:19:31)
> 
> On 11/11/2019 13:32, Chris Wilson wrote:
> > Enable gup to retry and fault the pages outside of the mmap_sem lock in
> > our worker. As we are inside our worker, outside of any critical path,
> > we can allow the mmap_sem lock to be dropped in order to service a page
> > fault; this in turn allows the mm to populate the page using a slow
> > fault handler.
> > 
> > Testcase: igt/gem_userptr/userfault
> 
> There are no references or explanation on what does this fix?

gup simply fails if it is not allowed to drop the lock for some faults,

__get_user_pages_locked:
                ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages,
                                       vmas, locked);
                if (!locked)
                        /* VM_FAULT_RETRY couldn't trigger, bypass */
                        return ret;

userfault being the first time I discovered this even existed. Since we
are only holding the mmap_sem for the gup (and not protecting anything
else) we can simply allow gup to drop the lock if it needs to.
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 14:32         ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 14:32 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

Quoting Chris Wilson (2019-11-11 14:27:16)
> Quoting Tvrtko Ursulin (2019-11-11 14:19:31)
> > 
> > On 11/11/2019 13:32, Chris Wilson wrote:
> > > Enable gup to retry and fault the pages outside of the mmap_sem lock in
> > > our worker. As we are inside our worker, outside of any critical path,
> > > we can allow the mmap_sem lock to be dropped in order to service a page
> > > fault; this in turn allows the mm to populate the page using a slow
> > > fault handler.
> > > 
> > > Testcase: igt/gem_userptr/userfault
> > 
> > There are no references or explanation on what does this fix?
> 
> gup simply fails if it is not allowed to drop the lock for some faults,
> 
> __get_user_pages_locked:
>                 ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages,
>                                        vmas, locked);
>                 if (!locked)
>                         /* VM_FAULT_RETRY couldn't trigger, bypass */
>                         return ret;
> 
> userfault being the first time I discovered this even existed. Since we
> are only holding the mmap_sem for the gup (and not protecting anything
> else) we can simply allow gup to drop the lock if it needs to.

Fixes: 5b56d49fc31d ("mm: add locked parameter to get_user_pages_remote()")
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Intel-gfx] [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 14:32         ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 14:32 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

Quoting Chris Wilson (2019-11-11 14:27:16)
> Quoting Tvrtko Ursulin (2019-11-11 14:19:31)
> > 
> > On 11/11/2019 13:32, Chris Wilson wrote:
> > > Enable gup to retry and fault the pages outside of the mmap_sem lock in
> > > our worker. As we are inside our worker, outside of any critical path,
> > > we can allow the mmap_sem lock to be dropped in order to service a page
> > > fault; this in turn allows the mm to populate the page using a slow
> > > fault handler.
> > > 
> > > Testcase: igt/gem_userptr/userfault
> > 
> > There are no references or explanation on what does this fix?
> 
> gup simply fails if it is not allowed to drop the lock for some faults,
> 
> __get_user_pages_locked:
>                 ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages,
>                                        vmas, locked);
>                 if (!locked)
>                         /* VM_FAULT_RETRY couldn't trigger, bypass */
>                         return ret;
> 
> userfault being the first time I discovered this even existed. Since we
> are only holding the mmap_sem for the gup (and not protecting anything
> else) we can simply allow gup to drop the lock if it needs to.

Fixes: 5b56d49fc31d ("mm: add locked parameter to get_user_pages_remote()")
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 15:44           ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 15:44 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 11/11/2019 14:32, Chris Wilson wrote:
> Quoting Chris Wilson (2019-11-11 14:27:16)
>> Quoting Tvrtko Ursulin (2019-11-11 14:19:31)
>>>
>>> On 11/11/2019 13:32, Chris Wilson wrote:
>>>> Enable gup to retry and fault the pages outside of the mmap_sem lock in
>>>> our worker. As we are inside our worker, outside of any critical path,
>>>> we can allow the mmap_sem lock to be dropped in order to service a page
>>>> fault; this in turn allows the mm to populate the page using a slow
>>>> fault handler.
>>>>
>>>> Testcase: igt/gem_userptr/userfault
>>>
>>> There are no references or explanation on what does this fix?
>>
>> gup simply fails if it is not allowed to drop the lock for some faults,
>>
>> __get_user_pages_locked:
>>                  ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages,
>>                                         vmas, locked);
>>                  if (!locked)
>>                          /* VM_FAULT_RETRY couldn't trigger, bypass */
>>                          return ret;
>>
>> userfault being the first time I discovered this even existed. Since we
>> are only holding the mmap_sem for the gup (and not protecting anything
>> else) we can simply allow gup to drop the lock if it needs to.
> 
> Fixes: 5b56d49fc31d ("mm: add locked parameter to get_user_pages_remote()")

s/Fixes/Reference/ I guess.

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Intel-gfx] [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries
@ 2019-11-11 15:44           ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 15:44 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 11/11/2019 14:32, Chris Wilson wrote:
> Quoting Chris Wilson (2019-11-11 14:27:16)
>> Quoting Tvrtko Ursulin (2019-11-11 14:19:31)
>>>
>>> On 11/11/2019 13:32, Chris Wilson wrote:
>>>> Enable gup to retry and fault the pages outside of the mmap_sem lock in
>>>> our worker. As we are inside our worker, outside of any critical path,
>>>> we can allow the mmap_sem lock to be dropped in order to service a page
>>>> fault; this in turn allows the mm to populate the page using a slow
>>>> fault handler.
>>>>
>>>> Testcase: igt/gem_userptr/userfault
>>>
>>> There are no references or explanation on what does this fix?
>>
>> gup simply fails if it is not allowed to drop the lock for some faults,
>>
>> __get_user_pages_locked:
>>                  ret = __get_user_pages(tsk, mm, start, nr_pages, flags, pages,
>>                                         vmas, locked);
>>                  if (!locked)
>>                          /* VM_FAULT_RETRY couldn't trigger, bypass */
>>                          return ret;
>>
>> userfault being the first time I discovered this even existed. Since we
>> are only holding the mmap_sem for the gup (and not protecting anything
>> else) we can simply allow gup to drop the lock if it needs to.
> 
> Fixes: 5b56d49fc31d ("mm: add locked parameter to get_user_pages_remote()")

s/Fixes/Reference/ I guess.

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [FIXES 3/3] drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
@ 2019-11-11 16:31     ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 16:31 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 11/11/2019 13:32, Chris Wilson wrote:
> The gem_ctx_persistence/smoketest was detecting an odd coherency issue
> inside the LRC context image; that the address of the ring buffer did
> not match our associated struct intel_ring. As we set the address into
> the context image when we pin the ring buffer into place before the
> context is active, that leaves the question of where did it get
> overwritten. Either the HW context save occurred after our pin which
> would imply that our idle barriers are broken, or we overwrote the
> context image ourselves. It is only in reset_active() where we dabble
> inside the context image outside of a serialised path from schedule-out;
> but we could equally perform the operation inside schedule-in which is
> then fully serialised with the context pin -- and remains serialised by
> the engine pulse with kill_context(). (The only downside, aside from
> doing more work inside the engine->active.lock, was the plan to merge
> all the reset paths into doing their context scrubbing on schedule-out
> needs more thought.)

So process_csb is not under the engine lock and hence schedule_out can 
race with schedule_in meaning schedule_out should refrain from doing 
non-trivial work.

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko

> 
> Fixes: d12acee84ffb ("drm/i915/execlists: Cancel banned contexts on schedule-out")
> Testcase: igt/gem_ctx_persistence/smoketest
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/gt/intel_lrc.c | 114 ++++++++++++++--------------
>   1 file changed, 57 insertions(+), 57 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
> index e57345795c08..4b6d9e6b1bfd 100644
> --- a/drivers/gpu/drm/i915/gt/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
> @@ -1042,6 +1042,59 @@ execlists_check_context(const struct intel_context *ce,
>   	WARN_ONCE(!valid, "Invalid lrc state found before submission\n");
>   }
>   
> +static void restore_default_state(struct intel_context *ce,
> +				  struct intel_engine_cs *engine)
> +{
> +	u32 *regs = ce->lrc_reg_state;
> +
> +	if (engine->pinned_default_state)
> +		memcpy(regs, /* skip restoring the vanilla PPHWSP */
> +		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
> +		       engine->context_size - PAGE_SIZE);
> +
> +	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
> +}
> +
> +static void reset_active(struct i915_request *rq,
> +			 struct intel_engine_cs *engine)
> +{
> +	struct intel_context * const ce = rq->hw_context;
> +	u32 head;
> +
> +	/*
> +	 * The executing context has been cancelled. We want to prevent
> +	 * further execution along this context and propagate the error on
> +	 * to anything depending on its results.
> +	 *
> +	 * In __i915_request_submit(), we apply the -EIO and remove the
> +	 * requests' payloads for any banned requests. But first, we must
> +	 * rewind the context back to the start of the incomplete request so
> +	 * that we do not jump back into the middle of the batch.
> +	 *
> +	 * We preserve the breadcrumbs and semaphores of the incomplete
> +	 * requests so that inter-timeline dependencies (i.e other timelines)
> +	 * remain correctly ordered. And we defer to __i915_request_submit()
> +	 * so that all asynchronous waits are correctly handled.
> +	 */
> +	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
> +		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
> +
> +	/* On resubmission of the active request, payload will be scrubbed */
> +	if (i915_request_completed(rq))
> +		head = rq->tail;
> +	else
> +		head = active_request(ce->timeline, rq)->head;
> +	ce->ring->head = intel_ring_wrap(ce->ring, head);
> +	intel_ring_update_space(ce->ring);
> +
> +	/* Scrub the context image to prevent replaying the previous batch */
> +	restore_default_state(ce, engine);
> +	__execlists_update_reg_state(ce, engine);
> +
> +	/* We've switched away, so this should be a no-op, but intent matters */
> +	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
> +}
> +
>   static inline struct intel_engine_cs *
>   __execlists_schedule_in(struct i915_request *rq)
>   {
> @@ -1050,8 +1103,11 @@ __execlists_schedule_in(struct i915_request *rq)
>   
>   	intel_context_get(ce);
>   
> +	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
> +		reset_active(rq, engine);
> +
>   	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
> -		execlists_check_context(ce, rq->engine);
> +		execlists_check_context(ce, engine);
>   
>   	if (ce->tag) {
>   		/* Use a fixed tag for OA and friends */
> @@ -1102,59 +1158,6 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
>   		tasklet_schedule(&ve->base.execlists.tasklet);
>   }
>   
> -static void restore_default_state(struct intel_context *ce,
> -				  struct intel_engine_cs *engine)
> -{
> -	u32 *regs = ce->lrc_reg_state;
> -
> -	if (engine->pinned_default_state)
> -		memcpy(regs, /* skip restoring the vanilla PPHWSP */
> -		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
> -		       engine->context_size - PAGE_SIZE);
> -
> -	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
> -}
> -
> -static void reset_active(struct i915_request *rq,
> -			 struct intel_engine_cs *engine)
> -{
> -	struct intel_context * const ce = rq->hw_context;
> -	u32 head;
> -
> -	/*
> -	 * The executing context has been cancelled. We want to prevent
> -	 * further execution along this context and propagate the error on
> -	 * to anything depending on its results.
> -	 *
> -	 * In __i915_request_submit(), we apply the -EIO and remove the
> -	 * requests' payloads for any banned requests. But first, we must
> -	 * rewind the context back to the start of the incomplete request so
> -	 * that we do not jump back into the middle of the batch.
> -	 *
> -	 * We preserve the breadcrumbs and semaphores of the incomplete
> -	 * requests so that inter-timeline dependencies (i.e other timelines)
> -	 * remain correctly ordered. And we defer to __i915_request_submit()
> -	 * so that all asynchronous waits are correctly handled.
> -	 */
> -	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
> -		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
> -
> -	/* On resubmission of the active request, payload will be scrubbed */
> -	if (i915_request_completed(rq))
> -		head = rq->tail;
> -	else
> -		head = active_request(ce->timeline, rq)->head;
> -	ce->ring->head = intel_ring_wrap(ce->ring, head);
> -	intel_ring_update_space(ce->ring);
> -
> -	/* Scrub the context image to prevent replaying the previous batch */
> -	restore_default_state(ce, engine);
> -	__execlists_update_reg_state(ce, engine);
> -
> -	/* We've switched away, so this should be a no-op, but intent matters */
> -	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
> -}
> -
>   static inline void
>   __execlists_schedule_out(struct i915_request *rq,
>   			 struct intel_engine_cs * const engine)
> @@ -1165,9 +1168,6 @@ __execlists_schedule_out(struct i915_request *rq,
>   	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
>   	intel_gt_pm_put(engine->gt);
>   
> -	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
> -		reset_active(rq, engine);
> -
>   	/*
>   	 * If this is part of a virtual engine, its next request may
>   	 * have been blocked waiting for access to the active context.
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Intel-gfx] [FIXES 3/3] drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
@ 2019-11-11 16:31     ` Tvrtko Ursulin
  0 siblings, 0 replies; 22+ messages in thread
From: Tvrtko Ursulin @ 2019-11-11 16:31 UTC (permalink / raw)
  To: Chris Wilson, intel-gfx


On 11/11/2019 13:32, Chris Wilson wrote:
> The gem_ctx_persistence/smoketest was detecting an odd coherency issue
> inside the LRC context image; that the address of the ring buffer did
> not match our associated struct intel_ring. As we set the address into
> the context image when we pin the ring buffer into place before the
> context is active, that leaves the question of where did it get
> overwritten. Either the HW context save occurred after our pin which
> would imply that our idle barriers are broken, or we overwrote the
> context image ourselves. It is only in reset_active() where we dabble
> inside the context image outside of a serialised path from schedule-out;
> but we could equally perform the operation inside schedule-in which is
> then fully serialised with the context pin -- and remains serialised by
> the engine pulse with kill_context(). (The only downside, aside from
> doing more work inside the engine->active.lock, was the plan to merge
> all the reset paths into doing their context scrubbing on schedule-out
> needs more thought.)

So process_csb is not under the engine lock and hence schedule_out can 
race with schedule_in meaning schedule_out should refrain from doing 
non-trivial work.

Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Regards,

Tvrtko

> 
> Fixes: d12acee84ffb ("drm/i915/execlists: Cancel banned contexts on schedule-out")
> Testcase: igt/gem_ctx_persistence/smoketest
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
> ---
>   drivers/gpu/drm/i915/gt/intel_lrc.c | 114 ++++++++++++++--------------
>   1 file changed, 57 insertions(+), 57 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
> index e57345795c08..4b6d9e6b1bfd 100644
> --- a/drivers/gpu/drm/i915/gt/intel_lrc.c
> +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
> @@ -1042,6 +1042,59 @@ execlists_check_context(const struct intel_context *ce,
>   	WARN_ONCE(!valid, "Invalid lrc state found before submission\n");
>   }
>   
> +static void restore_default_state(struct intel_context *ce,
> +				  struct intel_engine_cs *engine)
> +{
> +	u32 *regs = ce->lrc_reg_state;
> +
> +	if (engine->pinned_default_state)
> +		memcpy(regs, /* skip restoring the vanilla PPHWSP */
> +		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
> +		       engine->context_size - PAGE_SIZE);
> +
> +	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
> +}
> +
> +static void reset_active(struct i915_request *rq,
> +			 struct intel_engine_cs *engine)
> +{
> +	struct intel_context * const ce = rq->hw_context;
> +	u32 head;
> +
> +	/*
> +	 * The executing context has been cancelled. We want to prevent
> +	 * further execution along this context and propagate the error on
> +	 * to anything depending on its results.
> +	 *
> +	 * In __i915_request_submit(), we apply the -EIO and remove the
> +	 * requests' payloads for any banned requests. But first, we must
> +	 * rewind the context back to the start of the incomplete request so
> +	 * that we do not jump back into the middle of the batch.
> +	 *
> +	 * We preserve the breadcrumbs and semaphores of the incomplete
> +	 * requests so that inter-timeline dependencies (i.e other timelines)
> +	 * remain correctly ordered. And we defer to __i915_request_submit()
> +	 * so that all asynchronous waits are correctly handled.
> +	 */
> +	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
> +		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
> +
> +	/* On resubmission of the active request, payload will be scrubbed */
> +	if (i915_request_completed(rq))
> +		head = rq->tail;
> +	else
> +		head = active_request(ce->timeline, rq)->head;
> +	ce->ring->head = intel_ring_wrap(ce->ring, head);
> +	intel_ring_update_space(ce->ring);
> +
> +	/* Scrub the context image to prevent replaying the previous batch */
> +	restore_default_state(ce, engine);
> +	__execlists_update_reg_state(ce, engine);
> +
> +	/* We've switched away, so this should be a no-op, but intent matters */
> +	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
> +}
> +
>   static inline struct intel_engine_cs *
>   __execlists_schedule_in(struct i915_request *rq)
>   {
> @@ -1050,8 +1103,11 @@ __execlists_schedule_in(struct i915_request *rq)
>   
>   	intel_context_get(ce);
>   
> +	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
> +		reset_active(rq, engine);
> +
>   	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
> -		execlists_check_context(ce, rq->engine);
> +		execlists_check_context(ce, engine);
>   
>   	if (ce->tag) {
>   		/* Use a fixed tag for OA and friends */
> @@ -1102,59 +1158,6 @@ static void kick_siblings(struct i915_request *rq, struct intel_context *ce)
>   		tasklet_schedule(&ve->base.execlists.tasklet);
>   }
>   
> -static void restore_default_state(struct intel_context *ce,
> -				  struct intel_engine_cs *engine)
> -{
> -	u32 *regs = ce->lrc_reg_state;
> -
> -	if (engine->pinned_default_state)
> -		memcpy(regs, /* skip restoring the vanilla PPHWSP */
> -		       engine->pinned_default_state + LRC_STATE_PN * PAGE_SIZE,
> -		       engine->context_size - PAGE_SIZE);
> -
> -	execlists_init_reg_state(regs, ce, engine, ce->ring, false);
> -}
> -
> -static void reset_active(struct i915_request *rq,
> -			 struct intel_engine_cs *engine)
> -{
> -	struct intel_context * const ce = rq->hw_context;
> -	u32 head;
> -
> -	/*
> -	 * The executing context has been cancelled. We want to prevent
> -	 * further execution along this context and propagate the error on
> -	 * to anything depending on its results.
> -	 *
> -	 * In __i915_request_submit(), we apply the -EIO and remove the
> -	 * requests' payloads for any banned requests. But first, we must
> -	 * rewind the context back to the start of the incomplete request so
> -	 * that we do not jump back into the middle of the batch.
> -	 *
> -	 * We preserve the breadcrumbs and semaphores of the incomplete
> -	 * requests so that inter-timeline dependencies (i.e other timelines)
> -	 * remain correctly ordered. And we defer to __i915_request_submit()
> -	 * so that all asynchronous waits are correctly handled.
> -	 */
> -	GEM_TRACE("%s(%s): { rq=%llx:%lld }\n",
> -		  __func__, engine->name, rq->fence.context, rq->fence.seqno);
> -
> -	/* On resubmission of the active request, payload will be scrubbed */
> -	if (i915_request_completed(rq))
> -		head = rq->tail;
> -	else
> -		head = active_request(ce->timeline, rq)->head;
> -	ce->ring->head = intel_ring_wrap(ce->ring, head);
> -	intel_ring_update_space(ce->ring);
> -
> -	/* Scrub the context image to prevent replaying the previous batch */
> -	restore_default_state(ce, engine);
> -	__execlists_update_reg_state(ce, engine);
> -
> -	/* We've switched away, so this should be a no-op, but intent matters */
> -	ce->lrc_desc |= CTX_DESC_FORCE_RESTORE;
> -}
> -
>   static inline void
>   __execlists_schedule_out(struct i915_request *rq,
>   			 struct intel_engine_cs * const engine)
> @@ -1165,9 +1168,6 @@ __execlists_schedule_out(struct i915_request *rq,
>   	execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_OUT);
>   	intel_gt_pm_put(engine->gt);
>   
> -	if (unlikely(i915_gem_context_is_banned(ce->gem_context)))
> -		reset_active(rq, engine);
> -
>   	/*
>   	 * If this is part of a virtual engine, its next request may
>   	 * have been blocked waiting for access to the active context.
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [FIXES 3/3] drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
@ 2019-11-11 16:34       ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 16:34 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

Quoting Tvrtko Ursulin (2019-11-11 16:31:09)
> 
> On 11/11/2019 13:32, Chris Wilson wrote:
> > The gem_ctx_persistence/smoketest was detecting an odd coherency issue
> > inside the LRC context image; that the address of the ring buffer did
> > not match our associated struct intel_ring. As we set the address into
> > the context image when we pin the ring buffer into place before the
> > context is active, that leaves the question of where did it get
> > overwritten. Either the HW context save occurred after our pin which
> > would imply that our idle barriers are broken, or we overwrote the
> > context image ourselves. It is only in reset_active() where we dabble
> > inside the context image outside of a serialised path from schedule-out;
> > but we could equally perform the operation inside schedule-in which is
> > then fully serialised with the context pin -- and remains serialised by
> > the engine pulse with kill_context(). (The only downside, aside from
> > doing more work inside the engine->active.lock, was the plan to merge
> > all the reset paths into doing their context scrubbing on schedule-out
> > needs more thought.)
> 
> So process_csb is not under the engine lock and hence schedule_out can 
> race with schedule_in meaning schedule_out should refrain from doing 
> non-trivial work.

I'm stealing that for a comment in schedule_out! Thanks,
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* Re: [Intel-gfx] [FIXES 3/3] drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
@ 2019-11-11 16:34       ` Chris Wilson
  0 siblings, 0 replies; 22+ messages in thread
From: Chris Wilson @ 2019-11-11 16:34 UTC (permalink / raw)
  To: Tvrtko Ursulin, intel-gfx

Quoting Tvrtko Ursulin (2019-11-11 16:31:09)
> 
> On 11/11/2019 13:32, Chris Wilson wrote:
> > The gem_ctx_persistence/smoketest was detecting an odd coherency issue
> > inside the LRC context image; that the address of the ring buffer did
> > not match our associated struct intel_ring. As we set the address into
> > the context image when we pin the ring buffer into place before the
> > context is active, that leaves the question of where did it get
> > overwritten. Either the HW context save occurred after our pin which
> > would imply that our idle barriers are broken, or we overwrote the
> > context image ourselves. It is only in reset_active() where we dabble
> > inside the context image outside of a serialised path from schedule-out;
> > but we could equally perform the operation inside schedule-in which is
> > then fully serialised with the context pin -- and remains serialised by
> > the engine pulse with kill_context(). (The only downside, aside from
> > doing more work inside the engine->active.lock, was the plan to merge
> > all the reset paths into doing their context scrubbing on schedule-out
> > needs more thought.)
> 
> So process_csb is not under the engine lock and hence schedule_out can 
> race with schedule_in meaning schedule_out should refrain from doing 
> non-trivial work.

I'm stealing that for a comment in schedule_out! Thanks,
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* ✗ Fi.CI.BAT: failure for series starting with [FIXES,1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
@ 2019-11-11 18:33   ` Patchwork
  0 siblings, 0 replies; 22+ messages in thread
From: Patchwork @ 2019-11-11 18:33 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [FIXES,1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
URL   : https://patchwork.freedesktop.org/series/69296/
State : failure

== Summary ==

Applying: drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/i915/gem/i915_gem_userptr.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/i915/gem/i915_gem_userptr.c
No changes -- Patch already applied.
Applying: drm/i915/userptr: Handle unlocked gup retries
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/i915/gem/i915_gem_userptr.c
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Applying: drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/i915/gt/intel_lrc.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/i915/gt/intel_lrc.c
No changes -- Patch already applied.

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

* [Intel-gfx] ✗ Fi.CI.BAT: failure for series starting with [FIXES,1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
@ 2019-11-11 18:33   ` Patchwork
  0 siblings, 0 replies; 22+ messages in thread
From: Patchwork @ 2019-11-11 18:33 UTC (permalink / raw)
  To: Chris Wilson; +Cc: intel-gfx

== Series Details ==

Series: series starting with [FIXES,1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
URL   : https://patchwork.freedesktop.org/series/69296/
State : failure

== Summary ==

Applying: drm/i915/userptr: Try to acquire the page lock around set_page_dirty()
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/i915/gem/i915_gem_userptr.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/i915/gem/i915_gem_userptr.c
No changes -- Patch already applied.
Applying: drm/i915/userptr: Handle unlocked gup retries
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/i915/gem/i915_gem_userptr.c
Falling back to patching base and 3-way merge...
No changes -- Patch already applied.
Applying: drm/i915/execlists: Move reset_active() from schedule-out to schedule-in
Using index info to reconstruct a base tree...
M	drivers/gpu/drm/i915/gt/intel_lrc.c
Falling back to patching base and 3-way merge...
Auto-merging drivers/gpu/drm/i915/gt/intel_lrc.c
No changes -- Patch already applied.

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2019-11-11 18:33 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-11 13:32 [FIXES 1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty() Chris Wilson
2019-11-11 13:32 ` [Intel-gfx] " Chris Wilson
2019-11-11 13:32 ` [FIXES 2/3] drm/i915/userptr: Handle unlocked gup retries Chris Wilson
2019-11-11 13:32   ` [Intel-gfx] " Chris Wilson
2019-11-11 14:19   ` Tvrtko Ursulin
2019-11-11 14:19     ` [Intel-gfx] " Tvrtko Ursulin
2019-11-11 14:27     ` Chris Wilson
2019-11-11 14:27       ` [Intel-gfx] " Chris Wilson
2019-11-11 14:32       ` Chris Wilson
2019-11-11 14:32         ` [Intel-gfx] " Chris Wilson
2019-11-11 15:44         ` Tvrtko Ursulin
2019-11-11 15:44           ` [Intel-gfx] " Tvrtko Ursulin
2019-11-11 13:32 ` [FIXES 3/3] drm/i915/execlists: Move reset_active() from schedule-out to schedule-in Chris Wilson
2019-11-11 13:32   ` [Intel-gfx] " Chris Wilson
2019-11-11 16:31   ` Tvrtko Ursulin
2019-11-11 16:31     ` [Intel-gfx] " Tvrtko Ursulin
2019-11-11 16:34     ` Chris Wilson
2019-11-11 16:34       ` [Intel-gfx] " Chris Wilson
2019-11-11 14:12 ` [FIXES 1/3] drm/i915/userptr: Try to acquire the page lock around set_page_dirty() Tvrtko Ursulin
2019-11-11 14:12   ` [Intel-gfx] " Tvrtko Ursulin
2019-11-11 18:33 ` ✗ Fi.CI.BAT: failure for series starting with [FIXES,1/3] " Patchwork
2019-11-11 18:33   ` [Intel-gfx] " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.