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