[PATCH 17/71] drm/i915/execlists: Handle copying default context state for atomic reset

Chris Wilson chris at chris-wilson.co.uk
Fri May 4 20:16:34 UTC 2018


We want to be able to reset the GPU from inside a timer callback
(hardirq context). One step requires us to copy the default context
state over to the guilty context, which means we have to forgo our
general routine as that assumes it may block, and poke directly at the
object's shmemfs backing store, allowing ourselves the privilege of
doing so from atomic context.

References: 5692251c254a ("drm/i915/lrc: Scrub the GPU state of the guilty hanging request")
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/intel_lrc.c | 83 +++++++++++++++++++-------------
 1 file changed, 50 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 54930b65ebda..22198e4b1746 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1919,6 +1919,47 @@ execlists_reset_prepare(struct intel_engine_cs *engine)
 	return active;
 }
 
+static int
+copy_default_state(struct intel_engine_cs *engine, void *dst, gfp_t gfp)
+{
+	struct address_space *mapping;
+	unsigned int pfn, last;
+
+	if (!engine->default_state)
+		return 0;
+
+	/*
+	 * As we need to peek directly into the backing store, we assume that
+	 * this is a regular old basic shmemfs object.
+	 */
+	GEM_BUG_ON(!engine->default_state->base.filp);
+
+	/*
+	 * We only want to copy over the template context state;
+	 * skipping over the headers reserved for GuC communication,
+	 * leaving those as zero.
+	 */
+	mapping = engine->default_state->base.filp->f_mapping;
+	last = engine->default_state->base.size >> PAGE_SHIFT;
+	for (pfn = LRC_STATE_PN; pfn < last; pfn++) {
+		struct page *page;
+		void *src;
+
+		/* We may be called to handle reset from irq context! */
+		page = shmem_read_mapping_page_gfp(mapping, pfn, gfp);
+		if (IS_ERR(page))
+			return PTR_ERR(page);
+
+		src = kmap_atomic(page);
+		copy_page(dst, src);
+		kunmap_atomic(src);
+
+		dst += PAGE_SIZE;
+	}
+
+	return 0;
+}
+
 static void execlists_reset(struct intel_engine_cs *engine,
 			    struct i915_request *request)
 {
@@ -1978,18 +2019,8 @@ static void execlists_reset(struct intel_engine_cs *engine,
 	 * to recreate its own state.
 	 */
 	regs = request->hw_context->lrc_reg_state;
-	if (engine->default_state) {
-		void *defaults;
-
-		defaults = i915_gem_object_pin_map(engine->default_state,
-						   I915_MAP_WB);
-		if (!IS_ERR(defaults)) {
-			memcpy(regs, /* skip restoring the vanilla PPHWSP */
-			       defaults + LRC_STATE_PN * PAGE_SIZE,
-			       engine->context_size - PAGE_SIZE);
-			i915_gem_object_unpin_map(engine->default_state);
-		}
-	}
+	if (copy_default_state(engine, regs, GFP_ATOMIC))
+		DRM_DEBUG_DRIVER("Failed to restore logical context state to defaults; continuing anyway\n");
 	execlists_init_reg_state(regs,
 				 request->gem_context, engine, request->ring);
 
@@ -2690,28 +2721,14 @@ populate_lr_context(struct i915_gem_context *ctx,
 	}
 	ctx_obj->mm.dirty = true;
 
-	if (engine->default_state) {
-		/*
-		 * We only want to copy over the template context state;
-		 * skipping over the headers reserved for GuC communication,
-		 * leaving those as zero.
-		 */
-		const unsigned long start = LRC_HEADER_PAGES * PAGE_SIZE;
-		void *defaults;
-
-		defaults = i915_gem_object_pin_map(engine->default_state,
-						   I915_MAP_WB);
-		if (IS_ERR(defaults))
-			return PTR_ERR(defaults);
+	regs = vaddr + LRC_STATE_PN * PAGE_SIZE;
 
-		memcpy(vaddr + start, defaults + start, engine->context_size);
-		i915_gem_object_unpin_map(engine->default_state);
-	}
+	ret = copy_default_state(engine, regs, GFP_KERNEL);
+	if (ret)
+		goto out;
 
-	/* The second page of the context object contains some fields which must
-	 * be set up prior to the first execution. */
-	regs = vaddr + LRC_STATE_PN * PAGE_SIZE;
 	execlists_init_reg_state(regs, ctx, engine, ring);
+
 	if (!engine->default_state)
 		regs[CTX_CONTEXT_CONTROL + 1] |=
 			_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
@@ -2720,9 +2737,9 @@ populate_lr_context(struct i915_gem_context *ctx,
 			_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
 					   CTX_CTRL_ENGINE_CTX_SAVE_INHIBIT);
 
+out:
 	i915_gem_object_unpin_map(ctx_obj);
-
-	return 0;
+	return ret;
 }
 
 static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
-- 
2.17.0



More information about the Intel-gfx-trybot mailing list