[Intel-gfx] [PATCH] Ring buffer dumping (Working)

Ben Gamari bgamari at gmail.com
Sat Feb 14 04:16:28 CET 2009


After reimplementing the batch buffer dumping semantics (thanks to Chris Wilson
for his suggestion), it seems that batch buffer dumping is finally pretty
stable. Despite what are probably pretty bad inadequacies in my parsing script,
the output looks pretty reasonable. Moreover, we now are dumping as many batch
buffers as are still in memory, so we should be guaranteed to dump any
batchbuffers which cause a gpu crash. Anyways, I'll be putting up a git
repository soon with all of this. Finally, I've included the latest revision of
my parsing script below, so dumping functionality should even be usable. Let me
know what you think. Thanks,

- Ben


gpu-dump.py:
======================

#!/usr/bin/python

import glob
import re

follow_batch_buffers = True
root = "/sys/kernel/debug/dri/0/"


cmds_mi = {
      0x00: "MI_NOOP",
      0x01: "Reserved 01",
      0x02: "MI_USER_INTERRUPT",
      0x03: "MI_WAIT_FOR_EVENT",
      0x04: "MI_FLUSH",
      0x05: "MI_ARB_CHECK",
      0x06: "MI_REPORT_HEAD",
      0x09: "MI_BATCH_BUFFER_END",
      0x11: "MI_OVERLAY_FLIP",
      0x12: "MI_LOAD_SCAN_LINES_INCL",
      0x13: "MI_LOAD_SCAN_LINES_EXCL",
      0x14: "MI_DISPLAY_BUFFER_INFO",
      0x18: "MI_SET_CONTEXT",
      0x20: "MI_STORE_DATA_IMM",
      0x21: "MI_STORE_DATA_INDEX",
      0x22: "MI_LOAD_REGISTER_IMM",
      0x24: "MI_STORE_REGISTER_MEM",
      0x31: "MI_BATCH_BUFFER_START",
}

cmds_2d = {
      0x01: "XY_SETUP_BLT",
      0x03: "XY_SETUP_CLIP_BLT",
      0x11: "XY_SETUP_MONO_PATTERN_SL_BLT",
      0x24: "XY_PIXEL_BLT",
      0x25: "XY_SCANLINE_BLT",
      0x26: "XY_TEXT_BLT",
      0x31: "XY_TEXT_IMMEDIATE_BLT",
      0x40: "COLOR_BLT",
      0x43: "SRC_COPY_BLT",
      0x50: "XY_COLOR_BLT",
      0x51: "XY_PAT_BLT",
      0x52: "XY_MONO_PAT_BLT",
      0x53: "XY_SRC_COPY_BLT",
      0x54: "XY_MONO_SRC_COPY_BLT",
      0x55: "XY_FULL_BLT",
      0x56: "XY_FULL_MONO_SRC_BLT",
      0x57: "XY_FULL_MONO_PATTERN_BLT",
      0x58: "XY_FULL_MONO_PATTERN_MONO_SRC_BLT",
      0x59: "XY_MONO_PAT_FIXED_BLT",
      0x71: "XY_MONO_SRC_COPY_IMMEDIATE_BLT",
      0x72: "XY_PAT_BLT_IMMEDIATE",
      0x73: "XY_SRC_COPY_CHROMA_BLT",
      0x74: "XY_FULL_IMMEDIATE_PATTERN_BLT",
      0x75: "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT",
      0x76: "XY_PAT_CHROMA_BLT",
      0x77: "XY_PAT_CHROMA_BLT_IMMEDIATE",
}

# cmds_3d[Pipeline Type][Opcode][Sub-opcode]
cmds_3d = {
       # Pipeline Type 00 (Common)
       00: {
               0: {
                       0x00: "URB_FENCE",
                       0x01: "CS_URB_STATE",
                       0x02: "CONSTANT_BUFFER",
                       0x03: "STATE_PREFETCH",
               },
               1: {
                       0x01: "STATE_BASE_ADDRESS",
                       0x02: "STATE_SIP",
                       0x04: "PIPELINE_SELECT",
               },
       },

       # Pipeline Type 01 (Single DW)
       01: {
               1: {
                       0x04: "PIPELINE_SELECT",
               },
       },

       # Pipeline Type 02 (Media)
       02: {
               0: {
                       0x00: "MEDIA_STATE_POINTERS",
               },
               1: {
                       0x00: "MEDIA_OBJECT",
                       0x01: "MEDIA_OBJECT_EX",
                       0x02: "MEDIA_OBJECT_PTR",
               },
       },

       # Pipeline Type 03 (3D
       03: {
               0: {
                       0x00: "3DSTATE_PIPELINED_POINTERS",
                       0x01: "3DSTATE_BINDING_TABLE_POINTERS",
                       0x05: "3DSTATE_URB",

                       0x08: "3DSTATE_VERTEX_BUFFERS",
                       0x09: "3DSTATE_VERTEX_ELEMENTS",
                       0x10: "3DSTATE_INDEX_BUFFER",
                       0x11: "3DSTATE_VF_STATISTICS",
                       0x0d: "3DSTATE_VIEWPORT_STATE_POINTERS",
               },
               1: {
                       0x00: "3DSTATE_DRAWING_RECTANGLE",
                       0x01: "3DSTATE_CONSTANT_COLOR",
                       0x02: "3DSTATE_SAMPLER_PALETTE_LOAD0",
                       0x04: "3DSTATE_CHROMA_KEY",
                       0x05: "3DSTATE_DEPTH_BUFFER",
                       0x06: "3DSTATE_POLY_STIPPLE_OFFSET",
                       0x07: "3DSTATE_POLY_STIPPLE_PATTERN",

                       0x08: "3DSTATE_LINE_STIPPLE",
                       0x09: "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP",
               },
               2: {
                       0x00: "PIPE_CONTROL",
               },
               3: {
                       0x00: "3DPRIMITIVE",
               },
       }
}

one_word_cmds = [
       (03, 0, 0x11), # 3DSTATE_VF_STATISTICS
       (00, 1, 0x04), # PIPELINE_SELECT
]




def read_dump(file):
	data = []
	for l in file:
		v = l.split()[2]
		v = int(v, 16)
		data.append(v)
	return data

def parse_instruction(stream):
       cmd = stream[0]
       type = (cmd >> 29) & 0x7
       if type == 0:           # MI
               opcode = (cmd >> 23) & 0x3f

               if opcode < 0x10:
                       count = 1
               else:
                       count = (cmd & 0x3f) + 2
               #if opcode == 0x00 and cmd != 0x00000000:
       #               count = -1

       elif type == 2:         # 2D
               opcode = (cmd >> 22) & 0x78f
               count = (cmd & 0x1f) + 2

       elif type == 3:         # 3D
               pipeline_type = (cmd >> 27) & 0x3
               opcode = (cmd >> 24) & 0x7
               subopcode = (cmd >> 16) & 0xff
               combined = (pipeline_type, opcode, subopcode)
               if combined in one_word_cmds:
                       count = 1
               else:
                       count = (cmd & 0xff) + 2

               return (count, type, combined)

       else:
               return (1, type, 1)
               #raise "Invalid instruction type %d" % type

       return (count, type, opcode)

def get_cmd_name(type, opcode):
       if type == 3:
               (pipeline, opcode, subop) = opcode
               if cmds_3d.has_key(pipeline) and cmds_3d[pipeline].has_key(opcode) and cmds_3d[pipeline][opcode].has_key(subop):
                       name = cmds_3d[pipeline][opcode][subop]
               else:
                       name = "3D Reserved"
       elif type == 0:
               if cmds_mi.has_key(opcode):
                       name = cmds_mi[opcode]
               else:
                       name = "MI Reserved"
       elif type == 2:
               if cmds_2d.has_key(opcode):
                       name = cmds_2d[opcode]
               else:
                       name = "2D Reserved"
       else:
               name = "Unknown"
       return name

def dump_stream(stream, depth=0, markers={}):
       stop = False
       i = 0
       while i < len(stream)-1 and not stop:
               (count, type, opcode) = parse_instruction(stream[i:-1])
               print "%s%08x\t%s\t" % ("  "*depth, 4*i, get_cmd_name(type, opcode).ljust(25)),

               print '[ ',
               for n in range(count):
                       print " %08x" % stream[(i+n) % len(stream)],
               print ' ] ',

               if markers.has_key(i):
                       print markers[i],

               if type == 0 and opcode == 0x09:        # End batch buffer
                       stop = True

               if type == 0 and opcode == 0x31:        # Start batch buffer
                       addr_type = stream[i] & (1 << 7)
                       addr = stream[i+1] & ~0x3
                       print "batch  (0x%08x)" % addr,
                       if addr_type and batches.has_key(addr) and follow_batch_buffers:
                               print "{"
                               batch = batches[addr]
                               dump_stream(batch, depth+1, markers)
                               print "}"

               print
               i += count


ringbuf = open(root + 'i915_ringbuffer_data', 'r')
data = read_dump(ringbuf)
ringbuf.close()

execinfo = open(root + 'i915_ringbuffer_info', 'r')
for l in execinfo:
       s = l.split()
       if re.match('RingHead', l):
               ring_head = int(s[2], 16)
       elif re.match('RingTail', l):
               ring_tail = int(s[2], 16)
       elif re.match('RingSize', l):
               ring_size = int(s[2], 16)
       elif re.match('Acthd', l):
               acthd = int(s[2], 16)
execinfo.close()

bb = open(root + 'i915_batchbuffers')
batches = {}
for l in bb:
	m = re.match('--- gtt_offset = 0x([0-9a-f]+)', l)
	if m:
		gtt_offset = int(m.group(1), 16)
		batches[gtt_offset] = []
		print "Batch buffer 0x%08x" % gtt_offset
	else:
		v = l.split()[2]
		v = int(v, 16)
		batches[gtt_offset].append(v)
bb.close()
	


markers = {
       ring_tail: 'TAIL',
       ring_head: 'HEAD',
       acthd: 'ACTHD'
}
print 'head: 0x%08x' % ring_head
dump_stream(data, 0, markers)




More information about the Intel-gfx mailing list