With changes going to drm-tip, the tracepoints field locations are
going to change. This change introduces a tracepoint parser (using a
peg parser) which lets us figure out field positions on the fly.

Signed-off-by: Lionel Landwerlin <lionel.g.landwer...@intel.com>
---
 configure.ac                  |   5 ++
 overlay/gpu-perf.c            | 164 ++++++++++++++++++++++++++++++++++--------
 overlay/meson.build           |  11 ++-
 overlay/tracepoint_format.leg |  34 +++++++++
 4 files changed, 184 insertions(+), 30 deletions(-)
 create mode 100644 overlay/tracepoint_format.leg

diff --git a/configure.ac b/configure.ac
index 8740f7a4..87ca9f91 100644
--- a/configure.ac
+++ b/configure.ac
@@ -151,6 +151,11 @@ else
        enable_overlay_xlib="no"
        enable_assembler="no"
        BUILD_SHADER_DEBUGGER="no"
+
+       AC_CHECK_TOOL([LEG], [leg])
+       if test "x$LEG" != "xleg"; then
+               AC_MSG_ERROR([leg command missing, try : apt-get install peg])
+       fi
 fi
 AM_CONDITIONAL(BUILD_X86, [test "x$build_x86" = xyes])
 
diff --git a/overlay/gpu-perf.c b/overlay/gpu-perf.c
index 3d4a9be9..7fa561e3 100644
--- a/overlay/gpu-perf.c
+++ b/overlay/gpu-perf.c
@@ -57,25 +57,120 @@ struct sample_event {
        uint64_t time;
        uint64_t id;
        uint32_t raw_size;
-       uint32_t raw_hdr0;
-       uint32_t raw_hdr1;
-       uint32_t raw[0];
+       uint8_t tracepoint_data[0];
 };
 
 enum {
-       DEVICE = 0,
-       CTX,
-       ENGINE,
-       CTX_SEQNO,
-       GLOBAL_SEQNO
+       TP_GEM_REQUEST_ADD,
+       TP_GEM_REQUEST_WAIT_BEGIN,
+       TP_GEM_REQUEST_WAIT_END,
+       TP_FLIP_COMPLETE,
+       TP_GEM_RING_SYNC_TO,
+       TP_GEM_RING_SWITCH_CONTEXT,
+
+       TP_NB
 };
 
-static uint64_t tracepoint_id(const char *sys, const char *name)
+struct tracepoint {
+       struct {
+               char name[128];
+               int offset;
+               int size;
+               int is_signed;
+       } fields[20];
+       const char *name;
+       int n_fields;
+
+       int device_field;
+       int ctx_field;
+       int ring_field;
+       int seqno_field;
+       int global_seqno_field;
+       int plane_field;
+} tracepoints[TP_NB] = {
+       [TP_GEM_REQUEST_ADD]         = { .name = "i915/i915_gem_request_add", },
+       [TP_GEM_REQUEST_WAIT_BEGIN]  = { .name = 
"i915/i915_gem_request_wait_begin", },
+       [TP_GEM_REQUEST_WAIT_END]    = { .name = 
"i915/i915_gem_request_wait_end", },
+       [TP_FLIP_COMPLETE]           = { .name = "i915/flip_complete", },
+       [TP_GEM_RING_SYNC_TO]        = { .name = "i915/gem_ring_sync_to", },
+       [TP_GEM_RING_SWITCH_CONTEXT] = { .name = 
"i915/gem_ring_switch_context", },
+};
+
+union parser_value {
+    char *string;
+    int integer;
+};
+
+struct parser_ctx {
+       struct tracepoint *tp;
+       FILE *fp;
+};
+
+#define YY_CTX_LOCAL
+#define YY_CTX_MEMBERS struct parser_ctx ctx;
+#define YYSTYPE union parser_value
+#define YY_PARSE(T) static T
+#define YY_INPUT(yy, buf, result, max)                         \
+       {                                                       \
+               int yyc = getc(yy->ctx.fp);                     \
+               result = (EOF == yyc) ? 0 : (*(buf)= yyc, 1);   \
+       }
+
+#include "tracepoint_format.h"
+
+static int
+parse_tracepoint(int tp_id)
+{
+       struct tracepoint *tp = &tracepoints[tp_id];
+       yycontext ctx;
+       char buf[1024];
+
+       /* Already parsed? */
+       if (tp->n_fields != 0)
+               return 0;
+
+       snprintf(buf, sizeof(buf), "%s/tracing/events/%s/format",
+                debugfs_path, tp->name);
+
+       memset(&ctx, 0, sizeof(ctx));
+       ctx.ctx.tp = tp;
+       ctx.ctx.fp = fopen(buf, "r");
+
+       if (ctx.ctx.fp == NULL)
+               return 0;
+
+       if (yyparse(&ctx)) {
+               for (int f = 0; f < tp->n_fields; f++) {
+                       if (!strcmp(tp->fields[f].name, "device")) {
+                               tp->device_field = f;
+                       } else if (!strcmp(tp->fields[f].name, "ctx")) {
+                               tp->ctx_field = f;
+                       } else if (!strcmp(tp->fields[f].name, "ring")) {
+                               tp->ring_field = f;
+                       } else if (!strcmp(tp->fields[f].name, "seqno")) {
+                               tp->seqno_field = f;
+                       } else if (!strcmp(tp->fields[f].name, "global_seqno")) 
{
+                               tp->global_seqno_field = f;
+                       } else if (!strcmp(tp->fields[f].name, "plane")) {
+                               tp->plane_field = f;
+                       }
+               }
+        } else
+               tp->n_fields = 0;
+
+       yyrelease(&ctx);
+       fclose(ctx.ctx.fp);
+
+       return tp->n_fields;
+}
+
+static uint64_t tracepoint_id(int tp_id)
 {
        char buf[1024];
        int fd, n;
 
-       snprintf(buf, sizeof(buf), "%s/tracing/events/%s/%s/id", debugfs_path, 
sys, name);
+       snprintf(buf, sizeof(buf), "%s/tracing/events/%s/id", debugfs_path,
+                tracepoints[tp_id].name);
        fd = open(buf, 0);
        if (fd < 0)
                return 0;
@@ -88,8 +183,12 @@ static uint64_t tracepoint_id(const char *sys, const char 
*name)
        return strtoull(buf, 0, 0);
 }
 
-static int perf_tracepoint_open(struct gpu_perf *gp,
-                               const char *sys, const char *name,
+#define READ_TP_FIELD_U32(sample, tp_id, field_name)                   \
+       (*(const uint32_t *)((sample)->tracepoint_data +                \
+                            tracepoints[tp_id].fields[                 \
+                                    
tracepoints[tp_id].field_name##_field].offset))
+
+static int perf_tracepoint_open(struct gpu_perf *gp, int tp_id,
                                int (*func)(struct gpu_perf *, const void *))
 {
        struct perf_event_attr attr;
@@ -99,10 +198,13 @@ static int perf_tracepoint_open(struct gpu_perf *gp,
        memset(&attr, 0, sizeof (attr));
 
        attr.type = PERF_TYPE_TRACEPOINT;
-       attr.config = tracepoint_id(sys, name);
+       attr.config = tracepoint_id(tp_id);
        if (attr.config == 0)
                return ENOENT;
 
+       if (parse_tracepoint(tp_id) == 0)
+               return ENOENT;
+
        attr.sample_period = 1;
        attr.sample_type = (PERF_SAMPLE_TIME | PERF_SAMPLE_STREAM_ID | 
PERF_SAMPLE_TID | PERF_SAMPLE_RAW);
        attr.read_format = PERF_FORMAT_ID;
@@ -227,7 +329,7 @@ static int request_add(struct gpu_perf *gp, const void 
*event)
        if (comm == NULL)
                return 0;
 
-       comm->nr_requests[sample->raw[ENGINE]]++;
+       comm->nr_requests[READ_TP_FIELD_U32(sample, TP_GEM_REQUEST_ADD, 
ring)]++;
        return 1;
 }
 
@@ -235,7 +337,7 @@ static int flip_complete(struct gpu_perf *gp, const void 
*event)
 {
        const struct sample_event *sample = event;
 
-       gp->flip_complete[sample->raw[0]]++;
+       gp->flip_complete[READ_TP_FIELD_U32(sample, TP_FLIP_COMPLETE, plane)]++;
        return 1;
 }
 
@@ -243,7 +345,7 @@ static int ctx_switch(struct gpu_perf *gp, const void 
*event)
 {
        const struct sample_event *sample = event;
 
-       gp->ctx_switch[sample->raw[ENGINE]]++;
+       gp->ctx_switch[READ_TP_FIELD_U32(sample, TP_GEM_RING_SWITCH_CONTEXT, 
ring)]++;
        return 1;
 }
 
@@ -278,11 +380,11 @@ static int wait_begin(struct gpu_perf *gp, const void 
*event)
 
        wait->comm = comm;
        wait->comm->active = true;
-       wait->context = sample->raw[ENGINE];
-       wait->seqno = sample->raw[CTX_SEQNO];
+       wait->context = READ_TP_FIELD_U32(sample, TP_GEM_REQUEST_WAIT_BEGIN, 
ctx);
+       wait->seqno = READ_TP_FIELD_U32(sample, TP_GEM_REQUEST_WAIT_BEGIN, 
seqno);
        wait->time = sample->time;
-       wait->next = gp->wait[sample->raw[CTX]];
-       gp->wait[sample->raw[CTX]] = wait;
+       wait->next = gp->wait[READ_TP_FIELD_U32(sample, 
TP_GEM_REQUEST_WAIT_BEGIN, ring)];
+       gp->wait[READ_TP_FIELD_U32(sample, TP_GEM_REQUEST_WAIT_BEGIN, ring)] = 
wait;
 
        return 0;
 }
@@ -292,9 +394,13 @@ static int wait_end(struct gpu_perf *gp, const void *event)
        const struct sample_event *sample = event;
        struct gpu_perf_time *wait, **prev;
 
-       for (prev = &gp->wait[sample->raw[ENGINE]]; (wait = *prev) != NULL; 
prev = &wait->next) {
-               if (wait->context != sample->raw[CTX] ||
-                   wait->seqno != sample->raw[CTX_SEQNO])
+       for (prev = &gp->wait[READ_TP_FIELD_U32(sample, 
TP_GEM_REQUEST_WAIT_END, ring)];
+            (wait = *prev) != NULL;
+            prev = &wait->next) {
+               if (wait->context != READ_TP_FIELD_U32(sample,
+                                                             
TP_GEM_REQUEST_WAIT_END, ctx) ||
+                   wait->seqno != READ_TP_FIELD_U32(sample,
+                                                           
TP_GEM_REQUEST_WAIT_END, seqno))
                        continue;
 
                wait->comm->wait_time += sample->time - wait->time;
@@ -314,12 +420,12 @@ void gpu_perf_init(struct gpu_perf *gp, unsigned flags)
        gp->nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
        gp->page_size = getpagesize();
 
-       perf_tracepoint_open(gp, "i915", "i915_gem_request_add", request_add);
-       if (perf_tracepoint_open(gp, "i915", "i915_gem_request_wait_begin", 
wait_begin) == 0)
-               perf_tracepoint_open(gp, "i915", "i915_gem_request_wait_end", 
wait_end);
-       perf_tracepoint_open(gp, "i915", "i915_flip_complete", flip_complete);
-       perf_tracepoint_open(gp, "i915", "i915_gem_ring_sync_to", ring_sync);
-       perf_tracepoint_open(gp, "i915", "i915_gem_ring_switch_context", 
ctx_switch);
+       perf_tracepoint_open(gp, TP_GEM_REQUEST_ADD, request_add);
+       if (perf_tracepoint_open(gp, TP_GEM_REQUEST_WAIT_BEGIN, wait_begin) == 
0)
+               perf_tracepoint_open(gp, TP_GEM_REQUEST_WAIT_END, wait_end);
+       perf_tracepoint_open(gp, TP_FLIP_COMPLETE, flip_complete);
+       perf_tracepoint_open(gp, TP_GEM_RING_SYNC_TO, ring_sync);
+       perf_tracepoint_open(gp, TP_GEM_RING_SWITCH_CONTEXT, ctx_switch);
 
        if (gp->nr_events == 0) {
                gp->error = "i915.ko tracepoints not available";
diff --git a/overlay/meson.build b/overlay/meson.build
index afacff5e..6a5691dc 100644
--- a/overlay/meson.build
+++ b/overlay/meson.build
@@ -14,6 +14,14 @@ gpu_overlay_src = [
        'rc6.c',
 ]
 
+leg = find_program('leg', required : true)
+leg_gen = generator(leg,
+                   output : '@BASENAME@.h',
+                   arguments : ['-o', '@OUTPUT@', '@INPUT@'])
+leg_file = leg_gen.process('tracepoint_format.leg')
+leg_lib = static_library('leg', leg_file)
+leg_inc = leg_lib.private_dir_include()
+
 xv = dependency('xv', required : false)
 x11 = dependency('x11', required : false)
 xext = dependency('xext', required : false)
@@ -53,8 +61,9 @@ gpu_overlay_src += 'kms/kms-overlay.c'
 
 if xrandr.found() and cairo.found()
        executable('intel-gpu-overlay', gpu_overlay_src,
-                       include_directories : inc,
+                       include_directories : [inc, leg_inc],
                        c_args : gpu_overlay_cflags,
                        dependencies : gpu_overlay_deps,
+                        link_with : leg_lib,
                        install : true)
 endif
diff --git a/overlay/tracepoint_format.leg b/overlay/tracepoint_format.leg
new file mode 100644
index 00000000..ea83db91
--- /dev/null
+++ b/overlay/tracepoint_format.leg
@@ -0,0 +1,34 @@
+TracepointFormat =
+    'name' ':' Space PropertyName EndLine
+    'ID' ':' Space Number EndLine
+    'format' ':' EndLine
+    Field+
+    'print fmt' ':' .*
+    !.
+
+Field         = Space (Property ';' Space)+ EndLine
+        { yy->ctx.tp->n_fields++; }
+              | EndLine
+
+Property      = 'offset' ':' v:Number
+        { yy->ctx.tp->fields[yy->ctx.tp->n_fields].offset = v.integer; }
+              | 'size' ':' v:Number
+        { yy->ctx.tp->fields[yy->ctx.tp->n_fields].size = v.integer; }
+              | 'signed' ':' v:Number
+        { yy->ctx.tp->fields[yy->ctx.tp->n_fields].is_signed = v.integer != 0; 
}
+              | 'field' ':' v:PropertyValue
+        { snprintf(yy->ctx.tp->fields[yy->ctx.tp->n_fields].name,
+                   sizeof(yy->ctx.tp->fields[yy->ctx.tp->n_fields].name),
+                   "%s", strrchr(v.string, ' ') + 1); free(v.string); }
+              | n:PropertyName ':' v:PropertyValue
+        { free(n.string); free(v.string); }
+
+PropertyName  = < [A-Za-z0-9_]+ >
+        { $$.string = strdup(yytext); }
+PropertyValue = < [^;]+ >
+        { $$.string = strdup(yytext); }
+Number        = < [0-9]+ >
+        { $$.integer = atoi(yytext); }
+
+EndLine       = [\n]
+Space         = [ \t]*
-- 
2.15.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to