diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index af0150e..f05d585 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2170,7 +2170,10 @@ request_to_vm(struct drm_i915_gem_request *request)
 	struct drm_i915_private *dev_priv = request->ring->dev->dev_private;
 	struct i915_address_space *vm;
 
-	vm = &dev_priv->gtt.base;
+	if (request->ctx)
+		vm = &request->ctx->ppgtt.base;
+	else
+		vm = &dev_priv->gtt.base;
 
 	return vm;
 }
@@ -2676,10 +2679,10 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj,
 
 	if (obj->has_global_gtt_mapping && is_i915_ggtt(vm))
 		i915_gem_gtt_unbind_object(obj);
-	if (obj->has_aliasing_ppgtt_mapping) {
-		i915_ppgtt_unbind_object(dev_priv->gtt.aliasing_ppgtt, obj);
-		obj->has_aliasing_ppgtt_mapping = 0;
-	}
+
+	vm->clear_range(vm, i915_gem_obj_offset(obj, vm) >> PAGE_SHIFT,
+			obj->base.size >> PAGE_SHIFT);
+
 	i915_gem_gtt_finish_object(obj);
 	i915_gem_object_unpin_pages(obj);
 
@@ -3444,11 +3447,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
 				return ret;
 		}
 
-		if (obj->has_global_gtt_mapping)
+		if (!is_i915_ggtt(vm) && obj->has_global_gtt_mapping)
 			i915_gem_gtt_bind_object(obj, cache_level);
-		if (obj->has_aliasing_ppgtt_mapping)
-			i915_ppgtt_bind_object(dev_priv->gtt.aliasing_ppgtt,
-					       obj, cache_level);
+
+		vm->insert_entries(vm, obj->pages,
+				   i915_gem_obj_offset(obj, vm) >> PAGE_SHIFT,
+				   cache_level);
 
 		i915_gem_obj_set_color(obj, vm, cache_level);
 	}
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 37ebfa2..cea036e 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -526,10 +526,14 @@ static int do_switch(struct intel_ring_buffer *ring,
 	if (from == to && from->last_ring == ring)
 		return 0;
 
+	ret = to->ppgtt.switch_mm(&to->ppgtt, ring);
+	if (ret)
+		return ret;
+
 	if (ring != &dev_priv->ring[RCS] && from) {
 		ret = i915_add_request(ring, NULL);
 		if (ret)
-			return ret;
+			goto err_out;
 		i915_gem_context_unreference(from);
 	}
 
@@ -538,7 +542,7 @@ static int do_switch(struct intel_ring_buffer *ring,
 
 	ret = i915_gem_ggtt_pin(to->obj, CONTEXT_ALIGN, false, false);
 	if (ret)
-		return ret;
+		goto err_out;
 
 	/* Clear this page out of any CPU caches for coherent swap-in/out. Note
 	 * that thanks to write = false in this call and us not setting any gpu
@@ -546,10 +550,8 @@ static int do_switch(struct intel_ring_buffer *ring,
 	 * (when switching away from it), this won't block.
 	 * XXX: We need a real interface to do this instead of trickery. */
 	ret = i915_gem_object_set_to_gtt_domain(to->obj, false);
-	if (ret) {
-		i915_gem_object_unpin(to->obj);
-		return ret;
-	}
+	if (ret)
+		goto unpin_out;
 
 	if (!to->obj->has_global_gtt_mapping)
 		i915_gem_gtt_bind_object(to->obj, to->obj->cache_level);
@@ -560,10 +562,8 @@ static int do_switch(struct intel_ring_buffer *ring,
 		hw_flags |= MI_FORCE_RESTORE;
 
 	ret = mi_set_context(ring, to, hw_flags);
-	if (ret) {
-		i915_gem_object_unpin(to->obj);
-		return ret;
-	}
+	if (ret)
+		goto unpin_out;
 
 	/* The backing object for the context is done after switching to the
 	 * *next* context. Therefore we cannot retire the previous context until
@@ -593,7 +593,7 @@ static int do_switch(struct intel_ring_buffer *ring,
 			 * scream.
 			 */
 			WARN_ON(mi_set_context(ring, from, MI_RESTORE_INHIBIT));
-			return ret;
+			goto err_out;
 		}
 
 		i915_gem_object_unpin(from->obj);
@@ -605,8 +605,13 @@ done:
 	ring->last_context = to;
 	to->is_initialized = true;
 	to->last_ring = ring;
-
 	return 0;
+
+unpin_out:
+	i915_gem_object_unpin(to->obj);
+err_out:
+	WARN_ON(from->ppgtt.switch_mm(&from->ppgtt, ring));
+	return ret;
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index aeec8c0..0f6bf3c 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -437,11 +437,21 @@ i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
 	}
 
 	/* Ensure ppgtt mapping exists if needed */
-	if (dev_priv->gtt.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
-		i915_ppgtt_bind_object(dev_priv->gtt.aliasing_ppgtt,
-				       obj, obj->cache_level);
-
+	if (is_i915_ggtt(vm) &&
+	    dev_priv->gtt.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
+		/* FIXME: remove this later */
+		struct i915_address_space *appgtt =
+			&dev_priv->gtt.aliasing_ppgtt->base;
+		unsigned long obj_offset = i915_gem_obj_offset(obj, appgtt);
+
+		appgtt->insert_entries(appgtt, obj->pages,
+				       obj_offset >> PAGE_SHIFT,
+				       obj->cache_level);
 		obj->has_aliasing_ppgtt_mapping = 1;
+	} else {
+		vm->insert_entries(vm, obj->pages,
+				   i915_gem_obj_offset(obj, vm) >> PAGE_SHIFT,
+				   obj->cache_level);
 	}
 
 	if (entry->offset != i915_gem_obj_offset(obj, vm)) {
@@ -864,7 +874,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 	struct i915_hw_context *ctx;
 	struct i915_address_space *vm;
 	u32 ctx_id = i915_execbuffer2_get_context_id(*args);
-	u32 exec_start, exec_len;
+	u32 exec_start = args->batch_start_offset, exec_len;
 	u32 mask, flags;
 	int ret, mode, i;
 	bool need_relocs;
@@ -1085,8 +1095,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
 			goto err;
 	}
 
-	exec_start = i915_gem_obj_offset(batch_obj, vm) +
-		args->batch_start_offset;
+	if (batch_obj->has_global_gtt_mapping)
+		exec_start += i915_gem_ggtt_offset(batch_obj);
+	else
+		exec_start += i915_gem_obj_offset(batch_obj, vm);
+
 	exec_len = args->batch_len;
 	if (cliprects) {
 		for (i = 0; i < args->num_cliprects; i++) {
