[Intel-gfx] [PATCH] drm/i915: Prevent loading of uninitialized context garbage
Chris Wilson
chris at chris-wilson.co.uk
Thu Aug 8 15:37:35 CEST 2013
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.
References: https://bugs.freedesktop.org/show_bug.cgi?id=64073
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Ben Widawsky <ben at bwidawsk.net>
---
drivers/gpu/drm/i915/i915_gem_context.c | 35 +++++++++++++++++++++++++--------
1 file changed, 27 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 70e9e40..cf35f01 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -351,7 +351,7 @@ mi_set_context(struct intel_ring_buffer *ring,
struct i915_hw_context *new_context,
u32 hw_flags)
{
- int ret;
+ int ret, len;
/* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB
* invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value
@@ -364,7 +364,16 @@ mi_set_context(struct intel_ring_buffer *ring,
return ret;
}
- ret = intel_ring_begin(ring, 6);
+ len = 4;
+ switch (INTEL_INFO(ring->dev)->gen) {
+ case 7:
+ case 5: len += 2;
+ break;
+ }
+ if (!new_context->is_initialized)
+ len += 2;
+
+ ret = intel_ring_begin(ring, len);
if (ret)
return ret;
@@ -376,9 +385,22 @@ mi_set_context(struct intel_ring_buffer *ring,
case 5:
intel_ring_emit(ring, MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
break;
- default:
- intel_ring_emit(ring, MI_NOOP);
- 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);
@@ -398,9 +420,6 @@ mi_set_context(struct intel_ring_buffer *ring,
case 5:
intel_ring_emit(ring, MI_SUSPEND_FLUSH);
break;
- default:
- intel_ring_emit(ring, MI_NOOP);
- break;
}
intel_ring_advance(ring);
--
1.8.4.rc1
More information about the Intel-gfx
mailing list