This requires doing an actual switch of the page tables during the context switch/execbuf. Along the way, cut away as much "aliasing" ppgtt as possible Signed-off-by: Ben Widawsky <ben at bwidawsk.net> --- drivers/gpu/drm/i915/i915_gem.c | 22 +++++++++++++--------- drivers/gpu/drm/i915/i915_gem_context.c | 29 +++++++++++++++++------------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 27 ++++++++++++++++++++------- 3 files changed, 50 insertions(+), 28 deletions(-) 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++) { -- 1.8.3.1