@@ -46,6 +46,11 @@ enum {
PINNED_LIST,
};
+enum {
+ LRC_CONTEXT_DUMP, /* First 1536 bytes of register state ctx */
+ FULL_CONTEXT_DUMP, /* Full context (HW status + reg state ctx) */
+};
+
static const char *yesno(int v)
{
return v ? "yes" : "no";
@@ -1969,18 +1974,16 @@ static int i915_context_status(struct seq_file *m, void *unused)
static void i915_dump_lrc_obj(struct seq_file *m,
struct intel_engine_cs *ring,
- struct drm_i915_gem_object *ctx_obj)
+ struct drm_i915_gem_object *ctx_obj,
+ unsigned long dump_type)
{
struct page *page;
+ struct sg_page_iter sg_iter;
uint32_t *reg_state;
+ int i;
int j;
unsigned long ggtt_offset = 0;
-
- if (ctx_obj == NULL) {
- seq_printf(m, "Context on %s with no gem object\n",
- ring->name);
- return;
- }
+ int hws_page_index;
seq_printf(m, "CONTEXT: %s %u\n", ring->name,
intel_execlists_ctx_id(ctx_obj));
@@ -1995,29 +1998,44 @@ static void i915_dump_lrc_obj(struct seq_file *m,
return;
}
- page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
- if (!WARN_ON(page == NULL)) {
- reg_state = kmap_atomic(page);
+ i = 0;
+ hws_page_index = LRC_PPHWSP_PN;
+ for_each_sg_page(ctx_obj->pages->sgl, &sg_iter,
+ ctx_obj->pages->nents, 0) {
+ if (dump_type == LRC_CONTEXT_DUMP) {
+ if (i < hws_page_index) {
+ ++i;
+ continue;
+ } else if (i > hws_page_index)
+ break;
+ }
- for (j = 0; j < 0x600 / sizeof(u32) / 4; j += 4) {
- seq_printf(m, "\t[0x%08lx] 0x%08x 0x%08x 0x%08x 0x%08x\n",
- ggtt_offset + 4096 + (j * 4),
- reg_state[j], reg_state[j + 1],
- reg_state[j + 2], reg_state[j + 3]);
+ page = sg_page_iter_page(&sg_iter);
+ if (!WARN_ON(page == NULL)) {
+ reg_state = kmap_atomic(page);
+
+ for (j = 0; j < PAGE_SIZE / sizeof(u32); j += 4) {
+ seq_printf(m, "\t[0x%08lx] 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ ggtt_offset + 4096 + (j * 4),
+ reg_state[j], reg_state[j + 1],
+ reg_state[j + 2], reg_state[j + 3]);
+ }
+ kunmap_atomic(reg_state);
}
- kunmap_atomic(reg_state);
+ ++i;
}
seq_putc(m, '\n');
}
-static int i915_dump_lrc(struct seq_file *m, void *unused)
+static int i915_dump_lrc(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *ring;
struct intel_context *ctx;
+ uintptr_t dump_type = (uintptr_t) node->info_ent->data;
int ret, i;
if (!i915.enable_execlists) {
@@ -2031,9 +2049,21 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
list_for_each_entry(ctx, &dev_priv->context_list, link) {
for_each_ring(ring, dev_priv, i) {
- if (ring->default_context != ctx)
- i915_dump_lrc_obj(m, ring,
- ctx->engine[i].state);
+ if (ring->default_context != ctx) {
+ struct drm_i915_gem_object *ctx_obj =
+ ctx->engine[i].state;
+ if (ctx_obj && ctx->file_priv) {
+ seq_printf(m, "CONTEXT: %s (PID: %u, UH:%d)\n",
+ ring->name,
+ pid_nr(ctx->file_priv->file->pid),
+ ctx->user_handle);
+ i915_dump_lrc_obj(m, ring,
+ ctx_obj,
+ dump_type);
+ } else
+ seq_printf(m, "Context on %s with no gem object\n",
+ ring->name);
+ }
}
}
@@ -5189,7 +5219,8 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_opregion", i915_opregion, 0},
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
{"i915_context_status", i915_context_status, 0},
- {"i915_dump_lrc", i915_dump_lrc, 0},
+ {"i915_dump_lrc", i915_dump_lrc, 0, (void *) LRC_CONTEXT_DUMP},
+ {"i915_context_dump", i915_dump_lrc, 0, (void *)FULL_CONTEXT_DUMP},
{"i915_execlists", i915_execlists, 0},
{"i915_forcewake_domains", i915_forcewake_domains, 0},
{"i915_swizzle_info", i915_swizzle_info, 0},