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