[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