All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 00/11] Add support for JSON event files.
@ 2015-04-14  6:40 ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

This is another attempt to resurrect Andi Kleen's patchset so users
can specify perf events by their event names rather than raw codes.

This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
(I fixed minor and not so minor conflicts).

This patchset includes the perf-download tool that was dropped and sets
the default download location to the (tools/perf/pmu-events/arch/...
directory in Linus's tree.

A follow-on patchset will include the actual JSON files for Powerpc, which
are currently available on github[2].

[1] https://lkml.org/lkml/2014/7/30/693
[2] https://github.com/open-power/power-pmu-events

Andi Kleen (9):
  perf, tools: Add jsmn `jasmine' JSON parser
  perf, tools: Add support for text descriptions of events and alias
    add
  perf, tools, list: Update perf list to output descriptions
  perf, tools: Add support for reading JSON event files
  perf, tools: Automatically look for event file name for cpu
  perf, tools: Query terminal width and use in perf list
  perf, tools: Add a new pmu interface to iterate over all events
  perf, tools, test: Add test case for alias and JSON parsing
  perf, tools: Add a --no-desc flag to perf list

Sukadev Bhattiprolu (2):
  powerpc/perf: Implement get_cpu_str()
  perf-download: Download the events json file

 tools/perf/Documentation/perf-download.txt |   31 +++
 tools/perf/Documentation/perf-list.txt     |   29 ++-
 tools/perf/Documentation/perf-record.txt   |    9 +-
 tools/perf/Documentation/perf-stat.txt     |    8 +-
 tools/perf/Makefile.perf                   |   12 +-
 tools/perf/arch/powerpc/util/header.c      |   12 ++
 tools/perf/arch/x86/util/header.c          |   19 +-
 tools/perf/builtin-list.c                  |   18 +-
 tools/perf/builtin-record.c                |    3 +
 tools/perf/builtin-stat.c                  |    2 +
 tools/perf/perf-download.sh                |  171 +++++++++++++++
 tools/perf/tests/aliases.c                 |   59 ++++++
 tools/perf/tests/builtin-test.c            |    4 +
 tools/perf/tests/tests.h                   |    1 +
 tools/perf/util/cache.h                    |    1 +
 tools/perf/util/jevents.c                  |  287 +++++++++++++++++++++++++
 tools/perf/util/jevents.h                  |    9 +
 tools/perf/util/jsmn.c                     |  313 ++++++++++++++++++++++++++++
 tools/perf/util/jsmn.h                     |   67 ++++++
 tools/perf/util/json.c                     |  162 ++++++++++++++
 tools/perf/util/json.h                     |   13 ++
 tools/perf/util/pager.c                    |   15 ++
 tools/perf/util/parse-events.c             |    4 +-
 tools/perf/util/parse-events.h             |    2 +-
 tools/perf/util/pmu.c                      |  160 +++++++++++---
 tools/perf/util/pmu.h                      |    5 +-
 26 files changed, 1365 insertions(+), 51 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-download.txt
 create mode 100755 tools/perf/perf-download.sh
 create mode 100644 tools/perf/tests/aliases.c
 create mode 100644 tools/perf/util/jevents.c
 create mode 100644 tools/perf/util/jevents.h
 create mode 100644 tools/perf/util/jsmn.c
 create mode 100644 tools/perf/util/jsmn.h
 create mode 100644 tools/perf/util/json.c
 create mode 100644 tools/perf/util/json.h

-- 
1.7.9.5


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

* [PATCH v9 00/11] Add support for JSON event files.
@ 2015-04-14  6:40 ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

This is another attempt to resurrect Andi Kleen's patchset so users
can specify perf events by their event names rather than raw codes.

This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
(I fixed minor and not so minor conflicts).

This patchset includes the perf-download tool that was dropped and sets
the default download location to the (tools/perf/pmu-events/arch/...
directory in Linus's tree.

A follow-on patchset will include the actual JSON files for Powerpc, which
are currently available on github[2].

[1] https://lkml.org/lkml/2014/7/30/693
[2] https://github.com/open-power/power-pmu-events

Andi Kleen (9):
  perf, tools: Add jsmn `jasmine' JSON parser
  perf, tools: Add support for text descriptions of events and alias
    add
  perf, tools, list: Update perf list to output descriptions
  perf, tools: Add support for reading JSON event files
  perf, tools: Automatically look for event file name for cpu
  perf, tools: Query terminal width and use in perf list
  perf, tools: Add a new pmu interface to iterate over all events
  perf, tools, test: Add test case for alias and JSON parsing
  perf, tools: Add a --no-desc flag to perf list

Sukadev Bhattiprolu (2):
  powerpc/perf: Implement get_cpu_str()
  perf-download: Download the events json file

 tools/perf/Documentation/perf-download.txt |   31 +++
 tools/perf/Documentation/perf-list.txt     |   29 ++-
 tools/perf/Documentation/perf-record.txt   |    9 +-
 tools/perf/Documentation/perf-stat.txt     |    8 +-
 tools/perf/Makefile.perf                   |   12 +-
 tools/perf/arch/powerpc/util/header.c      |   12 ++
 tools/perf/arch/x86/util/header.c          |   19 +-
 tools/perf/builtin-list.c                  |   18 +-
 tools/perf/builtin-record.c                |    3 +
 tools/perf/builtin-stat.c                  |    2 +
 tools/perf/perf-download.sh                |  171 +++++++++++++++
 tools/perf/tests/aliases.c                 |   59 ++++++
 tools/perf/tests/builtin-test.c            |    4 +
 tools/perf/tests/tests.h                   |    1 +
 tools/perf/util/cache.h                    |    1 +
 tools/perf/util/jevents.c                  |  287 +++++++++++++++++++++++++
 tools/perf/util/jevents.h                  |    9 +
 tools/perf/util/jsmn.c                     |  313 ++++++++++++++++++++++++++++
 tools/perf/util/jsmn.h                     |   67 ++++++
 tools/perf/util/json.c                     |  162 ++++++++++++++
 tools/perf/util/json.h                     |   13 ++
 tools/perf/util/pager.c                    |   15 ++
 tools/perf/util/parse-events.c             |    4 +-
 tools/perf/util/parse-events.h             |    2 +-
 tools/perf/util/pmu.c                      |  160 +++++++++++---
 tools/perf/util/pmu.h                      |    5 +-
 26 files changed, 1365 insertions(+), 51 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-download.txt
 create mode 100755 tools/perf/perf-download.sh
 create mode 100644 tools/perf/tests/aliases.c
 create mode 100644 tools/perf/util/jevents.c
 create mode 100644 tools/perf/util/jevents.h
 create mode 100644 tools/perf/util/jsmn.c
 create mode 100644 tools/perf/util/jsmn.h
 create mode 100644 tools/perf/util/json.c
 create mode 100644 tools/perf/util/json.h

-- 
1.7.9.5

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

* [PATCH v9 01/11] perf, tools: Add jsmn `jasmine' JSON parser
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

I need a JSON parser. This adds the simplest JSON
parser I could find -- Serge Zaitsev's jsmn `jasmine' --
to the perf library. I merely converted it to (mostly)
Linux style and added support for non 0 terminated input.

The parser is quite straight forward and does not
copy any data, just returns tokens with offsets
into the input buffer. So it's relatively efficient
and simple to use.

The code is not fully checkpatch clean, but I didn't
want to completely fork the upstream code.

Original source: http://zserge.bitbucket.org/jsmn.html

In addition I added a simple wrapper that mmaps a json
file and provides some straight forward access functions.

Used in follow-on patches to parse event files.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---

Changelog[v9] (by Sukadev Bhattiprolu)
	Rebase to 4.0 and fix minor conflicts in tools/perf/Makefile.perf
	Report error if specified events file is invalid.

v2: Address review feedback.
v3: Minor checkpatch fixes.
---
 tools/perf/Makefile.perf |    4 +
 tools/perf/util/jsmn.c   |  313 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/jsmn.h   |   67 ++++++++++
 tools/perf/util/json.c   |  160 ++++++++++++++++++++++++
 tools/perf/util/json.h   |   13 ++
 5 files changed, 557 insertions(+)
 create mode 100644 tools/perf/util/jsmn.c
 create mode 100644 tools/perf/util/jsmn.h
 create mode 100644 tools/perf/util/json.c
 create mode 100644 tools/perf/util/json.h

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index aa6a504..a558eb3 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -331,6 +331,8 @@ LIB_H += ui/ui.h
 LIB_H += util/data.h
 LIB_H += util/kvm-stat.h
 LIB_H += util/thread-stack.h
+LIB_H += util/jsmn.h
+LIB_H += util/json.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -410,6 +412,8 @@ LIB_OBJS += $(OUTPUT)util/data.o
 LIB_OBJS += $(OUTPUT)util/tsc.o
 LIB_OBJS += $(OUTPUT)util/cloexec.o
 LIB_OBJS += $(OUTPUT)util/thread-stack.o
+LIB_OBJS += $(OUTPUT)util/jsmn.o
+LIB_OBJS += $(OUTPUT)util/json.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
diff --git a/tools/perf/util/jsmn.c b/tools/perf/util/jsmn.c
new file mode 100644
index 0000000..11d1fa1
--- /dev/null
+++ b/tools/perf/util/jsmn.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2010 Serge A. Zaitsev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Slightly modified by AK to not assume 0 terminated input.
+ */
+
+#include <stdlib.h>
+#include "jsmn.h"
+
+/*
+ * Allocates a fresh unused token from the token pool.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+				   jsmntok_t *tokens, size_t num_tokens)
+{
+	jsmntok_t *tok;
+
+	if ((unsigned)parser->toknext >= num_tokens)
+		return NULL;
+	tok = &tokens[parser->toknext++];
+	tok->start = tok->end = -1;
+	tok->size = 0;
+	return tok;
+}
+
+/*
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+			    int start, int end)
+{
+	token->type = type;
+	token->start = start;
+	token->end = end;
+	token->size = 0;
+}
+
+/*
+ * Fills next available token with JSON primitive.
+ */
+static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+				      size_t len,
+				      jsmntok_t *tokens, size_t num_tokens)
+{
+	jsmntok_t *token;
+	int start;
+
+	start = parser->pos;
+
+	for (; parser->pos < len; parser->pos++) {
+		switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+		/*
+		 * In strict mode primitive must be followed by ","
+		 * or "}" or "]"
+		 */
+		case ':':
+#endif
+		case '\t':
+		case '\r':
+		case '\n':
+		case ' ':
+		case ',':
+		case ']':
+		case '}':
+			goto found;
+		default:
+			break;
+		}
+		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+			parser->pos = start;
+			return JSMN_ERROR_INVAL;
+		}
+	}
+#ifdef JSMN_STRICT
+	/*
+	 * In strict mode primitive must be followed by a
+	 * comma/object/array.
+	 */
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+#endif
+
+found:
+	token = jsmn_alloc_token(parser, tokens, num_tokens);
+	if (token == NULL) {
+		parser->pos = start;
+		return JSMN_ERROR_NOMEM;
+	}
+	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+	parser->pos--; /* parent sees closing brackets */
+	return JSMN_SUCCESS;
+}
+
+/*
+ * Fills next token with JSON string.
+ */
+static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
+				   size_t len,
+				   jsmntok_t *tokens, size_t num_tokens)
+{
+	jsmntok_t *token;
+	int start = parser->pos;
+
+	/* Skip starting quote */
+	parser->pos++;
+
+	for (; parser->pos < len; parser->pos++) {
+		char c = js[parser->pos];
+
+		/* Quote: end of string */
+		if (c == '\"') {
+			token = jsmn_alloc_token(parser, tokens, num_tokens);
+			if (token == NULL) {
+				parser->pos = start;
+				return JSMN_ERROR_NOMEM;
+			}
+			jsmn_fill_token(token, JSMN_STRING, start+1,
+					parser->pos);
+			return JSMN_SUCCESS;
+		}
+
+		/* Backslash: Quoted symbol expected */
+		if (c == '\\') {
+			parser->pos++;
+			switch (js[parser->pos]) {
+				/* Allowed escaped symbols */
+			case '\"':
+			case '/':
+			case '\\':
+			case 'b':
+			case 'f':
+			case 'r':
+			case 'n':
+			case 't':
+				break;
+				/* Allows escaped symbol \uXXXX */
+			case 'u':
+				/* TODO */
+				break;
+				/* Unexpected symbol */
+			default:
+				parser->pos = start;
+				return JSMN_ERROR_INVAL;
+			}
+		}
+	}
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+}
+
+/*
+ * Parse JSON string and fill tokens.
+ */
+jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+		     jsmntok_t *tokens, unsigned int num_tokens)
+{
+	jsmnerr_t r;
+	int i;
+	jsmntok_t *token;
+
+	for (; parser->pos < len; parser->pos++) {
+		char c;
+		jsmntype_t type;
+
+		c = js[parser->pos];
+		switch (c) {
+		case '{':
+		case '[':
+			token = jsmn_alloc_token(parser, tokens, num_tokens);
+			if (token == NULL)
+				return JSMN_ERROR_NOMEM;
+			if (parser->toksuper != -1)
+				tokens[parser->toksuper].size++;
+			token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+			token->start = parser->pos;
+			parser->toksuper = parser->toknext - 1;
+			break;
+		case '}':
+		case ']':
+			type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+			for (i = parser->toknext - 1; i >= 0; i--) {
+				token = &tokens[i];
+				if (token->start != -1 && token->end == -1) {
+					if (token->type != type)
+						return JSMN_ERROR_INVAL;
+					parser->toksuper = -1;
+					token->end = parser->pos + 1;
+					break;
+				}
+			}
+			/* Error if unmatched closing bracket */
+			if (i == -1)
+				return JSMN_ERROR_INVAL;
+			for (; i >= 0; i--) {
+				token = &tokens[i];
+				if (token->start != -1 && token->end == -1) {
+					parser->toksuper = i;
+					break;
+				}
+			}
+			break;
+		case '\"':
+			r = jsmn_parse_string(parser, js, len, tokens,
+					      num_tokens);
+			if (r < 0)
+				return r;
+			if (parser->toksuper != -1)
+				tokens[parser->toksuper].size++;
+			break;
+		case '\t':
+		case '\r':
+		case '\n':
+		case ':':
+		case ',':
+		case ' ':
+			break;
+#ifdef JSMN_STRICT
+			/*
+			 * In strict mode primitives are:
+			 * numbers and booleans.
+			 */
+		case '-':
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		case 't':
+		case 'f':
+		case 'n':
+#else
+			/*
+			 * In non-strict mode every unquoted value
+			 * is a primitive.
+			 */
+			/*FALL THROUGH */
+		default:
+#endif
+			r = jsmn_parse_primitive(parser, js, len, tokens,
+						 num_tokens);
+			if (r < 0)
+				return r;
+			if (parser->toksuper != -1)
+				tokens[parser->toksuper].size++;
+			break;
+
+#ifdef JSMN_STRICT
+			/* Unexpected char in strict mode */
+		default:
+			return JSMN_ERROR_INVAL;
+#endif
+		}
+	}
+
+	for (i = parser->toknext - 1; i >= 0; i--) {
+		/* Unmatched opened object or array */
+		if (tokens[i].start != -1 && tokens[i].end == -1)
+			return JSMN_ERROR_PART;
+	}
+
+	return JSMN_SUCCESS;
+}
+
+/*
+ * Creates a new parser based over a given  buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser)
+{
+	parser->pos = 0;
+	parser->toknext = 0;
+	parser->toksuper = -1;
+}
+
+const char *jsmn_strerror(jsmnerr_t err)
+{
+	switch (err) {
+	case JSMN_ERROR_NOMEM:
+		return "No enough tokens";
+	case JSMN_ERROR_INVAL:
+		return "Invalid character inside JSON string";
+	case JSMN_ERROR_PART:
+		return "The string is not a full JSON packet, more bytes expected";
+	case JSMN_SUCCESS:
+		return "Success";
+	default:
+		return "Unknown json error";
+	}
+}
diff --git a/tools/perf/util/jsmn.h b/tools/perf/util/jsmn.h
new file mode 100644
index 0000000..d666b10
--- /dev/null
+++ b/tools/perf/util/jsmn.h
@@ -0,0 +1,67 @@
+#ifndef __JSMN_H_
+#define __JSMN_H_
+
+/*
+ * JSON type identifier. Basic types are:
+ *	o Object
+ *	o Array
+ *	o String
+ *	o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+	JSMN_PRIMITIVE = 0,
+	JSMN_OBJECT = 1,
+	JSMN_ARRAY = 2,
+	JSMN_STRING = 3
+} jsmntype_t;
+
+typedef enum {
+	/* Not enough tokens were provided */
+	JSMN_ERROR_NOMEM = -1,
+	/* Invalid character inside JSON string */
+	JSMN_ERROR_INVAL = -2,
+	/* The string is not a full JSON packet, more bytes expected */
+	JSMN_ERROR_PART = -3,
+	/* Everything was fine */
+	JSMN_SUCCESS = 0
+} jsmnerr_t;
+
+/*
+ * JSON token description.
+ * @param		type	type (object, array, string etc.)
+ * @param		start	start position in JSON data string
+ * @param		end		end position in JSON data string
+ */
+typedef struct {
+	jsmntype_t type;
+	int start;
+	int end;
+	int size;
+} jsmntok_t;
+
+/*
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+	unsigned int pos; /* offset in the JSON string */
+	int toknext; /* next token to allocate */
+	int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+
+/*
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser *parser);
+
+/*
+ * Run JSON parser. It parses a JSON data string into and array of tokens,
+ * each describing a single JSON object.
+ */
+jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js,
+		     size_t len,
+		     jsmntok_t *tokens, unsigned int num_tokens);
+
+const char *jsmn_strerror(jsmnerr_t err);
+
+#endif /* __JSMN_H_ */
diff --git a/tools/perf/util/json.c b/tools/perf/util/json.c
new file mode 100644
index 0000000..e20001f
--- /dev/null
+++ b/tools/perf/util/json.c
@@ -0,0 +1,160 @@
+/* Parse JSON files using the JSMN parser. */
+
+/*
+ * Copyright (c) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "jsmn.h"
+#include "json.h"
+#include <linux/kernel.h>
+
+static char *mapfile(const char *fn, size_t *size)
+{
+	unsigned ps = sysconf(_SC_PAGESIZE);
+	struct stat st;
+	char *map = NULL;
+	int err;
+	int fd = open(fn, O_RDONLY);
+
+	if (fd < 0 && verbose && fn) {
+		pr_err("Error opening events file '%s': %s\n", fn,
+				strerror(errno));
+	}
+
+	if (fd < 0)
+		return NULL;
+	err = fstat(fd, &st);
+	if (err < 0)
+		goto out;
+	*size = st.st_size;
+	map = mmap(NULL,
+		   (st.st_size + ps - 1) & ~(ps - 1),
+		   PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+	if (map == MAP_FAILED)
+		map = NULL;
+out:
+	close(fd);
+	return map;
+}
+
+static void unmapfile(char *map, size_t size)
+{
+	unsigned ps = sysconf(_SC_PAGESIZE);
+	munmap(map, roundup(size, ps));
+}
+
+/*
+ * Parse json file using jsmn. Return array of tokens,
+ * and mapped file. Caller needs to free array.
+ */
+jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len)
+{
+	jsmn_parser parser;
+	jsmntok_t *tokens;
+	jsmnerr_t res;
+	unsigned sz;
+
+	*map = mapfile(fn, size);
+	if (!*map)
+		return NULL;
+	/* Heuristic */
+	sz = *size * 16;
+	tokens = malloc(sz);
+	if (!tokens)
+		goto error;
+	jsmn_init(&parser);
+	res = jsmn_parse(&parser, *map, *size, tokens,
+			 sz / sizeof(jsmntok_t));
+	if (res != JSMN_SUCCESS) {
+		pr_err("%s: json error %s\n", fn, jsmn_strerror(res));
+		goto error_free;
+	}
+	if (len)
+		*len = parser.toknext;
+	return tokens;
+error_free:
+	free(tokens);
+error:
+	unmapfile(*map, *size);
+	return NULL;
+}
+
+void free_json(char *map, size_t size, jsmntok_t *tokens)
+{
+	free(tokens);
+	unmapfile(map, size);
+}
+
+static int countchar(char *map, char c, int end)
+{
+	int i;
+	int count = 0;
+	for (i = 0; i < end; i++)
+		if (map[i] == c)
+			count++;
+	return count;
+}
+
+/* Return line number of a jsmn token */
+int json_line(char *map, jsmntok_t *t)
+{
+	return countchar(map, '\n', t->start) + 1;
+}
+
+static const char * const jsmn_types[] = {
+	[JSMN_PRIMITIVE] = "primitive",
+	[JSMN_ARRAY] = "array",
+	[JSMN_OBJECT] = "object",
+	[JSMN_STRING] = "string"
+};
+
+#define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?")
+
+/* Return type name of a jsmn token */
+const char *json_name(jsmntok_t *t)
+{
+	return LOOKUP(jsmn_types, t->type);
+}
+
+int json_len(jsmntok_t *t)
+{
+	return t->end - t->start;
+}
+
+/* Is string t equal to s? */
+int json_streq(char *map, jsmntok_t *t, const char *s)
+{
+	unsigned len = json_len(t);
+	return len == strlen(s) && !strncasecmp(map + t->start, s, len);
+}
diff --git a/tools/perf/util/json.h b/tools/perf/util/json.h
new file mode 100644
index 0000000..37dd9e9
--- /dev/null
+++ b/tools/perf/util/json.h
@@ -0,0 +1,13 @@
+#ifndef JSON_H
+#define JSON_H 1
+
+#include "jsmn.h"
+
+jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len);
+void free_json(char *map, size_t size, jsmntok_t *tokens);
+int json_line(char *map, jsmntok_t *t);
+const char *json_name(jsmntok_t *t);
+int json_streq(char *map, jsmntok_t *t, const char *s);
+int json_len(jsmntok_t *t);
+
+#endif
-- 
1.7.9.5


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

* [PATCH v9 01/11] perf, tools: Add jsmn `jasmine' JSON parser
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

I need a JSON parser. This adds the simplest JSON
parser I could find -- Serge Zaitsev's jsmn `jasmine' --
to the perf library. I merely converted it to (mostly)
Linux style and added support for non 0 terminated input.

The parser is quite straight forward and does not
copy any data, just returns tokens with offsets
into the input buffer. So it's relatively efficient
and simple to use.

The code is not fully checkpatch clean, but I didn't
want to completely fork the upstream code.

Original source: http://zserge.bitbucket.org/jsmn.html

In addition I added a simple wrapper that mmaps a json
file and provides some straight forward access functions.

Used in follow-on patches to parse event files.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---

Changelog[v9] (by Sukadev Bhattiprolu)
	Rebase to 4.0 and fix minor conflicts in tools/perf/Makefile.perf
	Report error if specified events file is invalid.

v2: Address review feedback.
v3: Minor checkpatch fixes.
---
 tools/perf/Makefile.perf |    4 +
 tools/perf/util/jsmn.c   |  313 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/jsmn.h   |   67 ++++++++++
 tools/perf/util/json.c   |  160 ++++++++++++++++++++++++
 tools/perf/util/json.h   |   13 ++
 5 files changed, 557 insertions(+)
 create mode 100644 tools/perf/util/jsmn.c
 create mode 100644 tools/perf/util/jsmn.h
 create mode 100644 tools/perf/util/json.c
 create mode 100644 tools/perf/util/json.h

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index aa6a504..a558eb3 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -331,6 +331,8 @@ LIB_H += ui/ui.h
 LIB_H += util/data.h
 LIB_H += util/kvm-stat.h
 LIB_H += util/thread-stack.h
+LIB_H += util/jsmn.h
+LIB_H += util/json.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -410,6 +412,8 @@ LIB_OBJS += $(OUTPUT)util/data.o
 LIB_OBJS += $(OUTPUT)util/tsc.o
 LIB_OBJS += $(OUTPUT)util/cloexec.o
 LIB_OBJS += $(OUTPUT)util/thread-stack.o
+LIB_OBJS += $(OUTPUT)util/jsmn.o
+LIB_OBJS += $(OUTPUT)util/json.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
diff --git a/tools/perf/util/jsmn.c b/tools/perf/util/jsmn.c
new file mode 100644
index 0000000..11d1fa1
--- /dev/null
+++ b/tools/perf/util/jsmn.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2010 Serge A. Zaitsev
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * Slightly modified by AK to not assume 0 terminated input.
+ */
+
+#include <stdlib.h>
+#include "jsmn.h"
+
+/*
+ * Allocates a fresh unused token from the token pool.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+				   jsmntok_t *tokens, size_t num_tokens)
+{
+	jsmntok_t *tok;
+
+	if ((unsigned)parser->toknext >= num_tokens)
+		return NULL;
+	tok = &tokens[parser->toknext++];
+	tok->start = tok->end = -1;
+	tok->size = 0;
+	return tok;
+}
+
+/*
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+			    int start, int end)
+{
+	token->type = type;
+	token->start = start;
+	token->end = end;
+	token->size = 0;
+}
+
+/*
+ * Fills next available token with JSON primitive.
+ */
+static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+				      size_t len,
+				      jsmntok_t *tokens, size_t num_tokens)
+{
+	jsmntok_t *token;
+	int start;
+
+	start = parser->pos;
+
+	for (; parser->pos < len; parser->pos++) {
+		switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+		/*
+		 * In strict mode primitive must be followed by ","
+		 * or "}" or "]"
+		 */
+		case ':':
+#endif
+		case '\t':
+		case '\r':
+		case '\n':
+		case ' ':
+		case ',':
+		case ']':
+		case '}':
+			goto found;
+		default:
+			break;
+		}
+		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+			parser->pos = start;
+			return JSMN_ERROR_INVAL;
+		}
+	}
+#ifdef JSMN_STRICT
+	/*
+	 * In strict mode primitive must be followed by a
+	 * comma/object/array.
+	 */
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+#endif
+
+found:
+	token = jsmn_alloc_token(parser, tokens, num_tokens);
+	if (token == NULL) {
+		parser->pos = start;
+		return JSMN_ERROR_NOMEM;
+	}
+	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+	parser->pos--; /* parent sees closing brackets */
+	return JSMN_SUCCESS;
+}
+
+/*
+ * Fills next token with JSON string.
+ */
+static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
+				   size_t len,
+				   jsmntok_t *tokens, size_t num_tokens)
+{
+	jsmntok_t *token;
+	int start = parser->pos;
+
+	/* Skip starting quote */
+	parser->pos++;
+
+	for (; parser->pos < len; parser->pos++) {
+		char c = js[parser->pos];
+
+		/* Quote: end of string */
+		if (c == '\"') {
+			token = jsmn_alloc_token(parser, tokens, num_tokens);
+			if (token == NULL) {
+				parser->pos = start;
+				return JSMN_ERROR_NOMEM;
+			}
+			jsmn_fill_token(token, JSMN_STRING, start+1,
+					parser->pos);
+			return JSMN_SUCCESS;
+		}
+
+		/* Backslash: Quoted symbol expected */
+		if (c == '\\') {
+			parser->pos++;
+			switch (js[parser->pos]) {
+				/* Allowed escaped symbols */
+			case '\"':
+			case '/':
+			case '\\':
+			case 'b':
+			case 'f':
+			case 'r':
+			case 'n':
+			case 't':
+				break;
+				/* Allows escaped symbol \uXXXX */
+			case 'u':
+				/* TODO */
+				break;
+				/* Unexpected symbol */
+			default:
+				parser->pos = start;
+				return JSMN_ERROR_INVAL;
+			}
+		}
+	}
+	parser->pos = start;
+	return JSMN_ERROR_PART;
+}
+
+/*
+ * Parse JSON string and fill tokens.
+ */
+jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+		     jsmntok_t *tokens, unsigned int num_tokens)
+{
+	jsmnerr_t r;
+	int i;
+	jsmntok_t *token;
+
+	for (; parser->pos < len; parser->pos++) {
+		char c;
+		jsmntype_t type;
+
+		c = js[parser->pos];
+		switch (c) {
+		case '{':
+		case '[':
+			token = jsmn_alloc_token(parser, tokens, num_tokens);
+			if (token == NULL)
+				return JSMN_ERROR_NOMEM;
+			if (parser->toksuper != -1)
+				tokens[parser->toksuper].size++;
+			token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+			token->start = parser->pos;
+			parser->toksuper = parser->toknext - 1;
+			break;
+		case '}':
+		case ']':
+			type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+			for (i = parser->toknext - 1; i >= 0; i--) {
+				token = &tokens[i];
+				if (token->start != -1 && token->end == -1) {
+					if (token->type != type)
+						return JSMN_ERROR_INVAL;
+					parser->toksuper = -1;
+					token->end = parser->pos + 1;
+					break;
+				}
+			}
+			/* Error if unmatched closing bracket */
+			if (i == -1)
+				return JSMN_ERROR_INVAL;
+			for (; i >= 0; i--) {
+				token = &tokens[i];
+				if (token->start != -1 && token->end == -1) {
+					parser->toksuper = i;
+					break;
+				}
+			}
+			break;
+		case '\"':
+			r = jsmn_parse_string(parser, js, len, tokens,
+					      num_tokens);
+			if (r < 0)
+				return r;
+			if (parser->toksuper != -1)
+				tokens[parser->toksuper].size++;
+			break;
+		case '\t':
+		case '\r':
+		case '\n':
+		case ':':
+		case ',':
+		case ' ':
+			break;
+#ifdef JSMN_STRICT
+			/*
+			 * In strict mode primitives are:
+			 * numbers and booleans.
+			 */
+		case '-':
+		case '0':
+		case '1':
+		case '2':
+		case '3':
+		case '4':
+		case '5':
+		case '6':
+		case '7':
+		case '8':
+		case '9':
+		case 't':
+		case 'f':
+		case 'n':
+#else
+			/*
+			 * In non-strict mode every unquoted value
+			 * is a primitive.
+			 */
+			/*FALL THROUGH */
+		default:
+#endif
+			r = jsmn_parse_primitive(parser, js, len, tokens,
+						 num_tokens);
+			if (r < 0)
+				return r;
+			if (parser->toksuper != -1)
+				tokens[parser->toksuper].size++;
+			break;
+
+#ifdef JSMN_STRICT
+			/* Unexpected char in strict mode */
+		default:
+			return JSMN_ERROR_INVAL;
+#endif
+		}
+	}
+
+	for (i = parser->toknext - 1; i >= 0; i--) {
+		/* Unmatched opened object or array */
+		if (tokens[i].start != -1 && tokens[i].end == -1)
+			return JSMN_ERROR_PART;
+	}
+
+	return JSMN_SUCCESS;
+}
+
+/*
+ * Creates a new parser based over a given  buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser)
+{
+	parser->pos = 0;
+	parser->toknext = 0;
+	parser->toksuper = -1;
+}
+
+const char *jsmn_strerror(jsmnerr_t err)
+{
+	switch (err) {
+	case JSMN_ERROR_NOMEM:
+		return "No enough tokens";
+	case JSMN_ERROR_INVAL:
+		return "Invalid character inside JSON string";
+	case JSMN_ERROR_PART:
+		return "The string is not a full JSON packet, more bytes expected";
+	case JSMN_SUCCESS:
+		return "Success";
+	default:
+		return "Unknown json error";
+	}
+}
diff --git a/tools/perf/util/jsmn.h b/tools/perf/util/jsmn.h
new file mode 100644
index 0000000..d666b10
--- /dev/null
+++ b/tools/perf/util/jsmn.h
@@ -0,0 +1,67 @@
+#ifndef __JSMN_H_
+#define __JSMN_H_
+
+/*
+ * JSON type identifier. Basic types are:
+ *	o Object
+ *	o Array
+ *	o String
+ *	o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+	JSMN_PRIMITIVE = 0,
+	JSMN_OBJECT = 1,
+	JSMN_ARRAY = 2,
+	JSMN_STRING = 3
+} jsmntype_t;
+
+typedef enum {
+	/* Not enough tokens were provided */
+	JSMN_ERROR_NOMEM = -1,
+	/* Invalid character inside JSON string */
+	JSMN_ERROR_INVAL = -2,
+	/* The string is not a full JSON packet, more bytes expected */
+	JSMN_ERROR_PART = -3,
+	/* Everything was fine */
+	JSMN_SUCCESS = 0
+} jsmnerr_t;
+
+/*
+ * JSON token description.
+ * @param		type	type (object, array, string etc.)
+ * @param		start	start position in JSON data string
+ * @param		end		end position in JSON data string
+ */
+typedef struct {
+	jsmntype_t type;
+	int start;
+	int end;
+	int size;
+} jsmntok_t;
+
+/*
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+	unsigned int pos; /* offset in the JSON string */
+	int toknext; /* next token to allocate */
+	int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+
+/*
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser *parser);
+
+/*
+ * Run JSON parser. It parses a JSON data string into and array of tokens,
+ * each describing a single JSON object.
+ */
+jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js,
+		     size_t len,
+		     jsmntok_t *tokens, unsigned int num_tokens);
+
+const char *jsmn_strerror(jsmnerr_t err);
+
+#endif /* __JSMN_H_ */
diff --git a/tools/perf/util/json.c b/tools/perf/util/json.c
new file mode 100644
index 0000000..e20001f
--- /dev/null
+++ b/tools/perf/util/json.c
@@ -0,0 +1,160 @@
+/* Parse JSON files using the JSMN parser. */
+
+/*
+ * Copyright (c) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "jsmn.h"
+#include "json.h"
+#include <linux/kernel.h>
+
+static char *mapfile(const char *fn, size_t *size)
+{
+	unsigned ps = sysconf(_SC_PAGESIZE);
+	struct stat st;
+	char *map = NULL;
+	int err;
+	int fd = open(fn, O_RDONLY);
+
+	if (fd < 0 && verbose && fn) {
+		pr_err("Error opening events file '%s': %s\n", fn,
+				strerror(errno));
+	}
+
+	if (fd < 0)
+		return NULL;
+	err = fstat(fd, &st);
+	if (err < 0)
+		goto out;
+	*size = st.st_size;
+	map = mmap(NULL,
+		   (st.st_size + ps - 1) & ~(ps - 1),
+		   PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+	if (map == MAP_FAILED)
+		map = NULL;
+out:
+	close(fd);
+	return map;
+}
+
+static void unmapfile(char *map, size_t size)
+{
+	unsigned ps = sysconf(_SC_PAGESIZE);
+	munmap(map, roundup(size, ps));
+}
+
+/*
+ * Parse json file using jsmn. Return array of tokens,
+ * and mapped file. Caller needs to free array.
+ */
+jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len)
+{
+	jsmn_parser parser;
+	jsmntok_t *tokens;
+	jsmnerr_t res;
+	unsigned sz;
+
+	*map = mapfile(fn, size);
+	if (!*map)
+		return NULL;
+	/* Heuristic */
+	sz = *size * 16;
+	tokens = malloc(sz);
+	if (!tokens)
+		goto error;
+	jsmn_init(&parser);
+	res = jsmn_parse(&parser, *map, *size, tokens,
+			 sz / sizeof(jsmntok_t));
+	if (res != JSMN_SUCCESS) {
+		pr_err("%s: json error %s\n", fn, jsmn_strerror(res));
+		goto error_free;
+	}
+	if (len)
+		*len = parser.toknext;
+	return tokens;
+error_free:
+	free(tokens);
+error:
+	unmapfile(*map, *size);
+	return NULL;
+}
+
+void free_json(char *map, size_t size, jsmntok_t *tokens)
+{
+	free(tokens);
+	unmapfile(map, size);
+}
+
+static int countchar(char *map, char c, int end)
+{
+	int i;
+	int count = 0;
+	for (i = 0; i < end; i++)
+		if (map[i] == c)
+			count++;
+	return count;
+}
+
+/* Return line number of a jsmn token */
+int json_line(char *map, jsmntok_t *t)
+{
+	return countchar(map, '\n', t->start) + 1;
+}
+
+static const char * const jsmn_types[] = {
+	[JSMN_PRIMITIVE] = "primitive",
+	[JSMN_ARRAY] = "array",
+	[JSMN_OBJECT] = "object",
+	[JSMN_STRING] = "string"
+};
+
+#define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?")
+
+/* Return type name of a jsmn token */
+const char *json_name(jsmntok_t *t)
+{
+	return LOOKUP(jsmn_types, t->type);
+}
+
+int json_len(jsmntok_t *t)
+{
+	return t->end - t->start;
+}
+
+/* Is string t equal to s? */
+int json_streq(char *map, jsmntok_t *t, const char *s)
+{
+	unsigned len = json_len(t);
+	return len == strlen(s) && !strncasecmp(map + t->start, s, len);
+}
diff --git a/tools/perf/util/json.h b/tools/perf/util/json.h
new file mode 100644
index 0000000..37dd9e9
--- /dev/null
+++ b/tools/perf/util/json.h
@@ -0,0 +1,13 @@
+#ifndef JSON_H
+#define JSON_H 1
+
+#include "jsmn.h"
+
+jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len);
+void free_json(char *map, size_t size, jsmntok_t *tokens);
+int json_line(char *map, jsmntok_t *t);
+const char *json_name(jsmntok_t *t);
+int json_streq(char *map, jsmntok_t *t, const char *s);
+int json_len(jsmntok_t *t);
+
+#endif
-- 
1.7.9.5

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

* [PATCH v9 02/11] perf, tools: Add support for text descriptions of events and alias add
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Change pmu.c to allow descriptions of events and add interfaces
to add aliases at runtime from another file. To be used by jevents in
a followon patch

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0
	v2: Move perf list changes to other patch.
---
 tools/perf/util/json.c |    1 +
 tools/perf/util/pmu.c  |   48 +++++++++++++++++++++++++++++++++---------------
 tools/perf/util/pmu.h  |    1 +
 3 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/json.c b/tools/perf/util/json.c
index e20001f..2219844 100644
--- a/tools/perf/util/json.c
+++ b/tools/perf/util/json.c
@@ -38,6 +38,7 @@
 #include "jsmn.h"
 #include "json.h"
 #include <linux/kernel.h>
+#include "debug.h"
 
 static char *mapfile(const char *fn, size_t *size)
 {
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 4841167..527da74 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -198,17 +198,12 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
 	return 0;
 }
 
-static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
+static int __perf_pmu__new_alias(struct list_head *list, char *name, char *dir,
+			char *desc, char *val)
 {
 	struct perf_pmu_alias *alias;
-	char buf[256];
 	int ret;
 
-	ret = fread(buf, 1, sizeof(buf), file);
-	if (ret == 0)
-		return -EINVAL;
-	buf[ret] = 0;
-
 	alias = malloc(sizeof(*alias));
 	if (!alias)
 		return -ENOMEM;
@@ -218,26 +213,49 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
 	alias->unit[0] = '\0';
 	alias->per_pkg = false;
 
-	ret = parse_events_terms(&alias->terms, buf);
+	ret = parse_events_terms(&alias->terms, val);
 	if (ret) {
+		pr_err("Cannot parse alias %s: %d\n", val, ret);
 		free(alias);
 		return ret;
 	}
 
 	alias->name = strdup(name);
-	/*
-	 * load unit name and scale if available
-	 */
-	perf_pmu__parse_unit(alias, dir, name);
-	perf_pmu__parse_scale(alias, dir, name);
-	perf_pmu__parse_per_pkg(alias, dir, name);
-	perf_pmu__parse_snapshot(alias, dir, name);
+
+	if (dir) {
+		/*
+		 * load unit name and scale if available
+		 */
+		perf_pmu__parse_unit(alias, dir, name);
+		perf_pmu__parse_scale(alias, dir, name);
+		perf_pmu__parse_per_pkg(alias, dir, name);
+		perf_pmu__parse_snapshot(alias, dir, name);
+	}
+
+	alias->desc = desc ? strdup(desc) : NULL;
 
 	list_add_tail(&alias->list, list);
 
 	return 0;
 }
 
+static int perf_pmu__new_alias(struct list_head *list,
+		char *dir,
+		char *name,
+		FILE *file)
+{
+	char buf[256];
+	int ret;
+
+	ret = fread(buf, 1, sizeof(buf), file);
+	if (ret == 0)
+		return -EINVAL;
+	buf[ret] = 0;
+
+	return __perf_pmu__new_alias(list, name, dir, NULL, buf);
+}
+
+
 static inline bool pmu_alias_info_file(char *name)
 {
 	size_t len;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6b1249f..d06496d 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -37,6 +37,7 @@ struct perf_pmu_info {
 
 struct perf_pmu_alias {
 	char *name;
+	char *desc;
 	struct list_head terms; /* HEAD struct parse_events_term -> list */
 	struct list_head list;  /* ELEM */
 	char unit[UNIT_MAX_LEN+1];
-- 
1.7.9.5


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

* [PATCH v9 02/11] perf, tools: Add support for text descriptions of events and alias add
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Change pmu.c to allow descriptions of events and add interfaces
to add aliases at runtime from another file. To be used by jevents in
a followon patch

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0
	v2: Move perf list changes to other patch.
---
 tools/perf/util/json.c |    1 +
 tools/perf/util/pmu.c  |   48 +++++++++++++++++++++++++++++++++---------------
 tools/perf/util/pmu.h  |    1 +
 3 files changed, 35 insertions(+), 15 deletions(-)

diff --git a/tools/perf/util/json.c b/tools/perf/util/json.c
index e20001f..2219844 100644
--- a/tools/perf/util/json.c
+++ b/tools/perf/util/json.c
@@ -38,6 +38,7 @@
 #include "jsmn.h"
 #include "json.h"
 #include <linux/kernel.h>
+#include "debug.h"
 
 static char *mapfile(const char *fn, size_t *size)
 {
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 4841167..527da74 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -198,17 +198,12 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
 	return 0;
 }
 
-static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FILE *file)
+static int __perf_pmu__new_alias(struct list_head *list, char *name, char *dir,
+			char *desc, char *val)
 {
 	struct perf_pmu_alias *alias;
-	char buf[256];
 	int ret;
 
-	ret = fread(buf, 1, sizeof(buf), file);
-	if (ret == 0)
-		return -EINVAL;
-	buf[ret] = 0;
-
 	alias = malloc(sizeof(*alias));
 	if (!alias)
 		return -ENOMEM;
@@ -218,26 +213,49 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
 	alias->unit[0] = '\0';
 	alias->per_pkg = false;
 
-	ret = parse_events_terms(&alias->terms, buf);
+	ret = parse_events_terms(&alias->terms, val);
 	if (ret) {
+		pr_err("Cannot parse alias %s: %d\n", val, ret);
 		free(alias);
 		return ret;
 	}
 
 	alias->name = strdup(name);
-	/*
-	 * load unit name and scale if available
-	 */
-	perf_pmu__parse_unit(alias, dir, name);
-	perf_pmu__parse_scale(alias, dir, name);
-	perf_pmu__parse_per_pkg(alias, dir, name);
-	perf_pmu__parse_snapshot(alias, dir, name);
+
+	if (dir) {
+		/*
+		 * load unit name and scale if available
+		 */
+		perf_pmu__parse_unit(alias, dir, name);
+		perf_pmu__parse_scale(alias, dir, name);
+		perf_pmu__parse_per_pkg(alias, dir, name);
+		perf_pmu__parse_snapshot(alias, dir, name);
+	}
+
+	alias->desc = desc ? strdup(desc) : NULL;
 
 	list_add_tail(&alias->list, list);
 
 	return 0;
 }
 
+static int perf_pmu__new_alias(struct list_head *list,
+		char *dir,
+		char *name,
+		FILE *file)
+{
+	char buf[256];
+	int ret;
+
+	ret = fread(buf, 1, sizeof(buf), file);
+	if (ret == 0)
+		return -EINVAL;
+	buf[ret] = 0;
+
+	return __perf_pmu__new_alias(list, name, dir, NULL, buf);
+}
+
+
 static inline bool pmu_alias_info_file(char *name)
 {
 	size_t len;
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 6b1249f..d06496d 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -37,6 +37,7 @@ struct perf_pmu_info {
 
 struct perf_pmu_alias {
 	char *name;
+	char *desc;
 	struct list_head terms; /* HEAD struct parse_events_term -> list */
 	struct list_head list;  /* ELEM */
 	char unit[UNIT_MAX_LEN+1];
-- 
1.7.9.5

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

* [PATCH v9 03/11] perf, tools, list: Update perf list to output descriptions
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add support to perf list to print aliases with descriptions.
Support word wrapping for descriptions.
Fix up the sorting code to put aliases with descriptions
last.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---

Changelov[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in tools/perf/util/pmu.c
---
 tools/perf/util/pmu.c |   86 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 70 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 527da74..623b107 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -877,11 +877,51 @@ static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
 	return buf;
 }
 
-static int cmp_string(const void *a, const void *b)
+struct pair {
+	char *name;
+	char *desc;
+};
+
+static int cmp_pair(const void *a, const void *b)
 {
-	const char * const *as = a;
-	const char * const *bs = b;
-	return strcmp(*as, *bs);
+	const struct pair *as = a;
+	const struct pair *bs = b;
+
+	/* Put downloaded event list last */
+	if (!!as->desc != !!bs->desc)
+		return !!as->desc - !!bs->desc;
+	return strcmp(as->name, bs->name);
+}
+
+static void wordwrap(char *s, int start, int max, int corr)
+{
+	int column = start;
+	int n;
+
+	while (*s) {
+		int wlen = strcspn(s, " \t");
+
+		if (column + wlen >= max && column > start) {
+			printf("\n%*s", start, "");
+			column = start + corr;
+		}
+		n = printf("%s%.*s", column > start ? " " : "", wlen, s);
+		if (n <= 0)
+			break;
+		s += wlen;
+		column += n;
+		while (isspace(*s))
+			s++;
+	}
+}
+
+static int get_columns(void)
+{
+	/*
+	 * Should ask the terminal with TIOCGWINSZ here, but we
+	 * need the original fd before the pager.
+	 */
+	return 79;
 }
 
 void print_pmu_events(const char *event_glob, bool name_only)
@@ -891,7 +931,9 @@ void print_pmu_events(const char *event_glob, bool name_only)
 	char buf[1024];
 	int printed = 0;
 	int len, j;
-	char **aliases;
+	struct pair *aliases;
+	int numdesc = 0;
+	int columns = get_columns();
 
 	pmu = NULL;
 	len = 0;
@@ -901,14 +943,15 @@ void print_pmu_events(const char *event_glob, bool name_only)
 		if (pmu->selectable)
 			len++;
 	}
-	aliases = zalloc(sizeof(char *) * len);
+	aliases = zalloc(sizeof(struct pair) * len);
 	if (!aliases)
 		goto out_enomem;
 	pmu = NULL;
 	j = 0;
 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
 		list_for_each_entry(alias, &pmu->aliases, list) {
-			char *name = format_alias(buf, sizeof(buf), pmu, alias);
+			char *name = alias->desc ? alias->name :
+				format_alias(buf, sizeof(buf), pmu, alias);
 			bool is_cpu = !strcmp(pmu->name, "cpu");
 
 			if (event_glob != NULL &&
@@ -917,11 +960,14 @@ void print_pmu_events(const char *event_glob, bool name_only)
 						       event_glob))))
 				continue;
 
-			if (is_cpu && !name_only)
-				name = format_alias_or(buf, sizeof(buf), pmu, alias);
+			aliases[j].name = name;
+			if (is_cpu && !name_only && !alias->desc)
+				aliases[j].name = format_alias_or(buf,
+						sizeof(buf), pmu, alias);
 
-			aliases[j] = strdup(name);
-			if (aliases[j] == NULL)
+			aliases[j].name = strdup(aliases[j].name);
+			aliases[j].desc = alias->desc;
+			if (aliases[j].name == NULL)
 				goto out_enomem;
 			j++;
 		}
@@ -929,25 +975,33 @@ void print_pmu_events(const char *event_glob, bool name_only)
 			char *s;
 			if (asprintf(&s, "%s//", pmu->name) < 0)
 				goto out_enomem;
-			aliases[j] = s;
+			aliases[j].name = s;
 			j++;
 		}
 	}
 	len = j;
-	qsort(aliases, len, sizeof(char *), cmp_string);
+	qsort(aliases, len, sizeof(struct pair), cmp_pair);
 	for (j = 0; j < len; j++) {
 		if (name_only) {
-			printf("%s ", aliases[j]);
+			printf("%s ", aliases[j].name);
 			continue;
 		}
-		printf("  %-50s [Kernel PMU event]\n", aliases[j]);
+		if (aliases[j].desc) {
+			if (numdesc++ == 0 && printed)
+				printf("\n");
+			printf("  %-50s [", aliases[j].name);
+			wordwrap(aliases[j].desc, 53, columns, 1);
+			printf("]\n");
+		} else
+			printf("  %-50s [Kernel PMU event]\n", aliases[j].name);
+		zfree(&aliases[j].name);
 		printed++;
 	}
 	if (printed)
 		printf("\n");
 out_free:
 	for (j = 0; j < len; j++)
-		zfree(&aliases[j]);
+		zfree(&aliases[j].name);
 	zfree(&aliases);
 	return;
 
-- 
1.7.9.5


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

* [PATCH v9 03/11] perf, tools, list: Update perf list to output descriptions
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add support to perf list to print aliases with descriptions.
Support word wrapping for descriptions.
Fix up the sorting code to put aliases with descriptions
last.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---

Changelov[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in tools/perf/util/pmu.c
---
 tools/perf/util/pmu.c |   86 ++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 70 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 527da74..623b107 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -877,11 +877,51 @@ static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
 	return buf;
 }
 
-static int cmp_string(const void *a, const void *b)
+struct pair {
+	char *name;
+	char *desc;
+};
+
+static int cmp_pair(const void *a, const void *b)
 {
-	const char * const *as = a;
-	const char * const *bs = b;
-	return strcmp(*as, *bs);
+	const struct pair *as = a;
+	const struct pair *bs = b;
+
+	/* Put downloaded event list last */
+	if (!!as->desc != !!bs->desc)
+		return !!as->desc - !!bs->desc;
+	return strcmp(as->name, bs->name);
+}
+
+static void wordwrap(char *s, int start, int max, int corr)
+{
+	int column = start;
+	int n;
+
+	while (*s) {
+		int wlen = strcspn(s, " \t");
+
+		if (column + wlen >= max && column > start) {
+			printf("\n%*s", start, "");
+			column = start + corr;
+		}
+		n = printf("%s%.*s", column > start ? " " : "", wlen, s);
+		if (n <= 0)
+			break;
+		s += wlen;
+		column += n;
+		while (isspace(*s))
+			s++;
+	}
+}
+
+static int get_columns(void)
+{
+	/*
+	 * Should ask the terminal with TIOCGWINSZ here, but we
+	 * need the original fd before the pager.
+	 */
+	return 79;
 }
 
 void print_pmu_events(const char *event_glob, bool name_only)
@@ -891,7 +931,9 @@ void print_pmu_events(const char *event_glob, bool name_only)
 	char buf[1024];
 	int printed = 0;
 	int len, j;
-	char **aliases;
+	struct pair *aliases;
+	int numdesc = 0;
+	int columns = get_columns();
 
 	pmu = NULL;
 	len = 0;
@@ -901,14 +943,15 @@ void print_pmu_events(const char *event_glob, bool name_only)
 		if (pmu->selectable)
 			len++;
 	}
-	aliases = zalloc(sizeof(char *) * len);
+	aliases = zalloc(sizeof(struct pair) * len);
 	if (!aliases)
 		goto out_enomem;
 	pmu = NULL;
 	j = 0;
 	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
 		list_for_each_entry(alias, &pmu->aliases, list) {
-			char *name = format_alias(buf, sizeof(buf), pmu, alias);
+			char *name = alias->desc ? alias->name :
+				format_alias(buf, sizeof(buf), pmu, alias);
 			bool is_cpu = !strcmp(pmu->name, "cpu");
 
 			if (event_glob != NULL &&
@@ -917,11 +960,14 @@ void print_pmu_events(const char *event_glob, bool name_only)
 						       event_glob))))
 				continue;
 
-			if (is_cpu && !name_only)
-				name = format_alias_or(buf, sizeof(buf), pmu, alias);
+			aliases[j].name = name;
+			if (is_cpu && !name_only && !alias->desc)
+				aliases[j].name = format_alias_or(buf,
+						sizeof(buf), pmu, alias);
 
-			aliases[j] = strdup(name);
-			if (aliases[j] == NULL)
+			aliases[j].name = strdup(aliases[j].name);
+			aliases[j].desc = alias->desc;
+			if (aliases[j].name == NULL)
 				goto out_enomem;
 			j++;
 		}
@@ -929,25 +975,33 @@ void print_pmu_events(const char *event_glob, bool name_only)
 			char *s;
 			if (asprintf(&s, "%s//", pmu->name) < 0)
 				goto out_enomem;
-			aliases[j] = s;
+			aliases[j].name = s;
 			j++;
 		}
 	}
 	len = j;
-	qsort(aliases, len, sizeof(char *), cmp_string);
+	qsort(aliases, len, sizeof(struct pair), cmp_pair);
 	for (j = 0; j < len; j++) {
 		if (name_only) {
-			printf("%s ", aliases[j]);
+			printf("%s ", aliases[j].name);
 			continue;
 		}
-		printf("  %-50s [Kernel PMU event]\n", aliases[j]);
+		if (aliases[j].desc) {
+			if (numdesc++ == 0 && printed)
+				printf("\n");
+			printf("  %-50s [", aliases[j].name);
+			wordwrap(aliases[j].desc, 53, columns, 1);
+			printf("]\n");
+		} else
+			printf("  %-50s [Kernel PMU event]\n", aliases[j].name);
+		zfree(&aliases[j].name);
 		printed++;
 	}
 	if (printed)
 		printf("\n");
 out_free:
 	for (j = 0; j < len; j++)
-		zfree(&aliases[j]);
+		zfree(&aliases[j].name);
 	zfree(&aliases);
 	return;
 
-- 
1.7.9.5

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

* [PATCH v9 04/11] perf, tools: Add support for reading JSON event files
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add a parser for Intel style JSON event files. This allows
to use an Intel event list directly with perf. The Intel
event lists can be quite large and are too big to store
in unswappable kernel memory.

The parser code knows how to convert the JSON fields
to perf fields. The conversion code is straight forward.
It knows (very little) Intel specific information, and can be easily
extended to handle fields for other CPUs.

The parser code is partially shared with an independent parsing
library, which is 2-clause BSD licenced. To avoid any conflicts I marked
those files as BSD licenced too. As part of perf they become GPLv2.

The events are handled using the existing alias machinery.

We output the BriefDescription in perf list.

Right now the json file can be specified as an argument
to perf stat/record/list. Followon patches will automate this.

JSON files look like this:

[
  {
    "EventCode": "0x00",
    "UMask": "0x01",
    "EventName": "INST_RETIRED.ANY",
    "BriefDescription": "Instructions retired from execution.",
    "PublicDescription": "Instructions retired from execution.",
    "Counter": "Fixed counter 1",
    "CounterHTOff": "Fixed counter 1",
    "SampleAfterValue": "2000003",
    "MSRIndex": "0",
    "MSRValue": "0",
    "TakenAlone": "0",
    "CounterMask": "0",
    "Invert": "0",
    "AnyThread": "0",
    "EdgeDetect": "0",
    "PEBS": "0",
    "PRECISE_STORE": "0",
    "Errata": "null",
    "Offcore": "0"
  }
]

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in:
		tools/perf/Documentation/perf-record.txt
		tools/perf/builtin-list.c
		tools/perf/builtin-record.c
		tools/perf/util/pmu.h
v2: Address review feedback. Rename option to --event-files
v3: Add JSON example
v4: Update manpages.
v5: Don't remove dot in fixname. Fix compile error. Add include
protection. Comment realloc.
v6: Include debug/util.h
---
 tools/perf/Documentation/perf-list.txt   |   12 +-
 tools/perf/Documentation/perf-record.txt |    9 +-
 tools/perf/Documentation/perf-stat.txt   |    8 +-
 tools/perf/Makefile.perf                 |    2 +
 tools/perf/builtin-list.c                |    2 +
 tools/perf/builtin-record.c              |    3 +
 tools/perf/builtin-stat.c                |    2 +
 tools/perf/util/jevents.c                |  247 ++++++++++++++++++++++++++++++
 tools/perf/util/jevents.h                |    8 +
 tools/perf/util/json.c                   |    1 +
 tools/perf/util/pmu.c                    |   14 ++
 tools/perf/util/pmu.h                    |    1 +
 12 files changed, 305 insertions(+), 4 deletions(-)
 create mode 100644 tools/perf/util/jevents.c
 create mode 100644 tools/perf/util/jevents.h

diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 3e2aec9..205ac40 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -15,8 +15,16 @@ DESCRIPTION
 This command displays the symbolic event types which can be selected in the
 various perf commands with the -e option.
 
-[[EVENT_MODIFIERS]]
-EVENT MODIFIERS
+OPTIONS
+-------
+--events-file=::
+Specify JSON event list file to use for parsing events. Files can be
+automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
+
+[[EVENT_MODIFIERS]] EVENT MODIFIERS
 ---------------
 
 Events can optionally have a modifier by appending a colon and one or
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 31e9774..13f34b0 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -235,6 +235,13 @@ Capture machine state (registers) at interrupt, i.e., on counter overflows for
 each sample. List of captured registers depends on the architecture. This option
 is off by default.
 
+--events-file=::
+Specify JSON event list file to use for parsing events. Must be specified
+before the -e option. Files can be automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
+
 SEE ALSO
 --------
-linkperf:perf-stat[1], linkperf:perf-list[1]
+linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-download[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 04e150d..3853245 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -154,6 +154,12 @@ filter out the startup phase of the program, which is often very different.
 
 Print statistics of transactional execution if supported.
 
+--events-file=::
+Specify JSON event list file to use for parsing events. Must be specified before
+the -e option. Files can be automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
 EXAMPLES
 --------
 
@@ -174,4 +180,4 @@ $ perf stat -- make -j
 
 SEE ALSO
 --------
-linkperf:perf-top[1], linkperf:perf-list[1]
+linkperf:perf-top[1], linkperf:perf-list[1], linkperf:perf-download[1]
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index a558eb3..d9c1a4c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -333,6 +333,7 @@ LIB_H += util/kvm-stat.h
 LIB_H += util/thread-stack.h
 LIB_H += util/jsmn.h
 LIB_H += util/json.h
+LIB_H += util/jevents.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -414,6 +415,7 @@ LIB_OBJS += $(OUTPUT)util/cloexec.o
 LIB_OBJS += $(OUTPUT)util/thread-stack.o
 LIB_OBJS += $(OUTPUT)util/jsmn.o
 LIB_OBJS += $(OUTPUT)util/json.o
+LIB_OBJS += $(OUTPUT)util/jevents.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 198f3c3..fd07cc1 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -22,6 +22,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 	bool raw_dump = false;
 	struct option list_options[] = {
 		OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
+		OPT_STRING(0, "events-file", &json_file, "json file",
+			   "Read event json file"),
 		OPT_END()
 	};
 	const char * const list_usage[] = {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 404ab34..365c9d4 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -27,6 +27,7 @@
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 #include "util/data.h"
+#include "util/pmu.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -839,6 +840,8 @@ struct option __record_options[] = {
 		    "use per-thread mmaps"),
 	OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
 		    "Sample machine registers on interrupt"),
+	OPT_STRING(0, "events-file", &json_file, "json file",
+		   "Read event json file"),
 	OPT_END()
 };
 
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e598e4e..f4ff31b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1757,6 +1757,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		     "aggregate counts per physical processor core", AGGR_CORE),
 	OPT_UINTEGER('D', "delay", &initial_delay,
 		     "ms to wait before starting measurement after program start"),
+	OPT_STRING(0, "events-file", &json_file, "json file",
+		   "Read event json file"),
 	OPT_END()
 	};
 	const char * const stat_usage[] = {
diff --git a/tools/perf/util/jevents.c b/tools/perf/util/jevents.c
new file mode 100644
index 0000000..023757c
--- /dev/null
+++ b/tools/perf/util/jevents.c
@@ -0,0 +1,247 @@
+/* Parse event JSON files */
+
+/*
+ * Copyright (c) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include "util/debug.h"
+#include "cache.h"
+#include "jsmn.h"
+#include "json.h"
+#include "jevents.h"
+
+static void addfield(char *map, char **dst, const char *sep,
+		     const char *a, jsmntok_t *bt)
+{
+	unsigned len = strlen(a) + 1 + strlen(sep);
+	int olen = *dst ? strlen(*dst) : 0;
+	int blen = bt ? json_len(bt) : 0;
+	char *out;
+
+	out = realloc(*dst, len + olen + blen);
+	if (!out) {
+		/* Don't add field in this case */
+		return;
+	}
+	*dst = out;
+
+	if (!olen)
+		*(*dst) = 0;
+	else
+		strcat(*dst, sep);
+	strcat(*dst, a);
+	if (bt)
+		strncat(*dst, map + bt->start, blen);
+}
+
+static void fixname(char *s)
+{
+	for (; *s; s++)
+		*s = tolower(*s);
+}
+
+static void fixdesc(char *s)
+{
+	char *e = s + strlen(s);
+
+	/* Remove trailing dots that look ugly in perf list */
+	--e;
+	while (e >= s && isspace(*e))
+		--e;
+	if (*e == '.')
+		*e = 0;
+}
+
+static struct msrmap {
+	const char *num;
+	const char *pname;
+} msrmap[] = {
+	{ "0x3F6", "ldlat=" },
+	{ "0x1A6", "offcore_rsp=" },
+	{ "0x1A7", "offcore_rsp=" },
+	{ NULL, NULL }
+};
+
+static struct field {
+	const char *field;
+	const char *kernel;
+} fields[] = {
+	{ "EventCode",	"event=" },
+	{ "UMask",	"umask=" },
+	{ "CounterMask", "cmask=" },
+	{ "Invert",	"inv=" },
+	{ "AnyThread",	"any=" },
+	{ "EdgeDetect",	"edge=" },
+	{ "SampleAfterValue", "period=" },
+	{ NULL, NULL }
+};
+
+static void cut_comma(char *map, jsmntok_t *newval)
+{
+	int i;
+
+	/* Cut off everything after comma */
+	for (i = newval->start; i < newval->end; i++) {
+		if (map[i] == ',')
+			newval->end = i;
+	}
+}
+
+static int match_field(char *map, jsmntok_t *field, int nz,
+		       char **event, jsmntok_t *val)
+{
+	struct field *f;
+	jsmntok_t newval = *val;
+
+	for (f = fields; f->field; f++)
+		if (json_streq(map, field, f->field) && nz) {
+			cut_comma(map, &newval);
+			addfield(map, event, ",", f->kernel, &newval);
+			return 1;
+		}
+	return 0;
+}
+
+static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
+{
+	jsmntok_t newval = *val;
+	static bool warned;
+	int i;
+
+	cut_comma(map, &newval);
+	for (i = 0; msrmap[i].num; i++)
+		if (json_streq(map, &newval, msrmap[i].num))
+			return &msrmap[i];
+	if (!warned) {
+		warned = true;
+		pr_err("Unknown MSR in event file %.*s\n",
+			json_len(val), map + val->start);
+	}
+	return NULL;
+}
+
+#define EXPECT(e, t, m) do { if (!(e)) {			\
+	jsmntok_t *loc = (t);					\
+	if (!(t)->start && (t) > tokens)			\
+		loc = (t) - 1;					\
+		pr_err("%s:%d: " m ", got %s\n", fn,		\
+			json_line(map, loc),			\
+			json_name(t));				\
+	goto out_free;						\
+} } while (0)
+
+/* Call func with each event in the json file */
+
+int json_events(const char *fn,
+	  int (*func)(void *data, char *name, char *event, char *desc),
+	  void *data)
+{
+	int err = -EIO;
+	size_t size;
+	jsmntok_t *tokens, *tok;
+	int i, j, len;
+	char *map;
+
+	tokens = parse_json(fn, &map, &size, &len);
+	if (!tokens)
+		return -EIO;
+	EXPECT(tokens->type == JSMN_ARRAY, tokens, "expected top level array");
+	tok = tokens + 1;
+	for (i = 0; i < tokens->size; i++) {
+		char *event = NULL, *desc = NULL, *name = NULL;
+		struct msrmap *msr = NULL;
+		jsmntok_t *msrval = NULL;
+		jsmntok_t *precise = NULL;
+		jsmntok_t *obj = tok++;
+
+		EXPECT(obj->type == JSMN_OBJECT, obj, "expected object");
+		for (j = 0; j < obj->size; j += 2) {
+			jsmntok_t *field, *val;
+			int nz;
+
+			field = tok + j;
+			EXPECT(field->type == JSMN_STRING, tok + j,
+			       "Expected field name");
+			val = tok + j + 1;
+			EXPECT(val->type == JSMN_STRING, tok + j + 1,
+			       "Expected string value");
+
+			nz = !json_streq(map, val, "0");
+			if (match_field(map, field, nz, &event, val)) {
+				/* ok */
+			} else if (json_streq(map, field, "EventName")) {
+				addfield(map, &name, "", "", val);
+			} else if (json_streq(map, field, "BriefDescription")) {
+				addfield(map, &desc, "", "", val);
+				fixdesc(desc);
+			} else if (json_streq(map, field, "PEBS") && nz) {
+				precise = val;
+			} else if (json_streq(map, field, "MSRIndex") && nz) {
+				msr = lookup_msr(map, val);
+			} else if (json_streq(map, field, "MSRValue")) {
+				msrval = val;
+			} else if (json_streq(map, field, "Errata") &&
+				   !json_streq(map, val, "null")) {
+				addfield(map, &desc, ". ",
+					" Spec update: ", val);
+			} else if (json_streq(map, field, "Data_LA") && nz) {
+				addfield(map, &desc, ". ",
+					" Supports address when precise",
+					NULL);
+			}
+			/* ignore unknown fields */
+		}
+		if (precise && !strstr(desc, "(Precise Event)")) {
+			if (json_streq(map, precise, "2"))
+				addfield(map, &desc, " ", "(Must be precise)",
+						NULL);
+			else
+				addfield(map, &desc, " ",
+						"(Precise event)", NULL);
+		}
+		if (msr != NULL)
+			addfield(map, &event, ",", msr->pname, msrval);
+		fixname(name);
+		err = func(data, name, event, desc);
+		free(event);
+		free(desc);
+		free(name);
+		if (err)
+			break;
+		tok += j;
+	}
+	EXPECT(tok - tokens == len, tok, "unexpected objects at end");
+	err = 0;
+out_free:
+	free_json(map, size, tokens);
+	return err;
+}
diff --git a/tools/perf/util/jevents.h b/tools/perf/util/jevents.h
new file mode 100644
index 0000000..fbc4549
--- /dev/null
+++ b/tools/perf/util/jevents.h
@@ -0,0 +1,8 @@
+#ifndef JEVENTS_H
+#define JEVENTS_H 1
+
+int json_events(const char *fn,
+		int (*func)(void *data, char *name, char *event, char *desc),
+		void *data);
+
+#endif
diff --git a/tools/perf/util/json.c b/tools/perf/util/json.c
index 2219844..45acadf 100644
--- a/tools/perf/util/json.c
+++ b/tools/perf/util/json.c
@@ -37,6 +37,7 @@
 #include <unistd.h>
 #include "jsmn.h"
 #include "json.h"
+#include "util/debug.h"
 #include <linux/kernel.h>
 #include "debug.h"
 
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 623b107..d7e5e1b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -11,6 +11,9 @@
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
+#include "jevents.h"
+
+const char *json_file;
 
 struct perf_pmu_format {
 	char *name;
@@ -316,6 +319,14 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
 	return ret;
 }
 
+static int add_alias(void *data, char *name, char *event, char *desc)
+{
+	struct list_head *head = (struct list_head *)data;
+
+	__perf_pmu__new_alias(head, name, NULL, desc, event);
+	return 0;
+}
+
 /*
  * Reading the pmu event aliases definition, which should be located at:
  * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
@@ -471,6 +482,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
 	if (pmu_aliases(name, &aliases))
 		return NULL;
 
+	if (!strcmp(name, "cpu") && json_file)
+		json_events(json_file, add_alias, &aliases);
+
 	if (pmu_type(name, &type))
 		return NULL;
 
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index d06496d..f8dac0f 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -77,4 +77,5 @@ int perf_pmu__test(void);
 
 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
 
+extern const char *json_file;
 #endif /* __PMU_H */
-- 
1.7.9.5


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

* [PATCH v9 04/11] perf, tools: Add support for reading JSON event files
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add a parser for Intel style JSON event files. This allows
to use an Intel event list directly with perf. The Intel
event lists can be quite large and are too big to store
in unswappable kernel memory.

The parser code knows how to convert the JSON fields
to perf fields. The conversion code is straight forward.
It knows (very little) Intel specific information, and can be easily
extended to handle fields for other CPUs.

The parser code is partially shared with an independent parsing
library, which is 2-clause BSD licenced. To avoid any conflicts I marked
those files as BSD licenced too. As part of perf they become GPLv2.

The events are handled using the existing alias machinery.

We output the BriefDescription in perf list.

Right now the json file can be specified as an argument
to perf stat/record/list. Followon patches will automate this.

JSON files look like this:

[
  {
    "EventCode": "0x00",
    "UMask": "0x01",
    "EventName": "INST_RETIRED.ANY",
    "BriefDescription": "Instructions retired from execution.",
    "PublicDescription": "Instructions retired from execution.",
    "Counter": "Fixed counter 1",
    "CounterHTOff": "Fixed counter 1",
    "SampleAfterValue": "2000003",
    "MSRIndex": "0",
    "MSRValue": "0",
    "TakenAlone": "0",
    "CounterMask": "0",
    "Invert": "0",
    "AnyThread": "0",
    "EdgeDetect": "0",
    "PEBS": "0",
    "PRECISE_STORE": "0",
    "Errata": "null",
    "Offcore": "0"
  }
]

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in:
		tools/perf/Documentation/perf-record.txt
		tools/perf/builtin-list.c
		tools/perf/builtin-record.c
		tools/perf/util/pmu.h
v2: Address review feedback. Rename option to --event-files
v3: Add JSON example
v4: Update manpages.
v5: Don't remove dot in fixname. Fix compile error. Add include
protection. Comment realloc.
v6: Include debug/util.h
---
 tools/perf/Documentation/perf-list.txt   |   12 +-
 tools/perf/Documentation/perf-record.txt |    9 +-
 tools/perf/Documentation/perf-stat.txt   |    8 +-
 tools/perf/Makefile.perf                 |    2 +
 tools/perf/builtin-list.c                |    2 +
 tools/perf/builtin-record.c              |    3 +
 tools/perf/builtin-stat.c                |    2 +
 tools/perf/util/jevents.c                |  247 ++++++++++++++++++++++++++++++
 tools/perf/util/jevents.h                |    8 +
 tools/perf/util/json.c                   |    1 +
 tools/perf/util/pmu.c                    |   14 ++
 tools/perf/util/pmu.h                    |    1 +
 12 files changed, 305 insertions(+), 4 deletions(-)
 create mode 100644 tools/perf/util/jevents.c
 create mode 100644 tools/perf/util/jevents.h

diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 3e2aec9..205ac40 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -15,8 +15,16 @@ DESCRIPTION
 This command displays the symbolic event types which can be selected in the
 various perf commands with the -e option.
 
-[[EVENT_MODIFIERS]]
-EVENT MODIFIERS
+OPTIONS
+-------
+--events-file=::
+Specify JSON event list file to use for parsing events. Files can be
+automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
+
+[[EVENT_MODIFIERS]] EVENT MODIFIERS
 ---------------
 
 Events can optionally have a modifier by appending a colon and one or
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 31e9774..13f34b0 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -235,6 +235,13 @@ Capture machine state (registers) at interrupt, i.e., on counter overflows for
 each sample. List of captured registers depends on the architecture. This option
 is off by default.
 
+--events-file=::
+Specify JSON event list file to use for parsing events. Must be specified
+before the -e option. Files can be automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
+
 SEE ALSO
 --------
-linkperf:perf-stat[1], linkperf:perf-list[1]
+linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-download[1]
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 04e150d..3853245 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -154,6 +154,12 @@ filter out the startup phase of the program, which is often very different.
 
 Print statistics of transactional execution if supported.
 
+--events-file=::
+Specify JSON event list file to use for parsing events. Must be specified before
+the -e option. Files can be automatically downloaded with perf download.
+The JSON event file can be also specified with the EVENTMAP environment
+variable.
+
 EXAMPLES
 --------
 
@@ -174,4 +180,4 @@ $ perf stat -- make -j
 
 SEE ALSO
 --------
-linkperf:perf-top[1], linkperf:perf-list[1]
+linkperf:perf-top[1], linkperf:perf-list[1], linkperf:perf-download[1]
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index a558eb3..d9c1a4c 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -333,6 +333,7 @@ LIB_H += util/kvm-stat.h
 LIB_H += util/thread-stack.h
 LIB_H += util/jsmn.h
 LIB_H += util/json.h
+LIB_H += util/jevents.h
 
 LIB_OBJS += $(OUTPUT)util/abspath.o
 LIB_OBJS += $(OUTPUT)util/alias.o
@@ -414,6 +415,7 @@ LIB_OBJS += $(OUTPUT)util/cloexec.o
 LIB_OBJS += $(OUTPUT)util/thread-stack.o
 LIB_OBJS += $(OUTPUT)util/jsmn.o
 LIB_OBJS += $(OUTPUT)util/json.o
+LIB_OBJS += $(OUTPUT)util/jevents.o
 
 LIB_OBJS += $(OUTPUT)ui/setup.o
 LIB_OBJS += $(OUTPUT)ui/helpline.o
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 198f3c3..fd07cc1 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -22,6 +22,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 	bool raw_dump = false;
 	struct option list_options[] = {
 		OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
+		OPT_STRING(0, "events-file", &json_file, "json file",
+			   "Read event json file"),
 		OPT_END()
 	};
 	const char * const list_usage[] = {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 404ab34..365c9d4 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -27,6 +27,7 @@
 #include "util/cpumap.h"
 #include "util/thread_map.h"
 #include "util/data.h"
+#include "util/pmu.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -839,6 +840,8 @@ struct option __record_options[] = {
 		    "use per-thread mmaps"),
 	OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
 		    "Sample machine registers on interrupt"),
+	OPT_STRING(0, "events-file", &json_file, "json file",
+		   "Read event json file"),
 	OPT_END()
 };
 
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e598e4e..f4ff31b 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -1757,6 +1757,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
 		     "aggregate counts per physical processor core", AGGR_CORE),
 	OPT_UINTEGER('D', "delay", &initial_delay,
 		     "ms to wait before starting measurement after program start"),
+	OPT_STRING(0, "events-file", &json_file, "json file",
+		   "Read event json file"),
 	OPT_END()
 	};
 	const char * const stat_usage[] = {
diff --git a/tools/perf/util/jevents.c b/tools/perf/util/jevents.c
new file mode 100644
index 0000000..023757c
--- /dev/null
+++ b/tools/perf/util/jevents.c
@@ -0,0 +1,247 @@
+/* Parse event JSON files */
+
+/*
+ * Copyright (c) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include "util/debug.h"
+#include "cache.h"
+#include "jsmn.h"
+#include "json.h"
+#include "jevents.h"
+
+static void addfield(char *map, char **dst, const char *sep,
+		     const char *a, jsmntok_t *bt)
+{
+	unsigned len = strlen(a) + 1 + strlen(sep);
+	int olen = *dst ? strlen(*dst) : 0;
+	int blen = bt ? json_len(bt) : 0;
+	char *out;
+
+	out = realloc(*dst, len + olen + blen);
+	if (!out) {
+		/* Don't add field in this case */
+		return;
+	}
+	*dst = out;
+
+	if (!olen)
+		*(*dst) = 0;
+	else
+		strcat(*dst, sep);
+	strcat(*dst, a);
+	if (bt)
+		strncat(*dst, map + bt->start, blen);
+}
+
+static void fixname(char *s)
+{
+	for (; *s; s++)
+		*s = tolower(*s);
+}
+
+static void fixdesc(char *s)
+{
+	char *e = s + strlen(s);
+
+	/* Remove trailing dots that look ugly in perf list */
+	--e;
+	while (e >= s && isspace(*e))
+		--e;
+	if (*e == '.')
+		*e = 0;
+}
+
+static struct msrmap {
+	const char *num;
+	const char *pname;
+} msrmap[] = {
+	{ "0x3F6", "ldlat=" },
+	{ "0x1A6", "offcore_rsp=" },
+	{ "0x1A7", "offcore_rsp=" },
+	{ NULL, NULL }
+};
+
+static struct field {
+	const char *field;
+	const char *kernel;
+} fields[] = {
+	{ "EventCode",	"event=" },
+	{ "UMask",	"umask=" },
+	{ "CounterMask", "cmask=" },
+	{ "Invert",	"inv=" },
+	{ "AnyThread",	"any=" },
+	{ "EdgeDetect",	"edge=" },
+	{ "SampleAfterValue", "period=" },
+	{ NULL, NULL }
+};
+
+static void cut_comma(char *map, jsmntok_t *newval)
+{
+	int i;
+
+	/* Cut off everything after comma */
+	for (i = newval->start; i < newval->end; i++) {
+		if (map[i] == ',')
+			newval->end = i;
+	}
+}
+
+static int match_field(char *map, jsmntok_t *field, int nz,
+		       char **event, jsmntok_t *val)
+{
+	struct field *f;
+	jsmntok_t newval = *val;
+
+	for (f = fields; f->field; f++)
+		if (json_streq(map, field, f->field) && nz) {
+			cut_comma(map, &newval);
+			addfield(map, event, ",", f->kernel, &newval);
+			return 1;
+		}
+	return 0;
+}
+
+static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
+{
+	jsmntok_t newval = *val;
+	static bool warned;
+	int i;
+
+	cut_comma(map, &newval);
+	for (i = 0; msrmap[i].num; i++)
+		if (json_streq(map, &newval, msrmap[i].num))
+			return &msrmap[i];
+	if (!warned) {
+		warned = true;
+		pr_err("Unknown MSR in event file %.*s\n",
+			json_len(val), map + val->start);
+	}
+	return NULL;
+}
+
+#define EXPECT(e, t, m) do { if (!(e)) {			\
+	jsmntok_t *loc = (t);					\
+	if (!(t)->start && (t) > tokens)			\
+		loc = (t) - 1;					\
+		pr_err("%s:%d: " m ", got %s\n", fn,		\
+			json_line(map, loc),			\
+			json_name(t));				\
+	goto out_free;						\
+} } while (0)
+
+/* Call func with each event in the json file */
+
+int json_events(const char *fn,
+	  int (*func)(void *data, char *name, char *event, char *desc),
+	  void *data)
+{
+	int err = -EIO;
+	size_t size;
+	jsmntok_t *tokens, *tok;
+	int i, j, len;
+	char *map;
+
+	tokens = parse_json(fn, &map, &size, &len);
+	if (!tokens)
+		return -EIO;
+	EXPECT(tokens->type == JSMN_ARRAY, tokens, "expected top level array");
+	tok = tokens + 1;
+	for (i = 0; i < tokens->size; i++) {
+		char *event = NULL, *desc = NULL, *name = NULL;
+		struct msrmap *msr = NULL;
+		jsmntok_t *msrval = NULL;
+		jsmntok_t *precise = NULL;
+		jsmntok_t *obj = tok++;
+
+		EXPECT(obj->type == JSMN_OBJECT, obj, "expected object");
+		for (j = 0; j < obj->size; j += 2) {
+			jsmntok_t *field, *val;
+			int nz;
+
+			field = tok + j;
+			EXPECT(field->type == JSMN_STRING, tok + j,
+			       "Expected field name");
+			val = tok + j + 1;
+			EXPECT(val->type == JSMN_STRING, tok + j + 1,
+			       "Expected string value");
+
+			nz = !json_streq(map, val, "0");
+			if (match_field(map, field, nz, &event, val)) {
+				/* ok */
+			} else if (json_streq(map, field, "EventName")) {
+				addfield(map, &name, "", "", val);
+			} else if (json_streq(map, field, "BriefDescription")) {
+				addfield(map, &desc, "", "", val);
+				fixdesc(desc);
+			} else if (json_streq(map, field, "PEBS") && nz) {
+				precise = val;
+			} else if (json_streq(map, field, "MSRIndex") && nz) {
+				msr = lookup_msr(map, val);
+			} else if (json_streq(map, field, "MSRValue")) {
+				msrval = val;
+			} else if (json_streq(map, field, "Errata") &&
+				   !json_streq(map, val, "null")) {
+				addfield(map, &desc, ". ",
+					" Spec update: ", val);
+			} else if (json_streq(map, field, "Data_LA") && nz) {
+				addfield(map, &desc, ". ",
+					" Supports address when precise",
+					NULL);
+			}
+			/* ignore unknown fields */
+		}
+		if (precise && !strstr(desc, "(Precise Event)")) {
+			if (json_streq(map, precise, "2"))
+				addfield(map, &desc, " ", "(Must be precise)",
+						NULL);
+			else
+				addfield(map, &desc, " ",
+						"(Precise event)", NULL);
+		}
+		if (msr != NULL)
+			addfield(map, &event, ",", msr->pname, msrval);
+		fixname(name);
+		err = func(data, name, event, desc);
+		free(event);
+		free(desc);
+		free(name);
+		if (err)
+			break;
+		tok += j;
+	}
+	EXPECT(tok - tokens == len, tok, "unexpected objects at end");
+	err = 0;
+out_free:
+	free_json(map, size, tokens);
+	return err;
+}
diff --git a/tools/perf/util/jevents.h b/tools/perf/util/jevents.h
new file mode 100644
index 0000000..fbc4549
--- /dev/null
+++ b/tools/perf/util/jevents.h
@@ -0,0 +1,8 @@
+#ifndef JEVENTS_H
+#define JEVENTS_H 1
+
+int json_events(const char *fn,
+		int (*func)(void *data, char *name, char *event, char *desc),
+		void *data);
+
+#endif
diff --git a/tools/perf/util/json.c b/tools/perf/util/json.c
index 2219844..45acadf 100644
--- a/tools/perf/util/json.c
+++ b/tools/perf/util/json.c
@@ -37,6 +37,7 @@
 #include <unistd.h>
 #include "jsmn.h"
 #include "json.h"
+#include "util/debug.h"
 #include <linux/kernel.h>
 #include "debug.h"
 
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 623b107..d7e5e1b 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -11,6 +11,9 @@
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
+#include "jevents.h"
+
+const char *json_file;
 
 struct perf_pmu_format {
 	char *name;
@@ -316,6 +319,14 @@ static int pmu_aliases_parse(char *dir, struct list_head *head)
 	return ret;
 }
 
+static int add_alias(void *data, char *name, char *event, char *desc)
+{
+	struct list_head *head = (struct list_head *)data;
+
+	__perf_pmu__new_alias(head, name, NULL, desc, event);
+	return 0;
+}
+
 /*
  * Reading the pmu event aliases definition, which should be located at:
  * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
@@ -471,6 +482,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
 	if (pmu_aliases(name, &aliases))
 		return NULL;
 
+	if (!strcmp(name, "cpu") && json_file)
+		json_events(json_file, add_alias, &aliases);
+
 	if (pmu_type(name, &type))
 		return NULL;
 
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index d06496d..f8dac0f 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -77,4 +77,5 @@ int perf_pmu__test(void);
 
 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
 
+extern const char *json_file;
 #endif /* __PMU_H */
-- 
1.7.9.5

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

* [PATCH v9 05/11] perf, tools: Automatically look for event file name for cpu
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

When no JSON event file is specified automatically look
for a suitable file in ~/.cache/pmu-events.

The event file format is per architecture, but can be
extended for other architectures.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix.
v2: Supports XDG_CACHE_HOME and defaults to ~/.cache/pmu-events
v3: Minor updates and handle EVENTMAP.
v4: Unify with header.c. Now uses CPUID directly.
---
 tools/perf/arch/x86/util/header.c |   19 +++++++++++++++---
 tools/perf/util/jevents.c         |   40 +++++++++++++++++++++++++++++++++++++
 tools/perf/util/jevents.h         |    1 +
 tools/perf/util/pmu.c             |    2 +-
 4 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c
index 146d12a..76e0ece 100644
--- a/tools/perf/arch/x86/util/header.c
+++ b/tools/perf/arch/x86/util/header.c
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #include "../../util/header.h"
+#include "../../util/jevents.h"
 
 static inline void
 cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
@@ -19,8 +20,8 @@ cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
 			: "a" (op));
 }
 
-int
-get_cpuid(char *buffer, size_t sz)
+static int
+__get_cpuid(char *buffer, size_t sz, const char *fmt)
 {
 	unsigned int a, b, c, d, lvl;
 	int family = -1, model = -1, step = -1;
@@ -48,7 +49,7 @@ get_cpuid(char *buffer, size_t sz)
 		if (family >= 0x6)
 			model += ((a >> 16) & 0xf) << 4;
 	}
-	nb = scnprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
+	nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
 
 	/* look for end marker to ensure the entire data fit */
 	if (strchr(buffer, '$')) {
@@ -57,3 +58,15 @@ get_cpuid(char *buffer, size_t sz)
 	}
 	return -1;
 }
+
+int get_cpuid(char *buffer, size_t sz)
+{
+	return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
+}
+
+char *get_cpu_str(void)
+{
+	char *buf = malloc(128);
+	__get_cpuid(buf, 128, "%s-%d-%X-core");
+	return buf;
+}
diff --git a/tools/perf/util/jevents.c b/tools/perf/util/jevents.c
index 023757c..ef4c047 100644
--- a/tools/perf/util/jevents.c
+++ b/tools/perf/util/jevents.c
@@ -39,6 +39,44 @@
 #include "json.h"
 #include "jevents.h"
 
+__attribute__((weak)) char *get_cpu_str(void)
+{
+	return NULL;
+}
+
+static const char *json_default_name(void)
+{
+	char *cache;
+	char *idstr = get_cpu_str();
+	char *res = NULL;
+	char *home = NULL;
+	char *emap;
+
+	emap = getenv("EVENTMAP");
+	if (emap) {
+		if (access(emap, R_OK) == 0)
+			return emap;
+		if (asprintf(&idstr, "%s-core", emap) < 0)
+			return NULL;
+	}
+
+	cache = getenv("XDG_CACHE_HOME");
+	if (!cache) {
+		home = getenv("HOME");
+		if (!home || asprintf(&cache, "%s/.cache", home) < 0)
+			goto out;
+	}
+	if (cache && idstr)
+		res = mkpath("%s/pmu-events/%s.json",
+			     cache,
+			     idstr);
+	if (home)
+		free(cache);
+out:
+	free(idstr);
+	return res;
+}
+
 static void addfield(char *map, char **dst, const char *sep,
 		     const char *a, jsmntok_t *bt)
 {
@@ -171,6 +209,8 @@ int json_events(const char *fn,
 	int i, j, len;
 	char *map;
 
+	if (!fn)
+		fn = json_default_name();
 	tokens = parse_json(fn, &map, &size, &len);
 	if (!tokens)
 		return -EIO;
diff --git a/tools/perf/util/jevents.h b/tools/perf/util/jevents.h
index fbc4549..86a94dd 100644
--- a/tools/perf/util/jevents.h
+++ b/tools/perf/util/jevents.h
@@ -4,5 +4,6 @@
 int json_events(const char *fn,
 		int (*func)(void *data, char *name, char *event, char *desc),
 		void *data);
+char *get_cpu_str(void);
 
 #endif
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index d7e5e1b..274aa18 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -482,7 +482,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
 	if (pmu_aliases(name, &aliases))
 		return NULL;
 
-	if (!strcmp(name, "cpu") && json_file)
+	if (!strcmp(name, "cpu"))
 		json_events(json_file, add_alias, &aliases);
 
 	if (pmu_type(name, &type))
-- 
1.7.9.5


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

* [PATCH v9 05/11] perf, tools: Automatically look for event file name for cpu
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

When no JSON event file is specified automatically look
for a suitable file in ~/.cache/pmu-events.

The event file format is per architecture, but can be
extended for other architectures.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix.
v2: Supports XDG_CACHE_HOME and defaults to ~/.cache/pmu-events
v3: Minor updates and handle EVENTMAP.
v4: Unify with header.c. Now uses CPUID directly.
---
 tools/perf/arch/x86/util/header.c |   19 +++++++++++++++---
 tools/perf/util/jevents.c         |   40 +++++++++++++++++++++++++++++++++++++
 tools/perf/util/jevents.h         |    1 +
 tools/perf/util/pmu.c             |    2 +-
 4 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/header.c b/tools/perf/arch/x86/util/header.c
index 146d12a..76e0ece 100644
--- a/tools/perf/arch/x86/util/header.c
+++ b/tools/perf/arch/x86/util/header.c
@@ -5,6 +5,7 @@
 #include <string.h>
 
 #include "../../util/header.h"
+#include "../../util/jevents.h"
 
 static inline void
 cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
@@ -19,8 +20,8 @@ cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
 			: "a" (op));
 }
 
-int
-get_cpuid(char *buffer, size_t sz)
+static int
+__get_cpuid(char *buffer, size_t sz, const char *fmt)
 {
 	unsigned int a, b, c, d, lvl;
 	int family = -1, model = -1, step = -1;
@@ -48,7 +49,7 @@ get_cpuid(char *buffer, size_t sz)
 		if (family >= 0x6)
 			model += ((a >> 16) & 0xf) << 4;
 	}
-	nb = scnprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
+	nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
 
 	/* look for end marker to ensure the entire data fit */
 	if (strchr(buffer, '$')) {
@@ -57,3 +58,15 @@ get_cpuid(char *buffer, size_t sz)
 	}
 	return -1;
 }
+
+int get_cpuid(char *buffer, size_t sz)
+{
+	return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
+}
+
+char *get_cpu_str(void)
+{
+	char *buf = malloc(128);
+	__get_cpuid(buf, 128, "%s-%d-%X-core");
+	return buf;
+}
diff --git a/tools/perf/util/jevents.c b/tools/perf/util/jevents.c
index 023757c..ef4c047 100644
--- a/tools/perf/util/jevents.c
+++ b/tools/perf/util/jevents.c
@@ -39,6 +39,44 @@
 #include "json.h"
 #include "jevents.h"
 
+__attribute__((weak)) char *get_cpu_str(void)
+{
+	return NULL;
+}
+
+static const char *json_default_name(void)
+{
+	char *cache;
+	char *idstr = get_cpu_str();
+	char *res = NULL;
+	char *home = NULL;
+	char *emap;
+
+	emap = getenv("EVENTMAP");
+	if (emap) {
+		if (access(emap, R_OK) == 0)
+			return emap;
+		if (asprintf(&idstr, "%s-core", emap) < 0)
+			return NULL;
+	}
+
+	cache = getenv("XDG_CACHE_HOME");
+	if (!cache) {
+		home = getenv("HOME");
+		if (!home || asprintf(&cache, "%s/.cache", home) < 0)
+			goto out;
+	}
+	if (cache && idstr)
+		res = mkpath("%s/pmu-events/%s.json",
+			     cache,
+			     idstr);
+	if (home)
+		free(cache);
+out:
+	free(idstr);
+	return res;
+}
+
 static void addfield(char *map, char **dst, const char *sep,
 		     const char *a, jsmntok_t *bt)
 {
@@ -171,6 +209,8 @@ int json_events(const char *fn,
 	int i, j, len;
 	char *map;
 
+	if (!fn)
+		fn = json_default_name();
 	tokens = parse_json(fn, &map, &size, &len);
 	if (!tokens)
 		return -EIO;
diff --git a/tools/perf/util/jevents.h b/tools/perf/util/jevents.h
index fbc4549..86a94dd 100644
--- a/tools/perf/util/jevents.h
+++ b/tools/perf/util/jevents.h
@@ -4,5 +4,6 @@
 int json_events(const char *fn,
 		int (*func)(void *data, char *name, char *event, char *desc),
 		void *data);
+char *get_cpu_str(void);
 
 #endif
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index d7e5e1b..274aa18 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -482,7 +482,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
 	if (pmu_aliases(name, &aliases))
 		return NULL;
 
-	if (!strcmp(name, "cpu") && json_file)
+	if (!strcmp(name, "cpu"))
 		json_events(json_file, add_alias, &aliases);
 
 	if (pmu_type(name, &type))
-- 
1.7.9.5

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

* [PATCH v9 06/11] powerpc/perf: Implement get_cpu_str()
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

With a file ~/.cache/pmu-events/004d0100-core.json describing Power8
PMU events we would need to run:

	perf stat \
		--events-file ~/.cache/pmu-events/004d0100-core.json \
		-e pm_cyc sleep 1

With this get_cpu_str(), on Powerpc, we can skip the --events-file option
and run:

	perf stat -e pm_cyc sleep 1

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0.

Changelog[v3]:
        [Tobias Klauser]: Fix some changelog damage to patch.

Changelog[v2]:
	[Michael Ellerman]: Use PVR instead of AUXV variables
---
 tools/perf/arch/powerpc/util/header.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index 6c1b8a7..306bf35 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -6,6 +6,7 @@
 
 #include "../../util/header.h"
 #include "../../util/util.h"
+#include "../../util/jevents.h"
 
 #define mfspr(rn)       ({unsigned long rval; \
 			 asm volatile("mfspr %0," __stringify(rn) \
@@ -32,3 +33,14 @@ get_cpuid(char *buffer, size_t sz)
 	}
 	return -1;
 }
+
+char *
+get_cpu_str(void)
+{
+	char *bufp;
+
+	if (asprintf(&bufp, "%.8lx-core", mfspr(SPRN_PVR)) < 0)
+		bufp = NULL;
+
+	return bufp;
+}
-- 
1.7.9.5


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

* [PATCH v9 06/11] powerpc/perf: Implement get_cpu_str()
@ 2015-04-14  6:40   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:40 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

With a file ~/.cache/pmu-events/004d0100-core.json describing Power8
PMU events we would need to run:

	perf stat \
		--events-file ~/.cache/pmu-events/004d0100-core.json \
		-e pm_cyc sleep 1

With this get_cpu_str(), on Powerpc, we can skip the --events-file option
and run:

	perf stat -e pm_cyc sleep 1

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0.

Changelog[v3]:
        [Tobias Klauser]: Fix some changelog damage to patch.

Changelog[v2]:
	[Michael Ellerman]: Use PVR instead of AUXV variables
---
 tools/perf/arch/powerpc/util/header.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index 6c1b8a7..306bf35 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -6,6 +6,7 @@
 
 #include "../../util/header.h"
 #include "../../util/util.h"
+#include "../../util/jevents.h"
 
 #define mfspr(rn)       ({unsigned long rval; \
 			 asm volatile("mfspr %0," __stringify(rn) \
@@ -32,3 +33,14 @@ get_cpuid(char *buffer, size_t sz)
 	}
 	return -1;
 }
+
+char *
+get_cpu_str(void)
+{
+	char *bufp;
+
+	if (asprintf(&bufp, "%.8lx-core", mfspr(SPRN_PVR)) < 0)
+		bufp = NULL;
+
+	return bufp;
+}
-- 
1.7.9.5

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

* [PATCH v9 07/11] perf, tools: Query terminal width and use in perf list
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Automatically adapt the now wider and word wrapped perf list
output to wider terminals. This requires querying the terminal
before the auto pager takes over, and exporting this
information from the pager subsystem.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>

---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0.
---
 tools/perf/util/cache.h |    1 +
 tools/perf/util/pager.c |   15 +++++++++++++++
 tools/perf/util/pmu.c   |   12 ++----------
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index d04d770..f1990c9 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -32,6 +32,7 @@ extern void setup_pager(void);
 extern const char *pager_program;
 extern int pager_in_use(void);
 extern int pager_use_color;
+int pager_get_columns(void);
 
 char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
index 31ee02d..9761202 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "run-command.h"
 #include "sigchain.h"
+#include <sys/ioctl.h>
 
 /*
  * This is split up from the rest of git so that we can do
@@ -8,6 +9,7 @@
  */
 
 static int spawned_pager;
+static int pager_columns;
 
 static void pager_preexec(void)
 {
@@ -47,9 +49,12 @@ static void wait_for_pager_signal(int signo)
 void setup_pager(void)
 {
 	const char *pager = getenv("PERF_PAGER");
+	struct winsize sz;
 
 	if (!isatty(1))
 		return;
+	if (ioctl(1, TIOCGWINSZ, &sz) == 0)
+		pager_columns = sz.ws_col;
 	if (!pager) {
 		if (!pager_program)
 			perf_config(perf_default_config, NULL);
@@ -98,3 +103,13 @@ int pager_in_use(void)
 	env = getenv("PERF_PAGER_IN_USE");
 	return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0;
 }
+
+int pager_get_columns(void)
+{
+	char *s;
+
+	s = getenv("COLUMNS");
+	if (s)
+		return atoi(s);
+	return (pager_columns ? pager_columns : 80) - 2;
+}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 274aa18..2150455 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -11,6 +11,7 @@
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
+#include "cache.h"
 #include "jevents.h"
 
 const char *json_file;
@@ -929,15 +930,6 @@ static void wordwrap(char *s, int start, int max, int corr)
 	}
 }
 
-static int get_columns(void)
-{
-	/*
-	 * Should ask the terminal with TIOCGWINSZ here, but we
-	 * need the original fd before the pager.
-	 */
-	return 79;
-}
-
 void print_pmu_events(const char *event_glob, bool name_only)
 {
 	struct perf_pmu *pmu;
@@ -947,7 +939,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
 	int len, j;
 	struct pair *aliases;
 	int numdesc = 0;
-	int columns = get_columns();
+	int columns = pager_get_columns();
 
 	pmu = NULL;
 	len = 0;
-- 
1.7.9.5


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

* [PATCH v9 07/11] perf, tools: Query terminal width and use in perf list
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Automatically adapt the now wider and word wrapped perf list
output to wider terminals. This requires querying the terminal
before the auto pager takes over, and exporting this
information from the pager subsystem.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>

---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0.
---
 tools/perf/util/cache.h |    1 +
 tools/perf/util/pager.c |   15 +++++++++++++++
 tools/perf/util/pmu.c   |   12 ++----------
 3 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index d04d770..f1990c9 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -32,6 +32,7 @@ extern void setup_pager(void);
 extern const char *pager_program;
 extern int pager_in_use(void);
 extern int pager_use_color;
+int pager_get_columns(void);
 
 char *alias_lookup(const char *alias);
 int split_cmdline(char *cmdline, const char ***argv);
diff --git a/tools/perf/util/pager.c b/tools/perf/util/pager.c
index 31ee02d..9761202 100644
--- a/tools/perf/util/pager.c
+++ b/tools/perf/util/pager.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "run-command.h"
 #include "sigchain.h"
+#include <sys/ioctl.h>
 
 /*
  * This is split up from the rest of git so that we can do
@@ -8,6 +9,7 @@
  */
 
 static int spawned_pager;
+static int pager_columns;
 
 static void pager_preexec(void)
 {
@@ -47,9 +49,12 @@ static void wait_for_pager_signal(int signo)
 void setup_pager(void)
 {
 	const char *pager = getenv("PERF_PAGER");
+	struct winsize sz;
 
 	if (!isatty(1))
 		return;
+	if (ioctl(1, TIOCGWINSZ, &sz) == 0)
+		pager_columns = sz.ws_col;
 	if (!pager) {
 		if (!pager_program)
 			perf_config(perf_default_config, NULL);
@@ -98,3 +103,13 @@ int pager_in_use(void)
 	env = getenv("PERF_PAGER_IN_USE");
 	return env ? perf_config_bool("PERF_PAGER_IN_USE", env) : 0;
 }
+
+int pager_get_columns(void)
+{
+	char *s;
+
+	s = getenv("COLUMNS");
+	if (s)
+		return atoi(s);
+	return (pager_columns ? pager_columns : 80) - 2;
+}
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 274aa18..2150455 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -11,6 +11,7 @@
 #include "pmu.h"
 #include "parse-events.h"
 #include "cpumap.h"
+#include "cache.h"
 #include "jevents.h"
 
 const char *json_file;
@@ -929,15 +930,6 @@ static void wordwrap(char *s, int start, int max, int corr)
 	}
 }
 
-static int get_columns(void)
-{
-	/*
-	 * Should ask the terminal with TIOCGWINSZ here, but we
-	 * need the original fd before the pager.
-	 */
-	return 79;
-}
-
 void print_pmu_events(const char *event_glob, bool name_only)
 {
 	struct perf_pmu *pmu;
@@ -947,7 +939,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
 	int len, j;
 	struct pair *aliases;
 	int numdesc = 0;
-	int columns = get_columns();
+	int columns = pager_get_columns();
 
 	pmu = NULL;
 	len = 0;
-- 
1.7.9.5

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

* [PATCH v9 08/11] perf, tools: Add a new pmu interface to iterate over all events
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

With calling a callback. To be used in test code added in the next
patch.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in:
		tools/perf/util/pmu.c
		tools/perf/util/pmu.h
---
 tools/perf/util/pmu.c |   18 ++++++++++++++++++
 tools/perf/util/pmu.h |    1 +
 2 files changed, 19 insertions(+)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 2150455..82f7654 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1068,3 +1068,21 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
 	va_end(args);
 	return ret;
 }
+
+int pmu_iterate_events(int (*func)(const char *pmu, const char *name))
+{
+	int ret = 0;
+	struct perf_pmu *pmu;
+	struct perf_pmu_alias *alias;
+
+	perf_pmu__find("cpu"); /* Load PMUs */
+	pmu = NULL;
+	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+		list_for_each_entry(alias, &pmu->aliases, list) {
+			ret = func(pmu->name, alias->name);
+			if (ret != 0)
+				break;
+		}
+	}
+	return ret;
+}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index f8dac0f..889cadf 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -76,6 +76,7 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
 int perf_pmu__test(void);
 
 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
+int pmu_iterate_events(int (*func)(const char *, const char *name));
 
 extern const char *json_file;
 #endif /* __PMU_H */
-- 
1.7.9.5


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

* [PATCH v9 08/11] perf, tools: Add a new pmu interface to iterate over all events
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

With calling a callback. To be used in test code added in the next
patch.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in:
		tools/perf/util/pmu.c
		tools/perf/util/pmu.h
---
 tools/perf/util/pmu.c |   18 ++++++++++++++++++
 tools/perf/util/pmu.h |    1 +
 2 files changed, 19 insertions(+)

diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 2150455..82f7654 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -1068,3 +1068,21 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
 	va_end(args);
 	return ret;
 }
+
+int pmu_iterate_events(int (*func)(const char *pmu, const char *name))
+{
+	int ret = 0;
+	struct perf_pmu *pmu;
+	struct perf_pmu_alias *alias;
+
+	perf_pmu__find("cpu"); /* Load PMUs */
+	pmu = NULL;
+	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+		list_for_each_entry(alias, &pmu->aliases, list) {
+			ret = func(pmu->name, alias->name);
+			if (ret != 0)
+				break;
+		}
+	}
+	return ret;
+}
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index f8dac0f..889cadf 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -76,6 +76,7 @@ int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
 int perf_pmu__test(void);
 
 struct perf_event_attr *perf_pmu__get_default_config(struct perf_pmu *pmu);
+int pmu_iterate_events(int (*func)(const char *, const char *name));
 
 extern const char *json_file;
 #endif /* __PMU_H */
-- 
1.7.9.5

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

* [PATCH v9 09/11] perf, tools, test: Add test case for alias and JSON parsing
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add a simple test case to perf test that parses all the available
events, including json events.

This needs adding an all event iterator to pmu.c

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in:
		tools/perf/tests/builtin-test.c
		tools/perf/tests/tests.h
Changelog:
v2: Rename identifiers
v3: Only iterate cpu pmu to avoid bogus errors.
Move pmu iterator to extra patch
v4: Include aliases.c again
v5: Include util/debug.h
---
 tools/perf/Makefile.perf        |    1 +
 tools/perf/tests/aliases.c      |   59 +++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/builtin-test.c |    4 +++
 tools/perf/tests/tests.h        |    1 +
 4 files changed, 65 insertions(+)
 create mode 100644 tools/perf/tests/aliases.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9c1a4c..d9c03c4 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -456,6 +456,7 @@ endif
 LIB_OBJS += $(OUTPUT)tests/code-reading.o
 LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
 LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
+LIB_OBJS += $(OUTPUT)tests/aliases.o
 ifndef NO_DWARF_UNWIND
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
 LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
diff --git a/tools/perf/tests/aliases.c b/tools/perf/tests/aliases.c
new file mode 100644
index 0000000..4209e51
--- /dev/null
+++ b/tools/perf/tests/aliases.c
@@ -0,0 +1,59 @@
+/* Check if we can set up all aliases and can read JSON files */
+#include <stdlib.h>
+#include "tests.h"
+#include "pmu.h"
+#include "evlist.h"
+#include "parse-events.h"
+#include "util/debug.h"
+
+static struct perf_evlist *evlist;
+
+static int num_events;
+static int failed;
+
+static int test__event(const char *pmu, const char *name)
+{
+	int ret;
+
+	/* Not supported for now */
+	if (strcmp(pmu, "cpu"))
+		return 0;
+
+	ret = parse_events(evlist, name);
+
+	if (ret) {
+		/*
+		 * We only print on failure because common perf setups
+		 * have events that cannot be parsed.
+		 */
+		fprintf(stderr, "invalid or unsupported event: '%s'\n", name);
+		ret = 0;
+		failed++;
+	} else
+		num_events++;
+	return ret;
+}
+
+int test__aliases(void)
+{
+	int err;
+
+	/* Download JSON files */
+	/* XXX assumes perf is installed */
+	/* For now user must manually download */
+	if (0 && system("perf download > /dev/null") < 0) {
+		/* Don't error out for this for now */
+		fprintf(stderr, "perf download failed\n");
+	}
+
+	evlist = perf_evlist__new();
+	if (evlist == NULL)
+		return -ENOMEM;
+
+	err = pmu_iterate_events(test__event);
+	fprintf(stderr, " Parsed %d events :", num_events);
+	if (failed > 0)
+		pr_debug(" %d events failed", failed);
+	perf_evlist__delete(evlist);
+	return err;
+}
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 4b7d9ab..2324b1c 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -167,6 +167,10 @@ static struct test {
 		.func = test__fdarray__add,
 	},
 	{
+		.desc = "Test parsing JSON aliases",
+		.func = test__aliases,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 00e776a..ddce231 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -51,6 +51,7 @@ int test__hists_cumulate(void);
 int test__switch_tracking(void);
 int test__fdarray__filter(void);
 int test__fdarray__add(void);
+int test__aliases(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-- 
1.7.9.5


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

* [PATCH v9 09/11] perf, tools, test: Add test case for alias and JSON parsing
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add a simple test case to perf test that parses all the available
events, including json events.

This needs adding an all event iterator to pmu.c

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in:
		tools/perf/tests/builtin-test.c
		tools/perf/tests/tests.h
Changelog:
v2: Rename identifiers
v3: Only iterate cpu pmu to avoid bogus errors.
Move pmu iterator to extra patch
v4: Include aliases.c again
v5: Include util/debug.h
---
 tools/perf/Makefile.perf        |    1 +
 tools/perf/tests/aliases.c      |   59 +++++++++++++++++++++++++++++++++++++++
 tools/perf/tests/builtin-test.c |    4 +++
 tools/perf/tests/tests.h        |    1 +
 4 files changed, 65 insertions(+)
 create mode 100644 tools/perf/tests/aliases.c

diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9c1a4c..d9c03c4 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -456,6 +456,7 @@ endif
 LIB_OBJS += $(OUTPUT)tests/code-reading.o
 LIB_OBJS += $(OUTPUT)tests/sample-parsing.o
 LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o
+LIB_OBJS += $(OUTPUT)tests/aliases.o
 ifndef NO_DWARF_UNWIND
 ifeq ($(ARCH),$(filter $(ARCH),x86 arm))
 LIB_OBJS += $(OUTPUT)tests/dwarf-unwind.o
diff --git a/tools/perf/tests/aliases.c b/tools/perf/tests/aliases.c
new file mode 100644
index 0000000..4209e51
--- /dev/null
+++ b/tools/perf/tests/aliases.c
@@ -0,0 +1,59 @@
+/* Check if we can set up all aliases and can read JSON files */
+#include <stdlib.h>
+#include "tests.h"
+#include "pmu.h"
+#include "evlist.h"
+#include "parse-events.h"
+#include "util/debug.h"
+
+static struct perf_evlist *evlist;
+
+static int num_events;
+static int failed;
+
+static int test__event(const char *pmu, const char *name)
+{
+	int ret;
+
+	/* Not supported for now */
+	if (strcmp(pmu, "cpu"))
+		return 0;
+
+	ret = parse_events(evlist, name);
+
+	if (ret) {
+		/*
+		 * We only print on failure because common perf setups
+		 * have events that cannot be parsed.
+		 */
+		fprintf(stderr, "invalid or unsupported event: '%s'\n", name);
+		ret = 0;
+		failed++;
+	} else
+		num_events++;
+	return ret;
+}
+
+int test__aliases(void)
+{
+	int err;
+
+	/* Download JSON files */
+	/* XXX assumes perf is installed */
+	/* For now user must manually download */
+	if (0 && system("perf download > /dev/null") < 0) {
+		/* Don't error out for this for now */
+		fprintf(stderr, "perf download failed\n");
+	}
+
+	evlist = perf_evlist__new();
+	if (evlist == NULL)
+		return -ENOMEM;
+
+	err = pmu_iterate_events(test__event);
+	fprintf(stderr, " Parsed %d events :", num_events);
+	if (failed > 0)
+		pr_debug(" %d events failed", failed);
+	perf_evlist__delete(evlist);
+	return err;
+}
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 4b7d9ab..2324b1c 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -167,6 +167,10 @@ static struct test {
 		.func = test__fdarray__add,
 	},
 	{
+		.desc = "Test parsing JSON aliases",
+		.func = test__aliases,
+	},
+	{
 		.func = NULL,
 	},
 };
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 00e776a..ddce231 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -51,6 +51,7 @@ int test__hists_cumulate(void);
 int test__switch_tracking(void);
 int test__fdarray__filter(void);
 int test__fdarray__add(void);
+int test__aliases(void);
 
 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__)
 #ifdef HAVE_DWARF_UNWIND_SUPPORT
-- 
1.7.9.5

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

* [PATCH v9 10/11] perf, tools: Add a --no-desc flag to perf list
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add a --no-desc flag to perf list to not print the event descriptions
that were earlier added for JSON events. This may be useful to
get a less crowded listing.

It's still default to print descriptions as that is the more useful
default for most users.

Before:

% perf list
...
  baclears.any                                       [Counts the total number when the front end is
                                                      resteered, mainly when the BPU cannot provide a
                                                      correct prediction and this is corrected by other
                                                      branch handling mechanisms at the front end]
  br_inst_exec.all_branches                          [Speculative and retired branches]

After:

% perf list --no-desc
...
  baclears.any                                       [Kernel PMU event]
  br_inst_exec.all_branches                          [Kernel PMU event]

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in
		tools/perf/builtin-list.c
v2: Rename --quiet to --no-desc. Add option to man page.
---
 tools/perf/Documentation/perf-list.txt |    5 ++++-
 tools/perf/builtin-list.c              |   16 +++++++++++-----
 tools/perf/util/parse-events.c         |    4 ++--
 tools/perf/util/parse-events.h         |    2 +-
 tools/perf/util/pmu.c                  |    4 ++--
 tools/perf/util/pmu.h                  |    2 +-
 6 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 205ac40..7479efe 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
 SYNOPSIS
 --------
 [verse]
-'perf list' [hw|sw|cache|tracepoint|pmu|event_glob]
+'perf list' [--no-desc] [hw|sw|cache|tracepoint|pmu|event_glob]
 
 DESCRIPTION
 -----------
@@ -23,6 +23,9 @@ automatically downloaded with perf download.
 The JSON event file can be also specified with the EVENTMAP environment
 variable.
 
+--no-desc::
+Don't print descriptions.
+
 
 [[EVENT_MODIFIERS]] EVENT MODIFIERS
 ---------------
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index fd07cc1..76dc23b 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -16,6 +16,8 @@
 #include "util/pmu.h"
 #include "util/parse-options.h"
 
+static bool desc_flag = true;
+
 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	int i;
@@ -24,10 +26,12 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 		OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
 		OPT_STRING(0, "events-file", &json_file, "json file",
 			   "Read event json file"),
+		OPT_BOOLEAN('d', "desc", &desc_flag,
+			    "Print extra event descriptions. --no-desc to not print."),
 		OPT_END()
 	};
 	const char * const list_usage[] = {
-		"perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
+		"perf list [--events-file FILE] [--no-desc] [hw|sw|cache|tracepoint|pmu|event_glob]",
 		NULL
 	};
 
@@ -39,12 +43,12 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 	setup_pager();
 
 	if (raw_dump) {
-		print_events(NULL, true);
+		print_events(NULL, true, !desc_flag);
 		return 0;
 	}
 
 	if (argc == 0) {
-		print_events(NULL, false);
+		print_events(NULL, false, !desc_flag);
 		return 0;
 	}
 
@@ -63,13 +67,15 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 			 strcmp(argv[i], "hwcache") == 0)
 			print_hwcache_events(NULL, false);
 		else if (strcmp(argv[i], "pmu") == 0)
-			print_pmu_events(NULL, false);
+			print_pmu_events(NULL, false, !desc_flag);
+		else if (strcmp(argv[i], "--raw-dump") == 0)
+			print_events(NULL, true, !desc_flag);
 		else {
 			char *sep = strchr(argv[i], ':'), *s;
 			int sep_idx;
 
 			if (sep == NULL) {
-				print_events(argv[i], false);
+				print_events(argv[i], false, !desc_flag);
 				continue;
 			}
 			sep_idx = sep - argv[i];
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7f8ec6c..039ba78 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1336,7 +1336,7 @@ static void print_symbol_events(const char *event_glob, unsigned type,
 /*
  * Print the help text for the event symbols:
  */
-void print_events(const char *event_glob, bool name_only)
+void print_events(const char *event_glob, bool name_only, bool silent)
 {
 	if (!name_only) {
 		printf("\n");
@@ -1351,7 +1351,7 @@ void print_events(const char *event_glob, bool name_only)
 
 	print_hwcache_events(event_glob, name_only);
 
-	print_pmu_events(event_glob, name_only);
+	print_pmu_events(event_glob, name_only, silent);
 
 	if (event_glob != NULL)
 		return;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ff6e1fa..202f81b 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -115,7 +115,7 @@ void parse_events_update_lists(struct list_head *list_event,
 			       struct list_head *list_all);
 void parse_events_error(void *data, void *scanner, char const *msg);
 
-void print_events(const char *event_glob, bool name_only);
+void print_events(const char *event_glob, bool name_only, bool quiet);
 void print_events_type(u8 type);
 void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
 			     bool name_only);
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 82f7654..b3c1937 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -930,7 +930,7 @@ static void wordwrap(char *s, int start, int max, int corr)
 	}
 }
 
-void print_pmu_events(const char *event_glob, bool name_only)
+void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag)
 {
 	struct perf_pmu *pmu;
 	struct perf_pmu_alias *alias;
@@ -992,7 +992,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
 			printf("%s ", aliases[j].name);
 			continue;
 		}
-		if (aliases[j].desc) {
+		if (aliases[j].desc && !quiet_flag) {
 			if (numdesc++ == 0 && printed)
 				printf("\n");
 			printf("  %-50s [", aliases[j].name);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 889cadf..5e375d6 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -67,7 +67,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
 
 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
 
-void print_pmu_events(const char *event_glob, bool name_only);
+void print_pmu_events(const char *event_glob, bool name_only, bool quiet);
 bool pmu_have_event(const char *pname, const char *name);
 
 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
-- 
1.7.9.5


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

* [PATCH v9 10/11] perf, tools: Add a --no-desc flag to perf list
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

From: Andi Kleen <ak@linux.intel.com>

Add a --no-desc flag to perf list to not print the event descriptions
that were earlier added for JSON events. This may be useful to
get a less crowded listing.

It's still default to print descriptions as that is the more useful
default for most users.

Before:

% perf list
...
  baclears.any                                       [Counts the total number when the front end is
                                                      resteered, mainly when the BPU cannot provide a
                                                      correct prediction and this is corrected by other
                                                      branch handling mechanisms at the front end]
  br_inst_exec.all_branches                          [Speculative and retired branches]

After:

% perf list --no-desc
...
  baclears.any                                       [Kernel PMU event]
  br_inst_exec.all_branches                          [Kernel PMU event]

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v9] by Sukadev Bhattiprolu
	Rebase to 4.0 and fix conflicts in
		tools/perf/builtin-list.c
v2: Rename --quiet to --no-desc. Add option to man page.
---
 tools/perf/Documentation/perf-list.txt |    5 ++++-
 tools/perf/builtin-list.c              |   16 +++++++++++-----
 tools/perf/util/parse-events.c         |    4 ++--
 tools/perf/util/parse-events.h         |    2 +-
 tools/perf/util/pmu.c                  |    4 ++--
 tools/perf/util/pmu.h                  |    2 +-
 6 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 205ac40..7479efe 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,7 +8,7 @@ perf-list - List all symbolic event types
 SYNOPSIS
 --------
 [verse]
-'perf list' [hw|sw|cache|tracepoint|pmu|event_glob]
+'perf list' [--no-desc] [hw|sw|cache|tracepoint|pmu|event_glob]
 
 DESCRIPTION
 -----------
@@ -23,6 +23,9 @@ automatically downloaded with perf download.
 The JSON event file can be also specified with the EVENTMAP environment
 variable.
 
+--no-desc::
+Don't print descriptions.
+
 
 [[EVENT_MODIFIERS]] EVENT MODIFIERS
 ---------------
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index fd07cc1..76dc23b 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -16,6 +16,8 @@
 #include "util/pmu.h"
 #include "util/parse-options.h"
 
+static bool desc_flag = true;
+
 int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 {
 	int i;
@@ -24,10 +26,12 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 		OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
 		OPT_STRING(0, "events-file", &json_file, "json file",
 			   "Read event json file"),
+		OPT_BOOLEAN('d', "desc", &desc_flag,
+			    "Print extra event descriptions. --no-desc to not print."),
 		OPT_END()
 	};
 	const char * const list_usage[] = {
-		"perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
+		"perf list [--events-file FILE] [--no-desc] [hw|sw|cache|tracepoint|pmu|event_glob]",
 		NULL
 	};
 
@@ -39,12 +43,12 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 	setup_pager();
 
 	if (raw_dump) {
-		print_events(NULL, true);
+		print_events(NULL, true, !desc_flag);
 		return 0;
 	}
 
 	if (argc == 0) {
-		print_events(NULL, false);
+		print_events(NULL, false, !desc_flag);
 		return 0;
 	}
 
@@ -63,13 +67,15 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
 			 strcmp(argv[i], "hwcache") == 0)
 			print_hwcache_events(NULL, false);
 		else if (strcmp(argv[i], "pmu") == 0)
-			print_pmu_events(NULL, false);
+			print_pmu_events(NULL, false, !desc_flag);
+		else if (strcmp(argv[i], "--raw-dump") == 0)
+			print_events(NULL, true, !desc_flag);
 		else {
 			char *sep = strchr(argv[i], ':'), *s;
 			int sep_idx;
 
 			if (sep == NULL) {
-				print_events(argv[i], false);
+				print_events(argv[i], false, !desc_flag);
 				continue;
 			}
 			sep_idx = sep - argv[i];
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 7f8ec6c..039ba78 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1336,7 +1336,7 @@ static void print_symbol_events(const char *event_glob, unsigned type,
 /*
  * Print the help text for the event symbols:
  */
-void print_events(const char *event_glob, bool name_only)
+void print_events(const char *event_glob, bool name_only, bool silent)
 {
 	if (!name_only) {
 		printf("\n");
@@ -1351,7 +1351,7 @@ void print_events(const char *event_glob, bool name_only)
 
 	print_hwcache_events(event_glob, name_only);
 
-	print_pmu_events(event_glob, name_only);
+	print_pmu_events(event_glob, name_only, silent);
 
 	if (event_glob != NULL)
 		return;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index ff6e1fa..202f81b 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -115,7 +115,7 @@ void parse_events_update_lists(struct list_head *list_event,
 			       struct list_head *list_all);
 void parse_events_error(void *data, void *scanner, char const *msg);
 
-void print_events(const char *event_glob, bool name_only);
+void print_events(const char *event_glob, bool name_only, bool quiet);
 void print_events_type(u8 type);
 void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
 			     bool name_only);
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 82f7654..b3c1937 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -930,7 +930,7 @@ static void wordwrap(char *s, int start, int max, int corr)
 	}
 }
 
-void print_pmu_events(const char *event_glob, bool name_only)
+void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag)
 {
 	struct perf_pmu *pmu;
 	struct perf_pmu_alias *alias;
@@ -992,7 +992,7 @@ void print_pmu_events(const char *event_glob, bool name_only)
 			printf("%s ", aliases[j].name);
 			continue;
 		}
-		if (aliases[j].desc) {
+		if (aliases[j].desc && !quiet_flag) {
 			if (numdesc++ == 0 && printed)
 				printf("\n");
 			printf("  %-50s [", aliases[j].name);
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 889cadf..5e375d6 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -67,7 +67,7 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
 
 struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
 
-void print_pmu_events(const char *event_glob, bool name_only);
+void print_pmu_events(const char *event_glob, bool name_only, bool quiet);
 bool pmu_have_event(const char *pname, const char *name);
 
 int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
-- 
1.7.9.5

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

* [PATCH v9 11/11] perf-download: Download the events json file
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

Add a downloader to automatically download the right files from a
download site.

This is implemented as a script calling curl, similar to perf archive.
The perf driver automatically calls the right binary. The downloader is
extensible, but currently only implements an Intel and Powerpc event
download.  It would be straightforward to add support for other architectures.

For now, there could be slight variations in how individual architectures
organize the JSON files. Eg. Powerpc has a simple mapping from its PVR
to cpu family eg power8's events file, which x86 uses, CPU vendor, family
model to locate the specific file to download.

The downloaded event files are put into ~/.cache/pmu-events, where the
builtin event parser in util/* can find them automatically.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/n/1405123165-22666-8-git-send-email-andi@firstfloor.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>

Changelog[v9] (by Sukadev Bhattiprolu)
	Add the perf-download script back into patchset. Set default
	download location to the tools/perf/pmu-events/ directory in
	Linus's tree.
	Include code to parse/download powerpc JSON files.
	Remove Acked-by: Namhyung Kim since this patch has major changes
---
 tools/perf/Documentation/perf-download.txt |   31 +++++
 tools/perf/Documentation/perf-list.txt     |   12 +-
 tools/perf/Makefile.perf                   |    5 +-
 tools/perf/perf-download.sh                |  171 ++++++++++++++++++++++++++++
 4 files changed, 217 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-download.txt
 create mode 100755 tools/perf/perf-download.sh

diff --git a/tools/perf/Documentation/perf-download.txt b/tools/perf/Documentation/perf-download.txt
new file mode 100644
index 0000000..9e5b28e
--- /dev/null
+++ b/tools/perf/Documentation/perf-download.txt
@@ -0,0 +1,31 @@
+perf-download(1)
+===============
+
+NAME
+----
+perf-download - Download event files for current CPU.
+
+SYNOPSIS
+--------
+[verse]
+'perf download' [vendor-family-model]
+
+DESCRIPTION
+-----------
+This command automatically downloads the event list for the current CPU and
+stores them in $XDG_CACHE_HOME/pmu-events (or $HOME/.cache/pmu-events).
+The other tools automatically look for them there. The CPU can be also
+specified at the command line.
+
+The downloading is done using http through wget, which needs
+to be installed. When behind a firewall the proxies
+may also need to be set up using "export https_proxy=...."
+
+The user should regularly call this to download updated event lists
+for the current CPU.
+
+Note the downloaded files are stored per user, so if perf is
+used as both normal user and with sudo the event files may
+also need to be moved to root's home directory with
+sudo mkdir /root/.cache ; sud cp -r ~/.cache/pmu-events /root/.cache
+after downloading.
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 7479efe..98637e8 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -66,6 +66,16 @@ Sampling). Examples to use IBS:
  perf record -a -e r076:p ...          # same as -e cpu-cycles:p
  perf record -a -e r0C1:p ...          # use ibs op counting micro-ops
 
+PER CPU EVENT LISTS
+-------------------
+
+For some CPUs (particularly modern Intel CPUs) "perf download" can
+download additional CPU specific event definitions, which then
+become visible in perf list and available in the other perf tools.
+
+This obsoletes the raw event description method described below
+for most cases.
+
 RAW HARDWARE EVENT DESCRIPTOR
 -----------------------------
 Even when an event is not available in a symbolic form within perf right now,
@@ -141,6 +151,6 @@ types specified.
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-top[1],
-linkperf:perf-record[1],
+linkperf:perf-record[1], linkperf:perf-download[1],
 http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],
 http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming]
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9c03c4..9f955b1 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -136,6 +136,7 @@ SCRIPT_SH =
 
 SCRIPT_SH += perf-archive.sh
 SCRIPT_SH += perf-with-kcore.sh
+SCRIPT_SH += perf-download.sh
 
 grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
@@ -946,6 +947,8 @@ endif
 		$(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 	$(call QUIET_INSTALL, perf-with-kcore) \
 		$(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+	$(call QUIET_INSTALL, perf-download) \
+		$(INSTALL) $(OUTPUT)perf-download -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 ifndef NO_LIBPERL
 	$(call QUIET_INSTALL, perl-scripts) \
 		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
@@ -991,7 +994,7 @@ config-clean:
 	@$(MAKE) -C config/feature-checks clean >/dev/null
 
 clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
-	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
+	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf-download $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
 	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
 	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
 	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
diff --git a/tools/perf/perf-download.sh b/tools/perf/perf-download.sh
new file mode 100755
index 0000000..79922c5
--- /dev/null
+++ b/tools/perf/perf-download.sh
@@ -0,0 +1,171 @@
+#!/bin/bash
+#
+# Download event files for current cpu for perf
+#
+
+set -e
+
+CURLOPT=${CURLOPT:- --max-time 5 --progress-bar}
+MAPFILE=${MAPFILE:-mapfile.csv}
+GKO=https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/;
+CACHEDIR=${XDG_CACHE_HOME:-~/.cache}
+
+ARCH="";
+CPUREV="";
+VENDOR="";
+VFM="";
+
+init_arch()
+{
+	arch=`uname -m  | sed -r 's/(x86.*|i.*86)/x86/' \
+			| sed -r 's/ppc.*/powerpc/'`;
+
+	if [ "x$arch" == "xpowerpc" -o "x$arch" == "xx86" ]; then
+		ARCH=$arch;
+	else
+		echo "Unknown architecture/CPU $arch"
+		exit 1;
+	fi
+}
+
+init_cpu_revision()
+{
+	if [ "x$ARCH" == "xpowerpc" ]; then
+		CPUREV=`grep revision /proc/cpuinfo | tail -1 |
+			awk '{ gsub(/\)/, "", $6); printf("%s%s", $5, $6); }'`
+	fi
+}
+
+init_vendor_family_model()
+{
+	if [ "x$ARCH" != "xx86" ]; then
+		return;
+	fi
+
+	VFM=$(awk '
+		/^vendor/     		{ V=$3 }
+		/^model/ && $2 == ":" 	{ M=$3 }
+		/^cpu family/ 		{ F = $4 }
+		END	      		{ printf("%s-%s-%X", V, F, M) }' \
+			/proc/cpuinfo)
+
+	VENDOR=$(echo $VFM  | ( IFS=- read v f m ; echo $v) )
+}
+
+init_defaults()
+{
+	# Not all architectures need all these
+	init_arch;
+	init_cpu_revision;
+	init_vendor_family_model;
+}
+
+download_x86_files()
+{
+	case "$VENDOR" in
+
+	GenuineIntel)
+		echo "Downloading readme.txt"
+		curl $CURLOPT $URLBASE/readme.txt -o readme.txt
+		if [ ! -f "readme.txt" ]; then
+			echo "Couldn't download $URLBASE/readme.txt, continuing"
+		fi
+
+		;;
+
+	# Add more CPU vendors here
+
+	*)
+		echo "Unsupported CPU vendor $V"
+		exit 1
+		;;
+	esac
+
+	echo "Downloading models file"
+	curl $CURLOPT $URLBASE/$MAPFILE -o $MAPFILE
+
+	if [ ! -f $MAPFILE ]; then
+		echo "Could not download $URLBASE/$MAPFILE"
+		exit 1;
+	fi
+
+	events_file=`mktemp`;
+	echo "Downloading events file"
+	awk -v urlbase=$URLBASE -v cpu="$VFM" -F, 			\
+		'$1 == cpu && $4 == "core" { 			\
+			print "url = \"" urlbase $3 "\"";	\
+			exit 0 }' 				\
+		$MAPFILE > $events_file
+
+	if [ -s $events_file ] ; then
+		curl $CURLOPT -K $events_file -o $VFM-core.json
+	else
+		echo "CPU $VFM not found"
+	fi
+
+	#rm -f $events_file
+}
+
+download_powerpc_files()
+{
+	#
+	# Mapfile for Power looks like this:
+	#
+	# 	004d0100,core,power8.json
+	#
+	# where first column is the PVR, and last column is the
+	# name of the events file for the CPU family. Download
+	# the events file and create a symlink to it:
+	#
+	# 	004d0100-core.json -> power8.json
+	#
+	echo "Downloading models file, $MAPFILE"
+	curl $CURLOPT ${URLBASE}/$MAPFILE -o $MAPFILE
+
+	if [ ! -f $MAPFILE ]; then
+		echo "Could not download $URLBASE/$MAPFILE"
+		exit 1;
+	fi
+
+	target=`awk -v cpu="$CPUREV" -F, \
+		'$1 == cpu && $2 == "core" { print $3 }' $MAPFILE`
+
+	cpurev=${CPUREV}-core.json
+	rm -f $cpurev;
+
+	echo "Downloading events file for CPU/Rev '$cpurev'"
+	curl $CURLOPT ${URLBASE}/$target -o $target
+	ln -s $target $cpurev 
+}
+#
+# Main
+#
+if ! type curl > /dev/null ; then
+	echo "please install curl"
+	exit 1
+fi
+
+if [ "$1" == "" ] ; then
+	init_defaults;
+else
+	ARCH=$1;
+	CPUREV=$2;
+	VENDOR=$3;
+fi;
+
+URLBASE=${URLBASE:-${GKO}/tools/perf/pmu-events/arch/${ARCH}/};
+
+[ ! -d $CACHEDIR/pmu-events ] && mkdir -p $CACHEDIR/pmu-events
+cd $CACHEDIR/pmu-events
+
+case $ARCH in
+
+x86)
+	download_x86_files
+	;;
+
+powerpc)
+
+	download_powerpc_files
+	;;
+esac
-- 
1.7.9.5


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

* [PATCH v9 11/11] perf-download: Download the events json file
@ 2015-04-14  6:41   ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14  6:41 UTC (permalink / raw)
  To: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo
  Cc: peterz, namhyung, linuxppc-dev, linux-kernel

Add a downloader to automatically download the right files from a
download site.

This is implemented as a script calling curl, similar to perf archive.
The perf driver automatically calls the right binary. The downloader is
extensible, but currently only implements an Intel and Powerpc event
download.  It would be straightforward to add support for other architectures.

For now, there could be slight variations in how individual architectures
organize the JSON files. Eg. Powerpc has a simple mapping from its PVR
to cpu family eg power8's events file, which x86 uses, CPU vendor, family
model to locate the specific file to download.

The downloaded event files are put into ~/.cache/pmu-events, where the
builtin event parser in util/* can find them automatically.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Link: http://lkml.kernel.org/n/1405123165-22666-8-git-send-email-andi@firstfloor.org
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>

Changelog[v9] (by Sukadev Bhattiprolu)
	Add the perf-download script back into patchset. Set default
	download location to the tools/perf/pmu-events/ directory in
	Linus's tree.
	Include code to parse/download powerpc JSON files.
	Remove Acked-by: Namhyung Kim since this patch has major changes
---
 tools/perf/Documentation/perf-download.txt |   31 +++++
 tools/perf/Documentation/perf-list.txt     |   12 +-
 tools/perf/Makefile.perf                   |    5 +-
 tools/perf/perf-download.sh                |  171 ++++++++++++++++++++++++++++
 4 files changed, 217 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-download.txt
 create mode 100755 tools/perf/perf-download.sh

diff --git a/tools/perf/Documentation/perf-download.txt b/tools/perf/Documentation/perf-download.txt
new file mode 100644
index 0000000..9e5b28e
--- /dev/null
+++ b/tools/perf/Documentation/perf-download.txt
@@ -0,0 +1,31 @@
+perf-download(1)
+===============
+
+NAME
+----
+perf-download - Download event files for current CPU.
+
+SYNOPSIS
+--------
+[verse]
+'perf download' [vendor-family-model]
+
+DESCRIPTION
+-----------
+This command automatically downloads the event list for the current CPU and
+stores them in $XDG_CACHE_HOME/pmu-events (or $HOME/.cache/pmu-events).
+The other tools automatically look for them there. The CPU can be also
+specified at the command line.
+
+The downloading is done using http through wget, which needs
+to be installed. When behind a firewall the proxies
+may also need to be set up using "export https_proxy=...."
+
+The user should regularly call this to download updated event lists
+for the current CPU.
+
+Note the downloaded files are stored per user, so if perf is
+used as both normal user and with sudo the event files may
+also need to be moved to root's home directory with
+sudo mkdir /root/.cache ; sud cp -r ~/.cache/pmu-events /root/.cache
+after downloading.
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 7479efe..98637e8 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -66,6 +66,16 @@ Sampling). Examples to use IBS:
  perf record -a -e r076:p ...          # same as -e cpu-cycles:p
  perf record -a -e r0C1:p ...          # use ibs op counting micro-ops
 
+PER CPU EVENT LISTS
+-------------------
+
+For some CPUs (particularly modern Intel CPUs) "perf download" can
+download additional CPU specific event definitions, which then
+become visible in perf list and available in the other perf tools.
+
+This obsoletes the raw event description method described below
+for most cases.
+
 RAW HARDWARE EVENT DESCRIPTOR
 -----------------------------
 Even when an event is not available in a symbolic form within perf right now,
@@ -141,6 +151,6 @@ types specified.
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-top[1],
-linkperf:perf-record[1],
+linkperf:perf-record[1], linkperf:perf-download[1],
 http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],
 http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming]
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index d9c03c4..9f955b1 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -136,6 +136,7 @@ SCRIPT_SH =
 
 SCRIPT_SH += perf-archive.sh
 SCRIPT_SH += perf-with-kcore.sh
+SCRIPT_SH += perf-download.sh
 
 grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
@@ -946,6 +947,8 @@ endif
 		$(INSTALL) $(OUTPUT)perf-archive -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 	$(call QUIET_INSTALL, perf-with-kcore) \
 		$(INSTALL) $(OUTPUT)perf-with-kcore -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
+	$(call QUIET_INSTALL, perf-download) \
+		$(INSTALL) $(OUTPUT)perf-download -t '$(DESTDIR_SQ)$(perfexec_instdir_SQ)'
 ifndef NO_LIBPERL
 	$(call QUIET_INSTALL, perl-scripts) \
 		$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/scripts/perl/Perf-Trace-Util/lib/Perf/Trace'; \
@@ -991,7 +994,7 @@ config-clean:
 	@$(MAKE) -C config/feature-checks clean >/dev/null
 
 clean: $(LIBTRACEEVENT)-clean $(LIBAPIKFS)-clean config-clean
-	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
+	$(call QUIET_CLEAN, core-objs)  $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(OUTPUT)perf-download $(OUTPUT)perf.o $(LANG_BINDINGS) $(GTK_OBJS)
 	$(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32
 	$(call QUIET_CLEAN, core-gen)   $(RM)  *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS $(OUTPUT)PERF-FEATURES $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex*
 	$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
diff --git a/tools/perf/perf-download.sh b/tools/perf/perf-download.sh
new file mode 100755
index 0000000..79922c5
--- /dev/null
+++ b/tools/perf/perf-download.sh
@@ -0,0 +1,171 @@
+#!/bin/bash
+#
+# Download event files for current cpu for perf
+#
+
+set -e
+
+CURLOPT=${CURLOPT:- --max-time 5 --progress-bar}
+MAPFILE=${MAPFILE:-mapfile.csv}
+GKO=https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/;
+CACHEDIR=${XDG_CACHE_HOME:-~/.cache}
+
+ARCH="";
+CPUREV="";
+VENDOR="";
+VFM="";
+
+init_arch()
+{
+	arch=`uname -m  | sed -r 's/(x86.*|i.*86)/x86/' \
+			| sed -r 's/ppc.*/powerpc/'`;
+
+	if [ "x$arch" == "xpowerpc" -o "x$arch" == "xx86" ]; then
+		ARCH=$arch;
+	else
+		echo "Unknown architecture/CPU $arch"
+		exit 1;
+	fi
+}
+
+init_cpu_revision()
+{
+	if [ "x$ARCH" == "xpowerpc" ]; then
+		CPUREV=`grep revision /proc/cpuinfo | tail -1 |
+			awk '{ gsub(/\)/, "", $6); printf("%s%s", $5, $6); }'`
+	fi
+}
+
+init_vendor_family_model()
+{
+	if [ "x$ARCH" != "xx86" ]; then
+		return;
+	fi
+
+	VFM=$(awk '
+		/^vendor/     		{ V=$3 }
+		/^model/ && $2 == ":" 	{ M=$3 }
+		/^cpu family/ 		{ F = $4 }
+		END	      		{ printf("%s-%s-%X", V, F, M) }' \
+			/proc/cpuinfo)
+
+	VENDOR=$(echo $VFM  | ( IFS=- read v f m ; echo $v) )
+}
+
+init_defaults()
+{
+	# Not all architectures need all these
+	init_arch;
+	init_cpu_revision;
+	init_vendor_family_model;
+}
+
+download_x86_files()
+{
+	case "$VENDOR" in
+
+	GenuineIntel)
+		echo "Downloading readme.txt"
+		curl $CURLOPT $URLBASE/readme.txt -o readme.txt
+		if [ ! -f "readme.txt" ]; then
+			echo "Couldn't download $URLBASE/readme.txt, continuing"
+		fi
+
+		;;
+
+	# Add more CPU vendors here
+
+	*)
+		echo "Unsupported CPU vendor $V"
+		exit 1
+		;;
+	esac
+
+	echo "Downloading models file"
+	curl $CURLOPT $URLBASE/$MAPFILE -o $MAPFILE
+
+	if [ ! -f $MAPFILE ]; then
+		echo "Could not download $URLBASE/$MAPFILE"
+		exit 1;
+	fi
+
+	events_file=`mktemp`;
+	echo "Downloading events file"
+	awk -v urlbase=$URLBASE -v cpu="$VFM" -F, 			\
+		'$1 == cpu && $4 == "core" { 			\
+			print "url = \"" urlbase $3 "\"";	\
+			exit 0 }' 				\
+		$MAPFILE > $events_file
+
+	if [ -s $events_file ] ; then
+		curl $CURLOPT -K $events_file -o $VFM-core.json
+	else
+		echo "CPU $VFM not found"
+	fi
+
+	#rm -f $events_file
+}
+
+download_powerpc_files()
+{
+	#
+	# Mapfile for Power looks like this:
+	#
+	# 	004d0100,core,power8.json
+	#
+	# where first column is the PVR, and last column is the
+	# name of the events file for the CPU family. Download
+	# the events file and create a symlink to it:
+	#
+	# 	004d0100-core.json -> power8.json
+	#
+	echo "Downloading models file, $MAPFILE"
+	curl $CURLOPT ${URLBASE}/$MAPFILE -o $MAPFILE
+
+	if [ ! -f $MAPFILE ]; then
+		echo "Could not download $URLBASE/$MAPFILE"
+		exit 1;
+	fi
+
+	target=`awk -v cpu="$CPUREV" -F, \
+		'$1 == cpu && $2 == "core" { print $3 }' $MAPFILE`
+
+	cpurev=${CPUREV}-core.json
+	rm -f $cpurev;
+
+	echo "Downloading events file for CPU/Rev '$cpurev'"
+	curl $CURLOPT ${URLBASE}/$target -o $target
+	ln -s $target $cpurev 
+}
+#
+# Main
+#
+if ! type curl > /dev/null ; then
+	echo "please install curl"
+	exit 1
+fi
+
+if [ "$1" == "" ] ; then
+	init_defaults;
+else
+	ARCH=$1;
+	CPUREV=$2;
+	VENDOR=$3;
+fi;
+
+URLBASE=${URLBASE:-${GKO}/tools/perf/pmu-events/arch/${ARCH}/};
+
+[ ! -d $CACHEDIR/pmu-events ] && mkdir -p $CACHEDIR/pmu-events
+cd $CACHEDIR/pmu-events
+
+case $ARCH in
+
+x86)
+	download_x86_files
+	;;
+
+powerpc)
+
+	download_powerpc_files
+	;;
+esac
-- 
1.7.9.5

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

* 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-14  6:40 ` Sukadev Bhattiprolu
@ 2015-04-14  8:55   ` Ingo Molnar
  -1 siblings, 0 replies; 50+ messages in thread
From: Ingo Molnar @ 2015-04-14  8:55 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: mingo, ak, Michael Ellerman, Jiri Olsa, Arnaldo Carvalho de Melo,
	peterz, namhyung, linuxppc-dev, linux-kernel, Pekka Enberg,
	Arnaldo Carvalho de Melo, Peter Zijlstra, Thomas Gleixner


* Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:

> This is another attempt to resurrect Andi Kleen's patchset so users
> can specify perf events by their event names rather than raw codes.
> 
> This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> (I fixed minor and not so minor conflicts).

So this series shows some progress, but instead of this limited 
checkout ability I'd still prefer it if 'perf download' downloaded the 
latest perf code itself and built it - it shouldn't be limited to just 
a small subset of the perf source code!

There's a few Git tricks we can use to make this palatable on most 
systems.

To save disk space and network bandwith this could be done using Git's 
'shallow clone' feature:

   git clone --depth 1 --bare

The initial checkout finishes in 1.5 minutes here, a continent away 
from korg. The resulting repository size is just 143MB.

The code could also check whether the user has already a ~/linux.git 
repository around, and use --reference ~/linux.git in that case. In 
such a case the cloning takes just 2 seconds.

To get the source code we could use Git's 'sparse checkout' feature:

   git config core.sparsecheckout true
   echo tools/ > .git/info/sparse-checkout
   git checkout tools/

Note that a sparse checkout build will need a few relatively simple 
other files as well, for the few files not in tools/ that the perf 
build needs - mostly include files.

I've attached below a working test script that will create a buildable 
tools/perf/ repository into ~/.perf/git/ of the latest tip/perf/core 
tree from kernel.org.

With ~/linux.git primed it takes under 10 seconds to execute. perf 
builds fine in the directory. The whole directory together with the 
Git repo is 53 MB - that could be shrunk some more if needed.

If there's no local Linux repository to fall back on to then the 
initial step takes 1.5 minutes (depending on network bandwidth) and 
another 140MB for the Git objects. It's a lot faster after that.

That way 'perf download' could also be renamed to 'perf upgrade'.

Building perf ought to be possible even on fairly limited development 
systems and our auto-detection and library install suggestions are 
pretty good.

And note that once we have that there's no reason to move the event 
descriptions into a separate file - it can be part of the perf binary 
itself.

> This patchset includes the perf-download tool that was dropped and 
> sets the default download location to the 
> (tools/perf/pmu-events/arch/... directory in Linus's tree.

So the way I think this would work best is for 'perf upgrade' to have 
different levels, similar to what the kernel has:

  perf upgrade devel               # pick files up from Arnaldo's korg tree
  perf upgrade next                # pick files up from tip.git on korg
  perf upgrade rc                  # pick files up from linus's Git tree
  perf upgrade stable              # pick files up the latest -stable version

'perf upgrade' would default to the most conservative, -stable 
variant, but of course users could pick whichever variant they prefer.

There's some limitations (such as if the build fails - but we want to 
fix such cases anyway), but note the fundamental power of this 
approach: 'perf upgrade' could turn any developer who has a perf 
binary into a perf tester and even into a contributor.

There's no need to even know Git or other development details - the 
latest code could be picked up and built.

'perf upgrade distro' could be offered as a way to downgrade to 
whatever previous (distro) perf version the user was using.

Likewise, later on this approach could be generalized into 
tools/build/ to enable self-hosting for other tools in tools/ as well, 
if they so desire.

Thanks,

	Ingo

============================>
#!/bin/bash
#
# Simple script that fetches the 'perf' utility from Linus's tree, builds and
# installs it, by creating a shallow clone and a sparse checkout for Linux's
# tools/ directory and related dependencies:
#

DIR=~/.perf/git

rm -rf $DIR
mkdir -p $DIR || { echo 'error: No write permissions in the current directory?'; exit -1; }
cd $DIR

#REPO=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
#BRANCH=HEAD
REPO=git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
BRANCH=perf/core

REFERENCE="."
[ -d ~/linux/.git     ] && REFERENCE=~/linux/
[ -d ~/linux.git/.git ] && REFERENCE=~/linux.git/
[ -d ~/tip/.git       ] && REFERENCE=~/tip/
[ -d ~/tip.git/.git   ] && REFERENCE=~/tip.git/

git clone --reference $REFERENCE --depth 1 --bare $REPO --branch $BRANCH .git
git config --local core.bare false

git config --local core.sparseCheckout true
git remote remove origin
git remote add -f origin $REPO -t $BRANCH

(
  echo '/tools/*'
  echo '/lib/*'
  echo '/include/*'
  echo '/arch/x86/lib/*'
  echo '/arch/x86/include/*'
  echo 'Makefile'
  echo '/scripts/*'

) > .git/info/sparse-checkout

git checkout $BRANCH

make -C tools/perf/ install


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

* 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-14  8:55   ` Ingo Molnar
  0 siblings, 0 replies; 50+ messages in thread
From: Ingo Molnar @ 2015-04-14  8:55 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linuxppc-dev, Arnaldo Carvalho de Melo, linux-kernel, mingo,
	namhyung, Thomas Gleixner, Jiri Olsa, Pekka Enberg


* Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:

> This is another attempt to resurrect Andi Kleen's patchset so users
> can specify perf events by their event names rather than raw codes.
> 
> This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> (I fixed minor and not so minor conflicts).

So this series shows some progress, but instead of this limited 
checkout ability I'd still prefer it if 'perf download' downloaded the 
latest perf code itself and built it - it shouldn't be limited to just 
a small subset of the perf source code!

There's a few Git tricks we can use to make this palatable on most 
systems.

To save disk space and network bandwith this could be done using Git's 
'shallow clone' feature:

   git clone --depth 1 --bare

The initial checkout finishes in 1.5 minutes here, a continent away 
from korg. The resulting repository size is just 143MB.

The code could also check whether the user has already a ~/linux.git 
repository around, and use --reference ~/linux.git in that case. In 
such a case the cloning takes just 2 seconds.

To get the source code we could use Git's 'sparse checkout' feature:

   git config core.sparsecheckout true
   echo tools/ > .git/info/sparse-checkout
   git checkout tools/

Note that a sparse checkout build will need a few relatively simple 
other files as well, for the few files not in tools/ that the perf 
build needs - mostly include files.

I've attached below a working test script that will create a buildable 
tools/perf/ repository into ~/.perf/git/ of the latest tip/perf/core 
tree from kernel.org.

With ~/linux.git primed it takes under 10 seconds to execute. perf 
builds fine in the directory. The whole directory together with the 
Git repo is 53 MB - that could be shrunk some more if needed.

If there's no local Linux repository to fall back on to then the 
initial step takes 1.5 minutes (depending on network bandwidth) and 
another 140MB for the Git objects. It's a lot faster after that.

That way 'perf download' could also be renamed to 'perf upgrade'.

Building perf ought to be possible even on fairly limited development 
systems and our auto-detection and library install suggestions are 
pretty good.

And note that once we have that there's no reason to move the event 
descriptions into a separate file - it can be part of the perf binary 
itself.

> This patchset includes the perf-download tool that was dropped and 
> sets the default download location to the 
> (tools/perf/pmu-events/arch/... directory in Linus's tree.

So the way I think this would work best is for 'perf upgrade' to have 
different levels, similar to what the kernel has:

  perf upgrade devel               # pick files up from Arnaldo's korg tree
  perf upgrade next                # pick files up from tip.git on korg
  perf upgrade rc                  # pick files up from linus's Git tree
  perf upgrade stable              # pick files up the latest -stable version

'perf upgrade' would default to the most conservative, -stable 
variant, but of course users could pick whichever variant they prefer.

There's some limitations (such as if the build fails - but we want to 
fix such cases anyway), but note the fundamental power of this 
approach: 'perf upgrade' could turn any developer who has a perf 
binary into a perf tester and even into a contributor.

There's no need to even know Git or other development details - the 
latest code could be picked up and built.

'perf upgrade distro' could be offered as a way to downgrade to 
whatever previous (distro) perf version the user was using.

Likewise, later on this approach could be generalized into 
tools/build/ to enable self-hosting for other tools in tools/ as well, 
if they so desire.

Thanks,

	Ingo

============================>
#!/bin/bash
#
# Simple script that fetches the 'perf' utility from Linus's tree, builds and
# installs it, by creating a shallow clone and a sparse checkout for Linux's
# tools/ directory and related dependencies:
#

DIR=~/.perf/git

rm -rf $DIR
mkdir -p $DIR || { echo 'error: No write permissions in the current directory?'; exit -1; }
cd $DIR

#REPO=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
#BRANCH=HEAD
REPO=git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
BRANCH=perf/core

REFERENCE="."
[ -d ~/linux/.git     ] && REFERENCE=~/linux/
[ -d ~/linux.git/.git ] && REFERENCE=~/linux.git/
[ -d ~/tip/.git       ] && REFERENCE=~/tip/
[ -d ~/tip.git/.git   ] && REFERENCE=~/tip.git/

git clone --reference $REFERENCE --depth 1 --bare $REPO --branch $BRANCH .git
git config --local core.bare false

git config --local core.sparseCheckout true
git remote remove origin
git remote add -f origin $REPO -t $BRANCH

(
  echo '/tools/*'
  echo '/lib/*'
  echo '/include/*'
  echo '/arch/x86/lib/*'
  echo '/arch/x86/include/*'
  echo 'Makefile'
  echo '/scripts/*'

) > .git/info/sparse-checkout

git checkout $BRANCH

make -C tools/perf/ install

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-14  8:55   ` Ingo Molnar
@ 2015-04-14 11:21     ` Michael Ellerman
  -1 siblings, 0 replies; 50+ messages in thread
From: Michael Ellerman @ 2015-04-14 11:21 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Sukadev Bhattiprolu, mingo, ak, Jiri Olsa,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds

On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
> * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> 
> > This is another attempt to resurrect Andi Kleen's patchset so users
> > can specify perf events by their event names rather than raw codes.
> > 
> > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > (I fixed minor and not so minor conflicts).
> 
> So this series shows some progress, but instead of this limited 
> checkout ability I'd still prefer it if 'perf download' downloaded the 
> latest perf code itself and built it - it shouldn't be limited to just 
> a small subset of the perf source code!

Ingo, can you please stop blocking this? It's getting ridiculous.

We've been waiting over 8 months for this to go in.

While we've been waiting most of our users have learnt to use operf instead,
which doesn't require raw codes.

I would also add that exactly zero users have asked for a feature where perf
downloads and rebuilds itself. In fact many of them would consider that a
security breach.

cheers



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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-14 11:21     ` Michael Ellerman
  0 siblings, 0 replies; 50+ messages in thread
From: Michael Ellerman @ 2015-04-14 11:21 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linuxppc-dev, linux-kernel, Arnaldo Carvalho de Melo,
	Linus Torvalds, mingo, namhyung, Thomas Gleixner,
	Sukadev Bhattiprolu, Jiri Olsa, Pekka Enberg

On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
> * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> 
> > This is another attempt to resurrect Andi Kleen's patchset so users
> > can specify perf events by their event names rather than raw codes.
> > 
> > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > (I fixed minor and not so minor conflicts).
> 
> So this series shows some progress, but instead of this limited 
> checkout ability I'd still prefer it if 'perf download' downloaded the 
> latest perf code itself and built it - it shouldn't be limited to just 
> a small subset of the perf source code!

Ingo, can you please stop blocking this? It's getting ridiculous.

We've been waiting over 8 months for this to go in.

While we've been waiting most of our users have learnt to use operf instead,
which doesn't require raw codes.

I would also add that exactly zero users have asked for a feature where perf
downloads and rebuilds itself. In fact many of them would consider that a
security breach.

cheers

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-14 11:21     ` Michael Ellerman
@ 2015-04-14 12:58       ` Ingo Molnar
  -1 siblings, 0 replies; 50+ messages in thread
From: Ingo Molnar @ 2015-04-14 12:58 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Sukadev Bhattiprolu, mingo, ak, Jiri Olsa,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds


* Michael Ellerman <mpe@ellerman.id.au> wrote:

> On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
> > * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> > 
> > > This is another attempt to resurrect Andi Kleen's patchset so users
> > > can specify perf events by their event names rather than raw codes.
> > > 
> > > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > > (I fixed minor and not so minor conflicts).
> > 
> > So this series shows some progress, but instead of this limited 
> > checkout ability I'd still prefer it if 'perf download' downloaded 
> > the latest perf code itself and built it - it shouldn't be limited 
> > to just a small subset of the perf source code!
> 
> Ingo, can you please stop blocking this? It's getting ridiculous.
> 
> We've been waiting over 8 months for this to go in.

We just merged a patch series that was first sent in 2013. Some things 
take time to get right.

> While we've been waiting most of our users have learnt to use operf 
> instead, which doesn't require raw codes.
> 
> I would also add that exactly zero users have asked for a feature 
> where perf downloads and rebuilds itself. In fact many of them would 
> consider that a security breach.

Fetching tracing scripts, plugins or other instrumentation scripts can 
be considered a 'security breach' as well. Fetching external tables 
(or network access to begin with) can be considered a 'security 
breach' as well, depending on how restricted an environment is.

But we don't design our code based on the most restrictive 
environments that are hostile to open source concepts!

Unfortunate users that are not allowed to update open source code that 
they are using should probably not update it. The other 99.9% of perf 
users would benefit from a properly done upgrading/updating feature.

Please stop thinking in terms of restricted, closed environments. 
Packaged perf will still work fine for them, and changes will still 
trickle down to them.

Thanks,

	Ingo

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-14 12:58       ` Ingo Molnar
  0 siblings, 0 replies; 50+ messages in thread
From: Ingo Molnar @ 2015-04-14 12:58 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linuxppc-dev, linux-kernel, Arnaldo Carvalho de Melo,
	Linus Torvalds, mingo, namhyung, Thomas Gleixner,
	Sukadev Bhattiprolu, Jiri Olsa, Pekka Enberg


* Michael Ellerman <mpe@ellerman.id.au> wrote:

> On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
> > * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> > 
> > > This is another attempt to resurrect Andi Kleen's patchset so users
> > > can specify perf events by their event names rather than raw codes.
> > > 
> > > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > > (I fixed minor and not so minor conflicts).
> > 
> > So this series shows some progress, but instead of this limited 
> > checkout ability I'd still prefer it if 'perf download' downloaded 
> > the latest perf code itself and built it - it shouldn't be limited 
> > to just a small subset of the perf source code!
> 
> Ingo, can you please stop blocking this? It's getting ridiculous.
> 
> We've been waiting over 8 months for this to go in.

We just merged a patch series that was first sent in 2013. Some things 
take time to get right.

> While we've been waiting most of our users have learnt to use operf 
> instead, which doesn't require raw codes.
> 
> I would also add that exactly zero users have asked for a feature 
> where perf downloads and rebuilds itself. In fact many of them would 
> consider that a security breach.

Fetching tracing scripts, plugins or other instrumentation scripts can 
be considered a 'security breach' as well. Fetching external tables 
(or network access to begin with) can be considered a 'security 
breach' as well, depending on how restricted an environment is.

But we don't design our code based on the most restrictive 
environments that are hostile to open source concepts!

Unfortunate users that are not allowed to update open source code that 
they are using should probably not update it. The other 99.9% of perf 
users would benefit from a properly done upgrading/updating feature.

Please stop thinking in terms of restricted, closed environments. 
Packaged perf will still work fine for them, and changes will still 
trickle down to them.

Thanks,

	Ingo

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-14 12:58       ` Ingo Molnar
@ 2015-04-14 18:03         ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14 18:03 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Michael Ellerman, mingo, ak, Jiri Olsa, Arnaldo Carvalho de Melo,
	peterz, namhyung, linuxppc-dev, linux-kernel, Pekka Enberg,
	Arnaldo Carvalho de Melo, Peter Zijlstra, Thomas Gleixner,
	Linus Torvalds, tom.huynh

Ingo Molnar [mingo@kernel.org] wrote:

Meant to Cc Tom Huynh as they had a related patchset a few months
ago.

| 
| * Michael Ellerman <mpe@ellerman.id.au> wrote:
| 
| > On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
| > > * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
| > > 
| > > > This is another attempt to resurrect Andi Kleen's patchset so users
| > > > can specify perf events by their event names rather than raw codes.
| > > > 
| > > > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
| > > > (I fixed minor and not so minor conflicts).
| > > 
| > > So this series shows some progress, but instead of this limited 
| > > checkout ability I'd still prefer it if 'perf download' downloaded 
| > > the latest perf code itself and built it - it shouldn't be limited 
| > > to just a small subset of the perf source code!
| > 
| > Ingo, can you please stop blocking this? It's getting ridiculous.
| > 
| > We've been waiting over 8 months for this to go in.
| 
| We just merged a patch series that was first sent in 2013. Some things 
| take time to get right.

I used to rebuild git years ago to work around bugs in rebase, but rarely
need to rebuild these days, because it is stable.  I am guessing it is the
same for most users of perf.

IOW, perf download/upgrade can be extended to fetch and build, but
dont' understand why that is _required_ to _use_ the JSON files.

- perf having an ability to parse JSON files
- perf downloading JSON files
- perf downloading latest source code
- perf downloading dependent RPMS/packages to build (which
  seem to be tied to distros)

all seem like independent steps to me. If current design can be
tweaked to not constrain future choices, we should definitely do
that.

If not, can we make incremental progress on this?

If necessary, we could add an option to 'perf upgrade' to fetch only
the JSON files?  Or by default, 'perf upgrade' can assume --all
and download everything it can download.

In the future we can add --json-files, --sources etc and still
ahve --all fetch everything it can.

Sukadev


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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-14 18:03         ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-14 18:03 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, tom.huynh, ak, Peter Zijlstra, peterz,
	linuxppc-dev, Arnaldo Carvalho de Melo, linux-kernel,
	Linus Torvalds, mingo, namhyung, Thomas Gleixner, Jiri Olsa,
	Pekka Enberg

Ingo Molnar [mingo@kernel.org] wrote:

Meant to Cc Tom Huynh as they had a related patchset a few months
ago.

| 
| * Michael Ellerman <mpe@ellerman.id.au> wrote:
| 
| > On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
| > > * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
| > > 
| > > > This is another attempt to resurrect Andi Kleen's patchset so users
| > > > can specify perf events by their event names rather than raw codes.
| > > > 
| > > > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
| > > > (I fixed minor and not so minor conflicts).
| > > 
| > > So this series shows some progress, but instead of this limited 
| > > checkout ability I'd still prefer it if 'perf download' downloaded 
| > > the latest perf code itself and built it - it shouldn't be limited 
| > > to just a small subset of the perf source code!
| > 
| > Ingo, can you please stop blocking this? It's getting ridiculous.
| > 
| > We've been waiting over 8 months for this to go in.
| 
| We just merged a patch series that was first sent in 2013. Some things 
| take time to get right.

I used to rebuild git years ago to work around bugs in rebase, but rarely
need to rebuild these days, because it is stable.  I am guessing it is the
same for most users of perf.

IOW, perf download/upgrade can be extended to fetch and build, but
dont' understand why that is _required_ to _use_ the JSON files.

- perf having an ability to parse JSON files
- perf downloading JSON files
- perf downloading latest source code
- perf downloading dependent RPMS/packages to build (which
  seem to be tied to distros)

all seem like independent steps to me. If current design can be
tweaked to not constrain future choices, we should definitely do
that.

If not, can we make incremental progress on this?

If necessary, we could add an option to 'perf upgrade' to fetch only
the JSON files?  Or by default, 'perf upgrade' can assume --all
and download everything it can download.

In the future we can add --json-files, --sources etc and still
ahve --all fetch everything it can.

Sukadev

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-14  8:55   ` Ingo Molnar
@ 2015-04-14 20:16     ` Andi Kleen
  -1 siblings, 0 replies; 50+ messages in thread
From: Andi Kleen @ 2015-04-14 20:16 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Sukadev Bhattiprolu, mingo, Michael Ellerman, Jiri Olsa,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner

On Tue, Apr 14, 2015 at 10:55:41AM +0200, Ingo Molnar wrote:
> 
> * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> 
> > This is another attempt to resurrect Andi Kleen's patchset so users
> > can specify perf events by their event names rather than raw codes.
> > 
> > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > (I fixed minor and not so minor conflicts).
> 
> So this series shows some progress, but instead of this limited 
> checkout ability I'd still prefer it if 'perf download' downloaded the 
> latest perf code itself and built it - it shouldn't be limited to just 
> a small subset of the perf source code!

I'm not against that idea (and can see it being useful in some cases[1]), 
but this would need some authentication. 

Otherwise it would be a "$bigbrother/nsa/anyone controling your network
can run everything on your computer" style hole.

The original JSON files don't have this problem because they didn't contain
any code.

-Andi

[1] especially to work around the broken perf setup on d./u. distros.

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-14 20:16     ` Andi Kleen
  0 siblings, 0 replies; 50+ messages in thread
From: Andi Kleen @ 2015-04-14 20:16 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, peterz, linuxppc-dev,
	Arnaldo Carvalho de Melo, linux-kernel, mingo, namhyung,
	Thomas Gleixner, Sukadev Bhattiprolu, Jiri Olsa, Pekka Enberg

On Tue, Apr 14, 2015 at 10:55:41AM +0200, Ingo Molnar wrote:
> 
> * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> 
> > This is another attempt to resurrect Andi Kleen's patchset so users
> > can specify perf events by their event names rather than raw codes.
> > 
> > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > (I fixed minor and not so minor conflicts).
> 
> So this series shows some progress, but instead of this limited 
> checkout ability I'd still prefer it if 'perf download' downloaded the 
> latest perf code itself and built it - it shouldn't be limited to just 
> a small subset of the perf source code!

I'm not against that idea (and can see it being useful in some cases[1]), 
but this would need some authentication. 

Otherwise it would be a "$bigbrother/nsa/anyone controling your network
can run everything on your computer" style hole.

The original JSON files don't have this problem because they didn't contain
any code.

-Andi

[1] especially to work around the broken perf setup on d./u. distros.

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-14 12:58       ` Ingo Molnar
@ 2015-04-14 22:53         ` Michael Ellerman
  -1 siblings, 0 replies; 50+ messages in thread
From: Michael Ellerman @ 2015-04-14 22:53 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Sukadev Bhattiprolu, mingo, ak, Jiri Olsa,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds

On Tue, 2015-04-14 at 14:58 +0200, Ingo Molnar wrote:
> * Michael Ellerman <mpe@ellerman.id.au> wrote:
> 
> > On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
> > > * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> > > 
> > > > This is another attempt to resurrect Andi Kleen's patchset so users
> > > > can specify perf events by their event names rather than raw codes.
> > > > 
> > > > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > > > (I fixed minor and not so minor conflicts).
> > > 
> > > So this series shows some progress, but instead of this limited 
> > > checkout ability I'd still prefer it if 'perf download' downloaded 
> > > the latest perf code itself and built it - it shouldn't be limited 
> > > to just a small subset of the perf source code!
> > 
> > Ingo, can you please stop blocking this? It's getting ridiculous.
> > 
> > We've been waiting over 8 months for this to go in.
> 
> We just merged a patch series that was first sent in 2013. Some things 
> take time to get right.

The first attempt to get symbolic event name support into perf was sent in
2010, that's FIVE years ago [1].

And what complicated feature are we asking for? The ability to map a human
readable name to a hex code, it has the complexity of a first year programming
assignment.

Variations have been submitted by IBM [1], by Facebook [2], now by Intel, and
Google have just given up and carry the libpfm4 patch in their perf tool [3].

Can we please just get this merged.

If you *then* want to add support for perf auto-updating that's fine, but don't
conflate the two.
 
cheers


[1]: https://lkml.org/lkml/2010/3/11/146
[2]: http://article.gmane.org/gmane.comp.linux.perfmon2.devel/2912
[3]: https://github.com/David-Levinthal/gooda/blob/master/gooda-analyzer/perf-patches/linux-v3.17/0001-perf-tools-add-support-for-libpfm4.patch



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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-14 22:53         ` Michael Ellerman
  0 siblings, 0 replies; 50+ messages in thread
From: Michael Ellerman @ 2015-04-14 22:53 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linuxppc-dev, linux-kernel, Arnaldo Carvalho de Melo,
	Linus Torvalds, mingo, namhyung, Thomas Gleixner,
	Sukadev Bhattiprolu, Jiri Olsa, Pekka Enberg

On Tue, 2015-04-14 at 14:58 +0200, Ingo Molnar wrote:
> * Michael Ellerman <mpe@ellerman.id.au> wrote:
> 
> > On Tue, 2015-04-14 at 10:55 +0200, Ingo Molnar wrote:
> > > * Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com> wrote:
> > > 
> > > > This is another attempt to resurrect Andi Kleen's patchset so users
> > > > can specify perf events by their event names rather than raw codes.
> > > > 
> > > > This is a rebase of Andi Kleen's patchset from Jul 30, 2014[1] to 4.0.
> > > > (I fixed minor and not so minor conflicts).
> > > 
> > > So this series shows some progress, but instead of this limited 
> > > checkout ability I'd still prefer it if 'perf download' downloaded 
> > > the latest perf code itself and built it - it shouldn't be limited 
> > > to just a small subset of the perf source code!
> > 
> > Ingo, can you please stop blocking this? It's getting ridiculous.
> > 
> > We've been waiting over 8 months for this to go in.
> 
> We just merged a patch series that was first sent in 2013. Some things 
> take time to get right.

The first attempt to get symbolic event name support into perf was sent in
2010, that's FIVE years ago [1].

And what complicated feature are we asking for? The ability to map a human
readable name to a hex code, it has the complexity of a first year programming
assignment.

Variations have been submitted by IBM [1], by Facebook [2], now by Intel, and
Google have just given up and carry the libpfm4 patch in their perf tool [3].

Can we please just get this merged.

If you *then* want to add support for perf auto-updating that's fine, but don't
conflate the two.
 
cheers


[1]: https://lkml.org/lkml/2010/3/11/146
[2]: http://article.gmane.org/gmane.comp.linux.perfmon2.devel/2912
[3]: https://github.com/David-Levinthal/gooda/blob/master/gooda-analyzer/perf-patches/linux-v3.17/0001-perf-tools-add-support-for-libpfm4.patch

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-14 22:53         ` Michael Ellerman
@ 2015-04-15  9:25           ` Ingo Molnar
  -1 siblings, 0 replies; 50+ messages in thread
From: Ingo Molnar @ 2015-04-15  9:25 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Sukadev Bhattiprolu, mingo, ak, Jiri Olsa,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds, Borislav Petkov


* Michael Ellerman <mpe@ellerman.id.au> wrote:

> > We just merged a patch series that was first sent in 2013. Some 
> > things take time to get right.
> 
> The first attempt to get symbolic event name support into perf was 
> sent in 2010, that's FIVE years ago [1].

kgdb took even longer, I think it was first proposed before 2000, over 
10 years before it got merged?

fs/overlayfs/ took similarly long I think, the first (Unionfs) patches 
I remember were from around 2003 - 11 years before the functionality 
was merged?

> And what complicated feature are we asking for? The ability to map a 
> human readable name to a hex code, it has the complexity of a first 
> year programming assignment.

No, what you are asking for, and which I NAK-ed, is:

 - to add a very limited 'update perf' capability which only updates a
   single issue that you care about, with no ability to do more.
   The 'perf upgrade' prototype I sent can update all or part of perf. 
   (The latest version is attached further below.)

 - to break the 'single binary' property of perf that many people rely on

 - to add JSON parsing overhead to every invocation of perf instead of
   pre-parsing the event tables at build time and putting them into 
   a nice data structure.

 - to blindly follow some poorly constructed vendor format with no 
   high level structure, that IMHO didn't work very well when OProfile 
   was written, and misrepresenting it as 'symbolic event names'.

   Take a look at:

     https://download.01.org/perfmon/HSW/Haswell_core_V17.json

   and weep. How is one supposed to see the higher level structure of
   the events with a format like that?

 - to add an ABI to support those vendor files

And those are IMHO five good technical reasons to disagree with your 
approach.

My suggestion to resolve the technical objections and lift the NAK 
would be:

 - to add the tables to the source code, in a more human readable 
   format and (optionally) structure the event names better into a 
   higher level hierarchy, than the humungous linear dumps with no 
   explanations that you propose - while still supporting the 'raw' 
   vendor event names you want to use, for those people who are used 
   to them.

 - to pre-parse the event descriptions at build time - beyond the 
   speedup this also keeps the 'single binary' property of perf.

 - to upgrade perf as a whole unit: this helps not just your usecase
   but many other usecases as well.

   For those who only want to update event tables: with
   'perf upgrade stable' basically only new event tables (backported 
   to -stable) would be picked up, plus regression fixes: it pretty 
   much does what your proposed 'perf download' solution does, except 
   it's much more capable.

Saying 'no' and suggesting better solutions is my job as a maintainer.

Thanks,

	Ingo

======={ perf-upgrade.sh }===========>

#!/bin/bash
#
# Simple script that fetches the 'perf' utility from Linus's tree, builds and
# installs it, by creating a shallow clone and a sparse checkout for Linux's
# tools/ directory and related dependencies:
#

DIR=~/.perf/git

rm -rf $DIR
mkdir -p $DIR || { echo 'error: No write permissions in the current directory?'; exit -1; }
cd $DIR

#REPO=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
#BRANCH=HEAD
REPO=git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
BRANCH=perf/core

REFERENCE="."
[ -d ~/linux/.git     ] && REFERENCE=~/linux/
[ -d ~/linux.git/.git ] && REFERENCE=~/linux.git/
[ -d ~/tip/.git       ] && REFERENCE=~/tip/
[ -d ~/tip.git/.git   ] && REFERENCE=~/tip.git/
[ -d ~/git/linux      ] && REFERENCE=~/git/linux/

git clone --reference $REFERENCE --depth 1 --bare $REPO --branch $BRANCH .git
git config --local core.bare false

git config --local core.sparseCheckout true
git remote remove origin
git remote add -f origin $REPO -t $BRANCH

(
  echo '/tools/*'
  echo '/lib/*'
  echo '/include/*'
  echo '/arch/x86/lib/*'
  echo '/arch/x86/include/*'
  echo 'Makefile'
  echo '/scripts/*'

) > .git/info/sparse-checkout

git checkout $BRANCH

make -C tools/perf/ install


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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-15  9:25           ` Ingo Molnar
  0 siblings, 0 replies; 50+ messages in thread
From: Ingo Molnar @ 2015-04-15  9:25 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linuxppc-dev, linux-kernel, Arnaldo Carvalho de Melo,
	Linus Torvalds, mingo, Borislav Petkov, namhyung,
	Thomas Gleixner, Sukadev Bhattiprolu, Jiri Olsa, Pekka Enberg


* Michael Ellerman <mpe@ellerman.id.au> wrote:

> > We just merged a patch series that was first sent in 2013. Some 
> > things take time to get right.
> 
> The first attempt to get symbolic event name support into perf was 
> sent in 2010, that's FIVE years ago [1].

kgdb took even longer, I think it was first proposed before 2000, over 
10 years before it got merged?

fs/overlayfs/ took similarly long I think, the first (Unionfs) patches 
I remember were from around 2003 - 11 years before the functionality 
was merged?

> And what complicated feature are we asking for? The ability to map a 
> human readable name to a hex code, it has the complexity of a first 
> year programming assignment.

No, what you are asking for, and which I NAK-ed, is:

 - to add a very limited 'update perf' capability which only updates a
   single issue that you care about, with no ability to do more.
   The 'perf upgrade' prototype I sent can update all or part of perf. 
   (The latest version is attached further below.)

 - to break the 'single binary' property of perf that many people rely on

 - to add JSON parsing overhead to every invocation of perf instead of
   pre-parsing the event tables at build time and putting them into 
   a nice data structure.

 - to blindly follow some poorly constructed vendor format with no 
   high level structure, that IMHO didn't work very well when OProfile 
   was written, and misrepresenting it as 'symbolic event names'.

   Take a look at:

     https://download.01.org/perfmon/HSW/Haswell_core_V17.json

   and weep. How is one supposed to see the higher level structure of
   the events with a format like that?

 - to add an ABI to support those vendor files

And those are IMHO five good technical reasons to disagree with your 
approach.

My suggestion to resolve the technical objections and lift the NAK 
would be:

 - to add the tables to the source code, in a more human readable 
   format and (optionally) structure the event names better into a 
   higher level hierarchy, than the humungous linear dumps with no 
   explanations that you propose - while still supporting the 'raw' 
   vendor event names you want to use, for those people who are used 
   to them.

 - to pre-parse the event descriptions at build time - beyond the 
   speedup this also keeps the 'single binary' property of perf.

 - to upgrade perf as a whole unit: this helps not just your usecase
   but many other usecases as well.

   For those who only want to update event tables: with
   'perf upgrade stable' basically only new event tables (backported 
   to -stable) would be picked up, plus regression fixes: it pretty 
   much does what your proposed 'perf download' solution does, except 
   it's much more capable.

Saying 'no' and suggesting better solutions is my job as a maintainer.

Thanks,

	Ingo

======={ perf-upgrade.sh }===========>

#!/bin/bash
#
# Simple script that fetches the 'perf' utility from Linus's tree, builds and
# installs it, by creating a shallow clone and a sparse checkout for Linux's
# tools/ directory and related dependencies:
#

DIR=~/.perf/git

rm -rf $DIR
mkdir -p $DIR || { echo 'error: No write permissions in the current directory?'; exit -1; }
cd $DIR

#REPO=git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
#BRANCH=HEAD
REPO=git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git
BRANCH=perf/core

REFERENCE="."
[ -d ~/linux/.git     ] && REFERENCE=~/linux/
[ -d ~/linux.git/.git ] && REFERENCE=~/linux.git/
[ -d ~/tip/.git       ] && REFERENCE=~/tip/
[ -d ~/tip.git/.git   ] && REFERENCE=~/tip.git/
[ -d ~/git/linux      ] && REFERENCE=~/git/linux/

git clone --reference $REFERENCE --depth 1 --bare $REPO --branch $BRANCH .git
git config --local core.bare false

git config --local core.sparseCheckout true
git remote remove origin
git remote add -f origin $REPO -t $BRANCH

(
  echo '/tools/*'
  echo '/lib/*'
  echo '/include/*'
  echo '/arch/x86/lib/*'
  echo '/arch/x86/include/*'
  echo 'Makefile'
  echo '/scripts/*'

) > .git/info/sparse-checkout

git checkout $BRANCH

make -C tools/perf/ install

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-15  9:25           ` Ingo Molnar
@ 2015-04-15 19:17             ` Andi Kleen
  -1 siblings, 0 replies; 50+ messages in thread
From: Andi Kleen @ 2015-04-15 19:17 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Michael Ellerman, Sukadev Bhattiprolu, mingo, Jiri Olsa,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds, Borislav Petkov

> My suggestion to resolve the technical objections and lift the NAK 
> would be:
> 
>  - to add the tables to the source code, in a more human readable 
>    format and (optionally) structure the event names better into a 
>    higher level hierarchy, than the humungous linear dumps with no 
>    explanations that you propose - while still supporting the 'raw' 
>    vendor event names you want to use, for those people who are used 
>    to them.

Trying to understand what you mean with high level hierarchy:

Do you mean something like the oprofile event / unit mask split,
with events having a default unit mask?

This one actually works poorly for modern Intel systems, as
unit masks can completely change the behavior, so there is 
not necessarily a direct relation between the name before the dot and the one
after, or a concept of a "default" unit mask.

Or do you mean someone creating a tree hierarchy of events to systematically
debug some particular problem?

I implemented this in my toplev tool here:
https://github.com/andikleen/pmu-tools/wiki/toplev-manual
http://github.com/andikleen/pmu-tools

But it's quite complicated and cannot really be done portable in
a full way without completely turning perf into an architecture specific
tool (which I assume you're opposed to)

Or just some sections grouping events into different topics?
"branches", "caches", "execution" or somesuch.

I think this could be done with the JSON format. Just add a new header.
Print them as sections in perf list.

Or do you mean something like the perf cache events tables?
We already have those. But they cannot replace direct micro architectural
specific events, as the cache event tables do not necessarily express
everything a given micro architecture supports. And also there is a lot
of documentation using the vendor event names, which the users
then want to use.

If it's something else please explain.

> 
>  - to pre-parse the event descriptions at build time - beyond the 
>    speedup 

FWIW I just measured it and the overhead parse time for the haswell JSON file on
my laptop is about 33ms. 

# with event map
% time ./obj-perf/perf list > /dev/null
real    0m0.045s
user    0m0.041s
sys     0m0.003s

% export EVENTMAP=/dev/zero
% time perf list > /dev/null

real    0m0.011s
user    0m0.004s
sys     0m0.006s


>  - to upgrade perf as a whole unit: this helps not just your usecase
>    but many other usecases as well.

With the downloader it actually automatically downloads any missing
files, so the upgrading just works.

-Andi

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-15 19:17             ` Andi Kleen
  0 siblings, 0 replies; 50+ messages in thread
From: Andi Kleen @ 2015-04-15 19:17 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, peterz, linuxppc-dev,
	Arnaldo Carvalho de Melo, linux-kernel, Linus Torvalds, mingo,
	Borislav Petkov, namhyung, Thomas Gleixner, Sukadev Bhattiprolu,
	Jiri Olsa, Pekka Enberg

> My suggestion to resolve the technical objections and lift the NAK 
> would be:
> 
>  - to add the tables to the source code, in a more human readable 
>    format and (optionally) structure the event names better into a 
>    higher level hierarchy, than the humungous linear dumps with no 
>    explanations that you propose - while still supporting the 'raw' 
>    vendor event names you want to use, for those people who are used 
>    to them.

Trying to understand what you mean with high level hierarchy:

Do you mean something like the oprofile event / unit mask split,
with events having a default unit mask?

This one actually works poorly for modern Intel systems, as
unit masks can completely change the behavior, so there is 
not necessarily a direct relation between the name before the dot and the one
after, or a concept of a "default" unit mask.

Or do you mean someone creating a tree hierarchy of events to systematically
debug some particular problem?

I implemented this in my toplev tool here:
https://github.com/andikleen/pmu-tools/wiki/toplev-manual
http://github.com/andikleen/pmu-tools

But it's quite complicated and cannot really be done portable in
a full way without completely turning perf into an architecture specific
tool (which I assume you're opposed to)

Or just some sections grouping events into different topics?
"branches", "caches", "execution" or somesuch.

I think this could be done with the JSON format. Just add a new header.
Print them as sections in perf list.

Or do you mean something like the perf cache events tables?
We already have those. But they cannot replace direct micro architectural
specific events, as the cache event tables do not necessarily express
everything a given micro architecture supports. And also there is a lot
of documentation using the vendor event names, which the users
then want to use.

If it's something else please explain.

> 
>  - to pre-parse the event descriptions at build time - beyond the 
>    speedup 

FWIW I just measured it and the overhead parse time for the haswell JSON file on
my laptop is about 33ms. 

# with event map
% time ./obj-perf/perf list > /dev/null
real    0m0.045s
user    0m0.041s
sys     0m0.003s

% export EVENTMAP=/dev/zero
% time perf list > /dev/null

real    0m0.011s
user    0m0.004s
sys     0m0.006s


>  - to upgrade perf as a whole unit: this helps not just your usecase
>    but many other usecases as well.

With the downloader it actually automatically downloads any missing
files, so the upgrading just works.

-Andi

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-15  9:25           ` Ingo Molnar
@ 2015-04-15 20:50             ` Sukadev Bhattiprolu
  -1 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-15 20:50 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Michael Ellerman, mingo, ak, Jiri Olsa, Arnaldo Carvalho de Melo,
	peterz, namhyung, linuxppc-dev, linux-kernel, Pekka Enberg,
	Arnaldo Carvalho de Melo, Peter Zijlstra, Thomas Gleixner,
	Linus Torvalds, Borislav Petkov

| 
| * Michael Ellerman <mpe@ellerman.id.au> wrote:
| 
| > > We just merged a patch series that was first sent in 2013. Some 
| > > things take time to get right.
| > 
| > The first attempt to get symbolic event name support into perf was 
| > sent in 2010, that's FIVE years ago [1].
| 
| kgdb took even longer, I think it was first proposed before 2000, over 
| 10 years before it got merged?
| 
| fs/overlayfs/ took similarly long I think, the first (Unionfs) patches 
| I remember were from around 2003 - 11 years before the functionality 
| was merged?
| 
| > And what complicated feature are we asking for? The ability to map a 
| > human readable name to a hex code, it has the complexity of a first 
| > year programming assignment.
| 
| No, what you are asking for, and which I NAK-ed, is:
| 
|  - to add a very limited 'update perf' capability which only updates a
|    single issue that you care about, with no ability to do more.

Yes, we are trying to solve one really annoying problem without precluding
the ability to do more (aka leave things better than they are even if we
can't solve everything).

Besides, I thought the discussion was where to host the JSON files.
I was not aware of the requirement to download/rebuild perf or not use
JSON at all (i.e generate data structures during build?).


|    The 'perf upgrade' prototype I sent can update all or part of perf. 
|    (The latest version is attached further below.)
| 
|  - to break the 'single binary' property of perf that many people rely on

Thats the part, I am having trouble with.

If the JSON files are like /etc/perfconfig, we don't need to rebuild the
binary when a config file changes right?

Second, if I build perf on my Power8 box, would the perf binary only include
events on my specific revision of the CPU or all Power8 versions?  Would the
perf binary from Power8 include events from all revisions of Power7 and
Power8?

If we include all possible revisions of the CPU, we would bloat perf.

If not we break the ability/convenience of copying rpms from one system
to the other? And we need to rebuild perf if the CPU on my system is
replaced and there are a couple of new event codes in the new CPU?


| 
|  - to add JSON parsing overhead to every invocation of perf instead of
|    pre-parsing the event tables at build time and putting them into 
|    a nice data structure.
| 
|  - to blindly follow some poorly constructed vendor format with no 
|    high level structure, that IMHO didn't work very well when OProfile 
|    was written, and misrepresenting it as 'symbolic event names'.
| 
|    Take a look at:
| 
|      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
| 
|    and weep.

Evil vendor formats, but to be fair, here is what _we_ have today:

	perf stat -e r10068,r20036,r40060,r40ac sleep 1

	 Performance counter stats for 'sleep 1':

		   554,608      r10068                                                      
		    47,948      r20036                                                      
		   491,084      r40060                                                      
		       249      r40ac                                                       

	       1.001561257 seconds time elapsed

| How is one supposed to see the higher level structure of
|    the events with a format like that?

True, having events like 'cycles', 'branches' makes sense, but there
are so many different flavors of "run cycles" events in just Power8.

    PM_ANY_THRD_RUN_CYC,
    PM_MRK_RUN_CYC,
    PM_RUN_CYC,
    PM_RUN_CYC_SMT2_MODE,
    PM_RUN_CYC_SMT2_SHRD_MODE,
    PM_RUN_CYC_SMT2_SPLIT_MODE,
    PM_RUN_CYC_SMT4_MODE,
    PM_RUN_CYC_SMT8_MODE,
    PM_RUN_CYC_ST_MODE,
    PM_THRD_ALL_RUN_CYC,
    PM_TM_TRANS_RUN_CYC,
    PM_TM_TX_PASS_RUN_CYC,

Are we trying to build a high level structures across architectures?

| 
|  - to add an ABI to support those vendor files
| 
| And those are IMHO five good technical reasons to disagree with your 
| approach.
| 
| My suggestion to resolve the technical objections and lift the NAK 
| would be:
| 
|  - to add the tables to the source code, in a more human readable 
|    format and (optionally) structure the event names better into a 
|    higher level hierarchy, than the humungous linear dumps with no 
|    explanations that you propose - while still supporting the 'raw' 
|    vendor event names you want to use, for those people who are used 
|    to them.
| 

A bit confused.

Have the JSON files in the tree and generate the C structure during
build?

Or, ditch the JSON files and add something like this in say,
tools/perf/arch/powerpc/util/power8-events.h?

static const  struct events power8_events[] = {
    [ 0 ] = {
        .name = "PM_1LPAR_CYC",
        .code = 0x1f05e,
        .brief_desc = " "Number of cycles in single lpar mode. All threads in the core are assigned to the same lpar,",
        .public_desc = "Number of cycles in single lpar mode.,",
      },

If we have the JSON files, would the 'make install' put the JSON files
in ~/.cache/pmu-events or in a standard location?

|  - to pre-parse the event descriptions at build time - beyond the 
|    speedup this also keeps the 'single binary' property of perf.
| 
|  - to upgrade perf as a whole unit: this helps not just your usecase
|    but many other usecases as well.

I will try the perf upgrade below,  but the only clear use case I have
is for the event files. I am a little confused about the use case for
downloading and rebuilding perf. 

Building perf requires more packages than simply running perf. Most
users just run perf without needing to rebuild.

Running perf doesn't require root access but if we want to install
JSON files in standard locations (to get latest event codes for
instance) we will need root access.

Or should ~/.cache/pmu-events/*.json complement the event codes builtin
to the perf binary?

Sukadev


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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-15 20:50             ` Sukadev Bhattiprolu
  0 siblings, 0 replies; 50+ messages in thread
From: Sukadev Bhattiprolu @ 2015-04-15 20:50 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linuxppc-dev, Arnaldo Carvalho de Melo, linux-kernel,
	Linus Torvalds, mingo, Borislav Petkov, namhyung,
	Thomas Gleixner, Jiri Olsa, Pekka Enberg

| 
| * Michael Ellerman <mpe@ellerman.id.au> wrote:
| 
| > > We just merged a patch series that was first sent in 2013. Some 
| > > things take time to get right.
| > 
| > The first attempt to get symbolic event name support into perf was 
| > sent in 2010, that's FIVE years ago [1].
| 
| kgdb took even longer, I think it was first proposed before 2000, over 
| 10 years before it got merged?
| 
| fs/overlayfs/ took similarly long I think, the first (Unionfs) patches 
| I remember were from around 2003 - 11 years before the functionality 
| was merged?
| 
| > And what complicated feature are we asking for? The ability to map a 
| > human readable name to a hex code, it has the complexity of a first 
| > year programming assignment.
| 
| No, what you are asking for, and which I NAK-ed, is:
| 
|  - to add a very limited 'update perf' capability which only updates a
|    single issue that you care about, with no ability to do more.

Yes, we are trying to solve one really annoying problem without precluding
the ability to do more (aka leave things better than they are even if we
can't solve everything).

Besides, I thought the discussion was where to host the JSON files.
I was not aware of the requirement to download/rebuild perf or not use
JSON at all (i.e generate data structures during build?).


|    The 'perf upgrade' prototype I sent can update all or part of perf. 
|    (The latest version is attached further below.)
| 
|  - to break the 'single binary' property of perf that many people rely on

Thats the part, I am having trouble with.

If the JSON files are like /etc/perfconfig, we don't need to rebuild the
binary when a config file changes right?

Second, if I build perf on my Power8 box, would the perf binary only include
events on my specific revision of the CPU or all Power8 versions?  Would the
perf binary from Power8 include events from all revisions of Power7 and
Power8?

If we include all possible revisions of the CPU, we would bloat perf.

If not we break the ability/convenience of copying rpms from one system
to the other? And we need to rebuild perf if the CPU on my system is
replaced and there are a couple of new event codes in the new CPU?


| 
|  - to add JSON parsing overhead to every invocation of perf instead of
|    pre-parsing the event tables at build time and putting them into 
|    a nice data structure.
| 
|  - to blindly follow some poorly constructed vendor format with no 
|    high level structure, that IMHO didn't work very well when OProfile 
|    was written, and misrepresenting it as 'symbolic event names'.
| 
|    Take a look at:
| 
|      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
| 
|    and weep.

Evil vendor formats, but to be fair, here is what _we_ have today:

	perf stat -e r10068,r20036,r40060,r40ac sleep 1

	 Performance counter stats for 'sleep 1':

		   554,608      r10068                                                      
		    47,948      r20036                                                      
		   491,084      r40060                                                      
		       249      r40ac                                                       

	       1.001561257 seconds time elapsed

| How is one supposed to see the higher level structure of
|    the events with a format like that?

True, having events like 'cycles', 'branches' makes sense, but there
are so many different flavors of "run cycles" events in just Power8.

    PM_ANY_THRD_RUN_CYC,
    PM_MRK_RUN_CYC,
    PM_RUN_CYC,
    PM_RUN_CYC_SMT2_MODE,
    PM_RUN_CYC_SMT2_SHRD_MODE,
    PM_RUN_CYC_SMT2_SPLIT_MODE,
    PM_RUN_CYC_SMT4_MODE,
    PM_RUN_CYC_SMT8_MODE,
    PM_RUN_CYC_ST_MODE,
    PM_THRD_ALL_RUN_CYC,
    PM_TM_TRANS_RUN_CYC,
    PM_TM_TX_PASS_RUN_CYC,

Are we trying to build a high level structures across architectures?

| 
|  - to add an ABI to support those vendor files
| 
| And those are IMHO five good technical reasons to disagree with your 
| approach.
| 
| My suggestion to resolve the technical objections and lift the NAK 
| would be:
| 
|  - to add the tables to the source code, in a more human readable 
|    format and (optionally) structure the event names better into a 
|    higher level hierarchy, than the humungous linear dumps with no 
|    explanations that you propose - while still supporting the 'raw' 
|    vendor event names you want to use, for those people who are used 
|    to them.
| 

A bit confused.

Have the JSON files in the tree and generate the C structure during
build?

Or, ditch the JSON files and add something like this in say,
tools/perf/arch/powerpc/util/power8-events.h?

static const  struct events power8_events[] = {
    [ 0 ] = {
        .name = "PM_1LPAR_CYC",
        .code = 0x1f05e,
        .brief_desc = " "Number of cycles in single lpar mode. All threads in the core are assigned to the same lpar,",
        .public_desc = "Number of cycles in single lpar mode.,",
      },

If we have the JSON files, would the 'make install' put the JSON files
in ~/.cache/pmu-events or in a standard location?

|  - to pre-parse the event descriptions at build time - beyond the 
|    speedup this also keeps the 'single binary' property of perf.
| 
|  - to upgrade perf as a whole unit: this helps not just your usecase
|    but many other usecases as well.

I will try the perf upgrade below,  but the only clear use case I have
is for the event files. I am a little confused about the use case for
downloading and rebuilding perf. 

Building perf requires more packages than simply running perf. Most
users just run perf without needing to rebuild.

Running perf doesn't require root access but if we want to install
JSON files in standard locations (to get latest event codes for
instance) we will need root access.

Or should ~/.cache/pmu-events/*.json complement the event codes builtin
to the perf binary?

Sukadev

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-15 20:50             ` Sukadev Bhattiprolu
@ 2015-04-17 15:31               ` Jiri Olsa
  -1 siblings, 0 replies; 50+ messages in thread
From: Jiri Olsa @ 2015-04-17 15:31 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: Ingo Molnar, Michael Ellerman, mingo, ak,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds, Borislav Petkov

On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:

SNIP

> | 
> |  - to blindly follow some poorly constructed vendor format with no 
> |    high level structure, that IMHO didn't work very well when OProfile 
> |    was written, and misrepresenting it as 'symbolic event names'.
> | 
> |    Take a look at:
> | 
> |      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
> | 
> |    and weep.
> 
> Evil vendor formats, but to be fair, here is what _we_ have today:
> 
> 	perf stat -e r10068,r20036,r40060,r40ac sleep 1

hum, you could also use the 'cpu/event=.../' syntax right?
It's not symbolic name, just to be fair ;-)

jirka

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-17 15:31               ` Jiri Olsa
  0 siblings, 0 replies; 50+ messages in thread
From: Jiri Olsa @ 2015-04-17 15:31 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linux-kernel, Arnaldo Carvalho de Melo, Pekka Enberg,
	Linus Torvalds, mingo, Borislav Petkov, namhyung,
	Thomas Gleixner, linuxppc-dev, Ingo Molnar

On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:

SNIP

> | 
> |  - to blindly follow some poorly constructed vendor format with no 
> |    high level structure, that IMHO didn't work very well when OProfile 
> |    was written, and misrepresenting it as 'symbolic event names'.
> | 
> |    Take a look at:
> | 
> |      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
> | 
> |    and weep.
> 
> Evil vendor formats, but to be fair, here is what _we_ have today:
> 
> 	perf stat -e r10068,r20036,r40060,r40ac sleep 1

hum, you could also use the 'cpu/event=.../' syntax right?
It's not symbolic name, just to be fair ;-)

jirka

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-17 15:31               ` Jiri Olsa
@ 2015-04-17 20:09                 ` Andi Kleen
  -1 siblings, 0 replies; 50+ messages in thread
From: Andi Kleen @ 2015-04-17 20:09 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Sukadev Bhattiprolu, Ingo Molnar, Michael Ellerman, mingo,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds, Borislav Petkov

On Fri, Apr 17, 2015 at 05:31:26PM +0200, Jiri Olsa wrote:
> On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:
> 
> SNIP
> 
> > | 
> > |  - to blindly follow some poorly constructed vendor format with no 
> > |    high level structure, that IMHO didn't work very well when OProfile 
> > |    was written, and misrepresenting it as 'symbolic event names'.
> > | 
> > |    Take a look at:
> > | 
> > |      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
> > | 
> > |    and weep.
> > 
> > Evil vendor formats, but to be fair, here is what _we_ have today:
> > 
> > 	perf stat -e r10068,r20036,r40060,r40ac sleep 1
> 
> hum, you could also use the 'cpu/event=.../' syntax right?

That's even worse -- same hex numbers, just more redundancy.

All the other profilers support symbolic names, which is what
users want.

-Andi

-- 
ak@linux.intel.com -- Speaking for myself only

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-17 20:09                 ` Andi Kleen
  0 siblings, 0 replies; 50+ messages in thread
From: Andi Kleen @ 2015-04-17 20:09 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, peterz, linux-kernel,
	Arnaldo Carvalho de Melo, Pekka Enberg, Linus Torvalds, mingo,
	Borislav Petkov, namhyung, Thomas Gleixner, Sukadev Bhattiprolu,
	linuxppc-dev, Ingo Molnar

On Fri, Apr 17, 2015 at 05:31:26PM +0200, Jiri Olsa wrote:
> On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:
> 
> SNIP
> 
> > | 
> > |  - to blindly follow some poorly constructed vendor format with no 
> > |    high level structure, that IMHO didn't work very well when OProfile 
> > |    was written, and misrepresenting it as 'symbolic event names'.
> > | 
> > |    Take a look at:
> > | 
> > |      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
> > | 
> > |    and weep.
> > 
> > Evil vendor formats, but to be fair, here is what _we_ have today:
> > 
> > 	perf stat -e r10068,r20036,r40060,r40ac sleep 1
> 
> hum, you could also use the 'cpu/event=.../' syntax right?

That's even worse -- same hex numbers, just more redundancy.

All the other profilers support symbolic names, which is what
users want.

-Andi

-- 
ak@linux.intel.com -- Speaking for myself only

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-17 20:09                 ` Andi Kleen
@ 2015-04-18 13:05                   ` Jiri Olsa
  -1 siblings, 0 replies; 50+ messages in thread
From: Jiri Olsa @ 2015-04-18 13:05 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Sukadev Bhattiprolu, Ingo Molnar, Michael Ellerman, mingo,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds, Borislav Petkov

On Fri, Apr 17, 2015 at 01:09:54PM -0700, Andi Kleen wrote:
> On Fri, Apr 17, 2015 at 05:31:26PM +0200, Jiri Olsa wrote:
> > On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:
> > 
> > SNIP
> > 
> > > | 
> > > |  - to blindly follow some poorly constructed vendor format with no 
> > > |    high level structure, that IMHO didn't work very well when OProfile 
> > > |    was written, and misrepresenting it as 'symbolic event names'.
> > > | 
> > > |    Take a look at:
> > > | 
> > > |      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
> > > | 
> > > |    and weep.
> > > 
> > > Evil vendor formats, but to be fair, here is what _we_ have today:
> > > 
> > > 	perf stat -e r10068,r20036,r40060,r40ac sleep 1
> > 
> > hum, you could also use the 'cpu/event=.../' syntax right?
> 
> That's even worse -- same hex numbers, just more redundancy.

no, it's far more readable then the rXXXX format,
you can just put in whatevent is in the spec..
event,umask,any etc and dont bother with making
rXXXX value

but I mentioned it just to give the whole picture,
I agree that we need the symbolic names support

jirka

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-18 13:05                   ` Jiri Olsa
  0 siblings, 0 replies; 50+ messages in thread
From: Jiri Olsa @ 2015-04-18 13:05 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Arnaldo Carvalho de Melo, Peter Zijlstra, peterz, linux-kernel,
	Arnaldo Carvalho de Melo, Pekka Enberg, Linus Torvalds, mingo,
	Borislav Petkov, namhyung, Thomas Gleixner, Sukadev Bhattiprolu,
	linuxppc-dev, Ingo Molnar

On Fri, Apr 17, 2015 at 01:09:54PM -0700, Andi Kleen wrote:
> On Fri, Apr 17, 2015 at 05:31:26PM +0200, Jiri Olsa wrote:
> > On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:
> > 
> > SNIP
> > 
> > > | 
> > > |  - to blindly follow some poorly constructed vendor format with no 
> > > |    high level structure, that IMHO didn't work very well when OProfile 
> > > |    was written, and misrepresenting it as 'symbolic event names'.
> > > | 
> > > |    Take a look at:
> > > | 
> > > |      https://download.01.org/perfmon/HSW/Haswell_core_V17.json
> > > | 
> > > |    and weep.
> > > 
> > > Evil vendor formats, but to be fair, here is what _we_ have today:
> > > 
> > > 	perf stat -e r10068,r20036,r40060,r40ac sleep 1
> > 
> > hum, you could also use the 'cpu/event=.../' syntax right?
> 
> That's even worse -- same hex numbers, just more redundancy.

no, it's far more readable then the rXXXX format,
you can just put in whatevent is in the spec..
event,umask,any etc and dont bother with making
rXXXX value

but I mentioned it just to give the whole picture,
I agree that we need the symbolic names support

jirka

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
  2015-04-15 20:50             ` Sukadev Bhattiprolu
@ 2015-04-18 13:12               ` Jiri Olsa
  -1 siblings, 0 replies; 50+ messages in thread
From: Jiri Olsa @ 2015-04-18 13:12 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: Ingo Molnar, Michael Ellerman, mingo, ak,
	Arnaldo Carvalho de Melo, peterz, namhyung, linuxppc-dev,
	linux-kernel, Pekka Enberg, Arnaldo Carvalho de Melo,
	Peter Zijlstra, Thomas Gleixner, Linus Torvalds, Borislav Petkov

On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:

SNIP

> 
> | 
> |  - to add an ABI to support those vendor files
> | 
> | And those are IMHO five good technical reasons to disagree with your 
> | approach.
> | 
> | My suggestion to resolve the technical objections and lift the NAK 
> | would be:
> | 
> |  - to add the tables to the source code, in a more human readable 
> |    format and (optionally) structure the event names better into a 
> |    higher level hierarchy, than the humungous linear dumps with no 
> |    explanations that you propose - while still supporting the 'raw' 
> |    vendor event names you want to use, for those people who are used 
> |    to them.
> | 
> 
> A bit confused.
> 
> Have the JSON files in the tree and generate the C structure during
> build?
> 
> Or, ditch the JSON files and add something like this in say,
> tools/perf/arch/powerpc/util/power8-events.h?
> 
> static const  struct events power8_events[] = {
>     [ 0 ] = {
>         .name = "PM_1LPAR_CYC",
>         .code = 0x1f05e,
>         .brief_desc = " "Number of cycles in single lpar mode. All threads in the core are assigned to the same lpar,",
>         .public_desc = "Number of cycles in single lpar mode.,",
>       },
> 
> If we have the JSON files, would the 'make install' put the JSON files
> in ~/.cache/pmu-events or in a standard location?

IIUC the intention is not to have external event data files
but have them compiled into perf binary.. like we could have
JSON with events description under perf source and build it
into 'struct perf_pmu_alias' data duting the build..

the pmu.c alias logic would need a little adjustments,
but it seems doable to me

jirka

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

* Re: 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.)
@ 2015-04-18 13:12               ` Jiri Olsa
  0 siblings, 0 replies; 50+ messages in thread
From: Jiri Olsa @ 2015-04-18 13:12 UTC (permalink / raw)
  To: Sukadev Bhattiprolu
  Cc: Arnaldo Carvalho de Melo, ak, Peter Zijlstra, peterz,
	linux-kernel, Arnaldo Carvalho de Melo, Pekka Enberg,
	Linus Torvalds, mingo, Borislav Petkov, namhyung,
	Thomas Gleixner, linuxppc-dev, Ingo Molnar

On Wed, Apr 15, 2015 at 01:50:42PM -0700, Sukadev Bhattiprolu wrote:

SNIP

> 
> | 
> |  - to add an ABI to support those vendor files
> | 
> | And those are IMHO five good technical reasons to disagree with your 
> | approach.
> | 
> | My suggestion to resolve the technical objections and lift the NAK 
> | would be:
> | 
> |  - to add the tables to the source code, in a more human readable 
> |    format and (optionally) structure the event names better into a 
> |    higher level hierarchy, than the humungous linear dumps with no 
> |    explanations that you propose - while still supporting the 'raw' 
> |    vendor event names you want to use, for those people who are used 
> |    to them.
> | 
> 
> A bit confused.
> 
> Have the JSON files in the tree and generate the C structure during
> build?
> 
> Or, ditch the JSON files and add something like this in say,
> tools/perf/arch/powerpc/util/power8-events.h?
> 
> static const  struct events power8_events[] = {
>     [ 0 ] = {
>         .name = "PM_1LPAR_CYC",
>         .code = 0x1f05e,
>         .brief_desc = " "Number of cycles in single lpar mode. All threads in the core are assigned to the same lpar,",
>         .public_desc = "Number of cycles in single lpar mode.,",
>       },
> 
> If we have the JSON files, would the 'make install' put the JSON files
> in ~/.cache/pmu-events or in a standard location?

IIUC the intention is not to have external event data files
but have them compiled into perf binary.. like we could have
JSON with events description under perf source and build it
into 'struct perf_pmu_alias' data duting the build..

the pmu.c alias logic would need a little adjustments,
but it seems doable to me

jirka

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

end of thread, other threads:[~2015-04-18 13:13 UTC | newest]

Thread overview: 50+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-04-14  6:40 [PATCH v9 00/11] Add support for JSON event files Sukadev Bhattiprolu
2015-04-14  6:40 ` Sukadev Bhattiprolu
2015-04-14  6:40 ` [PATCH v9 01/11] perf, tools: Add jsmn `jasmine' JSON parser Sukadev Bhattiprolu
2015-04-14  6:40   ` Sukadev Bhattiprolu
2015-04-14  6:40 ` [PATCH v9 02/11] perf, tools: Add support for text descriptions of events and alias add Sukadev Bhattiprolu
2015-04-14  6:40   ` Sukadev Bhattiprolu
2015-04-14  6:40 ` [PATCH v9 03/11] perf, tools, list: Update perf list to output descriptions Sukadev Bhattiprolu
2015-04-14  6:40   ` Sukadev Bhattiprolu
2015-04-14  6:40 ` [PATCH v9 04/11] perf, tools: Add support for reading JSON event files Sukadev Bhattiprolu
2015-04-14  6:40   ` Sukadev Bhattiprolu
2015-04-14  6:40 ` [PATCH v9 05/11] perf, tools: Automatically look for event file name for cpu Sukadev Bhattiprolu
2015-04-14  6:40   ` Sukadev Bhattiprolu
2015-04-14  6:40 ` [PATCH v9 06/11] powerpc/perf: Implement get_cpu_str() Sukadev Bhattiprolu
2015-04-14  6:40   ` Sukadev Bhattiprolu
2015-04-14  6:41 ` [PATCH v9 07/11] perf, tools: Query terminal width and use in perf list Sukadev Bhattiprolu
2015-04-14  6:41   ` Sukadev Bhattiprolu
2015-04-14  6:41 ` [PATCH v9 08/11] perf, tools: Add a new pmu interface to iterate over all events Sukadev Bhattiprolu
2015-04-14  6:41   ` Sukadev Bhattiprolu
2015-04-14  6:41 ` [PATCH v9 09/11] perf, tools, test: Add test case for alias and JSON parsing Sukadev Bhattiprolu
2015-04-14  6:41   ` Sukadev Bhattiprolu
2015-04-14  6:41 ` [PATCH v9 10/11] perf, tools: Add a --no-desc flag to perf list Sukadev Bhattiprolu
2015-04-14  6:41   ` Sukadev Bhattiprolu
2015-04-14  6:41 ` [PATCH v9 11/11] perf-download: Download the events json file Sukadev Bhattiprolu
2015-04-14  6:41   ` Sukadev Bhattiprolu
2015-04-14  8:55 ` 'perf upgrade' (was: Re: [PATCH v9 00/11] Add support for JSON event files.) Ingo Molnar
2015-04-14  8:55   ` Ingo Molnar
2015-04-14 11:21   ` Michael Ellerman
2015-04-14 11:21     ` Michael Ellerman
2015-04-14 12:58     ` Ingo Molnar
2015-04-14 12:58       ` Ingo Molnar
2015-04-14 18:03       ` Sukadev Bhattiprolu
2015-04-14 18:03         ` Sukadev Bhattiprolu
2015-04-14 22:53       ` Michael Ellerman
2015-04-14 22:53         ` Michael Ellerman
2015-04-15  9:25         ` Ingo Molnar
2015-04-15  9:25           ` Ingo Molnar
2015-04-15 19:17           ` Andi Kleen
2015-04-15 19:17             ` Andi Kleen
2015-04-15 20:50           ` Sukadev Bhattiprolu
2015-04-15 20:50             ` Sukadev Bhattiprolu
2015-04-17 15:31             ` Jiri Olsa
2015-04-17 15:31               ` Jiri Olsa
2015-04-17 20:09               ` Andi Kleen
2015-04-17 20:09                 ` Andi Kleen
2015-04-18 13:05                 ` Jiri Olsa
2015-04-18 13:05                   ` Jiri Olsa
2015-04-18 13:12             ` Jiri Olsa
2015-04-18 13:12               ` Jiri Olsa
2015-04-14 20:16   ` Andi Kleen
2015-04-14 20:16     ` Andi Kleen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.