/* Typical size of the average request (2 pipecontrols and a MI_BB) */
 #define EXECLISTS_REQUEST_SIZE 64 /* bytes */
 
+#define WA_TAIL_DWORDS 2
+
 static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
                                            struct intel_engine_cs *engine);
 static int intel_lr_context_pin(struct i915_gem_context *ctx,
                                struct intel_engine_cs *engine);
+static void execlists_init_reg_state(u32 *reg_state,
+                                    struct i915_gem_context *ctx,
+                                    struct intel_engine_cs *engine,
+                                    struct intel_ring *ring);
 
 /**
  * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists
 {
        struct intel_context *ce = &ctx->engine[engine->id];
        void *vaddr;
-       u32 *lrc_reg_state;
        int ret;
 
        lockdep_assert_held(&ctx->i915->drm.struct_mutex);
                goto unpin_vma;
        }
 
-       lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
-
        ret = intel_ring_pin(ce->ring);
        if (ret)
                goto unpin_map;
 
        intel_lr_context_descriptor_update(ctx, engine);
 
-       lrc_reg_state[CTX_RING_BUFFER_START+1] =
+       ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
+       ce->lrc_reg_state[CTX_RING_BUFFER_START+1] =
                i915_ggtt_offset(ce->ring->vma);
-       ce->lrc_reg_state = lrc_reg_state;
+
        ce->state->obj->dirty = true;
 
        /* Invalidate GuC TLB. */
        struct execlist_port *port = engine->execlist_port;
        struct intel_context *ce = &request->ctx->engine[engine->id];
 
+       /* We want a simple context + ring to execute the breadcrumb update.
+        * We cannot rely on the context being intact across the GPU hang,
+        * so clear it and rebuild just what we need for the breadcrumb.
+        * All pending requests for this context will be zapped, and any
+        * future request will be after userspace has had the opportunity
+        * to recreate its own state.
+        */
+       execlists_init_reg_state(ce->lrc_reg_state,
+                                request->ctx, engine, ce->ring);
+
        /* Move the RING_HEAD onto the breadcrumb, past the hanging batch */
+       ce->lrc_reg_state[CTX_RING_BUFFER_START+1] =
+               i915_ggtt_offset(ce->ring->vma);
        ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix;
+
        request->ring->head = request->postfix;
        request->ring->last_retired_head = -1;
        intel_ring_update_space(request->ring);
        GEM_BUG_ON(request->ctx != port[0].request->ctx);
        port[0].count = 0;
        port[1].count = 0;
+
+       /* Reset WaIdleLiteRestore:bdw,skl as well */
+       request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32);
 }
 
 static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req)
  * used as a workaround for not being allowed to do lite
  * restore with HEAD==TAIL (WaIdleLiteRestore).
  */
-#define WA_TAIL_DWORDS 2
 
 static int gen8_emit_request(struct drm_i915_gem_request *request)
 {
        return indirect_ctx_offset;
 }
 
-static int
-populate_lr_context(struct i915_gem_context *ctx,
-                   struct drm_i915_gem_object *ctx_obj,
-                   struct intel_engine_cs *engine,
-                   struct intel_ring *ring)
+static void execlists_init_reg_state(u32 *reg_state,
+                                    struct i915_gem_context *ctx,
+                                    struct intel_engine_cs *engine,
+                                    struct intel_ring *ring)
 {
-       struct drm_i915_private *dev_priv = ctx->i915;
-       struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
-       void *vaddr;
-       u32 *reg_state;
-       int ret;
-
-       if (!ppgtt)
-               ppgtt = dev_priv->mm.aliasing_ppgtt;
-
-       ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true);
-       if (ret) {
-               DRM_DEBUG_DRIVER("Could not set to CPU domain\n");
-               return ret;
-       }
-
-       vaddr = i915_gem_object_pin_map(ctx_obj, I915_MAP_WB);
-       if (IS_ERR(vaddr)) {
-               ret = PTR_ERR(vaddr);
-               DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret);
-               return ret;
-       }
-       ctx_obj->dirty = true;
-
-       /* The second page of the context object contains some fields which must
-        * be set up prior to the first execution. */
-       reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
+       struct drm_i915_private *dev_priv = engine->i915;
+       struct i915_hw_ppgtt *ppgtt = ctx->ppgtt ?: dev_priv->mm.aliasing_ppgtt;
 
        /* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM
         * commands followed by (reg, value) pairs. The values we are setting here are
                       _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH |
                                          CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT |
                                          (HAS_RESOURCE_STREAMER(dev_priv) ?
-                                           CTX_CTRL_RS_CTX_ENABLE : 0)));
+                                          CTX_CTRL_RS_CTX_ENABLE : 0)));
        ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(engine->mmio_base),
                       0);
        ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(engine->mmio_base),
                       0);
-       /* Ring buffer start address is not known until the buffer is pinned.
-        * It is written to the context image in execlists_update_context()
-        */
        ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START,
                       RING_START(engine->mmio_base), 0);
        ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL,
                ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE,
                               make_rpcs(dev_priv));
        }
+}
+
+static int
+populate_lr_context(struct i915_gem_context *ctx,
+                   struct drm_i915_gem_object *ctx_obj,
+                   struct intel_engine_cs *engine,
+                   struct intel_ring *ring)
+{
+       void *vaddr;
+       int ret;
+
+       ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true);
+       if (ret) {
+               DRM_DEBUG_DRIVER("Could not set to CPU domain\n");
+               return ret;
+       }
+
+       vaddr = i915_gem_object_pin_map(ctx_obj, I915_MAP_WB);
+       if (IS_ERR(vaddr)) {
+               ret = PTR_ERR(vaddr);
+               DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret);
+               return ret;
+       }
+       ctx_obj->dirty = true;
+
+       /* The second page of the context object contains some fields which must
+        * be set up prior to the first execution. */
+
+       execlists_init_reg_state(vaddr + LRC_STATE_PN * PAGE_SIZE,
+                                ctx, engine, ring);
 
        i915_gem_object_unpin_map(ctx_obj);