Intel-GFX Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location
@ 2017-12-19  1:06 Lionel Landwerlin
  2017-12-19  1:09 ` ✗ Fi.CI.BAT: failure for overlay: parse tracepoints from sysfs to figure out fields' location (rev2) Patchwork
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Lionel Landwerlin @ 2017-12-19  1:06 UTC (permalink / raw)
  To: intel-gfx

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.

v2: Fix automake build (Lionel)

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

diff --git a/configure.ac b/configure.ac
index 8740f7a4..f87f227a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,6 +146,11 @@ if test x"$build_x86" = xyes; then
 	AS_IF([test x"$LEX" != "x:" -a x"$YACC" != xyacc],
 		[enable_assembler=yes],
 		[enable_assembler=no])
+
+	AC_CHECK_TOOL([LEG], [leg])
+	if test "x$LEG" != "xleg"; then
+		AC_MSG_ERROR([leg command missing, try : apt-get install peg])
+	fi
 else
 	enable_overlay_xvlib="no"
 	enable_overlay_xlib="no"
diff --git a/overlay/Makefile.am b/overlay/Makefile.am
index fca04cae..0f553b7c 100644
--- a/overlay/Makefile.am
+++ b/overlay/Makefile.am
@@ -1,7 +1,12 @@
 if BUILD_OVERLAY
 bin_PROGRAMS = intel-gpu-overlay
+
+BUILT_SOURCES = tracepoint_format.h
 endif
 
+tracepoint_format.h: tracepoint_format.leg
+	$(LEG) -o $@ $<
+
 AM_CPPFLAGS = -I. -I$(top_srcdir)/include/drm-uapi
 AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) \
 	$(CAIRO_CFLAGS) $(OVERLAY_CFLAGS) $(WERROR_CFLAGS) -I$(srcdir)/../lib
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

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* ✗ Fi.CI.BAT: failure for overlay: parse tracepoints from sysfs to figure out fields' location (rev2)
  2017-12-19  1:06 [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Lionel Landwerlin
@ 2017-12-19  1:09 ` Patchwork
  2017-12-19  8:22 ` Patchwork
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Patchwork @ 2017-12-19  1:09 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: intel-gfx

== Series Details ==

Series: overlay: parse tracepoints from sysfs to figure out fields' location (rev2)
URL   : https://patchwork.freedesktop.org/series/35545/
State : failure

== Summary ==

IGT patchset build failed on latest successful build
cfb711c046c22c3881d2334f0b43ec4eb0b9a5fc scripts/trace.pl: Auto-detect tracepoint field order

make: *** No targets specified and no makefile found.  Stop.

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* ✗ Fi.CI.BAT: failure for overlay: parse tracepoints from sysfs to figure out fields' location (rev2)
  2017-12-19  1:06 [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Lionel Landwerlin
  2017-12-19  1:09 ` ✗ Fi.CI.BAT: failure for overlay: parse tracepoints from sysfs to figure out fields' location (rev2) Patchwork
@ 2017-12-19  8:22 ` Patchwork
  2017-12-19  8:35 ` Patchwork
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Patchwork @ 2017-12-19  8:22 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: intel-gfx

== Series Details ==

Series: overlay: parse tracepoints from sysfs to figure out fields' location (rev2)
URL   : https://patchwork.freedesktop.org/series/35545/
State : failure

== Summary ==

IGT patchset build failed on latest successful build
cfb711c046c22c3881d2334f0b43ec4eb0b9a5fc scripts/trace.pl: Auto-detect tracepoint field order

make: *** No targets specified and no makefile found.  Stop.

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* ✗ Fi.CI.BAT: failure for overlay: parse tracepoints from sysfs to figure out fields' location (rev2)
  2017-12-19  1:06 [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Lionel Landwerlin
  2017-12-19  1:09 ` ✗ Fi.CI.BAT: failure for overlay: parse tracepoints from sysfs to figure out fields' location (rev2) Patchwork
  2017-12-19  8:22 ` Patchwork
@ 2017-12-19  8:35 ` Patchwork
  2017-12-19  9:34 ` [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Chris Wilson
  2017-12-19 10:08 ` Petri Latvala
  4 siblings, 0 replies; 6+ messages in thread
From: Patchwork @ 2017-12-19  8:35 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: intel-gfx

== Series Details ==

Series: overlay: parse tracepoints from sysfs to figure out fields' location (rev2)
URL   : https://patchwork.freedesktop.org/series/35545/
State : failure

== Summary ==

IGT patchset build failed on latest successful build
cfb711c046c22c3881d2334f0b43ec4eb0b9a5fc scripts/trace.pl: Auto-detect tracepoint field order

checking if gcc supports -Werror=trigraphs... yes
checking if gcc supports -Werror=array-bounds... yes
checking if gcc supports -Werror=write-strings... yes
checking if gcc supports -Werror=address... yes
checking if gcc supports -Werror=int-to-pointer-cast... yes
checking if gcc supports -Werror=pointer-to-int-cast... yes
checking if gcc supports -pedantic... yes
checking if gcc supports -Werror... yes
checking if gcc supports -Werror=attributes... yes
checking whether make supports nested variables... (cached) yes
checking for DRM... yes
checking for PCIACCESS... yes
checking for KMOD... yes
checking for PROCPS... yes
checking for LIBUNWIND... yes
checking for VALGRIND... no
checking for OVERLAY_XVLIB... yes
checking for OVERLAY_XLIB... yes
checking for leg... no
configure: error: leg command missing, try : apt-get install peg

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location
  2017-12-19  1:06 [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Lionel Landwerlin
                   ` (2 preceding siblings ...)
  2017-12-19  8:35 ` Patchwork
@ 2017-12-19  9:34 ` Chris Wilson
  2017-12-19 10:08 ` Petri Latvala
  4 siblings, 0 replies; 6+ messages in thread
From: Chris Wilson @ 2017-12-19  9:34 UTC (permalink / raw)
  To: Lionel Landwerlin, intel-gfx

Quoting Lionel Landwerlin (2017-12-19 01:06:18)
> 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.
> 
> v2: Fix automake build (Lionel)
> 
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
> ---
> @@ -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;

u32 engine = READ_TP_FIELD_U32(sample, TP_GEM_REQUEST_WAIT_END, ring);
u32 context = READ_TP_FIELD_U32(sample, TP_GEM_REQUEST_WAIT_END, ctx);
u32 seqno = READ_TP_FIELD_U32(sample, TP_GEM_REQUEST_WAIT_END, seqno);

> -       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;

Looks very useful, thanks!
-Chris
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location
  2017-12-19  1:06 [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Lionel Landwerlin
                   ` (3 preceding siblings ...)
  2017-12-19  9:34 ` [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Chris Wilson
@ 2017-12-19 10:08 ` Petri Latvala
  4 siblings, 0 replies; 6+ messages in thread
From: Petri Latvala @ 2017-12-19 10:08 UTC (permalink / raw)
  To: Lionel Landwerlin; +Cc: intel-gfx

On Tue, Dec 19, 2017 at 01:06:18AM +0000, Lionel Landwerlin wrote:
> 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.
> 
> v2: Fix automake build (Lionel)
> 
> Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>


Adding a new dependency that doesn't involve the tests; that would be
preferrable to be optional. I gave some snippets already on IRC, here
they are in email form.



> ---
>  configure.ac                  |   5 ++
>  overlay/Makefile.am           |   5 ++
>  overlay/gpu-perf.c            | 164 ++++++++++++++++++++++++++++++++++--------
>  overlay/meson.build           |  11 ++-
>  overlay/tracepoint_format.leg |  34 +++++++++
>  5 files changed, 189 insertions(+), 30 deletions(-)
>  create mode 100644 overlay/tracepoint_format.leg
> 
> diff --git a/configure.ac b/configure.ac
> index 8740f7a4..f87f227a 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -146,6 +146,11 @@ if test x"$build_x86" = xyes; then
>  	AS_IF([test x"$LEX" != "x:" -a x"$YACC" != xyacc],
>  		[enable_assembler=yes],
>  		[enable_assembler=no])
> +
> +	AC_CHECK_TOOL([LEG], [leg])
> +	if test "x$LEG" != "xleg"; then
> +		AC_MSG_ERROR([leg command missing, try : apt-get install peg])
> +	fi
>  else


Squash for making peg optional:


        AC_CHECK_TOOL([LEG], [leg])
        if test "x$LEG" != "xleg"; then
-               AC_MSG_ERROR([leg command missing, try : apt-get install peg])
+               AC_MSG_NOTICE([leg command missing, disabling overlay; try : apt-get install peg])
+               enable_overlay_xvlib="no"
+               enable_overlay_xlib="no"
	fi





>  	enable_overlay_xvlib="no"
>  	enable_overlay_xlib="no"
> diff --git a/overlay/Makefile.am b/overlay/Makefile.am
> index fca04cae..0f553b7c 100644
> --- a/overlay/Makefile.am
> +++ b/overlay/Makefile.am
> @@ -1,7 +1,12 @@
>  if BUILD_OVERLAY
>  bin_PROGRAMS = intel-gpu-overlay
> +
> +BUILT_SOURCES = tracepoint_format.h
>  endif
>  
> +tracepoint_format.h: tracepoint_format.leg
> +	$(LEG) -o $@ $<
> +
>  AM_CPPFLAGS = -I. -I$(top_srcdir)/include/drm-uapi
>  AM_CFLAGS = $(DRM_CFLAGS) $(PCIACCESS_CFLAGS) $(CWARNFLAGS) \
>  	$(CAIRO_CFLAGS) $(OVERLAY_CFLAGS) $(WERROR_CFLAGS) -I$(srcdir)/../lib
> 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


Making that look a bit less nonsensical and also making peg optional:


@@ -14,14 +14,6 @@ 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)
@@ -59,11 +51,19 @@ gpu_overlay_src += both_x11_src
 
 gpu_overlay_src += 'kms/kms-overlay.c'
 
-if xrandr.found() and cairo.found()
-	executable('intel-gpu-overlay', gpu_overlay_src,
-			include_directories : [inc, leg_inc],
+leg = find_program('leg', required : false)
+if leg.found()
+	leg_file = custom_target('tracepoint_format',
+		output: 'tracepoint_format.h',
+		input: 'tracepoint_format.leg',
+		command: [leg, '-o', '@OUTPUT@', '@INPUT@'])
+	gpu_overlay_src += leg_file
+
+	if xrandr.found() and cairo.found()
+		executable('intel-gpu-overlay', gpu_overlay_src,
+			include_directories : inc,
 			c_args : gpu_overlay_cflags,
 			dependencies : gpu_overlay_deps,
-                        link_with : leg_lib,
 			install : true)
+	endif
 endif




-- 
Petri Latvala





> 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
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-12-19 10:08 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-12-19  1:06 [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Lionel Landwerlin
2017-12-19  1:09 ` ✗ Fi.CI.BAT: failure for overlay: parse tracepoints from sysfs to figure out fields' location (rev2) Patchwork
2017-12-19  8:22 ` Patchwork
2017-12-19  8:35 ` Patchwork
2017-12-19  9:34 ` [PATCH i-g-t v2] overlay: parse tracepoints from sysfs to figure out fields' location Chris Wilson
2017-12-19 10:08 ` Petri Latvala

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox