[Intel-gfx] [PATCH] Integrate former ring buffer dumping code
Ben Gamari
bgamari at gmail.com
Thu Jan 15 04:11:45 CET 2009
---
drivers/gpu/drm/i915/i915_gem_debugfs.c | 573 +++++++++++++++++++++++++++++++
1 files changed, 573 insertions(+), 0 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_gem_debugfs.c b/drivers/gpu/drm/i915/i915_gem_debugfs.c
index ccc6d5f..cc91461 100644
--- a/drivers/gpu/drm/i915/i915_gem_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_gem_debugfs.c
@@ -176,6 +176,576 @@ static int i915_hws_info(struct seq_file *m, void *data)
return 0;
}
+#define DRM_I915_RING_DEBUG 1
+#if DRM_I915_RING_DEBUG
+static char *mi_cmds[0x40] = {
+ "MI_NOOP", /* 00 */
+ "Reserved 01",
+ "MI_USER_INTERRUPT",
+ "MI_WAIT_FOR_EVENT",
+
+ "MI_FLUSH", /* 04 */
+ "MI_ARB_CHECK",
+ NULL,
+ "MI_REPORT_HEAD",
+
+ NULL, /* 08 */
+ NULL,
+ "MI_BATCH_BUFFER_END",
+ NULL,
+
+ NULL, /* 0c */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 10 */
+ "MI_OVERLAY_FLIP",
+ "MI_LOAD_SCAN_LINES_INCL",
+ "MI_LOAD_SCAN_LINES_EXCL",
+
+ "MI_DISPLAY_BUFFER_INFO", /* 14 */
+ NULL,
+ NULL,
+ NULL,
+
+ "MI_SET_CONTEXT", /* 18 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 1c */
+ NULL,
+ NULL,
+ NULL,
+
+ "MI_STORE_DATA_IMM", /* 20 */
+ "MI_STORE_DATA_INDEX",
+ "MI_LOAD_REGISTER_IMM",
+ NULL,
+
+ "MI_STORE_REGISTER_MEM", /* 24 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 28 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 2c */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 30 */
+ "MI_BATCH_BUFFER_START",
+ NULL,
+ NULL,
+
+ NULL, /* 34 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 38 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 3c */
+ NULL,
+ NULL,
+ NULL,
+};
+
+static char *_2d_cmds[0x80] = {
+ NULL, /* 00 */
+ "XY_SETUP_BLT",
+ NULL,
+ "XY_SETUP_CLIP_BLT",
+
+ NULL, /* 04 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 08 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 0c */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 10 */
+ "XY_SETUP_MONO_PATTERN_SL_BLT",
+ NULL,
+ NULL,
+
+ NULL, /* 14 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 18 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 1c */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 20 */
+ NULL,
+ NULL,
+ NULL,
+
+ "XY_PIXEL_BLT", /* 24 */
+ "XY_SCANLINE_BLT",
+ "XY_TEXT_BLT",
+ NULL,
+
+ NULL, /* 28 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 2c */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 30 */
+ "XY_TEXT_IMMEDIATE_BLT",
+ NULL,
+ NULL,
+
+ NULL, /* 34 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 38 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 3c */
+ NULL,
+ NULL,
+ NULL,
+
+ "COLOR_BLT", /* 40 */
+ NULL,
+ NULL,
+ "SRC_COPY_BLT",
+
+ NULL, /* 44 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 48 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 4c */
+ NULL,
+ NULL,
+ NULL,
+
+ "XY_COLOR_BLT", /* 50 */
+ "XY_PAT_BLT",
+ "XY_MONO_PAT_BLT",
+ "XY_SRC_COPY_BLT",
+
+ "XY_MONO_SRC_COPY_BLT", /* 54 */
+ "XY_FULL_BLT",
+ "XY_FULL_MONO_SRC_BLT",
+ "XY_FULL_MONO_PATTERN_BLT",
+
+ "XY_FULL_MONO_PATTERN_MONO_SRC_BLT", /* 58 */
+ "XY_MONO_PAT_FIXED_BLT",
+ NULL,
+ NULL,
+
+ NULL, /* 5c */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 60 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 64 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 68 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 6c */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 70 */
+ "XY_MONO_SRC_COPY_IMMEDIATE_BLT",
+ "XY_PAT_BLT_IMMEDIATE",
+ "XY_SRC_COPY_CHROMA_BLT",
+
+ "XY_FULL_IMMEDIATE_PATTERN_BLT", /* 74 */
+ "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT",
+ "XY_PAT_CHROMA_BLT",
+ "XY_PAT_CHROMA_BLT_IMMEDIATE",
+
+ NULL, /* 78 */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* 7c */
+ NULL,
+ NULL,
+ NULL,
+};
+
+#define _3D_ONE_WORD 1
+
+static struct {
+ char *name;
+ int flags;
+} _3d_cmds[0x4][0x8][0x100] = {
+ { /* Pipeline Type 00 (Common) */
+ { /* Opcode 0 */
+ { "URB_FENCE", 0 }, /* 00 */
+ { "CS_URB_STATE", 0 },
+ { "CONSTANT_BUFFER", 0 },
+ { "STATE_PREFETCH", 0 },
+ },
+ { /* Opcode 1 */
+ { NULL, 0 }, /* 00 */
+ { "STATE_BASE_ADDRESS", 0 },
+ { "STATE_SIP", 0 },
+ { NULL, 0 },
+
+ { "PIPELINE_SELECT", _3D_ONE_WORD }, /* 04 */
+ },
+ },
+ { /* Pipeline Type 01 (Single DW) */
+ { /* Opcode 0 */
+ },
+ { /* Opcode 1 */
+ { NULL, 0 }, /* 00 */
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+
+ { "PIPELINE_SELECT", 0 }, /* 04 */
+ { NULL, 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+ },
+ },
+ { /* Pipeline Type 02 (Media) */
+ { /* Opcode 0 */
+ { "MEDIA_STATE_POINTERS", 0 }, /* 00 */
+ },
+ { /* Opcode 1 */
+ { "MEDIA_OBJECT", 0 }, /* 00 */
+ { "MEDIA_OBJECT_EX", 0 },
+ { "MEDIA_OBJECT_PTR", 0 },
+ },
+ },
+ { /* Pipeline Type 03 (3D) */
+ { /* Opcode 0 */
+ { "3DSTATE_PIPELINED_POINTERS", 0 }, /* 00 */
+ { "3DSTATE_BINDING_TABLE_POINTERS", 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+
+ { NULL, 0 }, /* 04 */
+ { "3DSTATE_URB", 0 },
+ { NULL, 0 },
+ { NULL, 0 },
+
+ { "3DSTATE_VERTEX_BUFFERS", 0 }, /* 08 */
+ { "3DSTATE_VERTEX_ELEMENTS", 0 },
+ { "3DSTATE_INDEX_BUFFER", 0 },
+ { "3DSTATE_VF_STATISTICS", _3D_ONE_WORD },
+
+ { NULL, 0 }, /* 0c */
+ { "3DSTATE_VIEWPORT_STATE_POINTERS", 0 },
+ },
+ { /* Opcode 1 */
+ { "3DSTATE_DRAWING_RECTANGLE", 0 }, /* 00 */
+ { "3DSTATE_CONSTANT_COLOR", 0 },
+ { "3DSTATE_SAMPLER_PALETTE_LOAD0", 0 },
+ { NULL, 0 },
+
+ { "3DSTATE_CHROMA_KEY", 0 }, /* 04 */
+ { "3DSTATE_DEPTH_BUFFER", 0 },
+ { "3DSTATE_POLY_STIPPLE_OFFSET", 0 },
+ { "3DSTATE_POLY_STIPPLE_PATTERN", 0 },
+
+ { "3DSTATE_LINE_STIPPLE", 0 }, /* 08 */
+ { "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP", 0 },
+ },
+ { /* Opcode 2 */
+ { "PIPE_CONTROL", 0 }, /* 00 */
+ },
+ { /* Opcode 3 */
+ { "3DPRIMITIVE", 0 }, /* 00 */
+ },
+ },
+};
+
+static int valid_command(uint32_t cmd)
+{
+ uint32_t type = (cmd >> 29) & 0x7;
+ uint32_t pipeline_type;
+ uint32_t opcode;
+ uint32_t subopcode;
+ uint32_t count = 0;
+
+ switch (type) {
+ case 0: /* Memory Interface */
+ opcode = (cmd >> 23) & 0x3f;
+ if (opcode < 0x10)
+ count = 1;
+ else
+ count = (cmd & 0x3f) + 2;
+
+ if (opcode == 0x00 && cmd != 0x00000000)
+ return -1;
+ if (!mi_cmds[opcode])
+ return -1;
+ break;
+
+ case 1:
+ break;
+
+ case 2: /* 2D */
+ count = (cmd & 0x1f) + 2;
+ opcode = (cmd >> 22) & 0x7f;
+ if (!_2d_cmds[opcode])
+ return -1;
+ break;
+
+ case 3: /* 3D */
+ pipeline_type = (cmd >> 27) & 0x3;
+ opcode = (cmd >> 24) & 0x7;
+ subopcode = (cmd >> 16) & 0xff;
+ if (_3d_cmds[pipeline_type][opcode][subopcode].flags & _3D_ONE_WORD)
+ count = 1;
+ else
+ count = (cmd & 0xff) + 2;
+
+ if (pipeline_type <= 3)
+ return count;
+ if (!_3d_cmds[pipeline_type][opcode][subopcode].name)
+ return -1;
+ break;
+
+ default:
+ return -1;
+ }
+ return count;
+}
+
+static int dump_cmd(struct seq_file *m, uint32_t cmd, int count)
+{
+ uint32_t type = (cmd >> 29) & 0x7;
+ uint32_t opcode, subopcode;
+ uint32_t pipeline_type;
+ int ret = 1;
+
+ seq_printf(m, "\t");
+ switch (type) {
+ /* Memory Interface */
+ case 0:
+ opcode = (cmd >> 23) & 0x3f;
+ if (mi_cmds[opcode])
+ seq_printf(m, "%-40.40s %d\n", mi_cmds[opcode], count);
+ else
+ seq_printf(m, "Memory Interface Reserved\n");
+ break;
+
+ case 1:
+ break;
+
+ /* 2D */
+ case 2:
+ opcode = (cmd >> 22) & 0x7f;
+ if (_2d_cmds[opcode])
+ seq_printf(m, "%-40.40s %d\n", _2d_cmds[opcode], count);
+ else
+ seq_printf(m, "2D Reserved\n");
+ break;
+
+ /* 3D */
+ case 3:
+ pipeline_type = (cmd >> 27) & 0x3;
+ opcode = (cmd >> 24) & 0x7;
+ subopcode = (cmd >> 16) & 0xff;
+ if (_3d_cmds[pipeline_type][opcode][subopcode].name) {
+ seq_printf(m, "%-40.40s %d\n",
+ _3d_cmds[pipeline_type][opcode][subopcode].name,
+ count);
+ } else {
+ seq_printf(m, "3D/Media Reserved (pipe %d op %d sub %d)\n",
+ pipeline_type, opcode, subopcode);
+ }
+ break;
+
+ default:
+ seq_printf(m, "Reserved\n");
+ break;
+ }
+ return ret;
+}
+
+static void dump_cmds (struct seq_file *m,
+ volatile unsigned char *virt,
+ uint32_t start,
+ uint32_t stop,
+ uint32_t mask,
+ uint32_t acthd)
+{
+ uint32_t ring = start;
+ uint32_t cmd = start;
+ uint32_t data;
+ uint32_t batch_start_mask = ((0x7 << 29) |
+ (0x3f << 23) |
+ (0x7ff << 12) |
+ (1 << 11) |
+ (1 << 7) |
+ (1 << 6) |
+ (0x3f << 0));
+ uint32_t batch_start_cmd = ((0x0 << 29) |
+ (0x31 << 23) |
+ (0x00 << 12) |
+ (0 << 11) |
+ (1 << 7) |
+ (0 << 6) |
+ (0 << 0));
+ int count;
+ volatile uint32_t *ptr;
+
+ while (ring != stop) {
+ if (ring == acthd)
+ seq_printf(m, "****");
+
+ DRM_INFO("\t%08x: %08x", ring, *(volatile unsigned int*) (virt + ring));
+ if (ring == cmd) {
+ ptr = (volatile uint32_t *) (virt + ring);
+ data = *ptr;
+ count = valid_command(data);
+ dump_cmd(m, data, count);
+
+ /* check for MI_BATCH_BUFFER_END */
+ if (data == (0x0a << 23))
+ stop = (ring + 4) & mask;
+
+ /* check for MI_BATCH_BUFFER_START */
+ if ( (data & batch_start_mask) == batch_start_cmd) {
+ uint32_t batch = ptr[1] & ~3;
+ seq_printf(m, "\t%08x: %08x\n", (ring + 4) & mask, batch);
+ seq_printf(m, "Batch buffer at 0x%08x {\n", batch);
+ /* TODO: Implement batch buffer dumping
+ dump_cmds(m, acthd);
+ ring = (ring + (count -1)*4) & mask;
+ */
+ seq_printf(m, "}\n");
+ }
+ cmd = (cmd + count * 4) & mask;
+ } else
+ seq_printf(m, "\n");
+ ring = (ring + 4) & mask;
+ }
+}
+
+static int valid_chain(struct drm_device *dev, unsigned int ring, unsigned int end)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ unsigned int head, tail, mask;
+ volatile unsigned char *virt;
+ uint32_t data;
+ int count;
+ volatile uint32_t *ptr;
+
+ head = dev_priv->ring.head & HEAD_ADDR;
+ tail = dev_priv->ring.tail & TAIL_ADDR;
+ mask = dev_priv->ring.tail_mask;
+ virt = dev_priv->ring.virtual_start;
+
+ for (;;) {
+ ptr = (volatile uint32_t *) (virt + ring);
+ data = *ptr;
+ count = valid_command(data);
+ if (count < 0)
+ return 0;
+ while (count > 0 && ring != end) {
+ ring = (ring + 4) & mask;
+ count--;
+ }
+ if (ring == end) {
+ if (count == 0)
+ return 1;
+ else
+ return 0;
+ }
+ }
+}
+
+static void dump_ring(struct seq_file *m, struct drm_device *dev, uint32_t acthd)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ unsigned int head, tail, mask, cmd;
+ volatile unsigned char *virt;
+
+ head = dev_priv->ring.head & HEAD_ADDR;
+ tail = dev_priv->ring.tail & TAIL_ADDR;
+ mask = dev_priv->ring.tail_mask;
+ virt = dev_priv->ring.virtual_start;
+ seq_printf(m, "Ring at %p head 0x%x tail 0x%x count %d acthd 0x%x\n",
+ virt, head, tail, (((tail + mask + 1) - head) & mask) >> 2, acthd);
+
+ for (cmd = (head - 256) & mask;
+ cmd != (head & mask);
+ cmd = (cmd + 4) & mask) {
+ if (valid_chain(dev, cmd, (head & mask)))
+ break;
+ }
+
+ dump_cmds(m, virt, cmd, head, mask, acthd);
+ seq_printf(m, "Ring end\n");
+}
+
+static int i915_ring_buffer_info(struct seq_file *m, void *data)
+{
+ struct drm_minor *minor = (struct drm_minor *) m->private;
+ struct drm_device *dev = minor->dev;
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t acthd;
+
+ acthd = I915_READ(ACTHD_I965);
+ dump_ring(m, dev, acthd);
+ return 0;
+}
+#endif /* DRM_I915_RING_DEBUG */
static struct drm_debugfs_list i915_gem_debugfs_list[] = {
@@ -186,6 +756,9 @@ static struct drm_debugfs_list i915_gem_debugfs_list[] = {
{"i915_gem_seqno", i915_gem_seqno_info, 0},
{"i915_gem_interrupt", i915_interrupt_info, 0},
{"i915_gem_hws", i915_hws_info, 0},
+#if DRM_I915_RING_DEBUG
+ {"i915_gem_ringbuf", i915_ring_buffer_info, 0},
+#endif
};
#define I915_GEM_DEBUGFS_ENTRIES ARRAY_SIZE(i915_gem_debugfs_list)
--
1.6.0.6
More information about the Intel-gfx
mailing list