diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 7bdb9be..e0f56f5 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1385,7 +1385,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
 cleanup_gem:
 	mutex_lock(&dev->struct_mutex);
 	i915_gem_cleanup_ring(dev);
-	i915_gem_context_fini(dev);
+	i915_gem_context_fini(dev, dev_priv->lrc_enabled);
 	mutex_unlock(&dev->struct_mutex);
 	WARN_ON(dev_priv->mm.aliasing_ppgtt);
 	drm_mm_takedown(&dev_priv->gtt.base.mm);
@@ -1841,7 +1841,7 @@ int i915_driver_unload(struct drm_device *dev)
 		mutex_lock(&dev->struct_mutex);
 		i915_gem_free_all_phys_object(dev);
 		i915_gem_cleanup_ring(dev);
-		i915_gem_context_fini(dev);
+		i915_gem_context_fini(dev, dev_priv->lrc_enabled);
 		WARN_ON(dev_priv->mm.aliasing_ppgtt);
 		mutex_unlock(&dev->struct_mutex);
 		i915_gem_cleanup_stolen(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 41d3f95..1cc1042 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2390,7 +2390,7 @@ void i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj);
 /* i915_gem_context.c */
 #define ctx_to_ppgtt(ctx) container_of((ctx)->vm, struct i915_hw_ppgtt, base)
 int __must_check i915_gem_context_init(struct drm_device *dev);
-void i915_gem_context_fini(struct drm_device *dev);
+void i915_gem_context_fini(struct drm_device *dev, bool is_lrc);
 struct drm_i915_gem_object *intel_allocate_ctx_backing_obj(struct drm_device *dev,
 		size_t size);
 struct i915_hw_context *i915_gem_create_context(struct drm_device *dev,
@@ -2427,6 +2427,9 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
 
 /* intel_lrc.c */
 int gen8_gem_context_init(struct drm_device *dev);
+int gen8_create_lr_context(struct i915_hw_context *ctx,
+			   struct intel_engine *ring,
+			   struct drm_i915_file_private *file_priv);
 
 /* i915_gem_evict.c */
 int __must_check i915_gem_evict_something(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 708111d..16fc780 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -181,16 +181,22 @@ void i915_gem_context_free(struct kref *ctx_ref)
 	struct i915_hw_context *ctx = container_of(ctx_ref,
 						   typeof(*ctx), ref);
 	struct i915_hw_ppgtt *ppgtt = NULL;
-	struct drm_i915_gem_object *ctx_obj = ctx->engine[RCS].obj;
+	int i;
 
-	if (ctx_obj) {
-		/* We refcount even the aliasing PPGTT to keep the code symmetric */
-		if (USES_PPGTT(ctx_obj->base.dev))
-			ppgtt = ctx_to_ppgtt(ctx);
+	for (i = 0; i < I915_NUM_RINGS; i++) {
+		struct drm_i915_gem_object *ctx_obj = ctx->engine[i].obj;
+		if (ctx_obj) {
+			if (i == RCS) {
+				/* We refcount even the aliasing PPGTT to keep the
+				 * code symmetric */
+				if (USES_PPGTT(ctx_obj->base.dev))
+					ppgtt = ctx_to_ppgtt(ctx);
+			}
 
-		/* XXX: Free up the object before tearing down the address space, in
-		 * case we're bound in the PPGTT */
-		drm_gem_object_unreference(&ctx_obj->base);
+			/* XXX: Free up the object before tearing down the address
+			 * space, in case we're bound in the PPGTT */
+			drm_gem_object_unreference(&ctx_obj->base);
+		}
 	}
 
 	if (ppgtt)
@@ -447,15 +453,15 @@ int i915_gem_context_init(struct drm_device *dev)
 	return 0;
 }
 
-void i915_gem_context_fini(struct drm_device *dev)
+void i915_gem_context_fini(struct drm_device *dev, bool is_lrc)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
 	struct drm_i915_gem_object *dctx_obj = dctx->engine[RCS].obj;
 	struct intel_engine *ring;
-	int unused;
+	int ring_id;
 
-	if (dctx_obj) {
+	if (dctx_obj && !is_lrc) {
 		/* The only known way to stop the gpu from accessing the hw context is
 		 * to reset it. Do this as the very last operation to avoid confusing
 		 * other code, leading to spurious errors. */
@@ -477,15 +483,20 @@ void i915_gem_context_fini(struct drm_device *dev)
 		}
 	}
 
-	for_each_ring(ring, dev_priv, unused) {
+	for_each_ring(ring, dev_priv, ring_id) {
 		if (ring->last_context)
 			i915_gem_context_unreference(ring->last_context);
 
 		ring->default_context = NULL;
 		ring->last_context = NULL;
+
+		dctx_obj = dctx->engine[ring_id].obj;
+		if (dctx_obj) {
+			BUG_ON(ring_id != RCS && !is_lrc);
+			i915_gem_object_ggtt_unpin(dctx_obj);
+		}
 	}
 
-	i915_gem_object_ggtt_unpin(dctx_obj);
 	i915_gem_context_unreference(dctx);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 3a93e99..875d7b9 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -41,7 +41,90 @@
 #include <drm/i915_drm.h>
 #include "i915_drv.h"
 
+#define GEN8_LR_CONTEXT_RENDER_SIZE (20 * PAGE_SIZE)
+#define GEN8_LR_CONTEXT_OTHER_SIZE (2 * PAGE_SIZE)
+
+#define GEN8_LR_CONTEXT_ALIGN 4096
+
+static uint32_t get_lr_context_size(struct intel_engine *ring)
+{
+	int ret = 0;
+
+	BUG_ON(INTEL_INFO(ring->dev)->gen != 8);
+
+	switch (ring->id) {
+	case RCS:
+		ret = GEN8_LR_CONTEXT_RENDER_SIZE;
+		break;
+	case VCS:
+	case BCS:
+	case VECS:
+	case VCS2:
+		ret = GEN8_LR_CONTEXT_OTHER_SIZE;
+		break;
+	}
+
+	return ret;
+}
+
+int gen8_create_lr_context(struct i915_hw_context *ctx,
+			   struct intel_engine *ring,
+			   struct drm_i915_file_private *file_priv)
+{
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_gem_object *ctx_obj;
+	uint32_t context_size;
+	int ret;
+
+	if (ctx->engine[ring->id].obj)
+		return 0;
+
+	context_size = round_up(get_lr_context_size(ring), 4096);
+
+	ctx_obj = intel_allocate_ctx_backing_obj(dev, context_size);
+	if (IS_ERR_OR_NULL(ctx_obj)) {
+		ret = PTR_ERR(ctx_obj);
+		DRM_DEBUG_DRIVER("Alloc LRC backing obj failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN, 0);
+	if (ret) {
+		DRM_DEBUG_DRIVER("Pin LRC backing obj failed: %d\n", ret);
+		drm_gem_object_unreference(&ctx_obj->base);
+		return ret;
+	}
+
+	ctx->engine[ring->id].obj = ctx_obj;
+
+	return 0;
+}
+
 int gen8_gem_context_init(struct drm_device *dev)
 {
-	return -ENOSYS;
+	struct drm_i915_private *dev_priv = to_i915(dev);
+	struct i915_hw_context *ctx;
+	struct intel_engine *ring;
+	int ring_id;
+	int ret;
+
+	/* Any value != 0 works here */
+	dev_priv->hw_context_size = GEN8_LR_CONTEXT_RENDER_SIZE;
+
+	ctx = i915_gem_create_context(dev, NULL, true, false);
+	if (IS_ERR_OR_NULL(ctx)) {
+		ret = PTR_ERR(ctx);
+		DRM_ERROR("Init LR context failed: %d\n", ret);
+		goto err_out;
+	}
+
+	for_each_ring(ring, dev_priv, ring_id)
+		ring->default_context = ctx;
+
+	DRM_DEBUG_DRIVER("LR context support initialized\n");
+	return 0;
+
+err_out:
+	i915_gem_context_fini(dev, true);
+	return ret;
 }
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 6225123..e7f61d9 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1443,6 +1443,7 @@ err_unref:
 static int intel_init_ring(struct drm_device *dev,
 			   struct intel_engine *ring)
 {
+	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct intel_ringbuffer *ringbuf = &ring->default_ringbuf;
 	int ret;
 
@@ -1453,6 +1454,15 @@ static int intel_init_ring(struct drm_device *dev,
 
 	init_waitqueue_head(&ring->irq_queue);
 
+	if (dev_priv->lrc_enabled) {
+		ret = gen8_create_lr_context(ring->default_context, ring, NULL);
+		if (ret) {
+			DRM_ERROR("Create LR context for %s failed: %d\n",
+					ring->name, ret);
+			return ret;
+		}
+	}
+
 	if (I915_NEED_GFX_HWS(dev)) {
 		ret = init_status_page(ring);
 		if (ret)
