1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 /** 6 * @fileoverview Parses i915 driver events in the Linux event trace format. 7 */ 8 base.require('linux_perf_parser'); 9 base.exportTo('tracing', function() { 10 11 var LinuxPerfParser = tracing.LinuxPerfParser; 12 13 /** 14 * Parses linux i915 trace events. 15 * @constructor 16 */ 17 function LinuxPerfI915Parser(importer) { 18 LinuxPerfParser.call(this, importer); 19 20 importer.registerEventHandler('i915_gem_object_create', 21 LinuxPerfI915Parser.prototype.gemObjectCreateEvent.bind(this)); 22 importer.registerEventHandler('i915_gem_object_bind', 23 LinuxPerfI915Parser.prototype.gemObjectBindEvent.bind(this)); 24 importer.registerEventHandler('i915_gem_object_unbind', 25 LinuxPerfI915Parser.prototype.gemObjectBindEvent.bind(this)); 26 importer.registerEventHandler('i915_gem_object_change_domain', 27 LinuxPerfI915Parser.prototype.gemObjectChangeDomainEvent.bind(this)); 28 importer.registerEventHandler('i915_gem_object_pread', 29 LinuxPerfI915Parser.prototype.gemObjectPreadWriteEvent.bind(this)); 30 importer.registerEventHandler('i915_gem_object_pwrite', 31 LinuxPerfI915Parser.prototype.gemObjectPreadWriteEvent.bind(this)); 32 importer.registerEventHandler('i915_gem_object_fault', 33 LinuxPerfI915Parser.prototype.gemObjectFaultEvent.bind(this)); 34 importer.registerEventHandler('i915_gem_object_clflush', 35 // NB: reuse destroy handler 36 LinuxPerfI915Parser.prototype.gemObjectDestroyEvent.bind(this)); 37 importer.registerEventHandler('i915_gem_object_destroy', 38 LinuxPerfI915Parser.prototype.gemObjectDestroyEvent.bind(this)); 39 importer.registerEventHandler('i915_gem_ring_dispatch', 40 LinuxPerfI915Parser.prototype.gemRingDispatchEvent.bind(this)); 41 importer.registerEventHandler('i915_gem_ring_flush', 42 LinuxPerfI915Parser.prototype.gemRingFlushEvent.bind(this)); 43 importer.registerEventHandler('i915_gem_request', 44 LinuxPerfI915Parser.prototype.gemRequestEvent.bind(this)); 45 importer.registerEventHandler('i915_gem_request_add', 46 LinuxPerfI915Parser.prototype.gemRequestEvent.bind(this)); 47 importer.registerEventHandler('i915_gem_request_complete', 48 LinuxPerfI915Parser.prototype.gemRequestEvent.bind(this)); 49 importer.registerEventHandler('i915_gem_request_retire', 50 LinuxPerfI915Parser.prototype.gemRequestEvent.bind(this)); 51 importer.registerEventHandler('i915_gem_request_wait_begin', 52 LinuxPerfI915Parser.prototype.gemRequestEvent.bind(this)); 53 importer.registerEventHandler('i915_gem_request_wait_end', 54 LinuxPerfI915Parser.prototype.gemRequestEvent.bind(this)); 55 importer.registerEventHandler('i915_gem_ring_wait_begin', 56 LinuxPerfI915Parser.prototype.gemRingWaitEvent.bind(this)); 57 importer.registerEventHandler('i915_gem_ring_wait_end', 58 LinuxPerfI915Parser.prototype.gemRingWaitEvent.bind(this)); 59 importer.registerEventHandler('i915_reg_rw', 60 LinuxPerfI915Parser.prototype.regRWEvent.bind(this)); 61 importer.registerEventHandler('i915_flip_request', 62 LinuxPerfI915Parser.prototype.flipEvent.bind(this)); 63 importer.registerEventHandler('i915_flip_complete', 64 LinuxPerfI915Parser.prototype.flipEvent.bind(this)); 65 } 66 67 LinuxPerfI915Parser.prototype = { 68 __proto__: LinuxPerfParser.prototype, 69 70 i915FlipOpenSlice: function(ts, obj, plane) { 71 // use i915_flip_obj_plane? 72 var kthread = this.importer.getOrCreatePseudoThread('i915_flip'); 73 kthread.openSliceTS = ts; 74 kthread.openSlice = 'flip:' + obj + '/' + plane; 75 }, 76 77 i915FlipCloseSlice: function(ts, args) { 78 var kthread = this.importer.getOrCreatePseudoThread('i915_flip'); 79 if (kthread.openSlice) { 80 var slice = new tracing.TimelineSlice('', kthread.openSlice, 81 tracing.getStringColorId(kthread.openSlice), 82 kthread.openSliceTS, 83 args, 84 ts - kthread.openSliceTS); 85 86 kthread.thread.pushSlice(slice); 87 } 88 kthread.openSlice = undefined; 89 }, 90 91 i915GemObjectSlice: function(ts, eventName, obj, args) { 92 var kthread = this.importer.getOrCreatePseudoThread('i915_gem'); 93 kthread.openSlice = eventName + ':' + obj; 94 var slice = new tracing.TimelineSlice('', kthread.openSlice, 95 tracing.getStringColorId(kthread.openSlice), ts, args, 0); 96 97 kthread.thread.pushSlice(slice); 98 }, 99 100 i915GemRingSlice: function(ts, eventName, dev, ring, args) { 101 var kthread = this.importer.getOrCreatePseudoThread('i915_gem_ring'); 102 kthread.openSlice = eventName + ':' + dev + '.' + ring; 103 var slice = new tracing.TimelineSlice('', kthread.openSlice, 104 tracing.getStringColorId(kthread.openSlice), ts, args, 0); 105 106 kthread.thread.pushSlice(slice); 107 }, 108 109 i915RegSlice: function(ts, eventName, reg, args) { 110 var kthread = this.importer.getOrCreatePseudoThread('i915_reg'); 111 kthread.openSlice = eventName + ':' + reg; 112 var slice = new tracing.TimelineSlice('', kthread.openSlice, 113 tracing.getStringColorId(kthread.openSlice), ts, args, 0); 114 115 kthread.thread.pushSlice(slice); 116 }, 117 118 /** 119 * Parses i915 driver events and sets up state in the importer. 120 */ 121 gemObjectCreateEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 122 var event = /obj=(\w+), size=(\d+)/.exec(eventBase[5]); 123 if (!event) 124 return false; 125 126 var obj = event[1]; 127 var size = parseInt(event[2]); 128 this.i915GemObjectSlice(ts, eventName, obj, 129 { 130 obj: obj, 131 size: size 132 }); 133 return true; 134 }, 135 136 gemObjectBindEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 137 // TODO(sleffler) mappable 138 var event = /obj=(\w+), offset=(\w+), size=(\d+)/.exec(eventBase[5]); 139 if (!event) 140 return false; 141 142 var obj = event[1]; 143 var offset = event[2]; 144 var size = parseInt(event[3]); 145 this.i915ObjectGemSlice(ts, eventName + ':' + obj, 146 { 147 obj: obj, 148 offset: offset, 149 size: size 150 }); 151 return true; 152 }, 153 154 gemObjectChangeDomainEvent: function(eventName, cpuNumber, pid, ts, 155 eventBase) { 156 var event = /obj=(\w+), read=(\w+=>\w+), write=(\w+=>\w+)/ 157 .exec(eventBase[5]); 158 if (!event) 159 return false; 160 161 var obj = event[1]; 162 var read = event[2]; 163 var write = event[3]; 164 this.i915GemObjectSlice(ts, eventName, obj, 165 { 166 obj: obj, 167 read: read, 168 write: write 169 }); 170 return true; 171 }, 172 173 gemObjectPreadWriteEvent: function(eventName, cpuNumber, pid, ts, 174 eventBase) { 175 var event = /obj=(\w+), offset=(\d+), len=(\d+)/.exec(eventBase[5]); 176 if (!event) 177 return false; 178 179 var obj = event[1]; 180 var offset = parseInt(event[2]); 181 var len = parseInt(event[3]); 182 this.i915GemObjectSlice(ts, eventName, obj, 183 { 184 obj: obj, 185 offset: offset, 186 len: len 187 }); 188 return true; 189 }, 190 191 gemObjectFaultEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 192 // TODO(sleffler) writable 193 var event = /obj=(\w+), (\w+) index=(\d+)/.exec(eventBase[5]); 194 if (!event) 195 return false; 196 197 var obj = event[1]; 198 var type = event[2]; 199 var index = parseInt(event[3]); 200 this.i915GemObjectSlice(ts, eventName, obj, 201 { 202 obj: obj, 203 type: type, 204 index: index 205 }); 206 return true; 207 }, 208 209 gemObjectDestroyEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 210 var event = /obj=(\w+)/.exec(eventBase[5]); 211 if (!event) 212 return false; 213 214 var obj = event[1]; 215 this.i915GemObjectSlice(ts, eventName, obj, 216 { 217 obj: obj 218 }); 219 return true; 220 }, 221 222 gemRingDispatchEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 223 var event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase[5]); 224 if (!event) 225 return false; 226 227 var dev = parseInt(event[1]); 228 var ring = parseInt(event[2]); 229 var seqno = parseInt(event[3]); 230 this.i915GemRingSlice(ts, eventName, dev, ring, 231 { 232 dev: dev, 233 ring: ring, 234 seqno: seqno 235 }); 236 return true; 237 }, 238 239 gemRingFlushEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 240 var event = /dev=(\d+), ring=(\w+), invalidate=(\w+), flush=(\w+)/ 241 .exec(eventBase[5]); 242 if (!event) 243 return false; 244 245 var dev = parseInt(event[1]); 246 var ring = parseInt(event[2]); 247 var invalidate = event[3]; 248 var flush = event[4]; 249 this.i915GemRingSlice(ts, eventName, dev, ring, 250 { 251 dev: dev, 252 ring: ring, 253 invalidate: invalidate, 254 flush: flush 255 }); 256 return true; 257 }, 258 259 gemRequestEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 260 var event = /dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase[5]); 261 if (!event) 262 return false; 263 264 var dev = parseInt(event[1]); 265 var ring = parseInt(event[2]); 266 var seqno = parseInt(event[3]); 267 this.i915GemRingSlice(ts, eventName, dev, ring, 268 { 269 dev: dev, 270 ring: ring, 271 seqno: seqno 272 }); 273 return true; 274 }, 275 276 gemRingWaitEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 277 var event = /dev=(\d+), ring=(\d+)/.exec(eventBase[5]); 278 if (!event) 279 return false; 280 281 var dev = parseInt(event[1]); 282 var ring = parseInt(event[2]); 283 this.i915GemRingSlice(ts, eventName, dev, ring, 284 { 285 dev: dev, 286 ring: ring 287 }); 288 return true; 289 }, 290 291 regRWEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 292 var event = /(\w+) reg=(\w+), len=(\d+), val=(\(\w+, \w+\))/ 293 .exec(eventBase[5]); 294 if (!event) 295 return false; 296 297 var rw = event[1]; 298 var reg = event[2]; 299 var len = event[3]; 300 var data = event[3]; 301 this.i915RegSlice(ts, rw, reg, 302 { 303 rw: rw, 304 reg: reg, 305 len: len, 306 data: data 307 }); 308 return true; 309 }, 310 311 flipEvent: function(eventName, cpuNumber, pid, ts, eventBase) { 312 var event = /plane=(\d+), obj=(\w+)/.exec(eventBase[5]); 313 if (!event) 314 return false; 315 316 var plane = parseInt(event[1]); 317 var obj = event[2]; 318 if (eventName == 'i915_flip_request') 319 this.i915FlipOpenSlice(ts, obj, plane); 320 else 321 this.i915FlipCloseSlice(ts, 322 { 323 obj: obj, 324 plane: plane 325 }); 326 return true; 327 } 328 }; 329 330 LinuxPerfParser.registerSubtype(LinuxPerfI915Parser); 331 332 return { 333 LinuxPerfI915Parser: LinuxPerfI915Parser 334 }; 335 }); 336