Home | History | Annotate | Download | only in src
      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