From b34c59d179e766dceba77ed0a1eba49e1800f900 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 25 Mar 2014 18:44:59 -0700 Subject: [PATCH] drm/i915: Prevent context obj from being overwritten While the context is not being used, we can make the PTEs invalid, so nothing can accidentally corrupt it. Systems tend to have a lot of trouble when the context gets corrupted. Signed-off-by: Ben Widawsky --- drivers/gpu/drm/i915/i915_gem_context.c | 54 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6043062..4e9b2d4 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -584,6 +584,56 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) return ctx; } +static void +_ctx_ptes(struct intel_ring_buffer *ring, + struct i915_hw_context *ctx, + bool valid) +{ + const size_t ptes = ctx->obj->base.size >> PAGE_SHIFT; + const u32 base = i915_gem_obj_ggtt_offset(ctx->obj); + struct sg_page_iter sg_iter; + struct i915_address_space *vm = ctx->vm; + int i = 0; + + BUG_ON(!i915_gem_obj_is_pinned(ctx->obj)); + + if (WARN_ON(intel_ring_begin(ring, round_up(ptes * 3, 2)))) + return; + + for_each_sg_page(ctx->obj->pages->sgl, &sg_iter, ctx->obj->pages->nents, 0) { + u32 pte = vm->pte_encode(sg_page_iter_dma_address(&sg_iter), + I915_CACHE_L3_LLC, + valid); + intel_ring_emit(ring, MI_UPDATE_GTT | (1<<22)); + /* The docs contradict themselves on the offset. They say dword + * offset, yet the low 12 bits MBZ. */ + intel_ring_emit(ring, (base & PAGE_MASK) + i); + intel_ring_emit(ring, pte); + i+=PAGE_SIZE; + } + + if (i & PAGE_SHIFT) + intel_ring_emit(ring, MI_NOOP); + + intel_ring_advance(ring); +} + +static void +enable_ctx_ptes(struct intel_ring_buffer *ring, + struct i915_hw_context *ctx) +{ + if (INTEL_INFO(ring->dev)->gen < 8) + _ctx_ptes(ring, ctx, true); +} + +static void +disable_ctx_ptes(struct intel_ring_buffer *ring, + struct i915_hw_context *ctx) +{ + if (INTEL_INFO(ring->dev)->gen < 8) + _ctx_ptes(ring, ctx, false); +} + static inline int mi_set_context(struct intel_ring_buffer *ring, struct i915_hw_context *new_context, @@ -602,6 +652,8 @@ mi_set_context(struct intel_ring_buffer *ring, return ret; } + enable_ctx_ptes(ring, new_context); + ret = intel_ring_begin(ring, 6); if (ret) return ret; @@ -632,6 +684,8 @@ mi_set_context(struct intel_ring_buffer *ring, intel_ring_advance(ring); + disable_ctx_ptes(ring, new_context); + return ret; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9f9e2b7..d536706 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -367,7 +367,7 @@ #define MI_TOPOLOGY_FILTER MI_INSTR(0x0D, 0) #define MI_LOAD_SCAN_LINES_EXCL MI_INSTR(0x13, 0) #define MI_URB_CLEAR MI_INSTR(0x19, 0) -#define MI_UPDATE_GTT MI_INSTR(0x23, 0) +#define MI_UPDATE_GTT MI_INSTR(0x23, 1) #define MI_CLFLUSH MI_INSTR(0x27, 0) #define MI_REPORT_PERF_COUNT MI_INSTR(0x28, 0) #define MI_REPORT_PERF_COUNT_GGTT (1<<0) -- 1.9.1