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