All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/16] perf tools: Add support for using symbols in address filters
@ 2016-09-23 14:38 Adrian Hunter
  2016-09-23 14:38 ` [PATCH 01/16] perf record: Fix documentation 'event_sources' -> 'event_source' Adrian Hunter
                   ` (15 more replies)
  0 siblings, 16 replies; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Hi

Here are some patches that add support for using symbols in address
filters.  There are also some fixes for other things that I came across
during testing.

Finally there are patches for Intel PT, mainly to fix an issue with address
filters, but also these two:
      perf intel-pt: Fix snapshot overlap detection decoder errors
      perf intel-pt: Add support for recording the max non-turbo ratio

The patches are on top of Mathieu's patches:
	perf tools: adding support for address filters
	perf tools: new tracepoint specific function
	perf tools: making perf_evsel__append_filter() generic


Adrian Hunter (16):
      perf record: Fix documentation 'event_sources' -> 'event_source'
      perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change
      perf script: Fix vanished idle symbols
      perf record: Rename label 'out_symbol_exit'
      perf record: Fix error paths
      perf symbols: Add dso__last_symbol()
      perf record: Add support for using symbols in address filters
      perf tools: Increase debug level of SDT debug messages
      perf intel-pt: Fix snapshot overlap detection decoder errors
      perf intel-pt: Add support for recording the max non-turbo ratio
      perf intel-pt: Fix missing error codes processing auxtrace_info
      perf intel-pt: Add a helper function for processing AUXTRACE_INFO
      perf intel-pt: Record address filter in AUXTRACE_INFO event
      perf intel-pt: Read address filter from AUXTRACE_INFO event
      perf intel-pt: Enable decoder to handle TIP.PGD with missing IP
      perf intel-pt: Fix decoding when there are address filters

 tools/perf/Documentation/perf-record.txt           |  61 +-
 tools/perf/arch/x86/util/intel-pt.c                |  57 +-
 tools/perf/builtin-record.c                        |  32 +-
 tools/perf/util/auxtrace.c                         | 737 +++++++++++++++++++++
 tools/perf/util/auxtrace.h                         |  54 ++
 tools/perf/util/build-id.c                         |   4 +-
 tools/perf/util/event.c                            |   3 +-
 tools/perf/util/evsel_fprintf.c                    |   7 +-
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  |  30 +
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  |   1 +
 tools/perf/util/intel-pt.c                         | 172 ++++-
 tools/perf/util/intel-pt.h                         |   4 +-
 tools/perf/util/probe-file.c                       |   2 +-
 tools/perf/util/symbol.c                           |  15 +
 tools/perf/util/symbol.h                           |   1 +
 15 files changed, 1143 insertions(+), 37 deletions(-)


Regards
Adrian

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

* [PATCH 01/16] perf record: Fix documentation 'event_sources' -> 'event_source'
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:10   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 02/16] perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change Adrian Hunter
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Change '/sys/bus/event_sources' to the correct path which is
'/sys/bus/event_source'.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/Documentation/perf-record.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 1a24f4d64328..babbb63e6d9d 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -35,15 +35,15 @@ OPTIONS
 
 	- a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
 	  'param1', 'param2', etc are defined as formats for the PMU in
-	  /sys/bus/event_sources/devices/<pmu>/format/*.
+	  /sys/bus/event_source/devices/<pmu>/format/*.
 
 	- a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
 
           where M, N, K are numbers (in decimal, hex, octal format). Acceptable
           values for each of 'config', 'config1' and 'config2' are defined by
-          corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/*
+          corresponding entries in /sys/bus/event_source/devices/<pmu>/format/*
           param1 and param2 are defined as formats for the PMU in:
-          /sys/bus/event_sources/devices/<pmu>/format/*
+          /sys/bus/event_source/devices/<pmu>/format/*
 
 	  There are also some params which are not defined in .../<pmu>/format/*.
 	  These params can be used to overload default config values per event.
-- 
1.9.1

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

* [PATCH 02/16] perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
  2016-09-23 14:38 ` [PATCH 01/16] perf record: Fix documentation 'event_sources' -> 'event_source' Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:10   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 03/16] perf script: Fix vanished idle symbols Adrian Hunter
                   ` (13 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Patch "perf record: Mark MAP_HUGETLB when synthesizing mmap events") breaks
MMAP event synthesis.  The executable name comparison will match any name
if the length is zero, resulting in all the user space maps becoming
anonymous.  This is particularly noticeable with system-wide traces.
Example:

	perf record -a sleep 1
	perf script --show-mmap-events

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/event.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2880e2226fdb..8ab0d7da956b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -346,7 +346,8 @@ out:
 		if (!strcmp(execname, ""))
 			strcpy(execname, anonstr);
 
-		if (!strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
+		if (hugetlbfs_mnt_len &&
+		    !strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
 			strcpy(execname, anonstr);
 			event->mmap2.flags |= MAP_HUGETLB;
 		}
-- 
1.9.1

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

* [PATCH 03/16] perf script: Fix vanished idle symbols
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
  2016-09-23 14:38 ` [PATCH 01/16] perf record: Fix documentation 'event_sources' -> 'event_source' Adrian Hunter
  2016-09-23 14:38 ` [PATCH 02/16] perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:13   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 04/16] perf record: Rename label 'out_symbol_exit' Adrian Hunter
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Patch "perf symbols: Mark if a symbol is idle in the library" causes idle
symbols to vanish from perf script output. That is because print functions
suppress symbols marked as 'idle'. However, suppression of 'idle' functions
is only used by 'perf top' and 'perf top' does not use the print functions.
Consequently that functionality can simply be removed from the print
functions.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/evsel_fprintf.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 9111e0666950..662a0a6182e7 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -122,9 +122,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
 			if (!node)
 				break;
 
-			if (node->sym && node->sym->idle)
-				goto next;
-
 			printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
 
 			if (print_ip)
@@ -158,7 +155,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
 
 			if (!print_oneline)
 				printed += fprintf(fp, "\n");
-next:
+
 			callchain_cursor_advance(cursor);
 		}
 	}
@@ -181,7 +178,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
 	if (cursor != NULL) {
 		printed += sample__fprintf_callchain(sample, left_alignment,
 						     print_opts, cursor, fp);
-	} else if (!(al->sym && al->sym->idle)) {
+	} else {
 		printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
 
 		if (print_ip)
-- 
1.9.1

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

* [PATCH 04/16] perf record: Rename label 'out_symbol_exit'
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (2 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 03/16] perf script: Fix vanished idle symbols Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:14   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 05/16] perf record: Fix error paths Adrian Hunter
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

In preparation for fixing the error paths, rename label 'out_symbol_exit'
to be 'out' because that error path can be used irrespective of whether
symbols (or anything else) has been initialized.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/builtin-record.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 2d0d69be3bf8..b32a880ec473 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1643,7 +1643,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (rec->evlist->nr_entries == 0 &&
 	    perf_evlist__add_default(rec->evlist) < 0) {
 		pr_err("Not enough memory for event selector list\n");
-		goto out_symbol_exit;
+		goto out;
 	}
 
 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -1663,7 +1663,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 		ui__error("%s", errbuf);
 
 		err = -saved_errno;
-		goto out_symbol_exit;
+		goto out;
 	}
 
 	err = -ENOMEM;
@@ -1672,7 +1672,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
 	if (err)
-		goto out_symbol_exit;
+		goto out;
 
 	/*
 	 * We take all buildids when the file contains
@@ -1684,11 +1684,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	if (record_opts__config(&rec->opts)) {
 		err = -EINVAL;
-		goto out_symbol_exit;
+		goto out;
 	}
 
 	err = __cmd_record(&record, argc, argv);
-out_symbol_exit:
+out:
 	perf_evlist__delete(rec->evlist);
 	symbol__exit();
 	auxtrace_record__free(rec->itr);
-- 
1.9.1

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

* [PATCH 05/16] perf record: Fix error paths
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (3 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 04/16] perf record: Rename label 'out_symbol_exit' Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:14   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 06/16] perf symbols: Add dso__last_symbol() Adrian Hunter
                   ` (10 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Some error paths do not tidy-up. Fix that.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/builtin-record.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b32a880ec473..962adcfc43a5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1573,23 +1573,23 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (!rec->itr) {
 		rec->itr = auxtrace_record__init(rec->evlist, &err);
 		if (err)
-			return err;
+			goto out;
 	}
 
 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
 					      rec->opts.auxtrace_snapshot_opts);
 	if (err)
-		return err;
+		goto out;
 
 	if (dry_run)
-		return 0;
+		goto out;
 
 	err = bpf__setup_stdout(rec->evlist);
 	if (err) {
 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
 			 errbuf);
-		return err;
+		goto out;
 	}
 
 	err = -ENOMEM;
-- 
1.9.1

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

* [PATCH 06/16] perf symbols: Add dso__last_symbol()
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (4 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 05/16] perf record: Fix error paths Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:14   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 07/16] perf record: Add support for using symbols in address filters Adrian Hunter
                   ` (9 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Add a function to find the last symbol in a DSO. This will be used when
parsing address filters to calculate a region that includes the entire DSO.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/symbol.c | 15 +++++++++++++++
 tools/perf/util/symbol.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 19c9c558454f..aecff69a510d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -345,6 +345,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)
 	return NULL;
 }
 
+static struct symbol *symbols__last(struct rb_root *symbols)
+{
+	struct rb_node *n = rb_last(symbols);
+
+	if (n)
+		return rb_entry(n, struct symbol, rb_node);
+
+	return NULL;
+}
+
 static struct symbol *symbols__next(struct symbol *sym)
 {
 	struct rb_node *n = rb_next(&sym->rb_node);
@@ -466,6 +476,11 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
 	return symbols__first(&dso->symbols[type]);
 }
 
+struct symbol *dso__last_symbol(struct dso *dso, enum map_type type)
+{
+	return symbols__last(&dso->symbols[type]);
+}
+
 struct symbol *dso__next_symbol(struct symbol *sym)
 {
 	return symbols__next(sym);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0dacfb7d5b67..d964844eb314 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -259,6 +259,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
 struct symbol *symbol__next_by_name(struct symbol *sym);
 
 struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
+struct symbol *dso__last_symbol(struct dso *dso, enum map_type type);
 struct symbol *dso__next_symbol(struct symbol *sym);
 
 enum dso_type dso__type_fd(int fd);
-- 
1.9.1

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

* [PATCH 07/16] perf record: Add support for using symbols in address filters
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (5 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 06/16] perf symbols: Add dso__last_symbol() Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:15   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 08/16] perf tools: Increase debug level of SDT debug messages Adrian Hunter
                   ` (8 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Symbols come from either the DSO or /proc/kallsyms for the kernel.
Details of the functionality can be found in Documentation/perf-record.txt.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/Documentation/perf-record.txt |  55 ++-
 tools/perf/builtin-record.c              |  14 +-
 tools/perf/util/auxtrace.c               | 737 +++++++++++++++++++++++++++++++
 tools/perf/util/auxtrace.h               |  54 +++
 4 files changed, 857 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index babbb63e6d9d..92335193dc33 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -89,9 +89,62 @@ OPTIONS
 
 --filter=<filter>::
         Event filter. This option should follow a event selector (-e) which
-	selects tracepoint event(s). Multiple '--filter' options are combined
+	selects either tracepoint event(s) or a hardware trace PMU
+	(e.g. Intel PT or CoreSight).
+
+	- tracepoint filters
+
+	In the case of tracepoints, multiple '--filter' options are combined
 	using '&&'.
 
+	- address filters
+
+	A hardware trace PMU advertises its ability to accept a number of
+	address filters	by specifying a non-zero value in
+	/sys/bus/event_source/devices/<pmu>/nr_addr_filters.
+
+	Address filters have the format:
+
+	filter|start|stop|tracestop <start> [/ <size>] [@<file name>]
+
+	Where:
+	- 'filter': defines a region that will be traced.
+	- 'start': defines an address at which tracing will begin.
+	- 'stop': defines an address at which tracing will stop.
+	- 'tracestop': defines a region in which tracing will stop.
+
+	<file name> is the name of the object file, <start> is the offset to the
+	code to trace in that file, and <size> is the size of the region to
+	trace. 'start' and 'stop' filters need not specify a <size>.
+
+	If no object file is specified then the kernel is assumed, in which case
+	the start address must be a current kernel memory address.
+
+	<start> can also be specified by providing the name of a symbol. If the
+	symbol name is not unique, it can be disambiguated by inserting #n where
+	'n' selects the n'th symbol in address order. Alternately #0, #g or #G
+	select only a global symbol. <size> can also be specified by providing
+	the name of a symbol, in which case the size is calculated to the end
+	of that symbol. For 'filter' and 'tracestop' filters, if <size> is
+	omitted and <start> is a symbol, then the size is calculated to the end
+	of that symbol.
+
+	If <size> is omitted and <start> is '*', then the start and size will
+	be calculated from the first and last symbols, i.e. to trace the whole
+	file.
+
+	If symbol names (or '*') are provided, they must be surrounded by white
+	space.
+
+	The filter passed to the kernel is not necessarily the same as entered.
+	To see the filter that is passed, use the -v option.
+
+	The kernel may not be able to configure a trace region if it is not
+	within a single mapping.  MMAP events (or /proc/<pid>/maps) can be
+	examined to determine if that is a possibility.
+
+	Multiple filters can be separated with space or comma.
+
 --exclude-perf::
 	Don't record events issued by perf itself. This option should follow
 	a event selector (-e) which selects tracepoint event(s). It adds a
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 962adcfc43a5..67d2a9003294 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1581,6 +1581,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (err)
 		goto out;
 
+	/*
+	 * Allow aliases to facilitate the lookup of symbols for address
+	 * filters. Refer to auxtrace_parse_filters().
+	 */
+	symbol_conf.allow_aliases = true;
+
+	symbol__init(NULL);
+
+	err = auxtrace_parse_filters(rec->evlist);
+	if (err)
+		goto out;
+
 	if (dry_run)
 		goto out;
 
@@ -1594,8 +1606,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	err = -ENOMEM;
 
-	symbol__init(NULL);
-
 	if (symbol_conf.kptr_restrict)
 		pr_warning(
 "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c0aba8e839aa..c5a6e0b12452 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -16,6 +16,10 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <stdbool.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
 
 #include <linux/kernel.h>
 #include <linux/perf_event.h>
@@ -35,9 +39,14 @@
 #include "../perf.h"
 #include "util.h"
 #include "evlist.h"
+#include "dso.h"
+#include "map.h"
+#include "pmu.h"
+#include "evsel.h"
 #include "cpumap.h"
 #include "thread_map.h"
 #include "asm/bug.h"
+#include "symbol/kallsyms.h"
 #include "auxtrace.h"
 
 #include <linux/hash.h>
@@ -1399,3 +1408,731 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
 
 	return NULL;
 }
+
+static void addr_filter__free_str(struct addr_filter *filt)
+{
+	free(filt->str);
+	filt->action   = NULL;
+	filt->sym_from = NULL;
+	filt->sym_to   = NULL;
+	filt->filename = NULL;
+	filt->str      = NULL;
+}
+
+static struct addr_filter *addr_filter__new(void)
+{
+	struct addr_filter *filt = zalloc(sizeof(*filt));
+
+	if (filt)
+		INIT_LIST_HEAD(&filt->list);
+
+	return filt;
+}
+
+static void addr_filter__free(struct addr_filter *filt)
+{
+	if (filt)
+		addr_filter__free_str(filt);
+	free(filt);
+}
+
+static void addr_filters__add(struct addr_filters *filts,
+			      struct addr_filter *filt)
+{
+	list_add_tail(&filt->list, &filts->head);
+	filts->cnt += 1;
+}
+
+static void addr_filters__del(struct addr_filters *filts,
+			      struct addr_filter *filt)
+{
+	list_del_init(&filt->list);
+	filts->cnt -= 1;
+}
+
+void addr_filters__init(struct addr_filters *filts)
+{
+	INIT_LIST_HEAD(&filts->head);
+	filts->cnt = 0;
+}
+
+void addr_filters__exit(struct addr_filters *filts)
+{
+	struct addr_filter *filt, *n;
+
+	list_for_each_entry_safe(filt, n, &filts->head, list) {
+		addr_filters__del(filts, filt);
+		addr_filter__free(filt);
+	}
+}
+
+static int parse_num_or_str(char **inp, u64 *num, const char **str,
+			    const char *str_delim)
+{
+	*inp += strspn(*inp, " ");
+
+	if (isdigit(**inp)) {
+		char *endptr;
+
+		if (!num)
+			return -EINVAL;
+		errno = 0;
+		*num = strtoull(*inp, &endptr, 0);
+		if (errno)
+			return -errno;
+		if (endptr == *inp)
+			return -EINVAL;
+		*inp = endptr;
+	} else {
+		size_t n;
+
+		if (!str)
+			return -EINVAL;
+		*inp += strspn(*inp, " ");
+		*str = *inp;
+		n = strcspn(*inp, str_delim);
+		if (!n)
+			return -EINVAL;
+		*inp += n;
+		if (**inp) {
+			**inp = '\0';
+			*inp += 1;
+		}
+	}
+	return 0;
+}
+
+static int parse_action(struct addr_filter *filt)
+{
+	if (!strcmp(filt->action, "filter")) {
+		filt->start = true;
+		filt->range = true;
+	} else if (!strcmp(filt->action, "start")) {
+		filt->start = true;
+	} else if (!strcmp(filt->action, "stop")) {
+		filt->start = false;
+	} else if (!strcmp(filt->action, "tracestop")) {
+		filt->start = false;
+		filt->range = true;
+		filt->action += 5; /* Change 'tracestop' to 'stop' */
+	} else {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int parse_sym_idx(char **inp, int *idx)
+{
+	*idx = -1;
+
+	*inp += strspn(*inp, " ");
+
+	if (**inp != '#')
+		return 0;
+
+	*inp += 1;
+
+	if (**inp == 'g' || **inp == 'G') {
+		*inp += 1;
+		*idx = 0;
+	} else {
+		unsigned long num;
+		char *endptr;
+
+		errno = 0;
+		num = strtoul(*inp, &endptr, 0);
+		if (errno)
+			return -errno;
+		if (endptr == *inp || num > INT_MAX)
+			return -EINVAL;
+		*inp = endptr;
+		*idx = num;
+	}
+
+	return 0;
+}
+
+static int parse_addr_size(char **inp, u64 *num, const char **str, int *idx)
+{
+	int err = parse_num_or_str(inp, num, str, " ");
+
+	if (!err && *str)
+		err = parse_sym_idx(inp, idx);
+
+	return err;
+}
+
+static int parse_one_filter(struct addr_filter *filt, const char **filter_inp)
+{
+	char *fstr;
+	int err;
+
+	filt->str = fstr = strdup(*filter_inp);
+	if (!fstr)
+		return -ENOMEM;
+
+	err = parse_num_or_str(&fstr, NULL, &filt->action, " ");
+	if (err)
+		goto out_err;
+
+	err = parse_action(filt);
+	if (err)
+		goto out_err;
+
+	err = parse_addr_size(&fstr, &filt->addr, &filt->sym_from,
+			      &filt->sym_from_idx);
+	if (err)
+		goto out_err;
+
+	fstr += strspn(fstr, " ");
+
+	if (*fstr == '/') {
+		fstr += 1;
+		err = parse_addr_size(&fstr, &filt->size, &filt->sym_to,
+				      &filt->sym_to_idx);
+		if (err)
+			goto out_err;
+		filt->range = true;
+	}
+
+	fstr += strspn(fstr, " ");
+
+	if (*fstr == '@') {
+		fstr += 1;
+		err = parse_num_or_str(&fstr, NULL, &filt->filename, " ,");
+		if (err)
+			goto out_err;
+	}
+
+	fstr += strspn(fstr, " ,");
+
+	*filter_inp += fstr - filt->str;
+
+	return 0;
+
+out_err:
+	addr_filter__free_str(filt);
+
+	return err;
+}
+
+int addr_filters__parse_bare_filter(struct addr_filters *filts,
+				    const char *filter)
+{
+	struct addr_filter *filt;
+	const char *fstr = filter;
+	int err;
+
+	while (*fstr) {
+		filt = addr_filter__new();
+		err = parse_one_filter(filt, &fstr);
+		if (err) {
+			addr_filter__free(filt);
+			addr_filters__exit(filts);
+			return err;
+		}
+		addr_filters__add(filts, filt);
+	}
+
+	return 0;
+}
+
+struct sym_args {
+	const char	*name;
+	u64		start;
+	u64		size;
+	int		idx;
+	int		cnt;
+	bool		started;
+	bool		global;
+	bool		selected;
+	bool		duplicate;
+	bool		near;
+};
+
+static bool kern_sym_match(struct sym_args *args, const char *name, char type)
+{
+	/* A function with the same name, and global or the n'th found or any */
+	return symbol_type__is_a(type, MAP__FUNCTION) &&
+	       !strcmp(name, args->name) &&
+	       ((args->global && isupper(type)) ||
+		(args->selected && ++(args->cnt) == args->idx) ||
+		(!args->global && !args->selected));
+}
+
+static int find_kern_sym_cb(void *arg, const char *name, char type, u64 start)
+{
+	struct sym_args *args = arg;
+
+	if (args->started) {
+		if (!args->size)
+			args->size = start - args->start;
+		if (args->selected) {
+			if (args->size)
+				return 1;
+		} else if (kern_sym_match(args, name, type)) {
+			args->duplicate = true;
+			return 1;
+		}
+	} else if (kern_sym_match(args, name, type)) {
+		args->started = true;
+		args->start = start;
+	}
+
+	return 0;
+}
+
+static int print_kern_sym_cb(void *arg, const char *name, char type, u64 start)
+{
+	struct sym_args *args = arg;
+
+	if (kern_sym_match(args, name, type)) {
+		pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
+		       ++args->cnt, start, type, name);
+		args->near = true;
+	} else if (args->near) {
+		args->near = false;
+		pr_err("\t\twhich is near\t\t%s\n", name);
+	}
+
+	return 0;
+}
+
+static int sym_not_found_error(const char *sym_name, int idx)
+{
+	if (idx > 0) {
+		pr_err("N'th occurrence (N=%d) of symbol '%s' not found.\n",
+		       idx, sym_name);
+	} else if (!idx) {
+		pr_err("Global symbol '%s' not found.\n", sym_name);
+	} else {
+		pr_err("Symbol '%s' not found.\n", sym_name);
+	}
+	pr_err("Note that symbols must be functions.\n");
+
+	return -EINVAL;
+}
+
+static int find_kern_sym(const char *sym_name, u64 *start, u64 *size, int idx)
+{
+	struct sym_args args = {
+		.name = sym_name,
+		.idx = idx,
+		.global = !idx,
+		.selected = idx > 0,
+	};
+	int err;
+
+	*start = 0;
+	*size = 0;
+
+	err = kallsyms__parse("/proc/kallsyms", &args, find_kern_sym_cb);
+	if (err < 0) {
+		pr_err("Failed to parse /proc/kallsyms\n");
+		return err;
+	}
+
+	if (args.duplicate) {
+		pr_err("Multiple kernel symbols with name '%s'\n", sym_name);
+		args.cnt = 0;
+		kallsyms__parse("/proc/kallsyms", &args, print_kern_sym_cb);
+		pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
+		       sym_name);
+		pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
+		return -EINVAL;
+	}
+
+	if (!args.started) {
+		pr_err("Kernel symbol lookup: ");
+		return sym_not_found_error(sym_name, idx);
+	}
+
+	*start = args.start;
+	*size = args.size;
+
+	return 0;
+}
+
+static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
+			       char type, u64 start)
+{
+	struct sym_args *args = arg;
+
+	if (!symbol_type__is_a(type, MAP__FUNCTION))
+		return 0;
+
+	if (!args->started) {
+		args->started = true;
+		args->start = start;
+	}
+	/* Don't know exactly where the kernel ends, so we add a page */
+	args->size = round_up(start, page_size) + page_size - args->start;
+
+	return 0;
+}
+
+static int addr_filter__entire_kernel(struct addr_filter *filt)
+{
+	struct sym_args args = { .started = false };
+	int err;
+
+	err = kallsyms__parse("/proc/kallsyms", &args, find_entire_kern_cb);
+	if (err < 0 || !args.started) {
+		pr_err("Failed to parse /proc/kallsyms\n");
+		return err;
+	}
+
+	filt->addr = args.start;
+	filt->size = args.size;
+
+	return 0;
+}
+
+static int check_end_after_start(struct addr_filter *filt, u64 start, u64 size)
+{
+	if (start + size >= filt->addr)
+		return 0;
+
+	if (filt->sym_from) {
+		pr_err("Symbol '%s' (0x%"PRIx64") comes before '%s' (0x%"PRIx64")\n",
+		       filt->sym_to, start, filt->sym_from, filt->addr);
+	} else {
+		pr_err("Symbol '%s' (0x%"PRIx64") comes before address 0x%"PRIx64")\n",
+		       filt->sym_to, start, filt->addr);
+	}
+
+	return -EINVAL;
+}
+
+static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
+{
+	bool no_size = false;
+	u64 start, size;
+	int err;
+
+	if (symbol_conf.kptr_restrict) {
+		pr_err("Kernel addresses are restricted. Unable to resolve kernel symbols.\n");
+		return -EINVAL;
+	}
+
+	if (filt->sym_from && !strcmp(filt->sym_from, "*"))
+		return addr_filter__entire_kernel(filt);
+
+	if (filt->sym_from) {
+		err = find_kern_sym(filt->sym_from, &start, &size,
+				    filt->sym_from_idx);
+		if (err)
+			return err;
+		filt->addr = start;
+		if (filt->range && !filt->size && !filt->sym_to) {
+			filt->size = size;
+			no_size = !!size;
+		}
+	}
+
+	if (filt->sym_to) {
+		err = find_kern_sym(filt->sym_to, &start, &size,
+				    filt->sym_to_idx);
+		if (err)
+			return err;
+
+		err = check_end_after_start(filt, start, size);
+		if (err)
+			return err;
+		filt->size = start + size - filt->addr;
+		no_size = !!size;
+	}
+
+	/* The very last symbol in kallsyms does not imply a particular size */
+	if (no_size) {
+		pr_err("Cannot determine size of symbol '%s'\n",
+		       filt->sym_to ? filt->sym_to : filt->sym_from);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct dso *load_dso(const char *name)
+{
+	struct map *map;
+	struct dso *dso;
+
+	map = dso__new_map(name);
+	if (!map)
+		return NULL;
+
+	map__load(map);
+
+	dso = dso__get(map->dso);
+
+	map__put(map);
+
+	return dso;
+}
+
+static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt,
+			  int idx)
+{
+	/* Same name, and global or the n'th found or any */
+	return !arch__compare_symbol_names(name, sym->name) &&
+	       ((!idx && sym->binding == STB_GLOBAL) ||
+		(idx > 0 && ++*cnt == idx) ||
+		idx < 0);
+}
+
+static void print_duplicate_syms(struct dso *dso, const char *sym_name)
+{
+	struct symbol *sym;
+	bool near = false;
+	int cnt = 0;
+
+	pr_err("Multiple symbols with name '%s'\n", sym_name);
+
+	sym = dso__first_symbol(dso, MAP__FUNCTION);
+	while (sym) {
+		if (dso_sym_match(sym, sym_name, &cnt, -1)) {
+			pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
+			       ++cnt, sym->start,
+			       sym->binding == STB_GLOBAL ? 'g' :
+			       sym->binding == STB_LOCAL  ? 'l' : 'w',
+			       sym->name);
+			near = true;
+		} else if (near) {
+			near = false;
+			pr_err("\t\twhich is near\t\t%s\n", sym->name);
+		}
+		sym = dso__next_symbol(sym);
+	}
+
+	pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
+	       sym_name);
+	pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
+}
+
+static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
+			u64 *size, int idx)
+{
+	struct symbol *sym;
+	int cnt = 0;
+
+	*start = 0;
+	*size = 0;
+
+	sym = dso__first_symbol(dso, MAP__FUNCTION);
+	while (sym) {
+		if (*start) {
+			if (!*size)
+				*size = sym->start - *start;
+			if (idx > 0) {
+				if (*size)
+					return 1;
+			} else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
+				print_duplicate_syms(dso, sym_name);
+				return -EINVAL;
+			}
+		} else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
+			*start = sym->start;
+			*size = sym->end - sym->start;
+		}
+		sym = dso__next_symbol(sym);
+	}
+
+	if (!*start)
+		return sym_not_found_error(sym_name, idx);
+
+	return 0;
+}
+
+static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
+{
+	struct symbol *first_sym = dso__first_symbol(dso, MAP__FUNCTION);
+	struct symbol *last_sym = dso__last_symbol(dso, MAP__FUNCTION);
+
+	if (!first_sym || !last_sym) {
+		pr_err("Failed to determine filter for %s\nNo symbols found.\n",
+		       filt->filename);
+		return -EINVAL;
+	}
+
+	filt->addr = first_sym->start;
+	filt->size = last_sym->end - first_sym->start;
+
+	return 0;
+}
+
+static int addr_filter__resolve_syms(struct addr_filter *filt)
+{
+	u64 start, size;
+	struct dso *dso;
+	int err = 0;
+
+	if (!filt->sym_from && !filt->sym_to)
+		return 0;
+
+	if (!filt->filename)
+		return addr_filter__resolve_kernel_syms(filt);
+
+	dso = load_dso(filt->filename);
+	if (!dso) {
+		pr_err("Failed to load symbols from: %s\n", filt->filename);
+		return -EINVAL;
+	}
+
+	if (filt->sym_from && !strcmp(filt->sym_from, "*")) {
+		err = addr_filter__entire_dso(filt, dso);
+		goto put_dso;
+	}
+
+	if (filt->sym_from) {
+		err = find_dso_sym(dso, filt->sym_from, &start, &size,
+				   filt->sym_from_idx);
+		if (err)
+			goto put_dso;
+		filt->addr = start;
+		if (filt->range && !filt->size && !filt->sym_to)
+			filt->size = size;
+	}
+
+	if (filt->sym_to) {
+		err = find_dso_sym(dso, filt->sym_to, &start, &size,
+				   filt->sym_to_idx);
+		if (err)
+			goto put_dso;
+
+		err = check_end_after_start(filt, start, size);
+		if (err)
+			return err;
+
+		filt->size = start + size - filt->addr;
+	}
+
+put_dso:
+	dso__put(dso);
+
+	return err;
+}
+
+static char *addr_filter__to_str(struct addr_filter *filt)
+{
+	char filename_buf[PATH_MAX];
+	const char *at = "";
+	const char *fn = "";
+	char *filter;
+	int err;
+
+	if (filt->filename) {
+		at = "@";
+		fn = realpath(filt->filename, filename_buf);
+		if (!fn)
+			return NULL;
+	}
+
+	if (filt->range) {
+		err = asprintf(&filter, "%s 0x%"PRIx64"/0x%"PRIx64"%s%s",
+			       filt->action, filt->addr, filt->size, at, fn);
+	} else {
+		err = asprintf(&filter, "%s 0x%"PRIx64"%s%s",
+			       filt->action, filt->addr, at, fn);
+	}
+
+	return err < 0 ? NULL : filter;
+}
+
+static int parse_addr_filter(struct perf_evsel *evsel, const char *filter,
+			     int max_nr)
+{
+	struct addr_filters filts;
+	struct addr_filter *filt;
+	int err;
+
+	addr_filters__init(&filts);
+
+	err = addr_filters__parse_bare_filter(&filts, filter);
+	if (err)
+		goto out_exit;
+
+	if (filts.cnt > max_nr) {
+		pr_err("Error: number of address filters (%d) exceeds maximum (%d)\n",
+		       filts.cnt, max_nr);
+		err = -EINVAL;
+		goto out_exit;
+	}
+
+	list_for_each_entry(filt, &filts.head, list) {
+		char *new_filter;
+
+		err = addr_filter__resolve_syms(filt);
+		if (err)
+			goto out_exit;
+
+		new_filter = addr_filter__to_str(filt);
+		if (!new_filter) {
+			err = -ENOMEM;
+			goto out_exit;
+		}
+
+		if (perf_evsel__append_addr_filter(evsel, new_filter)) {
+			err = -ENOMEM;
+			goto out_exit;
+		}
+	}
+
+out_exit:
+	addr_filters__exit(&filts);
+
+	if (err) {
+		pr_err("Failed to parse address filter: '%s'\n", filter);
+		pr_err("Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [@<file name>]\n");
+		pr_err("Where multiple filters are separated by space or comma.\n");
+	}
+
+	return err;
+}
+
+static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel)
+{
+	struct perf_pmu *pmu = NULL;
+
+	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+		if (pmu->type == evsel->attr.type)
+			break;
+	}
+
+	return pmu;
+}
+
+static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
+{
+	struct perf_pmu *pmu = perf_evsel__find_pmu(evsel);
+	int nr_addr_filters = 0;
+
+	if (!pmu)
+		return 0;
+
+	perf_pmu__scan_file(pmu, "nr_addr_filters", "%d", &nr_addr_filters);
+
+	return nr_addr_filters;
+}
+
+int auxtrace_parse_filters(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel;
+	char *filter;
+	int err, max_nr;
+
+	evlist__for_each_entry(evlist, evsel) {
+		filter = evsel->filter;
+		max_nr = perf_evsel__nr_addr_filter(evsel);
+		if (!filter || !max_nr)
+			continue;
+		evsel->filter = NULL;
+		err = parse_addr_filter(evsel, filter, max_nr);
+		free(filter);
+		if (err)
+			return err;
+		pr_debug("Address filter: %s\n", evsel->filter);
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 09286f193532..26fb1ee5746a 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -318,6 +318,48 @@ struct auxtrace_record {
 	unsigned int alignment;
 };
 
+/**
+ * struct addr_filter - address filter.
+ * @list: list node
+ * @range: true if it is a range filter
+ * @start: true if action is 'filter' or 'start'
+ * @action: 'filter', 'start' or 'stop' ('tracestop' is accepted but converted
+ *          to 'stop')
+ * @sym_from: symbol name for the filter address
+ * @sym_to: symbol name that determines the filter size
+ * @sym_from_idx: selects n'th from symbols with the same name (0 means global
+ *                and less than 0 means symbol must be unique)
+ * @sym_to_idx: same as @sym_from_idx but for @sym_to
+ * @addr: filter address
+ * @size: filter region size (for range filters)
+ * @filename: DSO file name or NULL for the kernel
+ * @str: allocated string that contains the other string members
+ */
+struct addr_filter {
+	struct list_head	list;
+	bool			range;
+	bool			start;
+	const char		*action;
+	const char		*sym_from;
+	const char		*sym_to;
+	int			sym_from_idx;
+	int			sym_to_idx;
+	u64			addr;
+	u64			size;
+	const char		*filename;
+	char			*str;
+};
+
+/**
+ * struct addr_filters - list of address filters.
+ * @head: list of address filters
+ * @cnt: number of address filters
+ */
+struct addr_filters {
+	struct list_head	head;
+	int			cnt;
+};
+
 #ifdef HAVE_AUXTRACE_SUPPORT
 
 /*
@@ -482,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session,
 				      union perf_event *event);
 void events_stats__auxtrace_error_warn(const struct events_stats *stats);
 
+void addr_filters__init(struct addr_filters *filts);
+void addr_filters__exit(struct addr_filters *filts);
+int addr_filters__parse_bare_filter(struct addr_filters *filts,
+				    const char *filter);
+int auxtrace_parse_filters(struct perf_evlist *evlist);
+
 static inline int auxtrace__process_event(struct perf_session *session,
 					  union perf_event *event,
 					  struct perf_sample *sample,
@@ -640,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
 {
 }
 
+static inline
+int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
+{
+	return 0;
+}
+
 int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
 			struct auxtrace_mmap_params *mp,
 			void *userpg, int fd);
-- 
1.9.1

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

* [PATCH 08/16] perf tools: Increase debug level of SDT debug messages
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (6 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 07/16] perf record: Add support for using symbols in address filters Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-24  0:15   ` Masami Hiramatsu
  2016-09-29 18:15   ` [tip:perf/core] perf probe: " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 09/16] perf intel-pt: Fix snapshot overlap detection decoder errors Adrian Hunter
                   ` (7 subsequent siblings)
  15 siblings, 2 replies; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Two SDT debug messages can occur for every DSO which is too noisy.
Consequently, increase debug level of SDT messages.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/build-id.c   | 4 ++--
 tools/perf/util/probe-file.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5651f3c12f93..e528c40739cc 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
 
 	ret = probe_cache__scan_sdt(cache, realname);
 	if (ret >= 0) {
-		pr_debug("Found %d SDTs in %s\n", ret, realname);
+		pr_debug4("Found %d SDTs in %s\n", ret, realname);
 		if (probe_cache__commit(cache) < 0)
 			ret = -1;
 	}
@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 
 	/* Update SDT cache : error is just warned */
 	if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
-		pr_debug("Failed to update/scan SDT cache for %s\n", realname);
+		pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
 
 out_free:
 	if (!is_kallsyms)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 6f931e442f14..436b64731f65 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 	INIT_LIST_HEAD(&sdtlist);
 	ret = get_sdt_note_list(&sdtlist, pathname);
 	if (ret < 0) {
-		pr_debug("Failed to get sdt note: %d\n", ret);
+		pr_debug4("Failed to get sdt note: %d\n", ret);
 		return ret;
 	}
 	list_for_each_entry(note, &sdtlist, note_list) {
-- 
1.9.1

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

* [PATCH 09/16] perf intel-pt: Fix snapshot overlap detection decoder errors
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (7 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 08/16] perf tools: Increase debug level of SDT debug messages Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:16   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 10/16] perf intel-pt: Add support for recording the max non-turbo ratio Adrian Hunter
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Fix occasional decoder errors decoding trace data collected in snapshot
mode.

Snapshot mode can take successive snapshots of trace which might overlap.
The decoder checks whether there is an overlap but only looks at the
current and previous buffer. However buffers that do not contain
synchronization (i.e. PSB) packets cannot be decoded or used for overlap
checking. That means the decoder actually needs to check overlaps between
the current buffer and the previous buffer that contained usable data.
Make that change.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: stable@vger.kernel.org # v4.3+
---
 tools/perf/util/intel-pt.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index b9cc353cace2..b744ea812a2e 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -241,7 +241,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
 	}
 
 	queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
-
+next:
 	buffer = auxtrace_buffer__next(queue, buffer);
 	if (!buffer) {
 		if (old_buffer)
@@ -264,9 +264,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
 	    intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
 		return -ENOMEM;
 
-	if (old_buffer)
-		auxtrace_buffer__drop_data(old_buffer);
-
 	if (buffer->use_data) {
 		b->len = buffer->use_size;
 		b->buf = buffer->use_data;
@@ -276,6 +273,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
 	}
 	b->ref_timestamp = buffer->reference;
 
+	/*
+	 * If in snapshot mode and the buffer has no usable data, get next
+	 * buffer and again check overlap against old_buffer.
+	 */
+	if (ptq->pt->snapshot_mode && !b->len)
+		goto next;
+
+	if (old_buffer)
+		auxtrace_buffer__drop_data(old_buffer);
+
 	if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
 						      !buffer->consecutive)) {
 		b->consecutive = false;
-- 
1.9.1

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

* [PATCH 10/16] perf intel-pt: Add support for recording the max non-turbo ratio
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (8 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 09/16] perf intel-pt: Fix snapshot overlap detection decoder errors Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:16   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 11/16] perf intel-pt: Fix missing error codes processing auxtrace_info Adrian Hunter
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Previously the maximum non-turbo ratio was calculated from TSC assuming a
100 MHz multiplier which is correct for current hardware supporting
Intel PT.  However more recent kernels also now export the value, so use
that in preference to the calculated value.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/arch/x86/util/intel-pt.c |  6 ++++++
 tools/perf/util/intel-pt.c          | 14 +++++++++++++-
 tools/perf/util/intel-pt.h          |  1 +
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index a2412e9d883b..18b21514c153 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -302,6 +302,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	bool cap_user_time_zero = false, per_cpu_mmaps;
 	u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
 	u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
+	unsigned long max_non_turbo_ratio;
 	int err;
 
 	if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE)
@@ -317,6 +318,10 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 
 	intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
 
+	if (perf_pmu__scan_file(intel_pt_pmu, "max_nonturbo_ratio",
+				"%lu", &max_non_turbo_ratio) != 1)
+		max_non_turbo_ratio = 0;
+
 	if (!session->evlist->nr_mmaps)
 		return -EINVAL;
 
@@ -351,6 +356,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
 	auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
 	auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
+	auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
 
 	return 0;
 }
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index b744ea812a2e..77fbf02c8e41 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2023,6 +2023,7 @@ static const char * const intel_pt_info_fmts[] = {
 	[INTEL_PT_TSC_CTC_N]		= "  TSC:CTC numerator   %"PRIu64"\n",
 	[INTEL_PT_TSC_CTC_D]		= "  TSC:CTC denominator %"PRIu64"\n",
 	[INTEL_PT_CYC_BIT]		= "  CYC bit             %#"PRIx64"\n",
+	[INTEL_PT_MAX_NONTURBO_RATIO]	= "  Max non-turbo ratio %"PRIu64"\n",
 };
 
 static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2087,6 +2088,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				    INTEL_PT_CYC_BIT);
 	}
 
+	if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
+				(sizeof(u64) * INTEL_PT_MAX_NONTURBO_RATIO)) {
+		pt->max_non_turbo_ratio =
+			auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
+		intel_pt_print_info(&auxtrace_info->priv[0],
+				    INTEL_PT_MAX_NONTURBO_RATIO,
+				    INTEL_PT_MAX_NONTURBO_RATIO);
+	}
+
 	pt->timeless_decoding = intel_pt_timeless_decoding(pt);
 	pt->have_tsc = intel_pt_have_tsc(pt);
 	pt->sampling_mode = false;
@@ -2156,7 +2166,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	if (pt->tc.time_mult) {
 		u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000);
 
-		pt->max_non_turbo_ratio = (tsc_freq + 50000000) / 100000000;
+		if (!pt->max_non_turbo_ratio)
+			pt->max_non_turbo_ratio =
+					(tsc_freq + 50000000) / 100000000;
 		intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
 		intel_pt_log("Maximum non-turbo ratio %u\n",
 			     pt->max_non_turbo_ratio);
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h
index 0065949df693..8b8356233e6a 100644
--- a/tools/perf/util/intel-pt.h
+++ b/tools/perf/util/intel-pt.h
@@ -34,6 +34,7 @@ enum {
 	INTEL_PT_TSC_CTC_N,
 	INTEL_PT_TSC_CTC_D,
 	INTEL_PT_CYC_BIT,
+	INTEL_PT_MAX_NONTURBO_RATIO,
 	INTEL_PT_AUXTRACE_PRIV_MAX,
 };
 
-- 
1.9.1

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

* [PATCH 11/16] perf intel-pt: Fix missing error codes processing auxtrace_info
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (9 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 10/16] perf intel-pt: Add support for recording the max non-turbo ratio Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:17   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 12/16] perf intel-pt: Add a helper function for processing AUXTRACE_INFO Adrian Hunter
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Fix 2 places where the err variable was not being set.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 77fbf02c8e41..96519e801e53 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2138,11 +2138,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 		pt->switch_evsel = intel_pt_find_sched_switch(session->evlist);
 		if (!pt->switch_evsel) {
 			pr_err("%s: missing sched_switch event\n", __func__);
+			err = -EINVAL;
 			goto err_delete_thread;
 		}
 	} else if (pt->have_sched_switch == 2 &&
 		   !intel_pt_find_switch(session->evlist)) {
 		pr_err("%s: missing context_switch attribute flag\n", __func__);
+		err = -EINVAL;
 		goto err_delete_thread;
 	}
 
-- 
1.9.1

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

* [PATCH 12/16] perf intel-pt: Add a helper function for processing AUXTRACE_INFO
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (10 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 11/16] perf intel-pt: Fix missing error codes processing auxtrace_info Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:17   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 13/16] perf intel-pt: Record address filter in AUXTRACE_INFO event Adrian Hunter
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Add a helper function 'intel_pt_has()' to make it easier to determine which
members the AUXTRACE_INFO event contains.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 96519e801e53..f16b00f55a19 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2037,6 +2037,12 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
 		fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
 }
 
+static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
+{
+	return auxtrace_info->header.size >=
+		sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1));
+}
+
 int intel_pt_process_auxtrace_info(union perf_event *event,
 				   struct perf_session *session)
 {
@@ -2077,8 +2083,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
 			    INTEL_PT_PER_CPU_MMAPS);
 
-	if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
-					(sizeof(u64) * INTEL_PT_CYC_BIT)) {
+	if (intel_pt_has(auxtrace_info, INTEL_PT_CYC_BIT)) {
 		pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
 		pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
 		pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
@@ -2088,8 +2093,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				    INTEL_PT_CYC_BIT);
 	}
 
-	if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
-				(sizeof(u64) * INTEL_PT_MAX_NONTURBO_RATIO)) {
+	if (intel_pt_has(auxtrace_info, INTEL_PT_MAX_NONTURBO_RATIO)) {
 		pt->max_non_turbo_ratio =
 			auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
 		intel_pt_print_info(&auxtrace_info->priv[0],
-- 
1.9.1

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

* [PATCH 13/16] perf intel-pt: Record address filter in AUXTRACE_INFO event
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (11 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 12/16] perf intel-pt: Add a helper function for processing AUXTRACE_INFO Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:17   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 14/16] perf intel-pt: Read address filter from " Adrian Hunter
                   ` (2 subsequent siblings)
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

The address filter is needed to help decode the trace, so store it in the
AUXTRACE_INFO event.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/arch/x86/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++---
 tools/perf/util/intel-pt.h          |  3 +--
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 18b21514c153..90fa2286edcf 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -62,6 +62,7 @@ struct intel_pt_recording {
 	size_t				snapshot_ref_buf_size;
 	int				snapshot_ref_cnt;
 	struct intel_pt_snapshot_ref	*snapshot_refs;
+	size_t				priv_size;
 };
 
 static int intel_pt_parse_terms_with_default(struct list_head *formats,
@@ -273,11 +274,37 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
 	return attr;
 }
 
+static const char *intel_pt_find_filter(struct perf_evlist *evlist,
+					struct perf_pmu *intel_pt_pmu)
+{
+	struct perf_evsel *evsel;
+
+	evlist__for_each_entry(evlist, evsel) {
+		if (evsel->attr.type == intel_pt_pmu->type)
+			return evsel->filter;
+	}
+
+	return NULL;
+}
+
+static size_t intel_pt_filter_bytes(const char *filter)
+{
+	size_t len = filter ? strlen(filter) : 0;
+
+	return len ? roundup(len + 1, 8) : 0;
+}
+
 static size_t
-intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused,
-			struct perf_evlist *evlist __maybe_unused)
+intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
 {
-	return INTEL_PT_AUXTRACE_PRIV_SIZE;
+	struct intel_pt_recording *ptr =
+			container_of(itr, struct intel_pt_recording, itr);
+	const char *filter = intel_pt_find_filter(evlist, ptr->intel_pt_pmu);
+
+	ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) +
+			 intel_pt_filter_bytes(filter);
+
+	return ptr->priv_size;
 }
 
 static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
@@ -303,9 +330,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
 	u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
 	unsigned long max_non_turbo_ratio;
+	size_t filter_str_len;
+	const char *filter;
+	u64 *info;
 	int err;
 
-	if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE)
+	if (priv_size != ptr->priv_size)
 		return -EINVAL;
 
 	intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
@@ -322,6 +352,9 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 				"%lu", &max_non_turbo_ratio) != 1)
 		max_non_turbo_ratio = 0;
 
+	filter = intel_pt_find_filter(session->evlist, ptr->intel_pt_pmu);
+	filter_str_len = filter ? strlen(filter) : 0;
+
 	if (!session->evlist->nr_mmaps)
 		return -EINVAL;
 
@@ -357,6 +390,16 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
 	auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
 	auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
+	auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] = filter_str_len;
+
+	info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
+
+	if (filter_str_len) {
+		size_t len = intel_pt_filter_bytes(filter);
+
+		strncpy((char *)info, filter, len);
+		info += len >> 3;
+	}
 
 	return 0;
 }
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h
index 8b8356233e6a..e13b14e5a37b 100644
--- a/tools/perf/util/intel-pt.h
+++ b/tools/perf/util/intel-pt.h
@@ -35,11 +35,10 @@ enum {
 	INTEL_PT_TSC_CTC_D,
 	INTEL_PT_CYC_BIT,
 	INTEL_PT_MAX_NONTURBO_RATIO,
+	INTEL_PT_FILTER_STR_LEN,
 	INTEL_PT_AUXTRACE_PRIV_MAX,
 };
 
-#define INTEL_PT_AUXTRACE_PRIV_SIZE (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64))
-
 struct auxtrace_record;
 struct perf_tool;
 union perf_event;
-- 
1.9.1

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

* [PATCH 14/16] perf intel-pt: Read address filter from AUXTRACE_INFO event
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (12 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 13/16] perf intel-pt: Record address filter in AUXTRACE_INFO event Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:18   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 15/16] perf intel-pt: Enable decoder to handle TIP.PGD with missing IP Adrian Hunter
  2016-09-23 14:38 ` [PATCH 16/16] perf intel-pt: Fix decoding when there are address filters Adrian Hunter
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Read the address filter from the AUXTRACE_INFO event in preparation for
using it to assist in decoding.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index f16b00f55a19..c9fec19a7914 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -103,6 +103,8 @@ struct intel_pt {
 	unsigned max_non_turbo_ratio;
 
 	unsigned long num_events;
+
+	char *filter;
 };
 
 enum switch_state {
@@ -1774,6 +1776,7 @@ static void intel_pt_free(struct perf_session *session)
 	intel_pt_free_events(session);
 	session->auxtrace = NULL;
 	thread__put(pt->unknown_thread);
+	zfree(&pt->filter);
 	free(pt);
 }
 
@@ -2024,6 +2027,7 @@ static const char * const intel_pt_info_fmts[] = {
 	[INTEL_PT_TSC_CTC_D]		= "  TSC:CTC denominator %"PRIu64"\n",
 	[INTEL_PT_CYC_BIT]		= "  CYC bit             %#"PRIx64"\n",
 	[INTEL_PT_MAX_NONTURBO_RATIO]	= "  Max non-turbo ratio %"PRIu64"\n",
+	[INTEL_PT_FILTER_STR_LEN]	= "  Filter string len.  %"PRIu64"\n",
 };
 
 static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2037,6 +2041,14 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
 		fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
 }
 
+static void intel_pt_print_info_str(const char *name, const char *str)
+{
+	if (!dump_trace)
+		return;
+
+	fprintf(stdout, "  %-20s%s\n", name, str ? str : "");
+}
+
 static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
 {
 	return auxtrace_info->header.size >=
@@ -2049,6 +2061,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
 	size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
 	struct intel_pt *pt;
+	void *info_end;
+	u64 *info;
 	int err;
 
 	if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2101,6 +2115,42 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				    INTEL_PT_MAX_NONTURBO_RATIO);
 	}
 
+	info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
+	info_end = (void *)info + auxtrace_info->header.size;
+
+	if (intel_pt_has(auxtrace_info, INTEL_PT_FILTER_STR_LEN)) {
+		size_t len;
+
+		len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN];
+		intel_pt_print_info(&auxtrace_info->priv[0],
+				    INTEL_PT_FILTER_STR_LEN,
+				    INTEL_PT_FILTER_STR_LEN);
+		if (len) {
+			const char *filter = (const char *)info;
+
+			len = roundup(len + 1, 8);
+			info += len >> 3;
+			if ((void *)info > info_end) {
+				pr_err("%s: bad filter string length\n", __func__);
+				err = -EINVAL;
+				goto err_free_queues;
+			}
+			pt->filter = memdup(filter, len);
+			if (!pt->filter) {
+				err = -ENOMEM;
+				goto err_free_queues;
+			}
+			if (session->header.needs_swap)
+				mem_bswap_64(pt->filter, len);
+			if (pt->filter[len - 1]) {
+				pr_err("%s: filter string not null terminated\n", __func__);
+				err = -EINVAL;
+				goto err_free_queues;
+			}
+		}
+		intel_pt_print_info_str("Filter string", pt->filter);
+	}
+
 	pt->timeless_decoding = intel_pt_timeless_decoding(pt);
 	pt->have_tsc = intel_pt_have_tsc(pt);
 	pt->sampling_mode = false;
@@ -2218,6 +2268,7 @@ err_free_queues:
 	auxtrace_queues__free(&pt->queues);
 	session->auxtrace = NULL;
 err_free:
+	zfree(&pt->filter);
 	free(pt);
 	return err;
 }
-- 
1.9.1

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

* [PATCH 15/16] perf intel-pt: Enable decoder to handle TIP.PGD with missing IP
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (13 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 14/16] perf intel-pt: Read address filter from " Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:18   ` [tip:perf/core] " tip-bot for Adrian Hunter
  2016-09-23 14:38 ` [PATCH 16/16] perf intel-pt: Fix decoding when there are address filters Adrian Hunter
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

When address filters are used, the decoder must detect the end of a filter
region (or a branch into a tracestop region) by matching Packet Generation
Disabled (TIP.PGD) packets against the object code using the IP given in
the packet. However, due to errata SKL014 "Intel PT TIP.PGD May Not Have
Target IP Payload", that IP may not be present.

Enable the decoder to handle that by adding a new callback function
'pgd_ip()' which indicates whether the IP is not traced, in which case that
is the point where the trace was disabled.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  | 30 ++++++++++++++++++++++
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  |  1 +
 2 files changed, 31 insertions(+)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 8ff6c6a61291..7591a0c37473 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -80,6 +80,7 @@ struct intel_pt_decoder {
 	int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
 			 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
 			 uint64_t max_insn_cnt, void *data);
+	bool (*pgd_ip)(uint64_t ip, void *data);
 	void *data;
 	struct intel_pt_state state;
 	const unsigned char *buf;
@@ -186,6 +187,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
 
 	decoder->get_trace          = params->get_trace;
 	decoder->walk_insn          = params->walk_insn;
+	decoder->pgd_ip             = params->pgd_ip;
 	decoder->data               = params->data;
 	decoder->return_compression = params->return_compression;
 
@@ -1008,6 +1010,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
 	int err;
 
 	err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0);
+	if (err == INTEL_PT_RETURN &&
+	    decoder->pgd_ip &&
+	    decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
+	    (decoder->state.type & INTEL_PT_BRANCH) &&
+	    decoder->pgd_ip(decoder->state.to_ip, decoder->data)) {
+		/* Unconditional branch leaving filter region */
+		decoder->no_progress = 0;
+		decoder->pge = false;
+		decoder->continuous_period = false;
+		decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
+		decoder->state.to_ip = 0;
+		return 0;
+	}
 	if (err == INTEL_PT_RETURN)
 		return 0;
 	if (err)
@@ -1036,6 +1051,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
 	}
 
 	if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
+		uint64_t to_ip = decoder->ip + intel_pt_insn.length +
+				 intel_pt_insn.rel;
+
+		if (decoder->pgd_ip &&
+		    decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
+		    decoder->pgd_ip(to_ip, decoder->data)) {
+			/* Conditional branch leaving filter region */
+			decoder->pge = false;
+			decoder->continuous_period = false;
+			decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
+			decoder->ip = to_ip;
+			decoder->state.from_ip = decoder->ip;
+			decoder->state.to_ip = 0;
+			return 0;
+		}
 		intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
 				decoder->ip);
 		decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 02c38fec1c37..89399985fa4d 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -83,6 +83,7 @@ struct intel_pt_params {
 	int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
 			 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
 			 uint64_t max_insn_cnt, void *data);
+	bool (*pgd_ip)(uint64_t ip, void *data);
 	void *data;
 	bool return_compression;
 	uint64_t period;
-- 
1.9.1

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

* [PATCH 16/16] perf intel-pt: Fix decoding when there are address filters
  2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
                   ` (14 preceding siblings ...)
  2016-09-23 14:38 ` [PATCH 15/16] perf intel-pt: Enable decoder to handle TIP.PGD with missing IP Adrian Hunter
@ 2016-09-23 14:38 ` Adrian Hunter
  2016-09-29 18:19   ` [tip:perf/core] " tip-bot for Adrian Hunter
  15 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-23 14:38 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Jiri Olsa, Masami Hiramatsu, Mathieu Poirier, linux-kernel

Due to errata SKL014 "Intel PT TIP.PGD May Not Have Target IP Payload", the
Intel PT decoder needs to match address filters against TIP.PGD packets.
Parse the address filters and implement the decoder's 'pgd_ip()' callback
to match the IP against the filter regions.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/intel-pt.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index c9fec19a7914..dc041d4368c8 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -105,6 +105,7 @@ struct intel_pt {
 	unsigned long num_events;
 
 	char *filter;
+	struct addr_filters filts;
 };
 
 enum switch_state {
@@ -550,6 +551,76 @@ out_no_cache:
 	return 0;
 }
 
+static bool intel_pt_match_pgd_ip(struct intel_pt *pt, uint64_t ip,
+				  uint64_t offset, const char *filename)
+{
+	struct addr_filter *filt;
+	bool have_filter   = false;
+	bool hit_tracestop = false;
+	bool hit_filter    = false;
+
+	list_for_each_entry(filt, &pt->filts.head, list) {
+		if (filt->start)
+			have_filter = true;
+
+		if ((filename && !filt->filename) ||
+		    (!filename && filt->filename) ||
+		    (filename && strcmp(filename, filt->filename)))
+			continue;
+
+		if (!(offset >= filt->addr && offset < filt->addr + filt->size))
+			continue;
+
+		intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s hit filter: %s offset %#"PRIx64" size %#"PRIx64"\n",
+			     ip, offset, filename ? filename : "[kernel]",
+			     filt->start ? "filter" : "stop",
+			     filt->addr, filt->size);
+
+		if (filt->start)
+			hit_filter = true;
+		else
+			hit_tracestop = true;
+	}
+
+	if (!hit_tracestop && !hit_filter)
+		intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s is not in a filter region\n",
+			     ip, offset, filename ? filename : "[kernel]");
+
+	return hit_tracestop || (have_filter && !hit_filter);
+}
+
+static int __intel_pt_pgd_ip(uint64_t ip, void *data)
+{
+	struct intel_pt_queue *ptq = data;
+	struct thread *thread;
+	struct addr_location al;
+	u8 cpumode;
+	u64 offset;
+
+	if (ip >= ptq->pt->kernel_start)
+		return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
+
+	cpumode = PERF_RECORD_MISC_USER;
+
+	thread = ptq->thread;
+	if (!thread)
+		return -EINVAL;
+
+	thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al);
+	if (!al.map || !al.map->dso)
+		return -EINVAL;
+
+	offset = al.map->map_ip(al.map, ip);
+
+	return intel_pt_match_pgd_ip(ptq->pt, ip, offset,
+				     al.map->dso->long_name);
+}
+
+static bool intel_pt_pgd_ip(uint64_t ip, void *data)
+{
+	return __intel_pt_pgd_ip(ip, data) > 0;
+}
+
 static bool intel_pt_get_config(struct intel_pt *pt,
 				struct perf_event_attr *attr, u64 *config)
 {
@@ -726,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
 	params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
 	params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
 
+	if (pt->filts.cnt > 0)
+		params.pgd_ip = intel_pt_pgd_ip;
+
 	if (pt->synth_opts.instructions) {
 		if (pt->synth_opts.period) {
 			switch (pt->synth_opts.period_type) {
@@ -1776,6 +1850,7 @@ static void intel_pt_free(struct perf_session *session)
 	intel_pt_free_events(session);
 	session->auxtrace = NULL;
 	thread__put(pt->unknown_thread);
+	addr_filters__exit(&pt->filts);
 	zfree(&pt->filter);
 	free(pt);
 }
@@ -2073,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	if (!pt)
 		return -ENOMEM;
 
+	addr_filters__init(&pt->filts);
+
 	perf_config(intel_pt_perf_config, pt);
 
 	err = auxtrace_queues__init(&pt->queues);
@@ -2147,6 +2224,10 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				err = -EINVAL;
 				goto err_free_queues;
 			}
+			err = addr_filters__parse_bare_filter(&pt->filts,
+							      filter);
+			if (err)
+				goto err_free_queues;
 		}
 		intel_pt_print_info_str("Filter string", pt->filter);
 	}
@@ -2268,6 +2349,7 @@ err_free_queues:
 	auxtrace_queues__free(&pt->queues);
 	session->auxtrace = NULL;
 err_free:
+	addr_filters__exit(&pt->filts);
 	zfree(&pt->filter);
 	free(pt);
 	return err;
-- 
1.9.1

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

* Re: [PATCH 08/16] perf tools: Increase debug level of SDT debug messages
  2016-09-23 14:38 ` [PATCH 08/16] perf tools: Increase debug level of SDT debug messages Adrian Hunter
@ 2016-09-24  0:15   ` Masami Hiramatsu
  2016-09-26  7:27     ` Adrian Hunter
  2016-09-29 18:15   ` [tip:perf/core] perf probe: " tip-bot for Adrian Hunter
  1 sibling, 1 reply; 36+ messages in thread
From: Masami Hiramatsu @ 2016-09-24  0:15 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, Masami Hiramatsu,
	Mathieu Poirier, linux-kernel

On Fri, 23 Sep 2016 17:38:40 +0300
Adrian Hunter <adrian.hunter@intel.com> wrote:

> Two SDT debug messages can occur for every DSO which is too noisy.
> Consequently, increase debug level of SDT messages.

OK, but why "4" would you choose?

Thanks,

> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>  tools/perf/util/build-id.c   | 4 ++--
>  tools/perf/util/probe-file.c | 2 +-
>  2 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> index 5651f3c12f93..e528c40739cc 100644
> --- a/tools/perf/util/build-id.c
> +++ b/tools/perf/util/build-id.c
> @@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
>  
>  	ret = probe_cache__scan_sdt(cache, realname);
>  	if (ret >= 0) {
> -		pr_debug("Found %d SDTs in %s\n", ret, realname);
> +		pr_debug4("Found %d SDTs in %s\n", ret, realname);
>  		if (probe_cache__commit(cache) < 0)
>  			ret = -1;
>  	}
> @@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
>  
>  	/* Update SDT cache : error is just warned */
>  	if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
> -		pr_debug("Failed to update/scan SDT cache for %s\n", realname);
> +		pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
>  
>  out_free:
>  	if (!is_kallsyms)
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 6f931e442f14..436b64731f65 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>  	INIT_LIST_HEAD(&sdtlist);
>  	ret = get_sdt_note_list(&sdtlist, pathname);
>  	if (ret < 0) {
> -		pr_debug("Failed to get sdt note: %d\n", ret);
> +		pr_debug4("Failed to get sdt note: %d\n", ret);
>  		return ret;
>  	}
>  	list_for_each_entry(note, &sdtlist, note_list) {
> -- 
> 1.9.1
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 08/16] perf tools: Increase debug level of SDT debug messages
  2016-09-24  0:15   ` Masami Hiramatsu
@ 2016-09-26  7:27     ` Adrian Hunter
  2016-09-27 17:42       ` Masami Hiramatsu
  0 siblings, 1 reply; 36+ messages in thread
From: Adrian Hunter @ 2016-09-26  7:27 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, Mathieu Poirier, linux-kernel

On 24/09/16 03:15, Masami Hiramatsu wrote:
> On Fri, 23 Sep 2016 17:38:40 +0300
> Adrian Hunter <adrian.hunter@intel.com> wrote:
> 
>> Two SDT debug messages can occur for every DSO which is too noisy.
>> Consequently, increase debug level of SDT messages.
> 
> OK, but why "4" would you choose?

2 is used for displaying the event attributes, so it needs to be 3 or 4.  I
chose 4 because of the large number of messages and that the same messages
appear every time.

> 
> Thanks,
> 
>>
>> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
>> ---
>>  tools/perf/util/build-id.c   | 4 ++--
>>  tools/perf/util/probe-file.c | 2 +-
>>  2 files changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
>> index 5651f3c12f93..e528c40739cc 100644
>> --- a/tools/perf/util/build-id.c
>> +++ b/tools/perf/util/build-id.c
>> @@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
>>  
>>  	ret = probe_cache__scan_sdt(cache, realname);
>>  	if (ret >= 0) {
>> -		pr_debug("Found %d SDTs in %s\n", ret, realname);
>> +		pr_debug4("Found %d SDTs in %s\n", ret, realname);
>>  		if (probe_cache__commit(cache) < 0)
>>  			ret = -1;
>>  	}
>> @@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
>>  
>>  	/* Update SDT cache : error is just warned */
>>  	if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
>> -		pr_debug("Failed to update/scan SDT cache for %s\n", realname);
>> +		pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
>>  
>>  out_free:
>>  	if (!is_kallsyms)
>> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
>> index 6f931e442f14..436b64731f65 100644
>> --- a/tools/perf/util/probe-file.c
>> +++ b/tools/perf/util/probe-file.c
>> @@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>>  	INIT_LIST_HEAD(&sdtlist);
>>  	ret = get_sdt_note_list(&sdtlist, pathname);
>>  	if (ret < 0) {
>> -		pr_debug("Failed to get sdt note: %d\n", ret);
>> +		pr_debug4("Failed to get sdt note: %d\n", ret);
>>  		return ret;
>>  	}
>>  	list_for_each_entry(note, &sdtlist, note_list) {
>> -- 
>> 1.9.1
>>
> 
> 

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

* Re: [PATCH 08/16] perf tools: Increase debug level of SDT debug messages
  2016-09-26  7:27     ` Adrian Hunter
@ 2016-09-27 17:42       ` Masami Hiramatsu
  0 siblings, 0 replies; 36+ messages in thread
From: Masami Hiramatsu @ 2016-09-27 17:42 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: Arnaldo Carvalho de Melo, Jiri Olsa, Mathieu Poirier, linux-kernel

On Mon, 26 Sep 2016 10:27:41 +0300
Adrian Hunter <adrian.hunter@intel.com> wrote:

> On 24/09/16 03:15, Masami Hiramatsu wrote:
> > On Fri, 23 Sep 2016 17:38:40 +0300
> > Adrian Hunter <adrian.hunter@intel.com> wrote:
> > 
> >> Two SDT debug messages can occur for every DSO which is too noisy.
> >> Consequently, increase debug level of SDT messages.
> > 
> > OK, but why "4" would you choose?
> 
> 2 is used for displaying the event attributes, so it needs to be 3 or 4.  I
> chose 4 because of the large number of messages and that the same messages
> appear every time.

Hmm, yes, but this message is also useful for checking user to
stack on retrieving SDT or not. I think it is a time to introduce
debug printk like feature to perf, because we need to control on/off
depending on which subcommand we are debugging.

Anyway, at this point it is OK for me.

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

> 
> > 
> > Thanks,
> > 
> >>
> >> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> >> ---
> >>  tools/perf/util/build-id.c   | 4 ++--
> >>  tools/perf/util/probe-file.c | 2 +-
> >>  2 files changed, 3 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
> >> index 5651f3c12f93..e528c40739cc 100644
> >> --- a/tools/perf/util/build-id.c
> >> +++ b/tools/perf/util/build-id.c
> >> @@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
> >>  
> >>  	ret = probe_cache__scan_sdt(cache, realname);
> >>  	if (ret >= 0) {
> >> -		pr_debug("Found %d SDTs in %s\n", ret, realname);
> >> +		pr_debug4("Found %d SDTs in %s\n", ret, realname);
> >>  		if (probe_cache__commit(cache) < 0)
> >>  			ret = -1;
> >>  	}
> >> @@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
> >>  
> >>  	/* Update SDT cache : error is just warned */
> >>  	if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
> >> -		pr_debug("Failed to update/scan SDT cache for %s\n", realname);
> >> +		pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
> >>  
> >>  out_free:
> >>  	if (!is_kallsyms)
> >> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> >> index 6f931e442f14..436b64731f65 100644
> >> --- a/tools/perf/util/probe-file.c
> >> +++ b/tools/perf/util/probe-file.c
> >> @@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
> >>  	INIT_LIST_HEAD(&sdtlist);
> >>  	ret = get_sdt_note_list(&sdtlist, pathname);
> >>  	if (ret < 0) {
> >> -		pr_debug("Failed to get sdt note: %d\n", ret);
> >> +		pr_debug4("Failed to get sdt note: %d\n", ret);
> >>  		return ret;
> >>  	}
> >>  	list_for_each_entry(note, &sdtlist, note_list) {
> >> -- 
> >> 1.9.1
> >>
> > 
> > 
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* [tip:perf/core] perf record: Fix documentation 'event_sources' -> 'event_source'
  2016-09-23 14:38 ` [PATCH 01/16] perf record: Fix documentation 'event_sources' -> 'event_source' Adrian Hunter
@ 2016-09-29 18:10   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mathieu.poirier, linux-kernel, acme, tglx, mingo, jolsa,
	mhiramat, adrian.hunter, hpa

Commit-ID:  a9e57009dacd58052755cf58463ce41a14a01db5
Gitweb:     http://git.kernel.org/tip/a9e57009dacd58052755cf58463ce41a14a01db5
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:33 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 27 Sep 2016 15:00:29 -0300

perf record: Fix documentation 'event_sources' -> 'event_source'

Change '/sys/bus/event_sources' to the correct path which is
'/sys/bus/event_source'.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-2-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-record.txt | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 1a24f4d..babbb63 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -35,15 +35,15 @@ OPTIONS
 
 	- a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
 	  'param1', 'param2', etc are defined as formats for the PMU in
-	  /sys/bus/event_sources/devices/<pmu>/format/*.
+	  /sys/bus/event_source/devices/<pmu>/format/*.
 
 	- a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
 
           where M, N, K are numbers (in decimal, hex, octal format). Acceptable
           values for each of 'config', 'config1' and 'config2' are defined by
-          corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/*
+          corresponding entries in /sys/bus/event_source/devices/<pmu>/format/*
           param1 and param2 are defined as formats for the PMU in:
-          /sys/bus/event_sources/devices/<pmu>/format/*
+          /sys/bus/event_source/devices/<pmu>/format/*
 
 	  There are also some params which are not defined in .../<pmu>/format/*.
 	  These params can be used to overload default config values per event.

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

* [tip:perf/core] perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change
  2016-09-23 14:38 ` [PATCH 02/16] perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change Adrian Hunter
@ 2016-09-29 18:10   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: adrian.hunter, linux-kernel, mathieu.poirier, hpa, jolsa, acme,
	tglx, mhiramat, mingo

Commit-ID:  973186ca7fe94d770a9847d7d530864de6ab638b
Gitweb:     http://git.kernel.org/tip/973186ca7fe94d770a9847d7d530864de6ab638b
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:34 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 28 Sep 2016 10:21:15 -0300

perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change

Patch "perf record: Mark MAP_HUGETLB when synthesizing mmap events") breaks
MMAP event synthesis.  The executable name comparison will match any name
if the length is zero, resulting in all the user space maps becoming
anonymous.  This is particularly noticeable with system-wide traces.
Example:

	perf record -a sleep 1
	perf script --show-mmap-events

Committer note:

That is not the case when, say, one has a qemu instance and libvirt actually
mounts hugetlbfs. To test this I had to first umount it:

[root@jouet ~]# mount | grep hugetlbfs
hugetlbfs on /dev/hugepages type hugetlbfs (rw,relatime,seclabel)
[root@jouet ~]#

After unmount it the error fixed by this patch manifests itself:

  # perf record -a sleep 1
  # perf script --show-mmap-events | grep PERF_RECORD_MMAP2 | head -5
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x557d47ed8000(0x167000) @ 0 fd:00 3146896 7362875424355726126]: r-xp //anon
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c488d000(0x4000) @ 0 fd:00 3153214 7362875424355726126]: r-xp //anon
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4a92000(0x3d000) @ 0 fd:00 3159276 7362875424355726126]: r-xp //anon
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4cd5000(0x15000) @ 0 fd:00 3153725 7362875424355726126]: r-xp //anon
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4eeb000(0x25000) @ 0 fd:00 3153260 7362875424355726126]: r-xp //anon
  #

Fixed version:

  # perf record -a sleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 1.419 MB perf.data (182 samples) ]
  # perf script --show-mmap-events | grep PERF_RECORD_MMAP2 | head -5
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x557d47ed8000(0x167000) @ 0 fd:00 3146896 7362875424355726126]: r-xp /usr/lib/systemd/systemd
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c488d000(0x4000) @ 0 fd:00 3153214 7362875424355726126]: r-xp /usr/lib64/libuuid.so.1.3.0
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4a92000(0x3d000) @ 0 fd:00 3159276 7362875424355726126]: r-xp /usr/lib64/libblkid.so.1.1.0
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4cd5000(0x15000) @ 0 fd:00 3153725 7362875424355726126]: r-xp /usr/lib64/libz.so.1.2.8
    systemd 0 [000] 0.000000: PERF_RECORD_MMAP2 1/1: [0x7f96c4eeb000(0x25000) @ 0 fd:00 3153260 7362875424355726126]: r-xp /usr/lib64/liblzma.so.5.2.2
[root@jouet ~]#

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-3-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/event.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 2880e22..8ab0d7d 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -346,7 +346,8 @@ out:
 		if (!strcmp(execname, ""))
 			strcpy(execname, anonstr);
 
-		if (!strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
+		if (hugetlbfs_mnt_len &&
+		    !strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
 			strcpy(execname, anonstr);
 			event->mmap2.flags |= MAP_HUGETLB;
 		}

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

* [tip:perf/core] perf script: Fix vanished idle symbols
  2016-09-23 14:38 ` [PATCH 03/16] perf script: Fix vanished idle symbols Adrian Hunter
@ 2016-09-29 18:13   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:13 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: adrian.hunter, acme, mhiramat, mingo, jolsa, linux-kernel,
	mathieu.poirier, hpa, tglx

Commit-ID:  e7a06a5353574cac3a34211bd4e514bb8d00d766
Gitweb:     http://git.kernel.org/tip/e7a06a5353574cac3a34211bd4e514bb8d00d766
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:35 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:00 -0300

perf script: Fix vanished idle symbols

Commit 608c34de0b3d ("perf symbols: Mark if a symbol is idle in the
library") causes idle symbols to vanish from perf script output. That is
because print functions suppress symbols marked as 'idle'.

However, suppression of 'idle' functions is only used by 'perf top' and
'perf top' does not use the print functions.  Consequently that
functionality can simply be removed from the print functions.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Fixes: 608c34de0b3d ("perf symbols: Mark if a symbol is idle in the library")
Link: http://lkml.kernel.org/r/1474641528-18776-4-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/evsel_fprintf.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 9111e06..662a0a6 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -122,9 +122,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
 			if (!node)
 				break;
 
-			if (node->sym && node->sym->idle)
-				goto next;
-
 			printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
 
 			if (print_ip)
@@ -158,7 +155,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
 
 			if (!print_oneline)
 				printed += fprintf(fp, "\n");
-next:
+
 			callchain_cursor_advance(cursor);
 		}
 	}
@@ -181,7 +178,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
 	if (cursor != NULL) {
 		printed += sample__fprintf_callchain(sample, left_alignment,
 						     print_opts, cursor, fp);
-	} else if (!(al->sym && al->sym->idle)) {
+	} else {
 		printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
 
 		if (print_ip)

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

* [tip:perf/core] perf record: Rename label 'out_symbol_exit'
  2016-09-23 14:38 ` [PATCH 04/16] perf record: Rename label 'out_symbol_exit' Adrian Hunter
@ 2016-09-29 18:14   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:14 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, hpa, linux-kernel, tglx, acme, adrian.hunter, jolsa,
	mhiramat, mathieu.poirier

Commit-ID:  394c01ed8aafdf0f14fb18c6d320d8a783da243c
Gitweb:     http://git.kernel.org/tip/394c01ed8aafdf0f14fb18c6d320d8a783da243c
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:36 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:00 -0300

perf record: Rename label 'out_symbol_exit'

In preparation for fixing the error paths, rename label
'out_symbol_exit' to be 'out' because that error path can be used
irrespective of whether symbols (or anything else) has been initialized.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-5-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 2d0d69b..b32a880 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1643,7 +1643,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (rec->evlist->nr_entries == 0 &&
 	    perf_evlist__add_default(rec->evlist) < 0) {
 		pr_err("Not enough memory for event selector list\n");
-		goto out_symbol_exit;
+		goto out;
 	}
 
 	if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -1663,7 +1663,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 		ui__error("%s", errbuf);
 
 		err = -saved_errno;
-		goto out_symbol_exit;
+		goto out;
 	}
 
 	err = -ENOMEM;
@@ -1672,7 +1672,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
 	if (err)
-		goto out_symbol_exit;
+		goto out;
 
 	/*
 	 * We take all buildids when the file contains
@@ -1684,11 +1684,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	if (record_opts__config(&rec->opts)) {
 		err = -EINVAL;
-		goto out_symbol_exit;
+		goto out;
 	}
 
 	err = __cmd_record(&record, argc, argv);
-out_symbol_exit:
+out:
 	perf_evlist__delete(rec->evlist);
 	symbol__exit();
 	auxtrace_record__free(rec->itr);

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

* [tip:perf/core] perf record: Fix error paths
  2016-09-23 14:38 ` [PATCH 05/16] perf record: Fix error paths Adrian Hunter
@ 2016-09-29 18:14   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:14 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, jolsa, hpa, mhiramat, mathieu.poirier, acme, linux-kernel,
	adrian.hunter, mingo

Commit-ID:  5c01ad60b8a23f8ff59b9a5a756f07ed08f0b6d1
Gitweb:     http://git.kernel.org/tip/5c01ad60b8a23f8ff59b9a5a756f07ed08f0b6d1
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:37 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:01 -0300

perf record: Fix error paths

Some error paths do not tidy-up. Fix that.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-6-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/builtin-record.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index b32a880..962adcf 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1573,23 +1573,23 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (!rec->itr) {
 		rec->itr = auxtrace_record__init(rec->evlist, &err);
 		if (err)
-			return err;
+			goto out;
 	}
 
 	err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
 					      rec->opts.auxtrace_snapshot_opts);
 	if (err)
-		return err;
+		goto out;
 
 	if (dry_run)
-		return 0;
+		goto out;
 
 	err = bpf__setup_stdout(rec->evlist);
 	if (err) {
 		bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
 		pr_err("ERROR: Setup BPF stdout failed: %s\n",
 			 errbuf);
-		return err;
+		goto out;
 	}
 
 	err = -ENOMEM;

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

* [tip:perf/core] perf symbols: Add dso__last_symbol()
  2016-09-23 14:38 ` [PATCH 06/16] perf symbols: Add dso__last_symbol() Adrian Hunter
@ 2016-09-29 18:14   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:14 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, hpa, adrian.hunter, mingo, mathieu.poirier, tglx,
	linux-kernel, mhiramat, acme

Commit-ID:  cd67f99fe90dcf515f1c70c474b84d56b6236cbb
Gitweb:     http://git.kernel.org/tip/cd67f99fe90dcf515f1c70c474b84d56b6236cbb
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:38 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:01 -0300

perf symbols: Add dso__last_symbol()

Add a function to find the last symbol in a DSO. This will be used when
parsing address filters to calculate a region that includes the entire
DSO.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-7-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/symbol.c | 15 +++++++++++++++
 tools/perf/util/symbol.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 19c9c55..aecff69 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -345,6 +345,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)
 	return NULL;
 }
 
+static struct symbol *symbols__last(struct rb_root *symbols)
+{
+	struct rb_node *n = rb_last(symbols);
+
+	if (n)
+		return rb_entry(n, struct symbol, rb_node);
+
+	return NULL;
+}
+
 static struct symbol *symbols__next(struct symbol *sym)
 {
 	struct rb_node *n = rb_next(&sym->rb_node);
@@ -466,6 +476,11 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
 	return symbols__first(&dso->symbols[type]);
 }
 
+struct symbol *dso__last_symbol(struct dso *dso, enum map_type type)
+{
+	return symbols__last(&dso->symbols[type]);
+}
+
 struct symbol *dso__next_symbol(struct symbol *sym)
 {
 	return symbols__next(sym);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0dacfb7..d964844 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -259,6 +259,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
 struct symbol *symbol__next_by_name(struct symbol *sym);
 
 struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
+struct symbol *dso__last_symbol(struct dso *dso, enum map_type type);
 struct symbol *dso__next_symbol(struct symbol *sym);
 
 enum dso_type dso__type_fd(int fd);

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

* [tip:perf/core] perf record: Add support for using symbols in address filters
  2016-09-23 14:38 ` [PATCH 07/16] perf record: Add support for using symbols in address filters Adrian Hunter
@ 2016-09-29 18:15   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:15 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, linux-kernel, jolsa, mhiramat, hpa, acme, mathieu.poirier,
	tglx, adrian.hunter

Commit-ID:  1b36c03e356936d62abbe2accaae1573d3b66f14
Gitweb:     http://git.kernel.org/tip/1b36c03e356936d62abbe2accaae1573d3b66f14
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:39 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:02 -0300

perf record: Add support for using symbols in address filters

Symbols come from either the DSO or /proc/kallsyms for the kernel.
Details of the functionality can be found in Documentation/perf-record.txt.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-8-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/Documentation/perf-record.txt |  55 ++-
 tools/perf/builtin-record.c              |  14 +-
 tools/perf/util/auxtrace.c               | 737 +++++++++++++++++++++++++++++++
 tools/perf/util/auxtrace.h               |  54 +++
 4 files changed, 857 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index babbb63..9233519 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -89,9 +89,62 @@ OPTIONS
 
 --filter=<filter>::
         Event filter. This option should follow a event selector (-e) which
-	selects tracepoint event(s). Multiple '--filter' options are combined
+	selects either tracepoint event(s) or a hardware trace PMU
+	(e.g. Intel PT or CoreSight).
+
+	- tracepoint filters
+
+	In the case of tracepoints, multiple '--filter' options are combined
 	using '&&'.
 
+	- address filters
+
+	A hardware trace PMU advertises its ability to accept a number of
+	address filters	by specifying a non-zero value in
+	/sys/bus/event_source/devices/<pmu>/nr_addr_filters.
+
+	Address filters have the format:
+
+	filter|start|stop|tracestop <start> [/ <size>] [@<file name>]
+
+	Where:
+	- 'filter': defines a region that will be traced.
+	- 'start': defines an address at which tracing will begin.
+	- 'stop': defines an address at which tracing will stop.
+	- 'tracestop': defines a region in which tracing will stop.
+
+	<file name> is the name of the object file, <start> is the offset to the
+	code to trace in that file, and <size> is the size of the region to
+	trace. 'start' and 'stop' filters need not specify a <size>.
+
+	If no object file is specified then the kernel is assumed, in which case
+	the start address must be a current kernel memory address.
+
+	<start> can also be specified by providing the name of a symbol. If the
+	symbol name is not unique, it can be disambiguated by inserting #n where
+	'n' selects the n'th symbol in address order. Alternately #0, #g or #G
+	select only a global symbol. <size> can also be specified by providing
+	the name of a symbol, in which case the size is calculated to the end
+	of that symbol. For 'filter' and 'tracestop' filters, if <size> is
+	omitted and <start> is a symbol, then the size is calculated to the end
+	of that symbol.
+
+	If <size> is omitted and <start> is '*', then the start and size will
+	be calculated from the first and last symbols, i.e. to trace the whole
+	file.
+
+	If symbol names (or '*') are provided, they must be surrounded by white
+	space.
+
+	The filter passed to the kernel is not necessarily the same as entered.
+	To see the filter that is passed, use the -v option.
+
+	The kernel may not be able to configure a trace region if it is not
+	within a single mapping.  MMAP events (or /proc/<pid>/maps) can be
+	examined to determine if that is a possibility.
+
+	Multiple filters can be separated with space or comma.
+
 --exclude-perf::
 	Don't record events issued by perf itself. This option should follow
 	a event selector (-e) which selects tracepoint event(s). It adds a
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 962adcf..67d2a90 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -1581,6 +1581,18 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (err)
 		goto out;
 
+	/*
+	 * Allow aliases to facilitate the lookup of symbols for address
+	 * filters. Refer to auxtrace_parse_filters().
+	 */
+	symbol_conf.allow_aliases = true;
+
+	symbol__init(NULL);
+
+	err = auxtrace_parse_filters(rec->evlist);
+	if (err)
+		goto out;
+
 	if (dry_run)
 		goto out;
 
@@ -1594,8 +1606,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 
 	err = -ENOMEM;
 
-	symbol__init(NULL);
-
 	if (symbol_conf.kptr_restrict)
 		pr_warning(
 "WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c0aba8e..c5a6e0b 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -16,6 +16,10 @@
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <stdbool.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
 
 #include <linux/kernel.h>
 #include <linux/perf_event.h>
@@ -35,9 +39,14 @@
 #include "../perf.h"
 #include "util.h"
 #include "evlist.h"
+#include "dso.h"
+#include "map.h"
+#include "pmu.h"
+#include "evsel.h"
 #include "cpumap.h"
 #include "thread_map.h"
 #include "asm/bug.h"
+#include "symbol/kallsyms.h"
 #include "auxtrace.h"
 
 #include <linux/hash.h>
@@ -1399,3 +1408,731 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
 
 	return NULL;
 }
+
+static void addr_filter__free_str(struct addr_filter *filt)
+{
+	free(filt->str);
+	filt->action   = NULL;
+	filt->sym_from = NULL;
+	filt->sym_to   = NULL;
+	filt->filename = NULL;
+	filt->str      = NULL;
+}
+
+static struct addr_filter *addr_filter__new(void)
+{
+	struct addr_filter *filt = zalloc(sizeof(*filt));
+
+	if (filt)
+		INIT_LIST_HEAD(&filt->list);
+
+	return filt;
+}
+
+static void addr_filter__free(struct addr_filter *filt)
+{
+	if (filt)
+		addr_filter__free_str(filt);
+	free(filt);
+}
+
+static void addr_filters__add(struct addr_filters *filts,
+			      struct addr_filter *filt)
+{
+	list_add_tail(&filt->list, &filts->head);
+	filts->cnt += 1;
+}
+
+static void addr_filters__del(struct addr_filters *filts,
+			      struct addr_filter *filt)
+{
+	list_del_init(&filt->list);
+	filts->cnt -= 1;
+}
+
+void addr_filters__init(struct addr_filters *filts)
+{
+	INIT_LIST_HEAD(&filts->head);
+	filts->cnt = 0;
+}
+
+void addr_filters__exit(struct addr_filters *filts)
+{
+	struct addr_filter *filt, *n;
+
+	list_for_each_entry_safe(filt, n, &filts->head, list) {
+		addr_filters__del(filts, filt);
+		addr_filter__free(filt);
+	}
+}
+
+static int parse_num_or_str(char **inp, u64 *num, const char **str,
+			    const char *str_delim)
+{
+	*inp += strspn(*inp, " ");
+
+	if (isdigit(**inp)) {
+		char *endptr;
+
+		if (!num)
+			return -EINVAL;
+		errno = 0;
+		*num = strtoull(*inp, &endptr, 0);
+		if (errno)
+			return -errno;
+		if (endptr == *inp)
+			return -EINVAL;
+		*inp = endptr;
+	} else {
+		size_t n;
+
+		if (!str)
+			return -EINVAL;
+		*inp += strspn(*inp, " ");
+		*str = *inp;
+		n = strcspn(*inp, str_delim);
+		if (!n)
+			return -EINVAL;
+		*inp += n;
+		if (**inp) {
+			**inp = '\0';
+			*inp += 1;
+		}
+	}
+	return 0;
+}
+
+static int parse_action(struct addr_filter *filt)
+{
+	if (!strcmp(filt->action, "filter")) {
+		filt->start = true;
+		filt->range = true;
+	} else if (!strcmp(filt->action, "start")) {
+		filt->start = true;
+	} else if (!strcmp(filt->action, "stop")) {
+		filt->start = false;
+	} else if (!strcmp(filt->action, "tracestop")) {
+		filt->start = false;
+		filt->range = true;
+		filt->action += 5; /* Change 'tracestop' to 'stop' */
+	} else {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int parse_sym_idx(char **inp, int *idx)
+{
+	*idx = -1;
+
+	*inp += strspn(*inp, " ");
+
+	if (**inp != '#')
+		return 0;
+
+	*inp += 1;
+
+	if (**inp == 'g' || **inp == 'G') {
+		*inp += 1;
+		*idx = 0;
+	} else {
+		unsigned long num;
+		char *endptr;
+
+		errno = 0;
+		num = strtoul(*inp, &endptr, 0);
+		if (errno)
+			return -errno;
+		if (endptr == *inp || num > INT_MAX)
+			return -EINVAL;
+		*inp = endptr;
+		*idx = num;
+	}
+
+	return 0;
+}
+
+static int parse_addr_size(char **inp, u64 *num, const char **str, int *idx)
+{
+	int err = parse_num_or_str(inp, num, str, " ");
+
+	if (!err && *str)
+		err = parse_sym_idx(inp, idx);
+
+	return err;
+}
+
+static int parse_one_filter(struct addr_filter *filt, const char **filter_inp)
+{
+	char *fstr;
+	int err;
+
+	filt->str = fstr = strdup(*filter_inp);
+	if (!fstr)
+		return -ENOMEM;
+
+	err = parse_num_or_str(&fstr, NULL, &filt->action, " ");
+	if (err)
+		goto out_err;
+
+	err = parse_action(filt);
+	if (err)
+		goto out_err;
+
+	err = parse_addr_size(&fstr, &filt->addr, &filt->sym_from,
+			      &filt->sym_from_idx);
+	if (err)
+		goto out_err;
+
+	fstr += strspn(fstr, " ");
+
+	if (*fstr == '/') {
+		fstr += 1;
+		err = parse_addr_size(&fstr, &filt->size, &filt->sym_to,
+				      &filt->sym_to_idx);
+		if (err)
+			goto out_err;
+		filt->range = true;
+	}
+
+	fstr += strspn(fstr, " ");
+
+	if (*fstr == '@') {
+		fstr += 1;
+		err = parse_num_or_str(&fstr, NULL, &filt->filename, " ,");
+		if (err)
+			goto out_err;
+	}
+
+	fstr += strspn(fstr, " ,");
+
+	*filter_inp += fstr - filt->str;
+
+	return 0;
+
+out_err:
+	addr_filter__free_str(filt);
+
+	return err;
+}
+
+int addr_filters__parse_bare_filter(struct addr_filters *filts,
+				    const char *filter)
+{
+	struct addr_filter *filt;
+	const char *fstr = filter;
+	int err;
+
+	while (*fstr) {
+		filt = addr_filter__new();
+		err = parse_one_filter(filt, &fstr);
+		if (err) {
+			addr_filter__free(filt);
+			addr_filters__exit(filts);
+			return err;
+		}
+		addr_filters__add(filts, filt);
+	}
+
+	return 0;
+}
+
+struct sym_args {
+	const char	*name;
+	u64		start;
+	u64		size;
+	int		idx;
+	int		cnt;
+	bool		started;
+	bool		global;
+	bool		selected;
+	bool		duplicate;
+	bool		near;
+};
+
+static bool kern_sym_match(struct sym_args *args, const char *name, char type)
+{
+	/* A function with the same name, and global or the n'th found or any */
+	return symbol_type__is_a(type, MAP__FUNCTION) &&
+	       !strcmp(name, args->name) &&
+	       ((args->global && isupper(type)) ||
+		(args->selected && ++(args->cnt) == args->idx) ||
+		(!args->global && !args->selected));
+}
+
+static int find_kern_sym_cb(void *arg, const char *name, char type, u64 start)
+{
+	struct sym_args *args = arg;
+
+	if (args->started) {
+		if (!args->size)
+			args->size = start - args->start;
+		if (args->selected) {
+			if (args->size)
+				return 1;
+		} else if (kern_sym_match(args, name, type)) {
+			args->duplicate = true;
+			return 1;
+		}
+	} else if (kern_sym_match(args, name, type)) {
+		args->started = true;
+		args->start = start;
+	}
+
+	return 0;
+}
+
+static int print_kern_sym_cb(void *arg, const char *name, char type, u64 start)
+{
+	struct sym_args *args = arg;
+
+	if (kern_sym_match(args, name, type)) {
+		pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
+		       ++args->cnt, start, type, name);
+		args->near = true;
+	} else if (args->near) {
+		args->near = false;
+		pr_err("\t\twhich is near\t\t%s\n", name);
+	}
+
+	return 0;
+}
+
+static int sym_not_found_error(const char *sym_name, int idx)
+{
+	if (idx > 0) {
+		pr_err("N'th occurrence (N=%d) of symbol '%s' not found.\n",
+		       idx, sym_name);
+	} else if (!idx) {
+		pr_err("Global symbol '%s' not found.\n", sym_name);
+	} else {
+		pr_err("Symbol '%s' not found.\n", sym_name);
+	}
+	pr_err("Note that symbols must be functions.\n");
+
+	return -EINVAL;
+}
+
+static int find_kern_sym(const char *sym_name, u64 *start, u64 *size, int idx)
+{
+	struct sym_args args = {
+		.name = sym_name,
+		.idx = idx,
+		.global = !idx,
+		.selected = idx > 0,
+	};
+	int err;
+
+	*start = 0;
+	*size = 0;
+
+	err = kallsyms__parse("/proc/kallsyms", &args, find_kern_sym_cb);
+	if (err < 0) {
+		pr_err("Failed to parse /proc/kallsyms\n");
+		return err;
+	}
+
+	if (args.duplicate) {
+		pr_err("Multiple kernel symbols with name '%s'\n", sym_name);
+		args.cnt = 0;
+		kallsyms__parse("/proc/kallsyms", &args, print_kern_sym_cb);
+		pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
+		       sym_name);
+		pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
+		return -EINVAL;
+	}
+
+	if (!args.started) {
+		pr_err("Kernel symbol lookup: ");
+		return sym_not_found_error(sym_name, idx);
+	}
+
+	*start = args.start;
+	*size = args.size;
+
+	return 0;
+}
+
+static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
+			       char type, u64 start)
+{
+	struct sym_args *args = arg;
+
+	if (!symbol_type__is_a(type, MAP__FUNCTION))
+		return 0;
+
+	if (!args->started) {
+		args->started = true;
+		args->start = start;
+	}
+	/* Don't know exactly where the kernel ends, so we add a page */
+	args->size = round_up(start, page_size) + page_size - args->start;
+
+	return 0;
+}
+
+static int addr_filter__entire_kernel(struct addr_filter *filt)
+{
+	struct sym_args args = { .started = false };
+	int err;
+
+	err = kallsyms__parse("/proc/kallsyms", &args, find_entire_kern_cb);
+	if (err < 0 || !args.started) {
+		pr_err("Failed to parse /proc/kallsyms\n");
+		return err;
+	}
+
+	filt->addr = args.start;
+	filt->size = args.size;
+
+	return 0;
+}
+
+static int check_end_after_start(struct addr_filter *filt, u64 start, u64 size)
+{
+	if (start + size >= filt->addr)
+		return 0;
+
+	if (filt->sym_from) {
+		pr_err("Symbol '%s' (0x%"PRIx64") comes before '%s' (0x%"PRIx64")\n",
+		       filt->sym_to, start, filt->sym_from, filt->addr);
+	} else {
+		pr_err("Symbol '%s' (0x%"PRIx64") comes before address 0x%"PRIx64")\n",
+		       filt->sym_to, start, filt->addr);
+	}
+
+	return -EINVAL;
+}
+
+static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
+{
+	bool no_size = false;
+	u64 start, size;
+	int err;
+
+	if (symbol_conf.kptr_restrict) {
+		pr_err("Kernel addresses are restricted. Unable to resolve kernel symbols.\n");
+		return -EINVAL;
+	}
+
+	if (filt->sym_from && !strcmp(filt->sym_from, "*"))
+		return addr_filter__entire_kernel(filt);
+
+	if (filt->sym_from) {
+		err = find_kern_sym(filt->sym_from, &start, &size,
+				    filt->sym_from_idx);
+		if (err)
+			return err;
+		filt->addr = start;
+		if (filt->range && !filt->size && !filt->sym_to) {
+			filt->size = size;
+			no_size = !!size;
+		}
+	}
+
+	if (filt->sym_to) {
+		err = find_kern_sym(filt->sym_to, &start, &size,
+				    filt->sym_to_idx);
+		if (err)
+			return err;
+
+		err = check_end_after_start(filt, start, size);
+		if (err)
+			return err;
+		filt->size = start + size - filt->addr;
+		no_size = !!size;
+	}
+
+	/* The very last symbol in kallsyms does not imply a particular size */
+	if (no_size) {
+		pr_err("Cannot determine size of symbol '%s'\n",
+		       filt->sym_to ? filt->sym_to : filt->sym_from);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct dso *load_dso(const char *name)
+{
+	struct map *map;
+	struct dso *dso;
+
+	map = dso__new_map(name);
+	if (!map)
+		return NULL;
+
+	map__load(map);
+
+	dso = dso__get(map->dso);
+
+	map__put(map);
+
+	return dso;
+}
+
+static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt,
+			  int idx)
+{
+	/* Same name, and global or the n'th found or any */
+	return !arch__compare_symbol_names(name, sym->name) &&
+	       ((!idx && sym->binding == STB_GLOBAL) ||
+		(idx > 0 && ++*cnt == idx) ||
+		idx < 0);
+}
+
+static void print_duplicate_syms(struct dso *dso, const char *sym_name)
+{
+	struct symbol *sym;
+	bool near = false;
+	int cnt = 0;
+
+	pr_err("Multiple symbols with name '%s'\n", sym_name);
+
+	sym = dso__first_symbol(dso, MAP__FUNCTION);
+	while (sym) {
+		if (dso_sym_match(sym, sym_name, &cnt, -1)) {
+			pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
+			       ++cnt, sym->start,
+			       sym->binding == STB_GLOBAL ? 'g' :
+			       sym->binding == STB_LOCAL  ? 'l' : 'w',
+			       sym->name);
+			near = true;
+		} else if (near) {
+			near = false;
+			pr_err("\t\twhich is near\t\t%s\n", sym->name);
+		}
+		sym = dso__next_symbol(sym);
+	}
+
+	pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
+	       sym_name);
+	pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
+}
+
+static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
+			u64 *size, int idx)
+{
+	struct symbol *sym;
+	int cnt = 0;
+
+	*start = 0;
+	*size = 0;
+
+	sym = dso__first_symbol(dso, MAP__FUNCTION);
+	while (sym) {
+		if (*start) {
+			if (!*size)
+				*size = sym->start - *start;
+			if (idx > 0) {
+				if (*size)
+					return 1;
+			} else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
+				print_duplicate_syms(dso, sym_name);
+				return -EINVAL;
+			}
+		} else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
+			*start = sym->start;
+			*size = sym->end - sym->start;
+		}
+		sym = dso__next_symbol(sym);
+	}
+
+	if (!*start)
+		return sym_not_found_error(sym_name, idx);
+
+	return 0;
+}
+
+static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
+{
+	struct symbol *first_sym = dso__first_symbol(dso, MAP__FUNCTION);
+	struct symbol *last_sym = dso__last_symbol(dso, MAP__FUNCTION);
+
+	if (!first_sym || !last_sym) {
+		pr_err("Failed to determine filter for %s\nNo symbols found.\n",
+		       filt->filename);
+		return -EINVAL;
+	}
+
+	filt->addr = first_sym->start;
+	filt->size = last_sym->end - first_sym->start;
+
+	return 0;
+}
+
+static int addr_filter__resolve_syms(struct addr_filter *filt)
+{
+	u64 start, size;
+	struct dso *dso;
+	int err = 0;
+
+	if (!filt->sym_from && !filt->sym_to)
+		return 0;
+
+	if (!filt->filename)
+		return addr_filter__resolve_kernel_syms(filt);
+
+	dso = load_dso(filt->filename);
+	if (!dso) {
+		pr_err("Failed to load symbols from: %s\n", filt->filename);
+		return -EINVAL;
+	}
+
+	if (filt->sym_from && !strcmp(filt->sym_from, "*")) {
+		err = addr_filter__entire_dso(filt, dso);
+		goto put_dso;
+	}
+
+	if (filt->sym_from) {
+		err = find_dso_sym(dso, filt->sym_from, &start, &size,
+				   filt->sym_from_idx);
+		if (err)
+			goto put_dso;
+		filt->addr = start;
+		if (filt->range && !filt->size && !filt->sym_to)
+			filt->size = size;
+	}
+
+	if (filt->sym_to) {
+		err = find_dso_sym(dso, filt->sym_to, &start, &size,
+				   filt->sym_to_idx);
+		if (err)
+			goto put_dso;
+
+		err = check_end_after_start(filt, start, size);
+		if (err)
+			return err;
+
+		filt->size = start + size - filt->addr;
+	}
+
+put_dso:
+	dso__put(dso);
+
+	return err;
+}
+
+static char *addr_filter__to_str(struct addr_filter *filt)
+{
+	char filename_buf[PATH_MAX];
+	const char *at = "";
+	const char *fn = "";
+	char *filter;
+	int err;
+
+	if (filt->filename) {
+		at = "@";
+		fn = realpath(filt->filename, filename_buf);
+		if (!fn)
+			return NULL;
+	}
+
+	if (filt->range) {
+		err = asprintf(&filter, "%s 0x%"PRIx64"/0x%"PRIx64"%s%s",
+			       filt->action, filt->addr, filt->size, at, fn);
+	} else {
+		err = asprintf(&filter, "%s 0x%"PRIx64"%s%s",
+			       filt->action, filt->addr, at, fn);
+	}
+
+	return err < 0 ? NULL : filter;
+}
+
+static int parse_addr_filter(struct perf_evsel *evsel, const char *filter,
+			     int max_nr)
+{
+	struct addr_filters filts;
+	struct addr_filter *filt;
+	int err;
+
+	addr_filters__init(&filts);
+
+	err = addr_filters__parse_bare_filter(&filts, filter);
+	if (err)
+		goto out_exit;
+
+	if (filts.cnt > max_nr) {
+		pr_err("Error: number of address filters (%d) exceeds maximum (%d)\n",
+		       filts.cnt, max_nr);
+		err = -EINVAL;
+		goto out_exit;
+	}
+
+	list_for_each_entry(filt, &filts.head, list) {
+		char *new_filter;
+
+		err = addr_filter__resolve_syms(filt);
+		if (err)
+			goto out_exit;
+
+		new_filter = addr_filter__to_str(filt);
+		if (!new_filter) {
+			err = -ENOMEM;
+			goto out_exit;
+		}
+
+		if (perf_evsel__append_addr_filter(evsel, new_filter)) {
+			err = -ENOMEM;
+			goto out_exit;
+		}
+	}
+
+out_exit:
+	addr_filters__exit(&filts);
+
+	if (err) {
+		pr_err("Failed to parse address filter: '%s'\n", filter);
+		pr_err("Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [@<file name>]\n");
+		pr_err("Where multiple filters are separated by space or comma.\n");
+	}
+
+	return err;
+}
+
+static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel)
+{
+	struct perf_pmu *pmu = NULL;
+
+	while ((pmu = perf_pmu__scan(pmu)) != NULL) {
+		if (pmu->type == evsel->attr.type)
+			break;
+	}
+
+	return pmu;
+}
+
+static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
+{
+	struct perf_pmu *pmu = perf_evsel__find_pmu(evsel);
+	int nr_addr_filters = 0;
+
+	if (!pmu)
+		return 0;
+
+	perf_pmu__scan_file(pmu, "nr_addr_filters", "%d", &nr_addr_filters);
+
+	return nr_addr_filters;
+}
+
+int auxtrace_parse_filters(struct perf_evlist *evlist)
+{
+	struct perf_evsel *evsel;
+	char *filter;
+	int err, max_nr;
+
+	evlist__for_each_entry(evlist, evsel) {
+		filter = evsel->filter;
+		max_nr = perf_evsel__nr_addr_filter(evsel);
+		if (!filter || !max_nr)
+			continue;
+		evsel->filter = NULL;
+		err = parse_addr_filter(evsel, filter, max_nr);
+		free(filter);
+		if (err)
+			return err;
+		pr_debug("Address filter: %s\n", evsel->filter);
+	}
+
+	return 0;
+}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 09286f1..26fb1ee 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -318,6 +318,48 @@ struct auxtrace_record {
 	unsigned int alignment;
 };
 
+/**
+ * struct addr_filter - address filter.
+ * @list: list node
+ * @range: true if it is a range filter
+ * @start: true if action is 'filter' or 'start'
+ * @action: 'filter', 'start' or 'stop' ('tracestop' is accepted but converted
+ *          to 'stop')
+ * @sym_from: symbol name for the filter address
+ * @sym_to: symbol name that determines the filter size
+ * @sym_from_idx: selects n'th from symbols with the same name (0 means global
+ *                and less than 0 means symbol must be unique)
+ * @sym_to_idx: same as @sym_from_idx but for @sym_to
+ * @addr: filter address
+ * @size: filter region size (for range filters)
+ * @filename: DSO file name or NULL for the kernel
+ * @str: allocated string that contains the other string members
+ */
+struct addr_filter {
+	struct list_head	list;
+	bool			range;
+	bool			start;
+	const char		*action;
+	const char		*sym_from;
+	const char		*sym_to;
+	int			sym_from_idx;
+	int			sym_to_idx;
+	u64			addr;
+	u64			size;
+	const char		*filename;
+	char			*str;
+};
+
+/**
+ * struct addr_filters - list of address filters.
+ * @head: list of address filters
+ * @cnt: number of address filters
+ */
+struct addr_filters {
+	struct list_head	head;
+	int			cnt;
+};
+
 #ifdef HAVE_AUXTRACE_SUPPORT
 
 /*
@@ -482,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session,
 				      union perf_event *event);
 void events_stats__auxtrace_error_warn(const struct events_stats *stats);
 
+void addr_filters__init(struct addr_filters *filts);
+void addr_filters__exit(struct addr_filters *filts);
+int addr_filters__parse_bare_filter(struct addr_filters *filts,
+				    const char *filter);
+int auxtrace_parse_filters(struct perf_evlist *evlist);
+
 static inline int auxtrace__process_event(struct perf_session *session,
 					  union perf_event *event,
 					  struct perf_sample *sample,
@@ -640,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
 {
 }
 
+static inline
+int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
+{
+	return 0;
+}
+
 int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
 			struct auxtrace_mmap_params *mp,
 			void *userpg, int fd);

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

* [tip:perf/core] perf probe: Increase debug level of SDT debug messages
  2016-09-23 14:38 ` [PATCH 08/16] perf tools: Increase debug level of SDT debug messages Adrian Hunter
  2016-09-24  0:15   ` Masami Hiramatsu
@ 2016-09-29 18:15   ` tip-bot for Adrian Hunter
  1 sibling, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:15 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, hpa, mhiramat, mingo, adrian.hunter, mathieu.poirier,
	jolsa, linux-kernel, tglx

Commit-ID:  f9655200ecd2d6cc13900a727150177b94ca229e
Gitweb:     http://git.kernel.org/tip/f9655200ecd2d6cc13900a727150177b94ca229e
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:40 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:02 -0300

perf probe: Increase debug level of SDT debug messages

Two SDT debug messages can occur for every DSO which is too noisy.
Consequently, increase debug level of SDT messages.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-9-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/build-id.c   | 4 ++--
 tools/perf/util/probe-file.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5651f3c..e528c40 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -620,7 +620,7 @@ static int build_id_cache__add_sdt_cache(const char *sbuild_id,
 
 	ret = probe_cache__scan_sdt(cache, realname);
 	if (ret >= 0) {
-		pr_debug("Found %d SDTs in %s\n", ret, realname);
+		pr_debug4("Found %d SDTs in %s\n", ret, realname);
 		if (probe_cache__commit(cache) < 0)
 			ret = -1;
 	}
@@ -691,7 +691,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
 
 	/* Update SDT cache : error is just warned */
 	if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
-		pr_debug("Failed to update/scan SDT cache for %s\n", realname);
+		pr_debug4("Failed to update/scan SDT cache for %s\n", realname);
 
 out_free:
 	if (!is_kallsyms)
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 6f931e4..436b647 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -699,7 +699,7 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 	INIT_LIST_HEAD(&sdtlist);
 	ret = get_sdt_note_list(&sdtlist, pathname);
 	if (ret < 0) {
-		pr_debug("Failed to get sdt note: %d\n", ret);
+		pr_debug4("Failed to get sdt note: %d\n", ret);
 		return ret;
 	}
 	list_for_each_entry(note, &sdtlist, note_list) {

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

* [tip:perf/core] perf intel-pt: Fix snapshot overlap detection decoder errors
  2016-09-23 14:38 ` [PATCH 09/16] perf intel-pt: Fix snapshot overlap detection decoder errors Adrian Hunter
@ 2016-09-29 18:16   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: hpa, tglx, mathieu.poirier, adrian.hunter, acme, linux-kernel,
	jolsa, mhiramat, mingo

Commit-ID:  810c398bc09b2f2dfde52a7d2483a710612c5fb8
Gitweb:     http://git.kernel.org/tip/810c398bc09b2f2dfde52a7d2483a710612c5fb8
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:41 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:03 -0300

perf intel-pt: Fix snapshot overlap detection decoder errors

Fix occasional decoder errors decoding trace data collected in snapshot
mode.

Snapshot mode can take successive snapshots of trace which might overlap.
The decoder checks whether there is an overlap but only looks at the
current and previous buffer. However buffers that do not contain
synchronization (i.e. PSB) packets cannot be decoded or used for overlap
checking. That means the decoder actually needs to check overlaps between
the current buffer and the previous buffer that contained usable data.
Make that change.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: stable@vger.kernel.org # v4.3+
Link: http://lkml.kernel.org/r/1474641528-18776-10-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index b9cc353..b744ea8 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -241,7 +241,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
 	}
 
 	queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
-
+next:
 	buffer = auxtrace_buffer__next(queue, buffer);
 	if (!buffer) {
 		if (old_buffer)
@@ -264,9 +264,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
 	    intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
 		return -ENOMEM;
 
-	if (old_buffer)
-		auxtrace_buffer__drop_data(old_buffer);
-
 	if (buffer->use_data) {
 		b->len = buffer->use_size;
 		b->buf = buffer->use_data;
@@ -276,6 +273,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
 	}
 	b->ref_timestamp = buffer->reference;
 
+	/*
+	 * If in snapshot mode and the buffer has no usable data, get next
+	 * buffer and again check overlap against old_buffer.
+	 */
+	if (ptq->pt->snapshot_mode && !b->len)
+		goto next;
+
+	if (old_buffer)
+		auxtrace_buffer__drop_data(old_buffer);
+
 	if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
 						      !buffer->consecutive)) {
 		b->consecutive = false;

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

* [tip:perf/core] perf intel-pt: Add support for recording the max non-turbo ratio
  2016-09-23 14:38 ` [PATCH 10/16] perf intel-pt: Add support for recording the max non-turbo ratio Adrian Hunter
@ 2016-09-29 18:16   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: adrian.hunter, mhiramat, acme, mingo, linux-kernel, tglx, jolsa,
	mathieu.poirier, hpa

Commit-ID:  fa8025c37454501a2df4a90ae84ff01f4aff8ba8
Gitweb:     http://git.kernel.org/tip/fa8025c37454501a2df4a90ae84ff01f4aff8ba8
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:42 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:03 -0300

perf intel-pt: Add support for recording the max non-turbo ratio

Previously the maximum non-turbo ratio was calculated from TSC assuming
a 100 MHz multiplier which is correct for current hardware supporting
Intel PT.  However more recent kernels also now export the value, so use
that in preference to the calculated value.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-11-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/x86/util/intel-pt.c |  6 ++++++
 tools/perf/util/intel-pt.c          | 14 +++++++++++++-
 tools/perf/util/intel-pt.h          |  1 +
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index a2412e9..18b2151 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -302,6 +302,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	bool cap_user_time_zero = false, per_cpu_mmaps;
 	u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
 	u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
+	unsigned long max_non_turbo_ratio;
 	int err;
 
 	if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE)
@@ -317,6 +318,10 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 
 	intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
 
+	if (perf_pmu__scan_file(intel_pt_pmu, "max_nonturbo_ratio",
+				"%lu", &max_non_turbo_ratio) != 1)
+		max_non_turbo_ratio = 0;
+
 	if (!session->evlist->nr_mmaps)
 		return -EINVAL;
 
@@ -351,6 +356,7 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
 	auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
 	auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
+	auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
 
 	return 0;
 }
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index b744ea8..77fbf02 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2023,6 +2023,7 @@ static const char * const intel_pt_info_fmts[] = {
 	[INTEL_PT_TSC_CTC_N]		= "  TSC:CTC numerator   %"PRIu64"\n",
 	[INTEL_PT_TSC_CTC_D]		= "  TSC:CTC denominator %"PRIu64"\n",
 	[INTEL_PT_CYC_BIT]		= "  CYC bit             %#"PRIx64"\n",
+	[INTEL_PT_MAX_NONTURBO_RATIO]	= "  Max non-turbo ratio %"PRIu64"\n",
 };
 
 static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2087,6 +2088,15 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				    INTEL_PT_CYC_BIT);
 	}
 
+	if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
+				(sizeof(u64) * INTEL_PT_MAX_NONTURBO_RATIO)) {
+		pt->max_non_turbo_ratio =
+			auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
+		intel_pt_print_info(&auxtrace_info->priv[0],
+				    INTEL_PT_MAX_NONTURBO_RATIO,
+				    INTEL_PT_MAX_NONTURBO_RATIO);
+	}
+
 	pt->timeless_decoding = intel_pt_timeless_decoding(pt);
 	pt->have_tsc = intel_pt_have_tsc(pt);
 	pt->sampling_mode = false;
@@ -2156,7 +2166,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	if (pt->tc.time_mult) {
 		u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000);
 
-		pt->max_non_turbo_ratio = (tsc_freq + 50000000) / 100000000;
+		if (!pt->max_non_turbo_ratio)
+			pt->max_non_turbo_ratio =
+					(tsc_freq + 50000000) / 100000000;
 		intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
 		intel_pt_log("Maximum non-turbo ratio %u\n",
 			     pt->max_non_turbo_ratio);
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h
index 0065949..8b83562 100644
--- a/tools/perf/util/intel-pt.h
+++ b/tools/perf/util/intel-pt.h
@@ -34,6 +34,7 @@ enum {
 	INTEL_PT_TSC_CTC_N,
 	INTEL_PT_TSC_CTC_D,
 	INTEL_PT_CYC_BIT,
+	INTEL_PT_MAX_NONTURBO_RATIO,
 	INTEL_PT_AUXTRACE_PRIV_MAX,
 };
 

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

* [tip:perf/core] perf intel-pt: Fix missing error codes processing auxtrace_info
  2016-09-23 14:38 ` [PATCH 11/16] perf intel-pt: Fix missing error codes processing auxtrace_info Adrian Hunter
@ 2016-09-29 18:17   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: tglx, mathieu.poirier, adrian.hunter, acme, mingo, hpa, mhiramat,
	jolsa, linux-kernel

Commit-ID:  4d34e10a9f9a38c611cac0deda8f91b064282747
Gitweb:     http://git.kernel.org/tip/4d34e10a9f9a38c611cac0deda8f91b064282747
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:43 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:04 -0300

perf intel-pt: Fix missing error codes processing auxtrace_info

Fix 2 places where the err variable was not being set.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-12-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 77fbf02..96519e8 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2138,11 +2138,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 		pt->switch_evsel = intel_pt_find_sched_switch(session->evlist);
 		if (!pt->switch_evsel) {
 			pr_err("%s: missing sched_switch event\n", __func__);
+			err = -EINVAL;
 			goto err_delete_thread;
 		}
 	} else if (pt->have_sched_switch == 2 &&
 		   !intel_pt_find_switch(session->evlist)) {
 		pr_err("%s: missing context_switch attribute flag\n", __func__);
+		err = -EINVAL;
 		goto err_delete_thread;
 	}
 

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

* [tip:perf/core] perf intel-pt: Add a helper function for processing AUXTRACE_INFO
  2016-09-23 14:38 ` [PATCH 12/16] perf intel-pt: Add a helper function for processing AUXTRACE_INFO Adrian Hunter
@ 2016-09-29 18:17   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, tglx, mathieu.poirier, linux-kernel, hpa, adrian.hunter,
	mhiramat, jolsa, mingo

Commit-ID:  40b746a06332799786ba557fe84184428bef62fb
Gitweb:     http://git.kernel.org/tip/40b746a06332799786ba557fe84184428bef62fb
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:44 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:04 -0300

perf intel-pt: Add a helper function for processing AUXTRACE_INFO

Add a helper function 'intel_pt_has()' to make it easier to determine
which members the AUXTRACE_INFO event contains.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-13-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 96519e8..f16b00f 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -2037,6 +2037,12 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
 		fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
 }
 
+static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
+{
+	return auxtrace_info->header.size >=
+		sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1));
+}
+
 int intel_pt_process_auxtrace_info(union perf_event *event,
 				   struct perf_session *session)
 {
@@ -2077,8 +2083,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
 			    INTEL_PT_PER_CPU_MMAPS);
 
-	if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
-					(sizeof(u64) * INTEL_PT_CYC_BIT)) {
+	if (intel_pt_has(auxtrace_info, INTEL_PT_CYC_BIT)) {
 		pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
 		pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
 		pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
@@ -2088,8 +2093,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				    INTEL_PT_CYC_BIT);
 	}
 
-	if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
-				(sizeof(u64) * INTEL_PT_MAX_NONTURBO_RATIO)) {
+	if (intel_pt_has(auxtrace_info, INTEL_PT_MAX_NONTURBO_RATIO)) {
 		pt->max_non_turbo_ratio =
 			auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
 		intel_pt_print_info(&auxtrace_info->priv[0],

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

* [tip:perf/core] perf intel-pt: Record address filter in AUXTRACE_INFO event
  2016-09-23 14:38 ` [PATCH 13/16] perf intel-pt: Record address filter in AUXTRACE_INFO event Adrian Hunter
@ 2016-09-29 18:17   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:17 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, tglx, acme, mingo, mhiramat, hpa, adrian.hunter,
	mathieu.poirier, jolsa

Commit-ID:  c093f308cea3eb4be3ed6e7e9ad54bf67a26abe4
Gitweb:     http://git.kernel.org/tip/c093f308cea3eb4be3ed6e7e9ad54bf67a26abe4
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:45 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:05 -0300

perf intel-pt: Record address filter in AUXTRACE_INFO event

The address filter is needed to help decode the trace, so store it in
the AUXTRACE_INFO event.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-14-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/x86/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++---
 tools/perf/util/intel-pt.h          |  3 +--
 2 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index 18b2151..90fa228 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -62,6 +62,7 @@ struct intel_pt_recording {
 	size_t				snapshot_ref_buf_size;
 	int				snapshot_ref_cnt;
 	struct intel_pt_snapshot_ref	*snapshot_refs;
+	size_t				priv_size;
 };
 
 static int intel_pt_parse_terms_with_default(struct list_head *formats,
@@ -273,11 +274,37 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
 	return attr;
 }
 
+static const char *intel_pt_find_filter(struct perf_evlist *evlist,
+					struct perf_pmu *intel_pt_pmu)
+{
+	struct perf_evsel *evsel;
+
+	evlist__for_each_entry(evlist, evsel) {
+		if (evsel->attr.type == intel_pt_pmu->type)
+			return evsel->filter;
+	}
+
+	return NULL;
+}
+
+static size_t intel_pt_filter_bytes(const char *filter)
+{
+	size_t len = filter ? strlen(filter) : 0;
+
+	return len ? roundup(len + 1, 8) : 0;
+}
+
 static size_t
-intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused,
-			struct perf_evlist *evlist __maybe_unused)
+intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
 {
-	return INTEL_PT_AUXTRACE_PRIV_SIZE;
+	struct intel_pt_recording *ptr =
+			container_of(itr, struct intel_pt_recording, itr);
+	const char *filter = intel_pt_find_filter(evlist, ptr->intel_pt_pmu);
+
+	ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) +
+			 intel_pt_filter_bytes(filter);
+
+	return ptr->priv_size;
 }
 
 static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
@@ -303,9 +330,12 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
 	u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
 	unsigned long max_non_turbo_ratio;
+	size_t filter_str_len;
+	const char *filter;
+	u64 *info;
 	int err;
 
-	if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE)
+	if (priv_size != ptr->priv_size)
 		return -EINVAL;
 
 	intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
@@ -322,6 +352,9 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 				"%lu", &max_non_turbo_ratio) != 1)
 		max_non_turbo_ratio = 0;
 
+	filter = intel_pt_find_filter(session->evlist, ptr->intel_pt_pmu);
+	filter_str_len = filter ? strlen(filter) : 0;
+
 	if (!session->evlist->nr_mmaps)
 		return -EINVAL;
 
@@ -357,6 +390,16 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
 	auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
 	auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
 	auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
+	auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] = filter_str_len;
+
+	info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
+
+	if (filter_str_len) {
+		size_t len = intel_pt_filter_bytes(filter);
+
+		strncpy((char *)info, filter, len);
+		info += len >> 3;
+	}
 
 	return 0;
 }
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h
index 8b83562..e13b14e 100644
--- a/tools/perf/util/intel-pt.h
+++ b/tools/perf/util/intel-pt.h
@@ -35,11 +35,10 @@ enum {
 	INTEL_PT_TSC_CTC_D,
 	INTEL_PT_CYC_BIT,
 	INTEL_PT_MAX_NONTURBO_RATIO,
+	INTEL_PT_FILTER_STR_LEN,
 	INTEL_PT_AUXTRACE_PRIV_MAX,
 };
 
-#define INTEL_PT_AUXTRACE_PRIV_SIZE (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64))
-
 struct auxtrace_record;
 struct perf_tool;
 union perf_event;

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

* [tip:perf/core] perf intel-pt: Read address filter from AUXTRACE_INFO event
  2016-09-23 14:38 ` [PATCH 14/16] perf intel-pt: Read address filter from " Adrian Hunter
@ 2016-09-29 18:18   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:18 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: jolsa, hpa, tglx, adrian.hunter, mathieu.poirier, acme, mhiramat,
	mingo, linux-kernel

Commit-ID:  2b9e32c47fd3edb0373067de7a151775b0e005c2
Gitweb:     http://git.kernel.org/tip/2b9e32c47fd3edb0373067de7a151775b0e005c2
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:46 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:05 -0300

perf intel-pt: Read address filter from AUXTRACE_INFO event

Read the address filter from the AUXTRACE_INFO event in preparation for
using it to assist in decoding.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-15-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index f16b00f..c9fec19 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -103,6 +103,8 @@ struct intel_pt {
 	unsigned max_non_turbo_ratio;
 
 	unsigned long num_events;
+
+	char *filter;
 };
 
 enum switch_state {
@@ -1774,6 +1776,7 @@ static void intel_pt_free(struct perf_session *session)
 	intel_pt_free_events(session);
 	session->auxtrace = NULL;
 	thread__put(pt->unknown_thread);
+	zfree(&pt->filter);
 	free(pt);
 }
 
@@ -2024,6 +2027,7 @@ static const char * const intel_pt_info_fmts[] = {
 	[INTEL_PT_TSC_CTC_D]		= "  TSC:CTC denominator %"PRIu64"\n",
 	[INTEL_PT_CYC_BIT]		= "  CYC bit             %#"PRIx64"\n",
 	[INTEL_PT_MAX_NONTURBO_RATIO]	= "  Max non-turbo ratio %"PRIu64"\n",
+	[INTEL_PT_FILTER_STR_LEN]	= "  Filter string len.  %"PRIu64"\n",
 };
 
 static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2037,6 +2041,14 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
 		fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
 }
 
+static void intel_pt_print_info_str(const char *name, const char *str)
+{
+	if (!dump_trace)
+		return;
+
+	fprintf(stdout, "  %-20s%s\n", name, str ? str : "");
+}
+
 static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
 {
 	return auxtrace_info->header.size >=
@@ -2049,6 +2061,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
 	size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
 	struct intel_pt *pt;
+	void *info_end;
+	u64 *info;
 	int err;
 
 	if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2101,6 +2115,42 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				    INTEL_PT_MAX_NONTURBO_RATIO);
 	}
 
+	info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
+	info_end = (void *)info + auxtrace_info->header.size;
+
+	if (intel_pt_has(auxtrace_info, INTEL_PT_FILTER_STR_LEN)) {
+		size_t len;
+
+		len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN];
+		intel_pt_print_info(&auxtrace_info->priv[0],
+				    INTEL_PT_FILTER_STR_LEN,
+				    INTEL_PT_FILTER_STR_LEN);
+		if (len) {
+			const char *filter = (const char *)info;
+
+			len = roundup(len + 1, 8);
+			info += len >> 3;
+			if ((void *)info > info_end) {
+				pr_err("%s: bad filter string length\n", __func__);
+				err = -EINVAL;
+				goto err_free_queues;
+			}
+			pt->filter = memdup(filter, len);
+			if (!pt->filter) {
+				err = -ENOMEM;
+				goto err_free_queues;
+			}
+			if (session->header.needs_swap)
+				mem_bswap_64(pt->filter, len);
+			if (pt->filter[len - 1]) {
+				pr_err("%s: filter string not null terminated\n", __func__);
+				err = -EINVAL;
+				goto err_free_queues;
+			}
+		}
+		intel_pt_print_info_str("Filter string", pt->filter);
+	}
+
 	pt->timeless_decoding = intel_pt_timeless_decoding(pt);
 	pt->have_tsc = intel_pt_have_tsc(pt);
 	pt->sampling_mode = false;
@@ -2218,6 +2268,7 @@ err_free_queues:
 	auxtrace_queues__free(&pt->queues);
 	session->auxtrace = NULL;
 err_free:
+	zfree(&pt->filter);
 	free(pt);
 	return err;
 }

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

* [tip:perf/core] perf intel-pt: Enable decoder to handle TIP.PGD with missing IP
  2016-09-23 14:38 ` [PATCH 15/16] perf intel-pt: Enable decoder to handle TIP.PGD with missing IP Adrian Hunter
@ 2016-09-29 18:18   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:18 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mhiramat, adrian.hunter, mingo, hpa, mathieu.poirier,
	linux-kernel, tglx, acme, jolsa

Commit-ID:  9f1d122b528ef3ffcef1bdcf6a3dddf9450a864e
Gitweb:     http://git.kernel.org/tip/9f1d122b528ef3ffcef1bdcf6a3dddf9450a864e
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:47 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:06 -0300

perf intel-pt: Enable decoder to handle TIP.PGD with missing IP

When address filters are used, the decoder must detect the end of a
filter region (or a branch into a tracestop region) by matching Packet
Generation Disabled (TIP.PGD) packets against the object code using the
IP given in the packet. However, due to errata SKL014 "Intel PT TIP.PGD
May Not Have Target IP Payload", that IP may not be present.

Enable the decoder to handle that by adding a new callback function
'pgd_ip()' which indicates whether the IP is not traced, in which case
that is the point where the trace was disabled.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-16-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  | 30 ++++++++++++++++++++++
 .../perf/util/intel-pt-decoder/intel-pt-decoder.h  |  1 +
 2 files changed, 31 insertions(+)

diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 8ff6c6a..7591a0c 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -80,6 +80,7 @@ struct intel_pt_decoder {
 	int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
 			 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
 			 uint64_t max_insn_cnt, void *data);
+	bool (*pgd_ip)(uint64_t ip, void *data);
 	void *data;
 	struct intel_pt_state state;
 	const unsigned char *buf;
@@ -186,6 +187,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
 
 	decoder->get_trace          = params->get_trace;
 	decoder->walk_insn          = params->walk_insn;
+	decoder->pgd_ip             = params->pgd_ip;
 	decoder->data               = params->data;
 	decoder->return_compression = params->return_compression;
 
@@ -1008,6 +1010,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
 	int err;
 
 	err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0);
+	if (err == INTEL_PT_RETURN &&
+	    decoder->pgd_ip &&
+	    decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
+	    (decoder->state.type & INTEL_PT_BRANCH) &&
+	    decoder->pgd_ip(decoder->state.to_ip, decoder->data)) {
+		/* Unconditional branch leaving filter region */
+		decoder->no_progress = 0;
+		decoder->pge = false;
+		decoder->continuous_period = false;
+		decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
+		decoder->state.to_ip = 0;
+		return 0;
+	}
 	if (err == INTEL_PT_RETURN)
 		return 0;
 	if (err)
@@ -1036,6 +1051,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
 	}
 
 	if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
+		uint64_t to_ip = decoder->ip + intel_pt_insn.length +
+				 intel_pt_insn.rel;
+
+		if (decoder->pgd_ip &&
+		    decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
+		    decoder->pgd_ip(to_ip, decoder->data)) {
+			/* Conditional branch leaving filter region */
+			decoder->pge = false;
+			decoder->continuous_period = false;
+			decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
+			decoder->ip = to_ip;
+			decoder->state.from_ip = decoder->ip;
+			decoder->state.to_ip = 0;
+			return 0;
+		}
 		intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
 				decoder->ip);
 		decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 02c38fe..8939998 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -83,6 +83,7 @@ struct intel_pt_params {
 	int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
 			 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
 			 uint64_t max_insn_cnt, void *data);
+	bool (*pgd_ip)(uint64_t ip, void *data);
 	void *data;
 	bool return_compression;
 	uint64_t period;

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

* [tip:perf/core] perf intel-pt: Fix decoding when there are address filters
  2016-09-23 14:38 ` [PATCH 16/16] perf intel-pt: Fix decoding when there are address filters Adrian Hunter
@ 2016-09-29 18:19   ` tip-bot for Adrian Hunter
  0 siblings, 0 replies; 36+ messages in thread
From: tip-bot for Adrian Hunter @ 2016-09-29 18:19 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, hpa, mhiramat, mathieu.poirier, jolsa, linux-kernel, mingo,
	tglx, adrian.hunter

Commit-ID:  2acee108f58045d07475516852d4282ab73904dc
Gitweb:     http://git.kernel.org/tip/2acee108f58045d07475516852d4282ab73904dc
Author:     Adrian Hunter <adrian.hunter@intel.com>
AuthorDate: Fri, 23 Sep 2016 17:38:48 +0300
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 29 Sep 2016 11:17:06 -0300

perf intel-pt: Fix decoding when there are address filters

Due to errata SKL014 "Intel PT TIP.PGD May Not Have Target IP Payload",
the Intel PT decoder needs to match address filters against TIP.PGD
packets.  Parse the address filters and implement the decoder's
'pgd_ip()' callback to match the IP against the filter regions.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Link: http://lkml.kernel.org/r/1474641528-18776-17-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/intel-pt.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index c9fec19..dc041d4 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -105,6 +105,7 @@ struct intel_pt {
 	unsigned long num_events;
 
 	char *filter;
+	struct addr_filters filts;
 };
 
 enum switch_state {
@@ -550,6 +551,76 @@ out_no_cache:
 	return 0;
 }
 
+static bool intel_pt_match_pgd_ip(struct intel_pt *pt, uint64_t ip,
+				  uint64_t offset, const char *filename)
+{
+	struct addr_filter *filt;
+	bool have_filter   = false;
+	bool hit_tracestop = false;
+	bool hit_filter    = false;
+
+	list_for_each_entry(filt, &pt->filts.head, list) {
+		if (filt->start)
+			have_filter = true;
+
+		if ((filename && !filt->filename) ||
+		    (!filename && filt->filename) ||
+		    (filename && strcmp(filename, filt->filename)))
+			continue;
+
+		if (!(offset >= filt->addr && offset < filt->addr + filt->size))
+			continue;
+
+		intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s hit filter: %s offset %#"PRIx64" size %#"PRIx64"\n",
+			     ip, offset, filename ? filename : "[kernel]",
+			     filt->start ? "filter" : "stop",
+			     filt->addr, filt->size);
+
+		if (filt->start)
+			hit_filter = true;
+		else
+			hit_tracestop = true;
+	}
+
+	if (!hit_tracestop && !hit_filter)
+		intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s is not in a filter region\n",
+			     ip, offset, filename ? filename : "[kernel]");
+
+	return hit_tracestop || (have_filter && !hit_filter);
+}
+
+static int __intel_pt_pgd_ip(uint64_t ip, void *data)
+{
+	struct intel_pt_queue *ptq = data;
+	struct thread *thread;
+	struct addr_location al;
+	u8 cpumode;
+	u64 offset;
+
+	if (ip >= ptq->pt->kernel_start)
+		return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
+
+	cpumode = PERF_RECORD_MISC_USER;
+
+	thread = ptq->thread;
+	if (!thread)
+		return -EINVAL;
+
+	thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al);
+	if (!al.map || !al.map->dso)
+		return -EINVAL;
+
+	offset = al.map->map_ip(al.map, ip);
+
+	return intel_pt_match_pgd_ip(ptq->pt, ip, offset,
+				     al.map->dso->long_name);
+}
+
+static bool intel_pt_pgd_ip(uint64_t ip, void *data)
+{
+	return __intel_pt_pgd_ip(ip, data) > 0;
+}
+
 static bool intel_pt_get_config(struct intel_pt *pt,
 				struct perf_event_attr *attr, u64 *config)
 {
@@ -726,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
 	params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
 	params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
 
+	if (pt->filts.cnt > 0)
+		params.pgd_ip = intel_pt_pgd_ip;
+
 	if (pt->synth_opts.instructions) {
 		if (pt->synth_opts.period) {
 			switch (pt->synth_opts.period_type) {
@@ -1776,6 +1850,7 @@ static void intel_pt_free(struct perf_session *session)
 	intel_pt_free_events(session);
 	session->auxtrace = NULL;
 	thread__put(pt->unknown_thread);
+	addr_filters__exit(&pt->filts);
 	zfree(&pt->filter);
 	free(pt);
 }
@@ -2073,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 	if (!pt)
 		return -ENOMEM;
 
+	addr_filters__init(&pt->filts);
+
 	perf_config(intel_pt_perf_config, pt);
 
 	err = auxtrace_queues__init(&pt->queues);
@@ -2147,6 +2224,10 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
 				err = -EINVAL;
 				goto err_free_queues;
 			}
+			err = addr_filters__parse_bare_filter(&pt->filts,
+							      filter);
+			if (err)
+				goto err_free_queues;
 		}
 		intel_pt_print_info_str("Filter string", pt->filter);
 	}
@@ -2268,6 +2349,7 @@ err_free_queues:
 	auxtrace_queues__free(&pt->queues);
 	session->auxtrace = NULL;
 err_free:
+	addr_filters__exit(&pt->filts);
 	zfree(&pt->filter);
 	free(pt);
 	return err;

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

end of thread, other threads:[~2016-09-29 18:19 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-23 14:38 [PATCH 00/16] perf tools: Add support for using symbols in address filters Adrian Hunter
2016-09-23 14:38 ` [PATCH 01/16] perf record: Fix documentation 'event_sources' -> 'event_source' Adrian Hunter
2016-09-29 18:10   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 02/16] perf tools: Fix MMAP event synthesis broken by MAP_HUGETLB change Adrian Hunter
2016-09-29 18:10   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 03/16] perf script: Fix vanished idle symbols Adrian Hunter
2016-09-29 18:13   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 04/16] perf record: Rename label 'out_symbol_exit' Adrian Hunter
2016-09-29 18:14   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 05/16] perf record: Fix error paths Adrian Hunter
2016-09-29 18:14   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 06/16] perf symbols: Add dso__last_symbol() Adrian Hunter
2016-09-29 18:14   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 07/16] perf record: Add support for using symbols in address filters Adrian Hunter
2016-09-29 18:15   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 08/16] perf tools: Increase debug level of SDT debug messages Adrian Hunter
2016-09-24  0:15   ` Masami Hiramatsu
2016-09-26  7:27     ` Adrian Hunter
2016-09-27 17:42       ` Masami Hiramatsu
2016-09-29 18:15   ` [tip:perf/core] perf probe: " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 09/16] perf intel-pt: Fix snapshot overlap detection decoder errors Adrian Hunter
2016-09-29 18:16   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 10/16] perf intel-pt: Add support for recording the max non-turbo ratio Adrian Hunter
2016-09-29 18:16   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 11/16] perf intel-pt: Fix missing error codes processing auxtrace_info Adrian Hunter
2016-09-29 18:17   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 12/16] perf intel-pt: Add a helper function for processing AUXTRACE_INFO Adrian Hunter
2016-09-29 18:17   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 13/16] perf intel-pt: Record address filter in AUXTRACE_INFO event Adrian Hunter
2016-09-29 18:17   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 14/16] perf intel-pt: Read address filter from " Adrian Hunter
2016-09-29 18:18   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 15/16] perf intel-pt: Enable decoder to handle TIP.PGD with missing IP Adrian Hunter
2016-09-29 18:18   ` [tip:perf/core] " tip-bot for Adrian Hunter
2016-09-23 14:38 ` [PATCH 16/16] perf intel-pt: Fix decoding when there are address filters Adrian Hunter
2016-09-29 18:19   ` [tip:perf/core] " tip-bot for Adrian Hunter

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.