[Intel-gfx] [PATCH] Seq_file, debugfs, and ring buffer dumping
Ben Gamari
bgamari at gmail.com
Mon Jan 19 22:06:35 CET 2009
Hey all,
After the mail issues last time, hopefully you all will be receiving
this once and only once. This is the latest iteration of my patch set
porting the drm and i915 driver to the seq_file API, teaching them about
debugfs, and implementing ring buffer dumping on i915.
Things have changed a bit since this patch set was last sent out. In
particular, I reworked the debugfs/proc file (what I termed 'info file')
management. Things have been simplified a bit making the system much
more flexible. Now it is possible to use the same ``show'' function for
multiple info files. This is used in the exposing the batch buffers to
user-land in addition to the active, inactive, and flushing object
lists.
Moreover, the ring buffer dumping implementation has been entirely
overhauled, in response to the realization that too much logic was
formerly placed in the kernel. Now the driver exposes debugfs files from
which one can read the contents of the ring buffer and the last few
submitted batch buffers. I have a python script which decodes this data
which I have included below. Unfortunately, it seems that batch buffer
dumping is currently giving me jibberish. I haven't ruled out the
possibility that the batch buffers are being reused during dumping (I
don't make any attempt at keeping this from happening under the
assumption that if one is dumping the ring buffer, the GPU is probably
wedged). Nevertheless, this seems unlikely. If anyone can see an issue in
the patches that might cause this, I would love to know.
Anyways, I hope this is an improvement over what I sent last time. I
worked pretty to consolidate and restructure the patches more logically.
Let me know what you all think. Thanks,
- Ben
==============
Preliminary ring buffer parsing script:
#!/usr/bin/python
import glob
import re
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, markers={}):
stop = False
i = 0
while i < len(stream)-1 and not stop:
(count, type, opcode) = parse_instruction(stream[i:-1])
print "%08x\t%s\t" % (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 (%08x)" % addr
if addr_type and batches.has_key(addr):
print "{"
batch = read_dump(batches[addr])
dump_stream(batch, markers)
print "}"
print
i += count
ringbuf = open(root + 'i915_gem_ringbuf', 'r')
data = read_dump(ringbuf)
ringbuf.close()
execinfo = open(root + 'i915_execinfo', '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()
batches = { }
for file in glob.glob(root + 'i915_batchbuffer*'):
f = open(file, 'r')
l = f.readline()
m = re.match('GttOffset=([0-9a-f]+)', l)
gtt_offset = int(m.group(1), 16)
batches[gtt_offset] = f
print "Batch buffer %08x" % gtt_offset
markers = {
ring_tail: 'TAIL',
ring_head: 'HEAD',
acthd: 'ACTHD'
}
print 'head: %08x' % ring_head
dump_stream(data, markers)
More information about the Intel-gfx
mailing list