summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2013-09-05 14:18:41 +0100
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-10 23:30:52 +0200
commite2334cabc6b05a59d13b7f2881e71bd77011661b (patch)
treeb0cfaf43ade1553e772f3fa0ecc0cbff0bab5513
parente042f9bad6f75273c9ca67efb4740f9df7014d6d (diff)
drm/i915: Prevent loading of uninitialized context garbageilk-hw-contextfor-anholt
The extended state bits are stored in the LCA register and affect all updates to the LCA register - i.e. the state on the old context is saved when SAVE_EX_STATE_EN is currently set in the old context address before the update, and the new context is restored when RESTORE_EX_STATE_EN is set in the new context address. This is irrespective of the RESTORE_INHIBIT flag in the MI_SET_CONTEXT. Hence, upon initial loading the contents of the extended state is read from uninitialised data. To workaround this, on first load we do a dummy load without the mandatory RESTORE_EX_STATE_EN bit so that the real load causes us to initialise the extended state of the context before it is then loaded by the LCA update. v2: Split out the introduction of the variable length MI_SET_CONTEXT command sequence. References: https://bugs.freedesktop.org/show_bug.cgi?id=64073 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ben Widawsky <ben@bwidawsk.net>
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index e17192a311b4..0954341d979d 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -374,6 +374,8 @@ mi_set_context(struct intel_ring_buffer *ring,
case 5: len += 2;
break;
}
+ if (!new_context->is_initialized)
+ len += 2;
ret = intel_ring_begin(ring, len);
if (ret)
@@ -389,6 +391,22 @@ mi_set_context(struct intel_ring_buffer *ring,
break;
}
+ if (!new_context->is_initialized) {
+ /* The GPU tries to restore the extended state irrespective
+ * of RestoreInhibit (since it is part of the LCA switch
+ * itself rather than the MI_SET_CONTEXT command).
+ * Since the initial contents may be garbage we do a dummy
+ * load first then set the mandatory flag for any future
+ * ring context switches.
+ */
+ intel_ring_emit(ring, MI_SET_CONTEXT);
+ intel_ring_emit(ring,
+ i915_gem_obj_ggtt_offset(new_context->obj) |
+ MI_MM_SPACE_GTT |
+ MI_SAVE_EXT_STATE_EN |
+ hw_flags);
+ }
+
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_SET_CONTEXT);
intel_ring_emit(ring, i915_gem_obj_ggtt_offset(new_context->obj) |