Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL New Arnaldo Carvalho de Melo 2 participants 14 messages Sep 8, 2016 – Sep 9, 2016 perf events

lore
Share & tools
lore

Arnaldo Carvalho de Melo

author maintainer
#0 lore raw

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit c0b172e5b6770048751b2c0a4fe44346c2080c5d:

Merge tag 'perf-core-for-mingo-20160901' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2016-09-05 15:15:49 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160908

for you to fetch changes up to 25b8592e912f085ce2ff736a2927584ddeab238c:

perf powerpc: Fix build-test failure (2016-09-08 13:44:07 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

- Add branch stack / basic block info to 'perf annotate --stdio', where for each branch, we add an asm comment after the instruction with information on how often it was taken and predicted. See example with color output at:

http://vger.kernel.org/~acme/perf/annotate_basic_blocks.png

(Peter Zijlstra)

- Only open an evsel in CPUs in its cpu map, fixing some use cases in systems with multiple PMUs with different CPU maps (Mark Rutland)

- Fix handling of huge TLB maps, recognizing it as anonymous (Wang Nan)

Infrastructure:

- Remove the symbol filtering code, i.e. the callbacks passed to all functions that could end up loading a DSO symtab, simplifying the code, eventually allowing what we should have had since day one: removing the 'map' parameter from dso__load() functions (Arnaldo Carvalho de Melo)

Arch specific build fixes:

- Fix detached tarball build on powerpc, where we were still accessing a file outside tools/ (Ravi Bangoria)

----------------------------------------------------------------
Arnaldo Carvalho de Melo (5):
perf symbols: Mark if a symbol is idle in the library perf top: Remove old kernel-only symbol filter perf machine: Remove machine->symbol_filter and friends perf test vmlinux: Remove dead symbol_filter_t code perf symbols: Remove symbol_filter_t machinery

Mark Rutland (2):
perf evlist: Only open events on CPUs an evsel permits perf pmu: Support alternative sysfs cpumask

Peter Zijlstra (1):
perf annotate: Add branch stack / basic block

Ravi Bangoria (1):
perf powerpc: Fix build-test failure

Wang Nan (3):
perf tools: Recognize hugetlb mapping as anon mapping tools lib api fs: Add hugetlbfs filesystem detector perf record: Mark MAP_HUGETLB when synthesizing mmap events

 tools/lib/api/fs/fs.c                       |  15 ++
 tools/lib/api/fs/fs.h                       |   1 +
 tools/perf/arch/powerpc/util/sym-handling.c |   2 +-
 tools/perf/builtin-annotate.c               | 104 +++++++++
 tools/perf/builtin-inject.c                 |   2 +-
 tools/perf/builtin-kmem.c                   |  10 +-
 tools/perf/builtin-script.c                 |   4 +-
 tools/perf/builtin-top.c                    |  30 ---
 tools/perf/perf-sys.h                       |   1 -
 tools/perf/tests/code-reading.c             |   4 +-
 tools/perf/tests/vmlinux-kallsyms.c         |  17 +-
 tools/perf/ui/browsers/annotate.c           |   2 +-
 tools/perf/ui/browsers/map.c                |   4 +-
 tools/perf/util/Build                       |   1 +
 tools/perf/util/annotate.c                  |  95 +++++++-
 tools/perf/util/annotate.h                  |   1 +
 tools/perf/util/block-range.c               | 328 ++++++++++++++++++++++++++++
 tools/perf/util/block-range.h               |  71 ++++++
 tools/perf/util/event.c                     |  21 +-
 tools/perf/util/evlist.c                    |   8 +-
 tools/perf/util/intel-bts.c                 |   2 +-
 tools/perf/util/intel-pt.c                  |   4 +-
 tools/perf/util/machine.c                   |  38 +---
 tools/perf/util/machine.h                   |  34 +--
 tools/perf/util/map.c                       |  50 ++---
 tools/perf/util/map.h                       |  32 +--
 tools/perf/util/pmu.c                       |  15 +-
 tools/perf/util/probe-event.c               |  17 +-
 tools/perf/util/symbol-elf.c                |  32 +--
 tools/perf/util/symbol-minimal.c            |   4 +-
 tools/perf/util/symbol.c                    | 134 ++++++------
 tools/perf/util/symbol.h                    |  20 +-
 32 files changed, 817 insertions(+), 286 deletions(-)
 create mode 100644 tools/perf/util/block-range.c
 create mode 100644 tools/perf/util/block-range.h

Build stats:

[root@jouet ~]# time dm
1 69.078 alpine:3.4: Ok
2 24.055 android-ndk:r12b-arm: Ok
3 71.911 archlinux:latest: Ok
4 41.209 centos:5: Ok
5 58.240 centos:6: Ok
6 67.238 centos:7: Ok
7 62.040 debian:7: Ok
8 69.061 debian:8: Ok
9 38.124 debian:experimental: Ok
10 67.623 fedora:20: Ok
11 71.458 fedora:21: Ok
12 70.807 fedora:22: Ok
13 71.013 fedora:23: Ok
14 73.330 fedora:24: Ok
15 30.062 fedora:24-x-ARC-uClibc: Ok
16 77.616 fedora:rawhide: Ok
17 73.663 mageia:5: Ok
18 69.264 opensuse:13.2: Ok
19 71.532 opensuse:42.1: Ok
20 76.282 opensuse:tumbleweed: Ok
21 54.666 ubuntu:12.04.5: Ok
22 37.170 ubuntu:14.04: Ok
23 66.101 ubuntu:14.04.4: Ok
24 68.881 ubuntu:15.10: Ok
25 62.698 ubuntu:16.04: Ok
26 53.046 ubuntu:16.04-x-arm: Ok
27 51.609 ubuntu:16.04-x-arm64: Ok
28 51.842 ubuntu:16.04-x-powerpc64: Ok
29 53.347 ubuntu:16.04-x-powerpc64el: Ok
30 72.280 ubuntu:16.10: Ok
31 54.078 ubuntu:16.10-x-s390: Ok

real 31m19.919s
user 0m1.890s
sys 0m2.201s
[root@jouet ~]#

author maintainer
#1 lore raw

PATCH 1/12 perf symbols: Mark if a symbol is idle in the library

From: Arnaldo Carvalho de Melo <[email protected]>

This was being done just in 'perf top', but grouping idle symbols should be useful in other places as well, so remove one more symbol_filter_t user by moving this to the symbol library.

---
 tools/perf/builtin-top.c     |  3 ---
 tools/perf/util/symbol-elf.c |  2 +-
 tools/perf/util/symbol.c     | 32 +++++++++++++++++++++++---------
 tools/perf/util/symbol.h     |  2 +-
 4 files changed, 25 insertions(+), 14 deletions(-)
tools/perf/builtin-top.c +0 -3
index e0919006fcba..6f48df14e277 100644
@@ -679,9 +679,6 @@ static int symbol_filter(struct map *map, struct symbol *sym)
 	    strstr(name, "_text_end"))
 		return 1;
 
-	if (symbol__is_idle(sym))
-		sym->idle = 1;
-
 	return 0;
 }
 
tools/perf/util/symbol-elf.c +1 -1
index 295d3147a803..bd91a4f67080 100644
@@ -1127,7 +1127,7 @@ new_symbol:
 		if (filter && filter(curr_map, f))
 			symbol__delete(f);
 		else {
-			symbols__insert(&curr_dso->symbols[curr_map->type], f);
+			__symbols__insert(&curr_dso->symbols[curr_map->type], f, dso->kernel);
 			nr++;
 		}
 	}
tools/perf/util/symbol.c +23 -9
index 98cd50384c32..4c5788f30ced 100644
@@ -28,6 +28,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
 				symbol_filter_t filter);
 static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
 			symbol_filter_t filter);
+static bool symbol__is_idle(const char *name);
+
 int vmlinux_path__nr_entries;
 char **vmlinux_path;
 
@@ -277,13 +279,24 @@ void symbols__delete(struct rb_root *symbols)
 	}
 }
 
-void symbols__insert(struct rb_root *symbols, struct symbol *sym)
+void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel)
 {
 	struct rb_node **p = &symbols->rb_node;
 	struct rb_node *parent = NULL;
 	const u64 ip = sym->start;
 	struct symbol *s;
 
+	if (kernel) {
+		const char *name = sym->name;
+		/*
+		 * ppc64 uses function descriptors and appends a '.' to the
+		 * start of every instruction address. Remove it.
+		 */
+		if (name[0] == '.')
+			name++;
+		sym->idle = symbol__is_idle(name);
+	}
+
 	while (*p != NULL) {
 		parent = *p;
 		s = rb_entry(parent, struct symbol, rb_node);
@@ -296,6 +309,11 @@ void symbols__insert(struct rb_root *symbols, struct symbol *sym)
 	rb_insert_color(&sym->rb_node, symbols);
 }
 
+void symbols__insert(struct rb_root *symbols, struct symbol *sym)
+{
+	__symbols__insert(symbols, sym, false);
+}
+
 static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 {
 	struct rb_node *n;
@@ -424,7 +442,7 @@ void dso__reset_find_symbol_cache(struct dso *dso)
 
 void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
 {
-	symbols__insert(&dso->symbols[type], sym);
+	__symbols__insert(&dso->symbols[type], sym, dso->kernel);
 
 	/* update the symbol cache if necessary */
 	if (dso->last_find_result[type].addr >= sym->start &&
@@ -546,7 +564,7 @@ struct process_kallsyms_args {
  * These are symbols in the kernel image, so make sure that
  * sym is from a kernel DSO.
  */
-bool symbol__is_idle(struct symbol *sym)
+static bool symbol__is_idle(const char *name)
 {
 	const char * const idle_symbols[] = {
 		"cpu_idle",
@@ -563,14 +581,10 @@ bool symbol__is_idle(struct symbol *sym)
 		"pseries_dedicated_idle_sleep",
 		NULL
 	};
-
 	int i;
 
-	if (!sym)
-		return false;
-
 	for (i = 0; idle_symbols[i]; i++) {
-		if (!strcmp(idle_symbols[i], sym->name))
+		if (!strcmp(idle_symbols[i], name))
 			return true;
 	}
 
@@ -599,7 +613,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
 	 * We will pass the symbols to the filter later, in
 	 * map__split_kallsyms, when we have split the maps per module
 	 */
-	symbols__insert(root, sym);
+	__symbols__insert(root, sym, !strchr(name, '['));
 
 	return 0;
 }
tools/perf/util/symbol.h +1 -1
index e54ee7c78ca3..72d29312a694 100644
@@ -294,7 +294,6 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp);
 bool symbol_type__is_a(char symbol_type, enum map_type map_type);
 bool symbol__restricted_filename(const char *filename,
 				 const char *restricted_filename);
-bool symbol__is_idle(struct symbol *sym);
 int symbol__config_symfs(const struct option *opt __maybe_unused,
 			 const char *dir, int unset __maybe_unused);
 
@@ -304,6 +303,7 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
 int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
 				struct map *map, symbol_filter_t filter);
 
+void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
 void symbols__insert(struct rb_root *symbols, struct symbol *sym);
 void symbols__fixup_duplicate(struct rb_root *symbols);
 void symbols__fixup_end(struct rb_root *symbols);
Signature · 1 line
2.7.4
author maintainer
#2 lore raw

PATCH 2/12 perf top: Remove old kernel-only symbol filter

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

Not needed, we already have code to prune aliases.

---
 tools/perf/builtin-top.c | 27 ---------------------------
 1 file changed, 27 deletions(-)
tools/perf/builtin-top.c +0 -27
index 6f48df14e277..400785702566 100644
@@ -657,31 +657,6 @@ repeat:
 	return NULL;
 }
 
-static int symbol_filter(struct map *map, struct symbol *sym)
-{
-	const char *name = sym->name;
-
-	if (!__map__is_kernel(map))
-		return 0;
-	/*
-	 * ppc64 uses function descriptors and appends a '.' to the
-	 * start of every instruction address. Remove it.
-	 */
-	if (name[0] == '.')
-		name++;
-
-	if (!strcmp(name, "_text") ||
-	    !strcmp(name, "_etext") ||
-	    !strcmp(name, "_sinittext") ||
-	    !strncmp("init_module", name, 11) ||
-	    !strncmp("cleanup_module", name, 14) ||
-	    strstr(name, "_text_start") ||
-	    strstr(name, "_text_end"))
-		return 1;
-
-	return 0;
-}
-
 static int hist_iter__top_callback(struct hist_entry_iter *iter,
 				   struct addr_location *al, bool single,
 				   void *arg)
@@ -946,8 +921,6 @@ static int __cmd_top(struct perf_top *top)
 	if (top->session == NULL)
 		return -1;
 
-	machines__set_symbol_filter(&top->session->machines, symbol_filter);
-
 	if (!objdump_path) {
 		ret = perf_env__lookup_objdump(&top->session->header.env);
 		if (ret)
Signature · 1 line
2.7.4
author maintainer
#3 lore raw

PATCH 3/12 perf machine: Remove machine->symbol_filter and friends

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

Including machines__set_symbol_filter(), not used anymore.

---
 tools/perf/util/event.c     |  8 +++-----
 tools/perf/util/intel-bts.c |  2 +-
 tools/perf/util/intel-pt.c  |  4 ++--
 tools/perf/util/machine.c   | 21 +--------------------
 tools/perf/util/machine.h   |  4 ----
 5 files changed, 7 insertions(+), 32 deletions(-)
tools/perf/util/event.c +3 -5
index e20438b784be..2f91183f2779 100644
@@ -1286,7 +1286,7 @@ try_again:
 		 * must be done prior to using kernel maps.
 		 */
 		if (load_map)
-			map__load(al->map, machine->symbol_filter);
+			map__load(al->map, NULL);
 		al->addr = al->map->map_ip(al->map, al->addr);
 	}
 }
@@ -1297,8 +1297,7 @@ void thread__find_addr_location(struct thread *thread,
 {
 	thread__find_addr_map(thread, cpumode, type, addr, al);
 	if (al->map != NULL)
-		al->sym = map__find_symbol(al->map, al->addr,
-					   thread->mg->machine->symbol_filter);
+		al->sym = map__find_symbol(al->map, al->addr, NULL);
 	else
 		al->sym = NULL;
 }
@@ -1359,8 +1358,7 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
 			al->filtered |= (1 << HIST_FILTER__DSO);
 		}
 
-		al->sym = map__find_symbol(al->map, al->addr,
-					   machine->symbol_filter);
+		al->sym = map__find_symbol(al->map, al->addr, NULL);
 	}
 
 	if (symbol_conf.sym_list &&
tools/perf/util/intel-bts.c +1 -1
index 749e6f2e37ca..240b095eddba 100644
@@ -346,7 +346,7 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
 		goto out_put;
 
 	/* Load maps to ensure dso->is_64_bit has been updated */
-	map__load(al.map, machine->symbol_filter);
+	map__load(al.map, NULL);
 
 	x86_64 = al.map->dso->is_64_bit;
 
tools/perf/util/intel-pt.c +2 -2
index 551ff6f640be..d594052c8184 100644
@@ -477,7 +477,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 		start_ip = *ip;
 
 		/* Load maps to ensure dso->is_64_bit has been updated */
-		map__load(al.map, machine->symbol_filter);
+		map__load(al.map, NULL);
 
 		x86_64 = al.map->dso->is_64_bit;
 
@@ -1294,7 +1294,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
 	if (!map)
 		return 0;
 
-	if (map__load(map, machine->symbol_filter))
+	if (map__load(map, NULL))
 		return 0;
 
 	start = dso__first_symbol(map->dso, MAP__FUNCTION);
tools/perf/util/machine.c +1 -20
index cb6388dbdd98..7940ddc98f8c 100644
@@ -41,7 +41,6 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
 
 	machine->pid = pid;
 
-	machine->symbol_filter = NULL;
 	machine->id_hdr_size = 0;
 	machine->kptr_restrict_warned = false;
 	machine->comm_exec = false;
@@ -148,7 +147,6 @@ void machines__init(struct machines *machines)
 {
 	machine__init(&machines->host, "", HOST_KERNEL_ID);
 	machines->guests = RB_ROOT;
-	machines->symbol_filter = NULL;
 }
 
 void machines__exit(struct machines *machines)
@@ -172,8 +170,6 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
 		return NULL;
 	}
 
-	machine->symbol_filter = machines->symbol_filter;
-
 	while (*p != NULL) {
 		parent = *p;
 		pos = rb_entry(parent, struct machine, rb_node);
@@ -189,21 +185,6 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
 	return machine;
 }
 
-void machines__set_symbol_filter(struct machines *machines,
-				 symbol_filter_t symbol_filter)
-{
-	struct rb_node *nd;
-
-	machines->symbol_filter = symbol_filter;
-	machines->host.symbol_filter = symbol_filter;
-
-	for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
-		struct machine *machine = rb_entry(nd, struct machine, rb_node);
-
-		machine->symbol_filter = symbol_filter;
-	}
-}
-
 void machines__set_comm_exec(struct machines *machines, bool comm_exec)
 {
 	struct rb_node *nd;
@@ -2115,7 +2096,7 @@ int machine__get_kernel_start(struct machine *machine)
 	 */
 	machine->kernel_start = 1ULL << 63;
 	if (map) {
-		err = map__load(map, machine->symbol_filter);
+		err = map__load(map, NULL);
 		if (map->start)
 			machine->kernel_start = map->start;
 	}
tools/perf/util/machine.h +0 -4
index 20739f746bc4..b9e5588499c5 100644
@@ -41,7 +41,6 @@ struct machine {
 	struct map_groups kmaps;
 	struct map	  *vmlinux_maps[MAP__NR_TYPES];
 	u64		  kernel_start;
-	symbol_filter_t	  symbol_filter;
 	pid_t		  *current_tid;
 	union { /* Tool specific area */
 		void	  *priv;
@@ -110,7 +109,6 @@ typedef void (*machine__process_t)(struct machine *machine, void *data);
 struct machines {
 	struct machine host;
 	struct rb_root guests;
-	symbol_filter_t symbol_filter;
 };
 
 void machines__init(struct machines *machines);
@@ -128,8 +126,6 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid);
 void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
 char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
 
-void machines__set_symbol_filter(struct machines *machines,
-				 symbol_filter_t symbol_filter);
 void machines__set_comm_exec(struct machines *machines, bool comm_exec);
 
 struct machine *machine__new_host(void);
Signature · 1 line
2.7.4
author maintainer
#4 lore raw

PATCH 4/12 perf test vmlinux: Remove dead symbol_filter_t code

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We don't need to initialize that area as we're not using it afterwards, leftover, ditch it.

---
 tools/perf/tests/vmlinux-kallsyms.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)
tools/perf/tests/vmlinux-kallsyms.c +1 -10
index 77513bf99d1b..e6925d6400f2 100644
@@ -8,14 +8,6 @@
 #include "debug.h"
 #include "machine.h"
 
-static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
-					   struct symbol *sym)
-{
-	bool *visited = symbol__priv(sym);
-	*visited = true;
-	return 0;
-}
-
 #define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x))
 
 int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
@@ -100,8 +92,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
 	 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
 	 * to fixup the symbols.
 	 */
-	if (machine__load_vmlinux_path(&vmlinux, type,
-				       vmlinux_matches_kallsyms_filter) <= 0) {
+	if (machine__load_vmlinux_path(&vmlinux, type, NULL) <= 0) {
 		pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n");
 		err = TEST_SKIP;
 		goto out;
Signature · 1 line
2.7.4
author maintainer
#5 lore raw

PATCH 5/12 perf symbols: Remove symbol_filter_t machinery

In reply to Arnaldo Carvalho de Melo

From: Arnaldo Carvalho de Melo <[email protected]>

We're not using it anymore, few users were, but we really could do without it, simplify lots of functions by removing it.

---
 tools/perf/arch/powerpc/util/sym-handling.c |   2 +-
 tools/perf/builtin-inject.c                 |   2 +-
 tools/perf/builtin-kmem.c                   |  10 ++-
 tools/perf/builtin-script.c                 |   4 +-
 tools/perf/tests/code-reading.c             |   4 +-
 tools/perf/tests/vmlinux-kallsyms.c         |   8 +--
 tools/perf/ui/browsers/annotate.c           |   2 +-
 tools/perf/ui/browsers/map.c                |   4 +-
 tools/perf/util/annotate.c                  |   2 +-
 tools/perf/util/event.c                     |   8 +--
 tools/perf/util/intel-bts.c                 |   2 +-
 tools/perf/util/intel-pt.c                  |   4 +-
 tools/perf/util/machine.c                   |  19 +++---
 tools/perf/util/machine.h                   |  30 +++-----
 tools/perf/util/map.c                       |  37 ++++------
 tools/perf/util/map.h                       |  32 ++++-----
 tools/perf/util/probe-event.c               |  17 +++--
 tools/perf/util/symbol-elf.c                |  32 +++------
 tools/perf/util/symbol-minimal.c            |   4 +-
 tools/perf/util/symbol.c                    | 102 ++++++++++++----------------
 tools/perf/util/symbol.h                    |  18 ++---
 21 files changed, 141 insertions(+), 202 deletions(-)
tools/perf/arch/powerpc/util/sym-handling.c +1 -1
index 35745a733100..ed9d5d15d5b6 100644
@@ -108,7 +108,7 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
 	int i = 0;
 
 	map = get_target_map(pev->target, pev->uprobes);
-	if (!map || map__load(map, NULL) < 0)
+	if (!map || map__load(map) < 0)
 		return;
 
 	for (i = 0; i < ntevs; i++) {
tools/perf/builtin-inject.c +1 -1
index 73c1c4cc3600..b9bc7e39833a 100644
@@ -429,7 +429,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
 	if (al.map != NULL) {
 		if (!al.map->dso->hit) {
 			al.map->dso->hit = 1;
-			if (map__load(al.map, NULL) >= 0) {
+			if (map__load(al.map) >= 0) {
 				dso__inject_build_id(al.map->dso, tool, machine);
 				/*
 				 * If this fails, too bad, let the other side
tools/perf/builtin-kmem.c +4 -6
index fdde1bd3e306..d426dcb18ce9 100644
@@ -330,7 +330,7 @@ static int build_alloc_func_list(void)
 	}
 
 	kernel_map = machine__kernel_map(machine);
-	if (map__load(kernel_map, NULL) < 0) {
+	if (map__load(kernel_map) < 0) {
 		pr_err("cannot load kernel map\n");
 		return -ENOENT;
 	}
@@ -979,7 +979,7 @@ static void __print_slab_result(struct rb_root *root,
 		if (is_caller) {
 			addr = data->call_site;
 			if (!raw_ip)
-				sym = machine__find_kernel_function(machine, addr, &map, NULL);
+				sym = machine__find_kernel_function(machine, addr, &map);
 		} else
 			addr = data->ptr;
 
@@ -1043,8 +1043,7 @@ static void __print_page_alloc_result(struct perf_session *session, int n_lines)
 		char *caller = buf;
 
 		data = rb_entry(next, struct page_stat, node);
-		sym = machine__find_kernel_function(machine, data->callsite,
-						    &map, NULL);
+		sym = machine__find_kernel_function(machine, data->callsite, &map);
 		if (sym && sym->name)
 			caller = sym->name;
 		else
@@ -1086,8 +1085,7 @@ static void __print_page_caller_result(struct perf_session *session, int n_lines
 		char *caller = buf;
 
 		data = rb_entry(next, struct page_stat, node);
-		sym = machine__find_kernel_function(machine, data->callsite,
-						    &map, NULL);
+		sym = machine__find_kernel_function(machine, data->callsite, &map);
 		if (sym && sym->name)
 			caller = sym->name;
 		else
tools/perf/builtin-script.c +2 -2
index 6b3c8b0d3276..7228d141a789 100644
@@ -522,11 +522,11 @@ static void print_sample_brstacksym(struct perf_sample *sample,
 
 		thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf);
 		if (alf.map)
-			alf.sym = map__find_symbol(alf.map, alf.addr, NULL);
+			alf.sym = map__find_symbol(alf.map, alf.addr);
 
 		thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
 		if (alt.map)
-			alt.sym = map__find_symbol(alt.map, alt.addr, NULL);
+			alt.sym = map__find_symbol(alt.map, alt.addr);
 
 		symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
 		putchar('/');
tools/perf/tests/code-reading.c +2 -2
index 2af156a8d4e5..ff5bc6363a79 100644
@@ -263,7 +263,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
 	 * Converting addresses for use by objdump requires more information.
 	 * map__load() does that.  See map__rip_2objdump() for details.
 	 */
-	if (map__load(al.map, NULL))
+	if (map__load(al.map))
 		return -1;
 
 	/* objdump struggles with kcore - try each map only once */
@@ -511,7 +511,7 @@ static int do_test_code_reading(bool try_kcore)
 
 	/* Load kernel map */
 	map = machine__kernel_map(machine);
-	ret = map__load(map, NULL);
+	ret = map__load(map);
 	if (ret < 0) {
 		pr_debug("map__load failed\n");
 		goto out_err;
tools/perf/tests/vmlinux-kallsyms.c +4 -4
index e6925d6400f2..a5082331f246 100644
@@ -54,7 +54,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
 	 * be compacted against the list of modules found in the "vmlinux"
 	 * code and with the one got from /proc/modules from the "kallsyms" code.
 	 */
-	if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true, NULL) <= 0) {
+	if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true) <= 0) {
 		pr_debug("dso__load_kallsyms ");
 		goto out;
 	}
@@ -92,7 +92,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
 	 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
 	 * to fixup the symbols.
 	 */
-	if (machine__load_vmlinux_path(&vmlinux, type, NULL) <= 0) {
+	if (machine__load_vmlinux_path(&vmlinux, type) <= 0) {
 		pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n");
 		err = TEST_SKIP;
 		goto out;
@@ -118,7 +118,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
 		mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end);
 
 		first_pair = machine__find_kernel_symbol(&kallsyms, type,
-							 mem_start, NULL, NULL);
+							 mem_start, NULL);
 		pair = first_pair;
 
 		if (pair && UM(pair->start) == mem_start) {
@@ -147,7 +147,7 @@ next_pair:
 				 */
 				continue;
 			} else {
-				pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL, NULL);
+				pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL);
 				if (pair) {
 					if (UM(pair->start) == mem_start)
 						goto next_pair;
tools/perf/ui/browsers/annotate.c +1 -1
index 2e2d10022355..4c18271c71c9 100644
@@ -495,7 +495,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
 	if (!ins__is_call(dl->ins))
 		return false;
 
-	if (map_groups__find_ams(&target, NULL) ||
+	if (map_groups__find_ams(&target) ||
 	    map__rip_2objdump(target.map, target.map->map_ip(target.map,
 							     target.addr)) !=
 	    dl->ops.target.addr) {
tools/perf/ui/browsers/map.c +2 -2
index 80912778bb6d..98a34664bb7e 100644
@@ -52,9 +52,9 @@ static int map_browser__search(struct map_browser *browser)
 
 	if (target[0] == '0' && tolower(target[1]) == 'x') {
 		u64 addr = strtoull(target, NULL, 16);
-		sym = map__find_symbol(browser->map, addr, NULL);
+		sym = map__find_symbol(browser->map, addr);
 	} else
-		sym = map__find_symbol_by_name(browser->map, target, NULL);
+		sym = map__find_symbol_by_name(browser->map, target);
 
 	if (sym != NULL) {
 		u32 *idx = symbol__browser_index(sym);
tools/perf/util/annotate.c +1 -1
index 1b59e3129216..2ff6bd74e435 100644
@@ -1077,7 +1077,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
 			.addr = dl->ops.target.addr,
 		};
 
-		if (!map_groups__find_ams(&target, NULL) &&
+		if (!map_groups__find_ams(&target) &&
 		    target.sym->start == target.al_addr)
 			dl->ops.target.name = strdup(target.sym->name);
 	}
tools/perf/util/event.c +4 -4
index 2f91183f2779..9ad7d32dba2b 100644
@@ -1286,7 +1286,7 @@ try_again:
 		 * must be done prior to using kernel maps.
 		 */
 		if (load_map)
-			map__load(al->map, NULL);
+			map__load(al->map);
 		al->addr = al->map->map_ip(al->map, al->addr);
 	}
 }
@@ -1297,7 +1297,7 @@ void thread__find_addr_location(struct thread *thread,
 {
 	thread__find_addr_map(thread, cpumode, type, addr, al);
 	if (al->map != NULL)
-		al->sym = map__find_symbol(al->map, al->addr, NULL);
+		al->sym = map__find_symbol(al->map, al->addr);
 	else
 		al->sym = NULL;
 }
@@ -1358,7 +1358,7 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
 			al->filtered |= (1 << HIST_FILTER__DSO);
 		}
 
-		al->sym = map__find_symbol(al->map, al->addr, NULL);
+		al->sym = map__find_symbol(al->map, al->addr);
 	}
 
 	if (symbol_conf.sym_list &&
@@ -1414,5 +1414,5 @@ void thread__resolve(struct thread *thread, struct addr_location *al,
 	al->sym = NULL;
 
 	if (al->map)
-		al->sym = map__find_symbol(al->map, al->addr, NULL);
+		al->sym = map__find_symbol(al->map, al->addr);
 }
tools/perf/util/intel-bts.c +1 -1
index 240b095eddba..f545ec1e758a 100644
@@ -346,7 +346,7 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
 		goto out_put;
 
 	/* Load maps to ensure dso->is_64_bit has been updated */
-	map__load(al.map, NULL);
+	map__load(al.map);
 
 	x86_64 = al.map->dso->is_64_bit;
 
tools/perf/util/intel-pt.c +2 -2
index d594052c8184..b9cc353cace2 100644
@@ -477,7 +477,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 		start_ip = *ip;
 
 		/* Load maps to ensure dso->is_64_bit has been updated */
-		map__load(al.map, NULL);
+		map__load(al.map);
 
 		x86_64 = al.map->dso->is_64_bit;
 
@@ -1294,7 +1294,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
 	if (!map)
 		return 0;
 
-	if (map__load(map, NULL))
+	if (map__load(map))
 		return 0;
 
 	start = dso__first_symbol(map->dso, MAP__FUNCTION);
tools/perf/util/machine.c +9 -10
index 7940ddc98f8c..18e4519abef2 100644
@@ -897,10 +897,10 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
 }
 
 int __machine__load_kallsyms(struct machine *machine, const char *filename,
-			     enum map_type type, bool no_kcore, symbol_filter_t filter)
+			     enum map_type type, bool no_kcore)
 {
 	struct map *map = machine__kernel_map(machine);
-	int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter);
+	int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore);
 
 	if (ret > 0) {
 		dso__set_loaded(map->dso, type);
@@ -916,16 +916,15 @@ int __machine__load_kallsyms(struct machine *machine, const char *filename,
 }
 
 int machine__load_kallsyms(struct machine *machine, const char *filename,
-			   enum map_type type, symbol_filter_t filter)
+			   enum map_type type)
 {
-	return __machine__load_kallsyms(machine, filename, type, false, filter);
+	return __machine__load_kallsyms(machine, filename, type, false);
 }
 
-int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
-			       symbol_filter_t filter)
+int machine__load_vmlinux_path(struct machine *machine, enum map_type type)
 {
 	struct map *map = machine__kernel_map(machine);
-	int ret = dso__load_vmlinux_path(map->dso, map, filter);
+	int ret = dso__load_vmlinux_path(map->dso, map);
 
 	if (ret > 0)
 		dso__set_loaded(map->dso, type);
@@ -1294,7 +1293,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
 			/*
 			 * preload dso of guest kernel and modules
 			 */
-			dso__load(kernel, machine__kernel_map(machine), NULL);
+			dso__load(kernel, machine__kernel_map(machine));
 		}
 	}
 	return 0;
@@ -2096,7 +2095,7 @@ int machine__get_kernel_start(struct machine *machine)
 	 */
 	machine->kernel_start = 1ULL << 63;
 	if (map) {
-		err = map__load(map, NULL);
+		err = map__load(map);
 		if (map->start)
 			machine->kernel_start = map->start;
 	}
@@ -2112,7 +2111,7 @@ char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, ch
 {
 	struct machine *machine = vmachine;
 	struct map *map;
-	struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map,  NULL);
+	struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map);
 
 	if (sym == NULL)
 		return NULL;
tools/perf/util/machine.h +11 -19
index b9e5588499c5..354de6e56109 100644
@@ -174,40 +174,33 @@ size_t machine__fprintf(struct machine *machine, FILE *fp);
 static inline
 struct symbol *machine__find_kernel_symbol(struct machine *machine,
 					   enum map_type type, u64 addr,
-					   struct map **mapp,
-					   symbol_filter_t filter)
+					   struct map **mapp)
 {
-	return map_groups__find_symbol(&machine->kmaps, type, addr,
-				       mapp, filter);
+	return map_groups__find_symbol(&machine->kmaps, type, addr, mapp);
 }
 
 static inline
 struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
 						   enum map_type type, const char *name,
-						   struct map **mapp,
-						   symbol_filter_t filter)
+						   struct map **mapp)
 {
-	return map_groups__find_symbol_by_name(&machine->kmaps, type, name,
-					       mapp, filter);
+	return map_groups__find_symbol_by_name(&machine->kmaps, type, name, mapp);
 }
 
 static inline
 struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr,
-					     struct map **mapp,
-					     symbol_filter_t filter)
+					     struct map **mapp)
 {
 	return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr,
-					   mapp, filter);
+					   mapp);
 }
 
 static inline
 struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
 						     const char *name,
-						     struct map **mapp,
-						     symbol_filter_t filter)
+						     struct map **mapp)
 {
-	return map_groups__find_function_by_name(&machine->kmaps, name, mapp,
-						 filter);
+	return map_groups__find_function_by_name(&machine->kmaps, name, mapp);
 }
 
 struct map *machine__findnew_module_map(struct machine *machine, u64 start,
@@ -215,11 +208,10 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
 int arch__fix_module_text_start(u64 *start, const char *name);
 
 int __machine__load_kallsyms(struct machine *machine, const char *filename,
-			     enum map_type type, bool no_kcore, symbol_filter_t filter);
+			     enum map_type type, bool no_kcore);
 int machine__load_kallsyms(struct machine *machine, const char *filename,
-			   enum map_type type, symbol_filter_t filter);
-int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
-			       symbol_filter_t filter);
+			   enum map_type type);
+int machine__load_vmlinux_path(struct machine *machine, enum map_type type);
 
 size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
 				     bool (skip)(struct dso *dso, int parm), int parm);
tools/perf/util/map.c +15 -22
index 728129ac653a..0c54adb07ae9 100644
@@ -279,7 +279,7 @@ void map__fixup_end(struct map *map)
 
 #define DSO__DELETED "(deleted)"
 
-int map__load(struct map *map, symbol_filter_t filter)
+int map__load(struct map *map)
 {
 	const char *name = map->dso->long_name;
 	int nr;
@@ -287,7 +287,7 @@ int map__load(struct map *map, symbol_filter_t filter)
 	if (dso__loaded(map->dso, map->type))
 		return 0;
 
-	nr = dso__load(map->dso, map, filter);
+	nr = dso__load(map->dso, map);
 	if (nr < 0) {
 		if (map->dso->has_build_id) {
 			char sbuild_id[SBUILD_ID_SIZE];
@@ -312,9 +312,6 @@ int map__load(struct map *map, symbol_filter_t filter)
 			pr_warning("%.*s was updated (is prelink enabled?). "
 				"Restart the long running apps that use it!\n",
 				   (int)real_len, name);
-		} else if (filter) {
-			pr_warning("no symbols passed the given filter.\n");
-			return -2;	/* Empty but maybe by the filter */
 		} else {
 			pr_warning("no symbols found in %s, maybe install "
 				   "a debug package?\n", name);
@@ -331,19 +328,17 @@ int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
 	return strcmp(namea, nameb);
 }
 
-struct symbol *map__find_symbol(struct map *map, u64 addr,
-				symbol_filter_t filter)
+struct symbol *map__find_symbol(struct map *map, u64 addr)
 {
-	if (map__load(map, filter) < 0)
+	if (map__load(map) < 0)
 		return NULL;
 
 	return dso__find_symbol(map->dso, map->type, addr);
 }
 
-struct symbol *map__find_symbol_by_name(struct map *map, const char *name,
-					symbol_filter_t filter)
+struct symbol *map__find_symbol_by_name(struct map *map, const char *name)
 {
-	if (map__load(map, filter) < 0)
+	if (map__load(map) < 0)
 		return NULL;
 
 	if (!dso__sorted_by_name(map->dso, map->type))
@@ -556,23 +551,22 @@ void map_groups__put(struct map_groups *mg)
 
 struct symbol *map_groups__find_symbol(struct map_groups *mg,
 				       enum map_type type, u64 addr,
-				       struct map **mapp,
-				       symbol_filter_t filter)
+				       struct map **mapp)
 {
 	struct map *map = map_groups__find(mg, type, addr);
 
 	/* Ensure map is loaded before using map->map_ip */
-	if (map != NULL && map__load(map, filter) >= 0) {
+	if (map != NULL && map__load(map) >= 0) {
 		if (mapp != NULL)
 			*mapp = map;
-		return map__find_symbol(map, map->map_ip(map, addr), filter);
+		return map__find_symbol(map, map->map_ip(map, addr));
 	}
 
 	return NULL;
 }
 
 struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
-					 struct map **mapp, symbol_filter_t filter)
+					 struct map **mapp)
 {
 	struct symbol *sym;
 	struct rb_node *nd;
@@ -582,7 +576,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
 	for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
 		struct map *pos = rb_entry(nd, struct map, rb_node);
 
-		sym = map__find_symbol_by_name(pos, name, filter);
+		sym = map__find_symbol_by_name(pos, name);
 
 		if (sym == NULL)
 			continue;
@@ -600,15 +594,14 @@ out:
 struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
 					       enum map_type type,
 					       const char *name,
-					       struct map **mapp,
-					       symbol_filter_t filter)
+					       struct map **mapp)
 {
-	struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp, filter);
+	struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp);
 
 	return sym;
 }
 
-int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
+int map_groups__find_ams(struct addr_map_symbol *ams)
 {
 	if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
 		if (ams->map->groups == NULL)
@@ -620,7 +613,7 @@ int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
 	}
 
 	ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
-	ams->sym = map__find_symbol(ams->map, ams->al_addr, filter);
+	ams->sym = map__find_symbol(ams->map, ams->al_addr);
 
 	return ams->sym ? 0 : -1;
 }
tools/perf/util/map.h +12 -20
index d83396ceecba..abdacf800c98 100644
@@ -127,17 +127,14 @@ struct thread;
  * @map: the 'struct map *' in which symbols itereated
  * @sym_name: the symbol name
  * @pos: the 'struct symbol *' to use as a loop cursor
- * @filter: to use when loading the DSO
  */
-#define __map__for_each_symbol_by_name(map, sym_name, pos, filter)	\
-	for (pos = map__find_symbol_by_name(map, sym_name, filter);	\
+#define __map__for_each_symbol_by_name(map, sym_name, pos)	\
+	for (pos = map__find_symbol_by_name(map, sym_name);	\
 	     pos && arch__compare_symbol_names(pos->name, sym_name) == 0;	\
 	     pos = symbol__next_by_name(pos))
 
 #define map__for_each_symbol_by_name(map, sym_name, pos)		\
-	__map__for_each_symbol_by_name(map, sym_name, (pos), NULL)
-
-typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
+	__map__for_each_symbol_by_name(map, sym_name, (pos))
 
 int arch__compare_symbol_names(const char *namea, const char *nameb);
 void map__init(struct map *map, enum map_type type,
@@ -173,11 +170,9 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp);
 int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
 			 FILE *fp);
 
-int map__load(struct map *map, symbol_filter_t filter);
-struct symbol *map__find_symbol(struct map *map,
-				u64 addr, symbol_filter_t filter);
-struct symbol *map__find_symbol_by_name(struct map *map, const char *name,
-					symbol_filter_t filter);
+int map__load(struct map *map);
+struct symbol *map__find_symbol(struct map *map, u64 addr);
+struct symbol *map__find_symbol_by_name(struct map *map, const char *name);
 void map__fixup_start(struct map *map);
 void map__fixup_end(struct map *map);
 
@@ -191,7 +186,7 @@ struct map *maps__find(struct maps *maps, u64 addr);
 struct map *maps__first(struct maps *maps);
 struct map *map__next(struct map *map);
 struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
-                                         struct map **mapp, symbol_filter_t filter);
+                                         struct map **mapp);
 void map_groups__init(struct map_groups *mg, struct machine *machine);
 void map_groups__exit(struct map_groups *mg);
 int map_groups__clone(struct thread *thread,
@@ -231,25 +226,22 @@ static inline struct map *map_groups__next(struct map *map)
 
 struct symbol *map_groups__find_symbol(struct map_groups *mg,
 				       enum map_type type, u64 addr,
-				       struct map **mapp,
-				       symbol_filter_t filter);
+				       struct map **mapp);
 
 struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
 					       enum map_type type,
 					       const char *name,
-					       struct map **mapp,
-					       symbol_filter_t filter);
+					       struct map **mapp);
 
 struct addr_map_symbol;
 
-int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter);
+int map_groups__find_ams(struct addr_map_symbol *ams);
 
 static inline
 struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
-						 const char *name, struct map **mapp,
-						 symbol_filter_t filter)
+						 const char *name, struct map **mapp)
 {
-	return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter);
+	return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp);
 }
 
 int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
tools/perf/util/probe-event.c +8 -9
index a543e9ca581c..bc60ce49720b 100644
@@ -110,13 +110,12 @@ void exit_probe_symbol_maps(void)
 static struct symbol *__find_kernel_function_by_name(const char *name,
 						     struct map **mapp)
 {
-	return machine__find_kernel_function_by_name(host_machine, name, mapp,
-						     NULL);
+	return machine__find_kernel_function_by_name(host_machine, name, mapp);
 }
 
 static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
 {
-	return machine__find_kernel_function(host_machine, addr, mapp, NULL);
+	return machine__find_kernel_function(host_machine, addr, mapp);
 }
 
 static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
@@ -125,7 +124,7 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
 	struct kmap *kmap;
 	struct map *map = machine__kernel_map(host_machine);
 
-	if (map__load(map, NULL) < 0)
+	if (map__load(map) < 0)
 		return NULL;
 
 	kmap = map__kmap(map);
@@ -351,9 +350,9 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
 	vmlinux_name = symbol_conf.vmlinux_name;
 	dso->load_errno = 0;
 	if (vmlinux_name)
-		ret = dso__load_vmlinux(dso, map, vmlinux_name, false, NULL);
+		ret = dso__load_vmlinux(dso, map, vmlinux_name, false);
 	else
-		ret = dso__load_vmlinux_path(dso, map, NULL);
+		ret = dso__load_vmlinux_path(dso, map);
 found:
 	*pdso = dso;
 	return ret;
@@ -1999,7 +1998,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
 		map = dso__new_map(tp->module);
 		if (!map)
 			goto out;
-		sym = map__find_symbol(map, addr, NULL);
+		sym = map__find_symbol(map, addr);
 	} else {
 		if (tp->symbol && !addr) {
 			if (kernel_get_symbol_address_by_name(tp->symbol,
@@ -2704,7 +2703,7 @@ static int find_probe_functions(struct map *map, char *name,
 	struct symbol *sym;
 	struct rb_node *tmp;
 
-	if (map__load(map, NULL) < 0)
+	if (map__load(map) < 0)
 		return 0;
 
 	map__for_each_symbol(map, sym, tmp) {
@@ -3368,7 +3367,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
 		return -EINVAL;
 	}
 
-	ret = map__load(map, NULL);
+	ret = map__load(map);
 	if (ret) {
 		if (ret == -2) {
 			char *str = strfilter__string(_filter);
tools/perf/util/symbol-elf.c +9 -23
index bd91a4f67080..99400b0e8f2a 100644
@@ -254,8 +254,7 @@ static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
  * And always look at the original dso, not at debuginfo packages, that
  * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
  */
-int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map,
-				symbol_filter_t filter)
+int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map)
 {
 	uint32_t nr_rel_entries, idx;
 	GElf_Sym sym;
@@ -351,12 +350,8 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 			if (!f)
 				goto out_elf_end;
 
-			if (filter && filter(map, f))
-				symbol__delete(f);
-			else {
-				symbols__insert(&dso->symbols[map->type], f);
-				++nr;
-			}
+			symbols__insert(&dso->symbols[map->type], f);
+			++nr;
 		}
 	} else if (shdr_rel_plt.sh_type == SHT_REL) {
 		GElf_Rel pos_mem, *pos;
@@ -381,12 +376,8 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 			if (!f)
 				goto out_elf_end;
 
-			if (filter && filter(map, f))
-				symbol__delete(f);
-			else {
-				symbols__insert(&dso->symbols[map->type], f);
-				++nr;
-			}
+			symbols__insert(&dso->symbols[map->type], f);
+			++nr;
 		}
 	}
 
@@ -825,9 +816,8 @@ static u64 ref_reloc(struct kmap *kmap)
 void __weak arch__sym_update(struct symbol *s __maybe_unused,
 		GElf_Sym *sym __maybe_unused) { }
 
-int dso__load_sym(struct dso *dso, struct map *map,
-		  struct symsrc *syms_ss, struct symsrc *runtime_ss,
-		  symbol_filter_t filter, int kmodule)
+int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
+		  struct symsrc *runtime_ss, int kmodule)
 {
 	struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
 	struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL;
@@ -1124,12 +1114,8 @@ new_symbol:
 
 		arch__sym_update(f, &sym);
 
-		if (filter && filter(curr_map, f))
-			symbol__delete(f);
-		else {
-			__symbols__insert(&curr_dso->symbols[curr_map->type], f, dso->kernel);
-			nr++;
-		}
+		__symbols__insert(&curr_dso->symbols[curr_map->type], f, dso->kernel);
+		nr++;
 	}
 
 	/*
tools/perf/util/symbol-minimal.c +1 -3
index 48906333a858..11cdde980545 100644
@@ -287,8 +287,7 @@ void symsrc__destroy(struct symsrc *ss)
 
 int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
 				struct symsrc *ss __maybe_unused,
-				struct map *map __maybe_unused,
-				symbol_filter_t filter __maybe_unused)
+				struct map *map __maybe_unused)
 {
 	return 0;
 }
@@ -334,7 +333,6 @@ enum dso_type dso__type_fd(int fd)
 int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
 		  struct symsrc *ss,
 		  struct symsrc *runtime_ss __maybe_unused,
-		  symbol_filter_t filter __maybe_unused,
 		  int kmodule __maybe_unused)
 {
 	unsigned char build_id[BUILD_ID_SIZE];
tools/perf/util/symbol.c +44 -58

263 lines not on this page · raw message

tools/perf/util/symbol.h +7 -11
index 72d29312a694..0dacfb7d5b67 100644
@@ -241,16 +241,13 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
 bool symsrc__has_symtab(struct symsrc *ss);
 bool symsrc__possibly_runtime(struct symsrc *ss);
 
-int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter);
+int dso__load(struct dso *dso, struct map *map);
 int dso__load_vmlinux(struct dso *dso, struct map *map,
-		      const char *vmlinux, bool vmlinux_allocated,
-		      symbol_filter_t filter);
-int dso__load_vmlinux_path(struct dso *dso, struct map *map,
-			   symbol_filter_t filter);
+		      const char *vmlinux, bool vmlinux_allocated);
+int dso__load_vmlinux_path(struct dso *dso, struct map *map);
 int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
-			 bool no_kcore, symbol_filter_t filter);
-int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
-		       symbol_filter_t filter);
+			 bool no_kcore);
+int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map);
 
 void dso__insert_symbol(struct dso *dso, enum map_type type,
 			struct symbol *sym);
@@ -298,10 +295,9 @@ int symbol__config_symfs(const struct option *opt __maybe_unused,
 			 const char *dir, int unset __maybe_unused);
 
 int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
-		  struct symsrc *runtime_ss, symbol_filter_t filter,
-		  int kmodule);
+		  struct symsrc *runtime_ss, int kmodule);
 int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
-				struct map *map, symbol_filter_t filter);
+				struct map *map);
 
 void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
 void symbols__insert(struct rb_root *symbols, struct symbol *sym);
Signature · 1 line
2.7.4
author maintainer
#6 lore raw

PATCH 6/12 perf tools: Recognize hugetlb mapping as anon mapping

In reply to Arnaldo Carvalho de Melo

From: Wang Nan <[email protected]>

Hugetlbfs mapping should be recognized as anon mapping so user has a chance to create /tmp/perf-<pid>.map file for symbol resolving. This patch utilizes MAP_HUGETLB to identify hugetlb mapping.

After this patch, if perf is started before a program starts using huge pages (so perf gets MMAP2 events from kernel), perf is able to recognize hugetlb mapping as anon mapping.

---
 tools/perf/util/map.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
tools/perf/util/map.c +10 -3
index 0c54adb07ae9..d51a1257973b 100644
@@ -6,6 +6,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/mman.h>
 #include "map.h"
 #include "thread.h"
 #include "strlist.h"
@@ -24,9 +25,15 @@ const char *map_type__name[MAP__NR_TYPES] = {
 	[MAP__VARIABLE] = "Variables",
 };
 
-static inline int is_anon_memory(const char *filename)
+static inline int is_anon_memory(const char *filename, u32 flags)
 {
-	return !strcmp(filename, "//anon") ||
+	u32 anon_flags = 0;
+
+#ifdef MAP_HUGETLB
+	anon_flags |= MAP_HUGETLB;
+#endif
+	return flags & anon_flags ||
+	       !strcmp(filename, "//anon") ||
 	       !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) ||
 	       !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1);
 }
@@ -155,7 +162,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
 		int anon, no_dso, vdso, android;
 
 		android = is_android_lib(filename);
-		anon = is_anon_memory(filename);
+		anon = is_anon_memory(filename, flags);
 		vdso = is_vdso_map(filename);
 		no_dso = is_no_dso_memory(filename);
 
Signature · 1 line
2.7.4
author maintainer
#7 lore raw

PATCH 7/12 tools lib api fs: Add hugetlbfs filesystem detector

In reply to Arnaldo Carvalho de Melo

From: Wang Nan <[email protected]>

Detect hugetlbfs. hugetlbfs__mountpoint() will be used during recording to help identifying hugetlb mmaps: which should be recognized as anon mapping.

---
 tools/lib/api/fs/fs.c | 15 +++++++++++++++
 tools/lib/api/fs/fs.h |  1 +
 2 files changed, 16 insertions(+)
tools/lib/api/fs/fs.c +15 -0
index ba7094b945ff..f99f49e4a31e 100644
@@ -34,6 +34,10 @@
 #define TRACEFS_MAGIC          0x74726163
 #endif
 
+#ifndef HUGETLBFS_MAGIC
+#define HUGETLBFS_MAGIC        0x958458f6
+#endif
+
 static const char * const sysfs__fs_known_mountpoints[] = {
 	"/sys",
 	0,
@@ -67,6 +71,10 @@ static const char * const tracefs__known_mountpoints[] = {
 	0,
 };
 
+static const char * const hugetlbfs__known_mountpoints[] = {
+	0,
+};
+
 struct fs {
 	const char		*name;
 	const char * const	*mounts;
@@ -80,6 +88,7 @@ enum {
 	FS__PROCFS  = 1,
 	FS__DEBUGFS = 2,
 	FS__TRACEFS = 3,
+	FS__HUGETLBFS = 4,
 };
 
 #ifndef TRACEFS_MAGIC
@@ -107,6 +116,11 @@ static struct fs fs__entries[] = {
 		.mounts	= tracefs__known_mountpoints,
 		.magic	= TRACEFS_MAGIC,
 	},
+	[FS__HUGETLBFS] = {
+		.name	= "hugetlbfs",
+		.mounts = hugetlbfs__known_mountpoints,
+		.magic	= HUGETLBFS_MAGIC,
+	},
 };
 
 static bool fs__read_mounts(struct fs *fs)
@@ -265,6 +279,7 @@ FS(sysfs,   FS__SYSFS);
 FS(procfs,  FS__PROCFS);
 FS(debugfs, FS__DEBUGFS);
 FS(tracefs, FS__TRACEFS);
+FS(hugetlbfs, FS__HUGETLBFS);
 
 int filename__read_int(const char *filename, int *value)
 {
tools/lib/api/fs/fs.h +1 -0
index 16c9c2ed7c5b..a63269f5d20c 100644
@@ -21,6 +21,7 @@ FS(sysfs)
 FS(procfs)
 FS(debugfs)
 FS(tracefs)
+FS(hugetlbfs)
 
 #undef FS
 
Signature · 1 line
2.7.4
author maintainer
#8 lore raw

PATCH 8/12 perf record: Mark MAP_HUGETLB when synthesizing mmap events

In reply to Arnaldo Carvalho de Melo

From: Wang Nan <[email protected]>

When synthesizing mmap events, add MAP_HUGETLB map flag if the source of mapping is file in hugetlbfs.

After this patch, perf can identify hugetlb mapping even if perf is started after the mapping of huge pages (like with 'perf top').

---
 tools/perf/util/event.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
tools/perf/util/event.c +11 -0
index 9ad7d32dba2b..6c3017139c67 100644
@@ -1,5 +1,6 @@
 #include <linux/types.h>
 #include <sys/mman.h>
+#include <api/fs/fs.h>
 #include "event.h"
 #include "debug.h"
 #include "hist.h"
@@ -248,6 +249,10 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
 	bool truncation = false;
 	unsigned long long timeout = proc_map_timeout * 1000000ULL;
 	int rc = 0;
+#ifdef MAP_HUGETLB
+	const char *hugetlbfs_mnt = hugetlbfs__mountpoint();
+	int hugetlbfs_mnt_len = hugetlbfs_mnt ? strlen(hugetlbfs_mnt) : 0;
+#endif
 
 	if (machine__is_default_guest(machine))
 		return 0;
@@ -342,6 +347,12 @@ out:
 
 		if (!strcmp(execname, ""))
 			strcpy(execname, anonstr);
+#ifdef MAP_HUGETLB
+		if (!strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
+			strcpy(execname, anonstr);
+			event->mmap2.flags |= MAP_HUGETLB;
+		}
+#endif
 
 		size = strlen(execname) + 1;
 		memcpy(event->mmap2.filename, execname, size);
Signature · 1 line
2.7.4
author maintainer
#9 lore raw

PATCH 9/12 perf annotate: Add branch stack / basic block

In reply to Arnaldo Carvalho de Melo

From: Peter Zijlstra <[email protected]>

I wanted to know the hottest path through a function and figured the branch-stack (LBR) information should be able to help out with that.

The below uses the branch-stack to create basic blocks and generate statistics from them.

from to branch_i
* ----> *
|
| block
v
* ----> *
from to branch_i+1

The blocks are broken down into non-overlapping ranges, while tracking if the start of each range is an entry point and/or the end of a range is a branch.

Each block iterates all ranges it covers (while splitting where required to exactly match the block) and increments the 'coverage' count.

For the range including the branch we increment the taken counter, as well as the pred counter if flags.predicted.

Using these number we can find if an instruction:

- had coverage; given by:

        br->coverage / br->sym->max_coverage

This metric ensures each symbol has a 100% spot, which reflects the observation that each symbol must have a most covered/hottest block.

- is a branch target: br->is_target && br->start == add

- for targets, how much of a branch's coverages comes from it:

	target->entry / branch->coverage

- is a branch: br->is_branch && br->end == addr

- for branches, how often it was taken:

        br->taken / br->coverage

after all, all execution that didn't take the branch would have incremented the coverage and continued onward to a later branch.

- for branches, how often it was predicted:

        br->pred / br->taken

The coverage percentage is used to color the address and asm sections; for low (<1%) coverage we use NORMAL (uncolored), indicating that these instructions are not 'important'. For high coverage (>75%) we color the address RED.

For each branch, we add an asm comment after the instruction with information on how often it was taken and predicted.

Output looks like (sans color, which does loose a lot of the information :/)

$ perf record --branch-filter u,any -e cycles:p ./branches 27
$ perf annotate branches

Percent | Source code & Disassembly of branches for cycles:pu (217 samples)
---------------------------------------------------------------------------------

         :	branches():
    0.00 :	  40057a:       push   %rbp
    0.00 :	  40057b:       mov    %rsp,%rbp
    0.00 :	  40057e:       sub    $0x20,%rsp
    0.00 :	  400582:       mov    %rdi,-0x18(%rbp)
    0.00 :	  400586:       mov    %rsi,-0x20(%rbp)
    0.00 :	  40058a:       mov    -0x18(%rbp),%rax
    0.00 :	  40058e:       mov    %rax,-0x10(%rbp)
    0.00 :	  400592:       movq   $0x0,-0x8(%rbp)
    0.00 :	  40059a:       jmpq   400656 <branches+0xdc>
    1.84 :	  40059f:       mov    -0x10(%rbp),%rax	# +100.00%
    3.23 :	  4005a3:       and    $0x1,%eax
    1.84 :	  4005a6:       test   %rax,%rax
    0.00 :	  4005a9:       je     4005bf <branches+0x45>	# -54.50% (p:42.00%)
    0.46 :	  4005ab:       mov    0x200bbe(%rip),%rax        # 601170 <acc>
   12.90 :	  4005b2:       add    $0x1,%rax
    2.30 :	  4005b6:       mov    %rax,0x200bb3(%rip)        # 601170 <acc>
    0.46 :	  4005bd:       jmp    4005d1 <branches+0x57>	# -100.00% (p:100.00%)
    0.92 :	  4005bf:       mov    0x200baa(%rip),%rax        # 601170 <acc>	# +49.54%
   13.82 :	  4005c6:       sub    $0x1,%rax
    0.46 :	  4005ca:       mov    %rax,0x200b9f(%rip)        # 601170 <acc>
    2.30 :	  4005d1:       mov    -0x10(%rbp),%rax	# +50.46%
    0.46 :	  4005d5:       mov    %rax,%rdi
    0.46 :	  4005d8:       callq  400526 <lfsr>	# -100.00% (p:100.00%)
    0.00 :	  4005dd:       mov    %rax,-0x10(%rbp)	# +100.00%
    0.92 :	  4005e1:       mov    -0x18(%rbp),%rax
    0.00 :	  4005e5:       and    $0x1,%eax
    0.00 :	  4005e8:       test   %rax,%rax
    0.00 :	  4005eb:       je     4005ff <branches+0x85>	# -100.00% (p:100.00%)
    0.00 :	  4005ed:       mov    0x200b7c(%rip),%rax        # 601170 <acc>
    0.00 :	  4005f4:       shr    $0x2,%rax
    0.00 :	  4005f8:       mov    %rax,0x200b71(%rip)        # 601170 <acc>
    0.00 :	  4005ff:       mov    -0x10(%rbp),%rax	# +100.00%
    7.37 :	  400603:       and    $0x1,%eax
    3.69 :	  400606:       test   %rax,%rax
    0.00 :	  400609:       jne    400612 <branches+0x98>	# -59.25% (p:42.99%)
    1.84 :	  40060b:       mov    $0x1,%eax
   14.29 :	  400610:       jmp    400617 <branches+0x9d>	# -100.00% (p:100.00%)
    1.38 :	  400612:       mov    $0x0,%eax	# +57.65%
   10.14 :	  400617:       test   %al,%al	# +42.35%
    0.00 :	  400619:       je     40062f <branches+0xb5>	# -57.65% (p:100.00%)
    0.46 :	  40061b:       mov    0x200b4e(%rip),%rax        # 601170 <acc>
    2.76 :	  400622:       sub    $0x1,%rax
    0.00 :	  400626:       mov    %rax,0x200b43(%rip)        # 601170 <acc>
    0.46 :	  40062d:       jmp    400641 <branches+0xc7>	# -100.00% (p:100.00%)
    0.92 :	  40062f:       mov    0x200b3a(%rip),%rax        # 601170 <acc>	# +56.13%
    2.30 :	  400636:       add    $0x1,%rax
    0.92 :	  40063a:       mov    %rax,0x200b2f(%rip)        # 601170 <acc>
    0.92 :	  400641:       mov    -0x10(%rbp),%rax	# +43.87%
    2.30 :	  400645:       mov    %rax,%rdi
    0.00 :	  400648:       callq  400526 <lfsr>	# -100.00% (p:100.00%)
    0.00 :	  40064d:       mov    %rax,-0x10(%rbp)	# +100.00%
    1.84 :	  400651:       addq   $0x1,-0x8(%rbp)
    0.92 :	  400656:       mov    -0x8(%rbp),%rax
    5.07 :	  40065a:       cmp    -0x20(%rbp),%rax
    0.00 :	  40065e:       jb     40059f <branches+0x25>	# -100.00% (p:100.00%)
    0.00 :	  400664:       nop
    0.00 :	  400665:       leaveq
    0.00 :	  400666:       retq

(Note: the --branch-filter u,any was used to avoid spurious target and branch points due to interrupts/faults, they show up as very small -/+ annotations on 'weird' locations)

Committer note:

Please take a look at:

http://vger.kernel.org/~acme/perf/annotate_basic_blocks.png

To see the colors.

Cc Alexander Shishkin <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Anshuman Khandual <[email protected]>
Cc David Carrillo-Cisneros <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Kan Liang <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Stephane Eranian <[email protected]>
[ Moved sym->max_coverage to 'struct annotate', aka symbol__annotate(sym) ]
---
 tools/perf/builtin-annotate.c | 104 ++++++++++++++
 tools/perf/util/Build         |   1 +
 tools/perf/util/annotate.c    |  93 +++++++++++-
 tools/perf/util/annotate.h    |   1 +
 tools/perf/util/block-range.c | 328 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/block-range.h |  71 +++++++++
 6 files changed, 596 insertions(+), 2 deletions(-)
 create mode 100644 tools/perf/util/block-range.c
 create mode 100644 tools/perf/util/block-range.h
tools/perf/builtin-annotate.c +104 -0
index f07b23011b22..ebb628332a6e 100644
@@ -30,6 +30,7 @@
 #include "util/tool.h"
 #include "util/data.h"
 #include "arch/common.h"
+#include "util/block-range.h"
 
 #include <dlfcn.h>
 #include <linux/bitmap.h>
@@ -46,6 +47,103 @@ struct perf_annotate {
 	DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 };
 
+/*
+ * Given one basic block:
+ *
+ *	from	to		branch_i
+ *	* ----> *
+ *		|
+ *		| block
+ *		v
+ *		* ----> *
+ *		from	to	branch_i+1
+ *
+ * where the horizontal are the branches and the vertical is the executed
+ * block of instructions.
+ *
+ * We count, for each 'instruction', the number of blocks that covered it as
+ * well as count the ratio each branch is taken.
+ *
+ * We can do this without knowing the actual instruction stream by keeping
+ * track of the address ranges. We break down ranges such that there is no
+ * overlap and iterate from the start until the end.
+ *
+ * @acme: once we parse the objdump output _before_ processing the samples,
+ * we can easily fold the branch.cycles IPC bits in.
+ */
+static void process_basic_block(struct addr_map_symbol *start,
+				struct addr_map_symbol *end,
+				struct branch_flags *flags)
+{
+	struct symbol *sym = start->sym;
+	struct annotation *notes = sym ? symbol__annotation(sym) : NULL;
+	struct block_range_iter iter;
+	struct block_range *entry;
+
+	/*
+	 * Sanity; NULL isn't executable and the CPU cannot execute backwards
+	 */
+	if (!start->addr || start->addr > end->addr)
+		return;
+
+	iter = block_range__create(start->addr, end->addr);
+	if (!block_range_iter__valid(&iter))
+		return;
+
+	/*
+	 * First block in range is a branch target.
+	 */
+	entry = block_range_iter(&iter);
+	assert(entry->is_target);
+	entry->entry++;
+
+	do {
+		entry = block_range_iter(&iter);
+
+		entry->coverage++;
+		entry->sym = sym;
+
+		if (notes)
+			notes->max_coverage = max(notes->max_coverage, entry->coverage);
+
+	} while (block_range_iter__next(&iter));
+
+	/*
+	 * Last block in rage is a branch.
+	 */
+	entry = block_range_iter(&iter);
+	assert(entry->is_branch);
+	entry->taken++;
+	if (flags->predicted)
+		entry->pred++;
+}
+
+static void process_branch_stack(struct branch_stack *bs, struct addr_location *al,
+				 struct perf_sample *sample)
+{
+	struct addr_map_symbol *prev = NULL;
+	struct branch_info *bi;
+	int i;
+
+	if (!bs || !bs->nr)
+		return;
+
+	bi = sample__resolve_bstack(sample, al);
+	if (!bi)
+		return;
+
+	for (i = bs->nr - 1; i >= 0; i--) {
+		/*
+		 * XXX filter against symbol
+		 */
+		if (prev)
+			process_basic_block(prev, &bi[i].from, &bi[i].flags);
+		prev = &bi[i].to;
+	}
+
+	free(bi);
+}
+
 static int perf_evsel__add_sample(struct perf_evsel *evsel,
 				  struct perf_sample *sample,
 				  struct addr_location *al,
@@ -72,6 +170,12 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
 		return 0;
 	}
 
+	/*
+	 * XXX filtered samples can still have branch entires pointing into our
+	 * symbol and are missed.
+	 */
+	process_branch_stack(sample->branch_stack, al, sample);
+
 	sample->period = 1;
 	sample->weight = 1;
 
tools/perf/util/Build +1 -0
index f1a6d17c5a37..96f99d608d00 100644
@@ -1,5 +1,6 @@
 libperf-y += alias.o
 libperf-y += annotate.o
+libperf-y += block-range.o
 libperf-y += build-id.o
 libperf-y += config.o
 libperf-y += ctype.o
tools/perf/util/annotate.c +91 -2

117 lines not on this page · raw message

tools/perf/util/annotate.h +1 -0
index e96f4daed9b9..ea44e4ff19c6 100644
@@ -130,6 +130,7 @@ struct annotated_source {
 
 struct annotation {
 	pthread_mutex_t		lock;
+	u64			max_coverage;
 	struct annotated_source *src;
 };
 
tools/perf/util/block-range.c new file +328 -0

328 lines not on this page · raw message

tools/perf/util/block-range.h new file +71 -0

71 lines not on this page · raw message

Signature · 1 line
2.7.4
author maintainer
#10 lore raw

PATCH 10/12 perf evlist: Only open events on CPUs an evsel permits

In reply to Arnaldo Carvalho de Melo

From: Mark Rutland <[email protected]>

In systems with heterogeneous CPU PMUs, it's possible for each evsel to cover a distinct set of CPUs, and hence the cpu_map associated with each evsel may have a distinct idx<->id mapping. Any of these may be distinct from the evlist's cpu map.

Events can be tied to the same fd so long as they use the same per-cpu ringbuffer (i.e. so long as they are on the same CPU). To acquire the correct FDs, we must compare the Linux logical IDs rather than the evsel or evlist indices.

This path adds logic to perf_evlist__mmap_per_evsel to handle this, translating IDs as required. As PMUs may cover a subset of CPUs from the evlist, we skip the CPUs a PMU cannot handle.

Without this patch, perf record may try to mmap erroneous FDs on heterogeneous systems, and will bail out early rather than running the workload.

---
 tools/perf/util/evlist.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +7 -1
index 097b3ed77fdd..ea34c5a32c11 100644
@@ -1032,16 +1032,18 @@ perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
 }
 
 static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
-				       struct mmap_params *mp, int cpu,
+				       struct mmap_params *mp, int cpu_idx,
 				       int thread, int *_output, int *_output_backward)
 {
 	struct perf_evsel *evsel;
 	int revent;
+	int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);
 
 	evlist__for_each_entry(evlist, evsel) {
 		struct perf_mmap *maps = evlist->mmap;
 		int *output = _output;
 		int fd;
+		int cpu;
 
 		if (evsel->attr.write_backward) {
 			output = _output_backward;
@@ -1060,6 +1062,10 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
 		if (evsel->system_wide && thread)
 			continue;
 
+		cpu = cpu_map__idx(evsel->cpus, evlist_cpu);
+		if (cpu == -1)
+			continue;
+
 		fd = FD(evsel, cpu, thread);
 
 		if (*output == -1) {
Signature · 1 line
2.7.4
author maintainer
#11 lore raw

PATCH 11/12 perf pmu: Support alternative sysfs cpumask

In reply to Arnaldo Carvalho de Melo

From: Mark Rutland <[email protected]>

The perf tools can read a cpumask file for a PMU, describing a subset of CPUs which that PMU covers. So far this has only been used to cater for uncore PMUs, which in practice happen to only have a single CPU described in the mask.

Until recently, the perf tools only correctly handled cpumask containing a single CPU, and only when monitoring in system-wide mode. For example, prior to commit 00e727bb389359c8 ("perf stat: Balance opening and reading events"), a mask with more than a single CPU could cause perf stat to hang. When a CPU PMU covers a subset of CPUs, but lacks a cpumask, perf record will fail to open events (on the cores the PMU does not support), and gives up.

For systems with heterogeneous CPUs such as ARM big.LITTLE systems, this presents a problem. We have a PMU for each microarchitecture (e.g. a big PMU and a little PMU), and would like to expose a cpumask for each (so as to allow perf record and other tools to do the right thing). However, doing so kernel-side will cause old perf binaries to not function (e.g. hitting the issue solved by 00e727bb389359c8), and thus commits the cardinal sin of breaking (existing) userspace.

To address this chicken-and-egg problem, this patch adds support got a new file, cpus, which is largely identical to the existing cpumask file. A kernel can expose this file, knowing that new perf binaries will correctly support it, while old perf binaries will not look for it (and thus will not be broken).

---
 tools/perf/util/pmu.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
tools/perf/util/pmu.c +12 -3
index ddb0261b2577..2babcdf62839 100644
@@ -445,14 +445,23 @@ static struct cpu_map *pmu_cpumask(const char *name)
 	FILE *file;
 	struct cpu_map *cpus;
 	const char *sysfs = sysfs__mountpoint();
+	const char *templates[] = {
+		 "%s/bus/event_source/devices/%s/cpumask",
+		 "%s/bus/event_source/devices/%s/cpus",
+		 NULL
+	};
+	const char **template;
 
 	if (!sysfs)
 		return NULL;
 
-	snprintf(path, PATH_MAX,
-		 "%s/bus/event_source/devices/%s/cpumask", sysfs, name);
+	for (template = templates; *template; template++) {
+		snprintf(path, PATH_MAX, *template, sysfs, name);
+		if (stat(path, &st) == 0)
+			break;
+	}
 
-	if (stat(path, &st) < 0)
+	if (!*template)
 		return NULL;
 
 	file = fopen(path, "r");
Signature · 1 line
2.7.4
author maintainer
#12 lore raw

PATCH 12/12 perf powerpc: Fix build-test failure

In reply to Arnaldo Carvalho de Melo

From: Ravi Bangoria <[email protected]>

'make -C tools/perf build-test' is failing with below log for poewrpc.

In file included from /tmp/tmp.3eEwmGlYaF/perf-4.8.0-rc4/tools/perf/perf.h:15:0,

                   from util/cpumap.h:8,
                   from util/env.c:1:

/tmp/tmp.3eEwmGlYaF/perf-4.8.0-rc4/tools/perf/perf-sys.h:23:56:
fatal error: ../../arch/powerpc/include/uapi/asm/unistd.h: No such file or directory compilation terminated.

I bisected it and found it's failing from commit ad430729ae00 ("Remove:
kernel unistd*h files from perf's MANIFEST, not used").

Header file '../../arch/powerpc/include/uapi/asm/unistd.h' is included only for powerpc in tools/perf/perf-sys.h.

By looking closly at commit history, I found little weird thing:

Commit f2d9cae9ea9e ("perf powerpc: Use uapi/unistd.h to fix build error") replaced 'asm/unistd.h' with 'uapi/asm/unistd.h'

Commit d2709c7ce4c5 ("perf: Make perf build for x86 with UAPI disintegration applied") removes all arch specific 'uapi/asm/unistd.h' for all archs and adds generic <asm/unistd.h>.

Commit f0b9abfb0446 ("Merge branch 'linus' into perf/core") again includes 'uapi/asm/unistd.h' for powerpc. Don't know how exactly this happened as this change is not part of commit also.

Cc Alexander Shishkin <[email protected]>
Cc Peter Zijlstra <[email protected]>
Fixes ad430729ae00 ("Remove: kernel unistd*h files from perf's MANIFEST, not used")
---
 tools/perf/perf-sys.h | 1 -
 1 file changed, 1 deletion(-)
tools/perf/perf-sys.h +0 -1
index 7ed72a475c57..e4b717e9eb6c 100644
@@ -20,7 +20,6 @@
 #endif
 
 #ifdef __powerpc__
-#include "../../arch/powerpc/include/uapi/asm/unistd.h"
 #define CPUINFO_PROC	{"cpu"}
 #endif
 
Signature · 1 line
2.7.4
#13 lore raw
In reply to Arnaldo Carvalho de Melo
Quoted 144 lines · Arnaldo Carvalho de Melo

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit c0b172e5b6770048751b2c0a4fe44346c2080c5d:

Merge tag 'perf-core-for-mingo-20160901' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2016-09-05 15:15:49 +0200)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo-20160908

for you to fetch changes up to 25b8592e912f085ce2ff736a2927584ddeab238c:

perf powerpc: Fix build-test failure (2016-09-08 13:44:07 -0300)

----------------------------------------------------------------
perf/core improvements and fixes:

User visible:

- Add branch stack / basic block info to 'perf annotate --stdio', where for each branch, we add an asm comment after the instruction with information on how often it was taken and predicted. See example with color output at:

http://vger.kernel.org/~acme/perf/annotate_basic_blocks.png

(Peter Zijlstra)

- Only open an evsel in CPUs in its cpu map, fixing some use cases in systems with multiple PMUs with different CPU maps (Mark Rutland)

- Fix handling of huge TLB maps, recognizing it as anonymous (Wang Nan)

Infrastructure:

- Remove the symbol filtering code, i.e. the callbacks passed to all functions that could end up loading a DSO symtab, simplifying the code, eventually allowing what we should have had since day one: removing the 'map' parameter from dso__load() functions (Arnaldo Carvalho de Melo)

Arch specific build fixes:

- Fix detached tarball build on powerpc, where we were still accessing a file outside tools/ (Ravi Bangoria)

----------------------------------------------------------------
Arnaldo Carvalho de Melo (5):
perf symbols: Mark if a symbol is idle in the library perf top: Remove old kernel-only symbol filter perf machine: Remove machine->symbol_filter and friends perf test vmlinux: Remove dead symbol_filter_t code perf symbols: Remove symbol_filter_t machinery

Mark Rutland (2):
perf evlist: Only open events on CPUs an evsel permits perf pmu: Support alternative sysfs cpumask

Peter Zijlstra (1):
perf annotate: Add branch stack / basic block

Ravi Bangoria (1):
perf powerpc: Fix build-test failure

Wang Nan (3):
perf tools: Recognize hugetlb mapping as anon mapping tools lib api fs: Add hugetlbfs filesystem detector perf record: Mark MAP_HUGETLB when synthesizing mmap events

 tools/lib/api/fs/fs.c                       |  15 ++
 tools/lib/api/fs/fs.h                       |   1 +
 tools/perf/arch/powerpc/util/sym-handling.c |   2 +-
 tools/perf/builtin-annotate.c               | 104 +++++++++
 tools/perf/builtin-inject.c                 |   2 +-
 tools/perf/builtin-kmem.c                   |  10 +-
 tools/perf/builtin-script.c                 |   4 +-
 tools/perf/builtin-top.c                    |  30 ---
 tools/perf/perf-sys.h                       |   1 -
 tools/perf/tests/code-reading.c             |   4 +-
 tools/perf/tests/vmlinux-kallsyms.c         |  17 +-
 tools/perf/ui/browsers/annotate.c           |   2 +-
 tools/perf/ui/browsers/map.c                |   4 +-
 tools/perf/util/Build                       |   1 +
 tools/perf/util/annotate.c                  |  95 +++++++-
 tools/perf/util/annotate.h                  |   1 +
 tools/perf/util/block-range.c               | 328 ++++++++++++++++++++++++++++
 tools/perf/util/block-range.h               |  71 ++++++
 tools/perf/util/event.c                     |  21 +-
 tools/perf/util/evlist.c                    |   8 +-
 tools/perf/util/intel-bts.c                 |   2 +-
 tools/perf/util/intel-pt.c                  |   4 +-
 tools/perf/util/machine.c                   |  38 +---
 tools/perf/util/machine.h                   |  34 +--
 tools/perf/util/map.c                       |  50 ++---
 tools/perf/util/map.h                       |  32 +--
 tools/perf/util/pmu.c                       |  15 +-
 tools/perf/util/probe-event.c               |  17 +-
 tools/perf/util/symbol-elf.c                |  32 +--
 tools/perf/util/symbol-minimal.c            |   4 +-
 tools/perf/util/symbol.c                    | 134 ++++++------
 tools/perf/util/symbol.h                    |  20 +-
 32 files changed, 817 insertions(+), 286 deletions(-)
 create mode 100644 tools/perf/util/block-range.c
 create mode 100644 tools/perf/util/block-range.h

Build stats:

[root@jouet ~]# time dm
1 69.078 alpine:3.4: Ok
2 24.055 android-ndk:r12b-arm: Ok
3 71.911 archlinux:latest: Ok
4 41.209 centos:5: Ok
5 58.240 centos:6: Ok
6 67.238 centos:7: Ok
7 62.040 debian:7: Ok
8 69.061 debian:8: Ok
9 38.124 debian:experimental: Ok
10 67.623 fedora:20: Ok
11 71.458 fedora:21: Ok
12 70.807 fedora:22: Ok
13 71.013 fedora:23: Ok
14 73.330 fedora:24: Ok
15 30.062 fedora:24-x-ARC-uClibc: Ok
16 77.616 fedora:rawhide: Ok
17 73.663 mageia:5: Ok
18 69.264 opensuse:13.2: Ok
19 71.532 opensuse:42.1: Ok
20 76.282 opensuse:tumbleweed: Ok
21 54.666 ubuntu:12.04.5: Ok
22 37.170 ubuntu:14.04: Ok
23 66.101 ubuntu:14.04.4: Ok
24 68.881 ubuntu:15.10: Ok
25 62.698 ubuntu:16.04: Ok
26 53.046 ubuntu:16.04-x-arm: Ok
27 51.609 ubuntu:16.04-x-arm64: Ok
28 51.842 ubuntu:16.04-x-powerpc64: Ok
29 53.347 ubuntu:16.04-x-powerpc64el: Ok
30 72.280 ubuntu:16.10: Ok
31 54.078 ubuntu:16.10-x-s390: Ok

Quoted 4 lines

real 31m19.919s
user 0m1.890s
sys 0m2.201s
[root@jouet ~]#

Pulled, thanks a lot Arnaldo!

Ingo