Skip to contentSkip to conversation

perf/core improvements and fixes

GIT PULL New Arnaldo Carvalho de Melo 1 participant 13 messages Nov 5, 2015

Subsystems (3)
lore
Share & tools
lore

Arnaldo Carvalho de Melo

author maintainer
#0 lore raw

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit bebd23a2ed31d47e7dd746d3b125068aa2c42d85:

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core (2015-10-30 10:09:37 +0100)

are available in the git repository at:

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

for you to fetch changes up to 0014de172d228e450377d1fd079d94e67128d27f:

perf sched latency: Fix thread pid reuse issue (2015-11-05 12:51:00 -0300)

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

User visible:

- Fix 'perf top' segfault related to splitting overlapping mmaps (Jiri Olsa)

- Fix 'perf sched latency' when there is pid/tid reuse (Jiri Olsa)

- Fix documentation for 'perf trace -i' (Peter Feiner)

Infrastructure:

- Make the LINUX_VERSION_CODE define available for bpf scriptlets to use (Wang Nan)

- Pass the number of configured CPUs via the __NR_CPUS__ define to bpf scriptlets (Wang Nan)

- Fix libbpf compiler warning on CentOS 6 (Namhyung Kim)

- Only be verbose in several perf test entries, bpf included, when -v is used (Wang Nan)

- Don't run the 'build-test' entries always in the same order, the full set takes a long time, so sometimes we interrupt, shuffling them avoids running just the first same few in interrupted runs (Arnaldo Carvalho de Melo)

- Change FEATURE-DUMP to FEATURE-DUMP.libbpf in .gitignore and 'clean' make target (Yunlong Song)

- 'perf stat' refactorings to avoid duplicated code (Andi Kleen)

----------------------------------------------------------------
Andi Kleen (2):
perf stat: Move sw clock metrics printout to stat-shadow perf stat: Use common printout function to avoid duplicated code

Arnaldo Carvalho de Melo (1):
perf tools: Allow shuffling the build tests

Jiri Olsa (2):
perf tools: Insert split maps correctly into origin group perf sched latency: Fix thread pid reuse issue

Namhyung Kim (1):
tools lib bpf: Fix compiler warning on CentOS 6

Peter Feiner (1):
perf trace: Fix documentation for -i

Wang Nan (5):
perf test: Keep test result clean if '-v' not set
perf bpf: Mute libbpf when '-v' not set
perf llvm: Pass number of configured CPUs to clang compiler
perf llvm: Pass LINUX_VERSION_CODE to BPF program when compiling perf tools: Fix find_perf_probe_point_from_map() which incorrectly returns success

Yunlong Song (1):
tools lib bpf: Change FEATURE-DUMP to FEATURE-DUMP.libbpf

 tools/lib/bpf/.gitignore                |  2 +-
 tools/lib/bpf/Makefile                  |  2 +-
 tools/lib/bpf/libbpf.c                  |  4 +--
 tools/lib/bpf/libbpf.h                  |  2 +-
 tools/perf/Documentation/perf-trace.txt |  1 -
 tools/perf/Makefile                     |  2 +-
 tools/perf/builtin-sched.c              |  5 +--
 tools/perf/builtin-stat.c               | 59 +++++++++++----------------------
 tools/perf/tests/attr.c                 |  3 +-
 tools/perf/tests/code-reading.c         |  8 ++---
 tools/perf/tests/keep-tracking.c        |  4 +--
 tools/perf/tests/llvm.c                 | 11 +++---
 tools/perf/tests/make                   |  5 +++
 tools/perf/tests/switch-tracking.c      |  4 +--
 tools/perf/util/bpf-loader.c            |  4 +--
 tools/perf/util/llvm-utils.c            | 51 ++++++++++++++++++++++++----
 tools/perf/util/map.c                   | 10 ++++--
 tools/perf/util/probe-event.c           |  3 ++
 tools/perf/util/stat-shadow.c           |  5 +++
 19 files changed, 110 insertions(+), 75 deletions(-)
author maintainer
#1 lore raw

PATCH 1/12 perf test: Keep test result clean if '-v' not set

From: Wang Nan <[email protected]>

According to [1], 'perf test' should avoid output too much information if '-v' is not set, only 'Ok', 'FAIL' or 'Skip' need to be printed.

This patch removes several messages sent directly to stderr to make the output clean.

Before this patch:

  # perf test dummy
  23: Test using a dummy software event to keep tracking       : (not supported) Ok

After this patch:

  # perf test dummy
  23: Test using a dummy software event to keep tracking       : Skip

[1] http://lkml.kernel.org/r/[email protected]

---
 tools/perf/tests/attr.c            |  3 +--
 tools/perf/tests/code-reading.c    |  8 ++++----
 tools/perf/tests/keep-tracking.c   |  4 ++--
 tools/perf/tests/llvm.c            | 11 ++++-------
 tools/perf/tests/switch-tracking.c |  4 ++--
 5 files changed, 13 insertions(+), 17 deletions(-)
tools/perf/tests/attr.c +1 -2
index 2dfc9ad0e6f2..638875a0960a 100644
@@ -171,6 +171,5 @@ int test__attr(void)
 	    !lstat(path_perf, &st))
 		return run_dir(path_dir, path_perf);
 
-	fprintf(stderr, " (omitted)");
-	return 0;
+	return TEST_SKIP;
 }
tools/perf/tests/code-reading.c +4 -4
index 49b1959dda41..a767a6400c5c 100644
@@ -613,16 +613,16 @@ int test__code_reading(void)
 	case TEST_CODE_READING_OK:
 		return 0;
 	case TEST_CODE_READING_NO_VMLINUX:
-		fprintf(stderr, " (no vmlinux)");
+		pr_debug("no vmlinux\n");
 		return 0;
 	case TEST_CODE_READING_NO_KCORE:
-		fprintf(stderr, " (no kcore)");
+		pr_debug("no kcore\n");
 		return 0;
 	case TEST_CODE_READING_NO_ACCESS:
-		fprintf(stderr, " (no access)");
+		pr_debug("no access\n");
 		return 0;
 	case TEST_CODE_READING_NO_KERNEL_OBJ:
-		fprintf(stderr, " (no kernel obj)");
+		pr_debug("no kernel obj\n");
 		return 0;
 	default:
 		return -1;
tools/perf/tests/keep-tracking.c +2 -2
index 4d4b9837b630..a2e2269aa093 100644
@@ -90,8 +90,8 @@ int test__keep_tracking(void)
 	evsel->attr.enable_on_exec = 0;
 
 	if (perf_evlist__open(evlist) < 0) {
-		fprintf(stderr, " (not supported)");
-		err = 0;
+		pr_debug("Unable to open dummy and cycles event\n");
+		err = TEST_SKIP;
 		goto out_err;
 	}
 
tools/perf/tests/llvm.c +4 -7
index 52d55971f66f..512d3620e9f9 100644
@@ -36,7 +36,7 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
 static int test__bpf_parsing(void *obj_buf __maybe_unused,
 			     size_t obj_buf_sz __maybe_unused)
 {
-	fprintf(stderr, " (skip bpf parsing)");
+	pr_debug("Skip bpf parsing\n");
 	return 0;
 }
 #endif
@@ -55,7 +55,7 @@ int test__llvm(void)
 	 * and clang is not found in $PATH, and this is not perf test -v
 	 */
 	if (verbose == 0 && !llvm_param.user_set_param && llvm__search_clang()) {
-		fprintf(stderr, " (no clang, try 'perf test -v LLVM')");
+		pr_debug("No clang and no verbosive, skip this test\n");
 		return TEST_SKIP;
 	}
 
@@ -86,11 +86,8 @@ int test__llvm(void)
 	err = llvm__compile_bpf("-", &obj_buf, &obj_buf_sz);
 
 	verbose = old_verbose;
-	if (err) {
-		if (!verbose)
-			fprintf(stderr, " (use -v to see error message)");
-		return -1;
-	}
+	if (err)
+		return TEST_FAIL;
 
 	err = test__bpf_parsing(obj_buf, obj_buf_sz);
 	free(obj_buf);
tools/perf/tests/switch-tracking.c +2 -2
index e698742d4fec..a02af503100c 100644
@@ -366,7 +366,7 @@ int test__switch_tracking(void)
 
 	/* Third event */
 	if (!perf_evlist__can_select_event(evlist, sched_switch)) {
-		fprintf(stderr, " (no sched_switch)");
+		pr_debug("No sched_switch\n");
 		err = 0;
 		goto out;
 	}
@@ -442,7 +442,7 @@ int test__switch_tracking(void)
 	}
 
 	if (perf_evlist__open(evlist) < 0) {
-		fprintf(stderr, " (not supported)");
+		pr_debug("Not supported\n");
 		err = 0;
 		goto out;
 	}
Signature · 1 line
2.1.0
author maintainer
#2 lore raw

PATCH 2/12 perf bpf: Mute libbpf when '-v' not set

In reply to Arnaldo Carvalho de Melo

From: Wang Nan <[email protected]>

According to [1], libbpf should be muted. This patch reset info and warning message level to ensure libbpf doesn't output anything even if error happened.

[1] http://lkml.kernel.org/r/[email protected]

Committer note:

Before:

Testing it with an incompatible kernel version in the .c file that generated foo.o:

[root@zoo ~]# perf record -e /tmp/foo.o sleep 1
libbpf: load bpf program failed: Invalid argument
libbpf: -- BEGIN DUMP LOG ---
libbpf:

libbpf: -- END LOG --
libbpf: failed to load program 'fork=_do_fork'
libbpf: failed to load object '/tmp/foo.o'
event syntax error: '/tmp/foo.o'
\___ Invalid argument: Are you root and runing a CONFIG_BPF_SYSCALL kernel?

(add -v to see detail)
Run 'perf list' for a list of valid events

Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]

-e, --event <event> event selector. use 'perf list' to list available events
[root@zoo ~]#

After:

[root@zoo ~]# perf record -e /tmp/foo.o sleep 1
event syntax error: '/tmp/foo.o'
\___ Invalid argument: Are you root and runing a CONFIG_BPF_SYSCALL kernel?

(add -v to see detail)
Run 'perf list' for a list of valid events

Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]

-e, --event <event> event selector. use 'perf list' to list available events
[root@zoo ~]#

This, BTW, need fixing to emit a proper message by validating the version in the foo.o "version" ELF section against the running kernel, warning the user instead of asking the kernel to load a binary that it will refuse due to unmatching kernel version.

---
 tools/perf/util/bpf-loader.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/util/bpf-loader.c +2 -2
index ba6f7526b282..0c5d174245bb 100644
@@ -26,8 +26,8 @@ static int libbpf_##name(const char *fmt, ...)	\
 	return ret;				\
 }
 
-DEFINE_PRINT_FN(warning, 0)
-DEFINE_PRINT_FN(info, 0)
+DEFINE_PRINT_FN(warning, 1)
+DEFINE_PRINT_FN(info, 1)
 DEFINE_PRINT_FN(debug, 1)
 
 struct bpf_prog_priv {
Signature · 1 line
2.1.0
author maintainer
#3 lore raw

PATCH 3/12 tools lib bpf: Fix compiler warning on CentOS 6

In reply to Arnaldo Carvalho de Melo

From: Namhyung Kim <[email protected]>

CC libbpf.o
cc1: warnings being treated as errors
libbpf.c: In function 'bpf_program__title':
libbpf.c:1037: error: declaration of 'dup' shadows a global declaration /usr/include/unistd.h:528: error: shadowed declaration is here
mv: cannot stat `./.libbpf.o.tmp': No such file or directory make[3]: *** [libbpf.o] Error 1
make[2]: *** [libbpf-in.o] Error 2
make[1]: *** [/linux/tools/lib/bpf/libbpf.a] Error 2 make[1]: *** Waiting for unfinished jobs....

---
 tools/lib/bpf/libbpf.c | 4 ++--
 tools/lib/bpf/libbpf.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
tools/lib/bpf/libbpf.c +2 -2
index 4252fc22f78f..9f3c8cf9249b 100644
@@ -1034,12 +1034,12 @@ int bpf_program__get_private(struct bpf_program *prog, void **ppriv)
 	return 0;
 }
 
-const char *bpf_program__title(struct bpf_program *prog, bool dup)
+const char *bpf_program__title(struct bpf_program *prog, bool needs_copy)
 {
 	const char *title;
 
 	title = prog->section_name;
-	if (dup) {
+	if (needs_copy) {
 		title = strdup(title);
 		if (!title) {
 			pr_warning("failed to strdup program title\n");
tools/lib/bpf/libbpf.h +1 -1
index f16170c95ffd..bc80af03c6f4 100644
@@ -63,7 +63,7 @@ int bpf_program__set_private(struct bpf_program *prog, void *priv,
 int bpf_program__get_private(struct bpf_program *prog,
 			     void **ppriv);
 
-const char *bpf_program__title(struct bpf_program *prog, bool dup);
+const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
 
 int bpf_program__fd(struct bpf_program *prog);
 
Signature · 1 line
2.1.0
author maintainer
#4 lore raw

PATCH 4/12 perf stat: Move sw clock metrics printout to stat-shadow

In reply to Arnaldo Carvalho de Melo

From: Andi Kleen <[email protected]>

The sw clock metrics printing was missed in the earlier move to stat-shadow of all the other metric printouts. Move it too.

v2: Fix metrics printing in this version to make bisect safe.

---
 tools/perf/builtin-stat.c     | 8 +++-----
 tools/perf/util/stat-shadow.c | 5 +++++
 2 files changed, 8 insertions(+), 5 deletions(-)
tools/perf/builtin-stat.c +3 -5
index 2f438f76cceb..8a788956b6a3 100644
@@ -493,6 +493,7 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	double msecs = avg / 1e6;
 	const char *fmt_v, *fmt_n;
 	char name[25];
+	int cpu = cpu_map__id_to_cpu(id);
 
 	fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
 	fmt_n = csv_output ? "%s" : "%-25s";
@@ -517,11 +518,8 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	if (csv_output || stat_config.interval)
 		return;
 
-	if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
-		fprintf(output, " # %8.3f CPUs utilized          ",
-			avg / avg_stats(&walltime_nsecs_stats));
-	else
-		fprintf(output, "                                   ");
+	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
+				      stat_config.aggr_mode);
 }
 
 static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
tools/perf/util/stat-shadow.c +5 -0
index 2a5d8d7698ae..6ac03146889d 100644
@@ -413,6 +413,11 @@ void perf_stat__print_shadow_stats(FILE *out, struct perf_evsel *evsel,
 			ratio = total / avg;
 
 		fprintf(out, " # %8.0f cycles / elision       ", ratio);
+	} else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) {
+		if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
+			fprintf(out, " # %8.3f CPUs utilized          ", avg / ratio);
+		else
+			fprintf(out, "                                   ");
 	} else if (runtime_nsecs_stats[cpu].n != 0) {
 		char unit = 'M';
 
Signature · 1 line
2.1.0
author maintainer
#5 lore raw

PATCH 5/12 perf stat: Use common printout function to avoid duplicated code

In reply to Arnaldo Carvalho de Melo

From: Andi Kleen <[email protected]>

Instead of every caller deciding whether to call abs or nsec printout do it all in a single central function. No functional changes.

---
 tools/perf/builtin-stat.c | 57 +++++++++++++++++------------------------------
 1 file changed, 20 insertions(+), 37 deletions(-)
tools/perf/builtin-stat.c +20 -37
index 8a788956b6a3..b74ee0f2e714 100644
@@ -493,7 +493,6 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	double msecs = avg / 1e6;
 	const char *fmt_v, *fmt_n;
 	char name[25];
-	int cpu = cpu_map__id_to_cpu(id);
 
 	fmt_v = csv_output ? "%.6f%s" : "%18.6f%s";
 	fmt_n = csv_output ? "%s" : "%-25s";
@@ -514,12 +513,6 @@ static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
-
-	if (csv_output || stat_config.interval)
-		return;
-
-	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
-				      stat_config.aggr_mode);
 }
 
 static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
@@ -527,7 +520,6 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 	FILE *output = stat_config.output;
 	double sc =  evsel->scale;
 	const char *fmt;
-	int cpu = cpu_map__id_to_cpu(id);
 
 	if (csv_output) {
 		fmt = sc != 1.0 ?  "%.2f%s" : "%.0f%s";
@@ -540,9 +532,6 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 	aggr_printout(evsel, id, nr);
 
-	if (stat_config.aggr_mode == AGGR_GLOBAL)
-		cpu = 0;
-
 	fprintf(output, fmt, avg, csv_sep);
 
 	if (evsel->unit)
@@ -554,12 +543,24 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
 
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
+}
 
-	if (csv_output || stat_config.interval)
-		return;
+static void printout(int id, int nr, struct perf_evsel *counter, double uval)
+{
+	int cpu = cpu_map__id_to_cpu(id);
+
+	if (stat_config.aggr_mode == AGGR_GLOBAL)
+		cpu = 0;
+
+	if (nsec_counter(counter))
+		nsec_printout(id, nr, counter, uval);
+	else
+		abs_printout(id, nr, counter, uval);
 
-	perf_stat__print_shadow_stats(output, evsel, avg, cpu,
-				      stat_config.aggr_mode);
+	if (!csv_output && !stat_config.interval)
+		perf_stat__print_shadow_stats(stat_config.output, counter,
+					      uval, cpu,
+					      stat_config.aggr_mode);
 }
 
 static void print_aggr(char *prefix)
@@ -615,12 +616,7 @@ static void print_aggr(char *prefix)
 				continue;
 			}
 			uval = val * counter->scale;
-
-			if (nsec_counter(counter))
-				nsec_printout(id, nr, counter, uval);
-			else
-				abs_printout(id, nr, counter, uval);
-
+			printout(id, nr, counter, uval);
 			if (!csv_output)
 				print_noise(counter, 1.0);
 
@@ -651,11 +647,7 @@ static void print_aggr_thread(struct perf_evsel *counter, char *prefix)
 			fprintf(output, "%s", prefix);
 
 		uval = val * counter->scale;
-
-		if (nsec_counter(counter))
-			nsec_printout(thread, 0, counter, uval);
-		else
-			abs_printout(thread, 0, counter, uval);
+		printout(thread, 0, counter, uval);
 
 		if (!csv_output)
 			print_noise(counter, 1.0);
@@ -705,11 +697,7 @@ static void print_counter_aggr(struct perf_evsel *counter, char *prefix)
 	}
 
 	uval = avg * counter->scale;
-
-	if (nsec_counter(counter))
-		nsec_printout(-1, 0, counter, uval);
-	else
-		abs_printout(-1, 0, counter, uval);
+	printout(-1, 0, counter, uval);
 
 	print_noise(counter, avg);
 
@@ -762,12 +750,7 @@ static void print_counter(struct perf_evsel *counter, char *prefix)
 		}
 
 		uval = val * counter->scale;
-
-		if (nsec_counter(counter))
-			nsec_printout(cpu, 0, counter, uval);
-		else
-			abs_printout(cpu, 0, counter, uval);
-
+		printout(cpu, 0, counter, uval);
 		if (!csv_output)
 			print_noise(counter, 1.0);
 		print_running(run, ena);
Signature · 1 line
2.1.0
author maintainer
#6 lore raw

PATCH 6/12 perf tools: Insert split maps correctly into origin group

In reply to Arnaldo Carvalho de Melo

From: Jiri Olsa <[email protected]>

When new maps are cloned out of split map they are added into origin map's group, but their groups pointer is not updated.

This could lead to a segfault, because map->groups is expected to be always set as reported by Markus:

__map__is_kernel (map=map@entry=0x1abb7a0) at util/map.c:238
238 return __machine__kernel_map(map->groups->machine, map->type) =
(gdb) bt

  #0  __map__is_kernel (map=map@entry=0x1abb7a0) at util/map.c:238
  #1  0x00000000004393e4 in symbol_filter (map=map@entry=0x1abb7a0, sym=sym@entry
  #2  0x00000000004fcd4d in dso__load_sym (dso=dso@entry=0x166dae0, map=map@entry
  #3  0x00000000004a64e0 in dso__load (dso=0x166dae0, map=map@entry=0x1abb7a0, fi
  #4  0x00000000004b941f in map__load (filter=0x4393c0 <symbol_filter>, map=<opti
  #5  map__find_symbol (map=0x1abb7a0, addr=40188, filter=0x4393c0 <symbol_filter

...

Adding __map_groups__insert function to add map into groups together with map->groups pointer update. It takes no lock as opposed to existing map_groups__insert, as maps__fixup_overlappings(), where it is being called, already has the necessary lock held.

Using __map_groups__insert to add new maps after map split.

Cc Andrew Morton <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
Fixes cfc5acd4c80b ("perf top: Filter symbols based on __map__is_kernel(map)")
---
 tools/perf/util/map.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
tools/perf/util/map.c +8 -2
index 4e38c396a897..afc6b56cf749 100644
@@ -644,6 +644,12 @@ size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
 	return printed;
 }
 
+static void __map_groups__insert(struct map_groups *mg, struct map *map)
+{
+	__maps__insert(&mg->maps[map->type], map);
+	map->groups = mg;
+}
+
 static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
 {
 	struct rb_root *root;
@@ -682,7 +688,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
 			}
 
 			before->end = map->start;
-			__maps__insert(maps, before);
+			__map_groups__insert(pos->groups, before);
 			if (verbose >= 2)
 				map__fprintf(before, fp);
 		}
@@ -696,7 +702,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
 			}
 
 			after->start = map->end;
-			__maps__insert(maps, after);
+			__map_groups__insert(pos->groups, after);
 			if (verbose >= 2)
 				map__fprintf(after, fp);
 		}
Signature · 1 line
2.1.0
author maintainer
#7 lore raw

PATCH 7/12 perf tools: Allow shuffling the build tests

In reply to Arnaldo Carvalho de Melo

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

Those tests take a long time and sometimes we stop it, so allow randomly shuffling the tests so that we have a better chance of running more of them in partial 'make build-test' runs.

Using it just on the 'build-test' target, i.e.:

make -C tools/perf build-test

Is equivalent to:

make SHUF=1 -C tools/perf -f tests/make

---
 tools/perf/Makefile   | 2 +-
 tools/perf/tests/make | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)
tools/perf/Makefile +1 -1
index 480546d5f13b..dcd9a70c7193 100644
@@ -78,7 +78,7 @@ clean:
 # The build-test target is not really parallel, don't print the jobs info:
 #
 build-test:
-	@$(MAKE) -f tests/make --no-print-directory
+	@$(MAKE) SHUF=1 -f tests/make --no-print-directory
 
 #
 # All other targets get passed through:
tools/perf/tests/make +5 -0
index 2cbd0c6901e3..8ea3dffc5065 100644
@@ -221,6 +221,11 @@ test_O = $(if $(test_$1),$(test_$1),$(test_default_O))
 
 all:
 
+ifdef SHUF
+run := $(shell shuf -e $(run))
+run_O := $(shell shuf -e $(run_O))
+endif
+
 ifdef DEBUG
 d := $(info run   $(run))
 d := $(info run_O $(run_O))
Signature · 1 line
2.1.0
author maintainer
#8 lore raw

PATCH 8/12 perf llvm: Pass available CPU number to clang compiler

In reply to Arnaldo Carvalho de Melo

From: Wang Nan <[email protected]>

This patch introduces a new macro "__NR_CPUS__" to perf's embedded clang compiler, which represent the available CPU counters in this system. BPF program can use this macro to create a map with same number of system CPUs. For exmaple:

struct bpf_map_def SEC("maps") pmu_map = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u32),
.max_entries = __NR_CPUS__,
};

---
 tools/perf/util/llvm-utils.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
tools/perf/util/llvm-utils.c +18 -6
index 4f6a4780bd5f..80eecefc604f 100644
@@ -11,10 +11,11 @@
 #include "cache.h"
 
 #define CLANG_BPF_CMD_DEFAULT_TEMPLATE				\
-		"$CLANG_EXEC -D__KERNEL__ $CLANG_OPTIONS "	\
-		"$KERNEL_INC_OPTIONS -Wno-unused-value "	\
-		"-Wno-pointer-sign -working-directory "		\
-		"$WORKING_DIR -c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
+		"$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
+		"$CLANG_OPTIONS $KERNEL_INC_OPTIONS "		\
+		"-Wno-unused-value -Wno-pointer-sign "		\
+		"-working-directory $WORKING_DIR "		\
+		"-c \"$CLANG_SOURCE\" -target bpf -O2 -o -"
 
 struct llvm_param llvm_param = {
 	.clang_path = "clang",
@@ -326,8 +327,8 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 int llvm__compile_bpf(const char *path, void **p_obj_buf,
 		      size_t *p_obj_buf_sz)
 {
-	int err;
-	char clang_path[PATH_MAX];
+	int err, nr_cpus_avail;
+	char clang_path[PATH_MAX], nr_cpus_avail_str[64];
 	const char *clang_opt = llvm_param.clang_opt;
 	const char *template = llvm_param.clang_bpf_cmd_template;
 	char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
@@ -354,6 +355,17 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
 	 */
 	get_kbuild_opts(&kbuild_dir, &kbuild_include_opts);
 
+	nr_cpus_avail = sysconf(_SC_NPROCESSORS_CONF);
+	if (nr_cpus_avail <= 0) {
+		pr_err(
+"WARNING:\tunable to get available CPUs in this system: %s\n"
+"        \tUse 128 instead.\n", strerror(errno));
+		nr_cpus_avail = 128;
+	}
+	snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
+		 nr_cpus_avail);
+
+	force_set_env("NR_CPUS", nr_cpus_avail_str);
 	force_set_env("CLANG_EXEC", clang_path);
 	force_set_env("CLANG_OPTIONS", clang_opt);
 	force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts);
Signature · 1 line
2.1.0
author maintainer
#9 lore raw

PATCH 9/12 perf llvm: Pass LINUX_VERSION_CODE to BPF program when compiling

In reply to Arnaldo Carvalho de Melo

From: Wang Nan <[email protected]>

Arnaldo suggests to make LINUX_VERSION_CODE works like __func__ and __FILE__ so user don't need to care setting right linux version too much. In this patch, perf llvm transfers LINUX_VERSION_CODE macro through clang cmdline.

[1] http://lkml.kernel.org/r/[email protected]

Committer notes:

Before, forgetting to update the version:

  # uname -r
  4.3.0-rc1+
  # cat bpf.c
  __attribute__((section("fork=_do_fork"), used))
  int fork(void *ctx)
  {
          return 1;
  }
  char _license[] __attribute__((section("license"), used)) = "GPL";
  int _version __attribute__((section("version"), used)) = 0x40200;
  #
  # perf record -e bpf.c sleep 1
  event syntax error: 'bpf.c'
                       \___ Invalid argument: Are you root and runing a CONFIG_BPF_SYSCALL kernel?

(add -v to see detail)
Run 'perf list' for a list of valid events

Usage: perf record [<options>] [<command>]
or: perf record [<options>] -- <command> [<options>]

-e, --event <event> event selector. use 'perf list' to list available events
#

After:

  # grep version bpf.c
  int _version __attribute__((section("version"), used)) = LINUX_VERSION_CODE;
  # perf record -e bpf.c sleep 1
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.017 MB perf.data ]
  # perf evlist -v
  perf_bpf_probe:fork: type: 2, size: 112, config: 0x5ee, { sample_period,
  sample_freq }: 1, sample_type: IP|TID|TIME|CPU|PERIOD|RAW, disabled: 1,
  inherit: 1, mmap: 1, comm: 1, enable_on_exec: 1, task: 1, sample_id_all:
  1, exclude_guest: 1, mmap2: 1, comm_exec: 1
  #
---
 tools/perf/util/llvm-utils.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
tools/perf/util/llvm-utils.c +27 -0
index 80eecefc604f..8ee25bea1b24 100644
@@ -12,6 +12,7 @@
 
 #define CLANG_BPF_CMD_DEFAULT_TEMPLATE				\
 		"$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
+		"-DLINUX_VERSION_CODE=$LINUX_VERSION_CODE "	\
 		"$CLANG_OPTIONS $KERNEL_INC_OPTIONS "		\
 		"-Wno-unused-value -Wno-pointer-sign "		\
 		"-working-directory $WORKING_DIR "		\
@@ -324,11 +325,33 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
 	pr_debug("include option is set to %s\n", *kbuild_include_opts);
 }
 
+static unsigned long
+fetch_kernel_version(void)
+{
+	struct utsname utsname;
+	int version, patchlevel, sublevel, err;
+
+	if (uname(&utsname))
+		return 0;
+
+	err = sscanf(utsname.release, "%d.%d.%d",
+		     &version, &patchlevel, &sublevel);
+
+	if (err != 3) {
+		pr_debug("Unablt to get kernel version from uname '%s'\n",
+			 utsname.release);
+		return 0;
+	}
+
+	return (version << 16) + (patchlevel << 8) + sublevel;
+}
+
 int llvm__compile_bpf(const char *path, void **p_obj_buf,
 		      size_t *p_obj_buf_sz)
 {
 	int err, nr_cpus_avail;
 	char clang_path[PATH_MAX], nr_cpus_avail_str[64];
+	char linux_version_code_str[64];
 	const char *clang_opt = llvm_param.clang_opt;
 	const char *template = llvm_param.clang_bpf_cmd_template;
 	char *kbuild_dir = NULL, *kbuild_include_opts = NULL;
@@ -365,7 +388,11 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
 	snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
 		 nr_cpus_avail);
 
+	snprintf(linux_version_code_str, sizeof(linux_version_code_str),
+		 "0x%lx", fetch_kernel_version());
+
 	force_set_env("NR_CPUS", nr_cpus_avail_str);
+	force_set_env("LINUX_VERSION_CODE", linux_version_code_str);
 	force_set_env("CLANG_EXEC", clang_path);
 	force_set_env("CLANG_OPTIONS", clang_opt);
 	force_set_env("KERNEL_INC_OPTIONS", kbuild_include_opts);
Signature · 1 line
2.1.0
author maintainer
#10 lore raw

PATCH 10/12 tools lib bpf: Change FEATURE-DUMP to FEATURE-DUMP.libbpf

In reply to Arnaldo Carvalho de Melo

From: Yunlong Song <[email protected]>

Commit ed63f34c026e9a60d17fa750ecdfe3f600d49393 ("perf tools: Make perf depend on libbpf") triggers the build of libbpf when building the perf tools, dynamically creating FEATURE-DUMP.libbpf.

It failed to update the tools/lib/bpf/.gitignore file to have that prefix, fix it.

Cc Adrian Hunter <[email protected]>
Cc Alexei Starovoitov <[email protected]>
Cc David Ahern <[email protected]>
Cc Jiri Olsa <[email protected]>
Cc Kan Liang <[email protected]>
Cc Masami Hiramatsu <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Paul Mackerras <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Wang Nan <[email protected]>
Fixes 65f041bee783 ("tools lib bpf: Use FEATURE_USER to allow building in the same dir as perf")
---
 tools/lib/bpf/.gitignore | 2 +-
 tools/lib/bpf/Makefile   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
tools/lib/bpf/.gitignore +1 -1
index 812aeedaea38..f81e549ddfdb 100644
@@ -1,2 +1,2 @@
 libbpf_version.h
-FEATURE-DUMP
+FEATURE-DUMP.libbpf
tools/lib/bpf/Makefile +1 -1
index fc9af57b666e..a3caaf3eafbd 100644
@@ -180,7 +180,7 @@ config-clean:
 clean:
 	$(call QUIET_CLEAN, libbpf) $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d \
 		$(RM) LIBBPF-CFLAGS
-	$(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP
+	$(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf
 
 
 
Signature · 1 line
2.1.0
author maintainer
#11 lore raw

PATCH 11/12 perf trace: Fix documentation for -i

In reply to Arnaldo Carvalho de Melo

From: Peter Feiner <[email protected]>

The -i flag was incorrectly listed as a short flag for --no-inherit. It should have only been listed as a short flag for --input.

This documentation error has existed since the --input flag was introduced in 6810fc915f7a89d8134edb3996dbbf8eac386c26 (perf trace: Add option to analyze events in a file versus live).

Cc David Ahern <[email protected]>
Fixes 6810fc915f7a ("perf trace: Add option to analyze events in a file versus live")
---
 tools/perf/Documentation/perf-trace.txt | 1 -
 1 file changed, 1 deletion(-)
tools/perf/Documentation/perf-trace.txt +0 -1
index 7ea078658a87..13293de8869f 100644
@@ -62,7 +62,6 @@ OPTIONS
 --verbose=::
         Verbosity level.
 
--i::
 --no-inherit::
 	Child tasks do not inherit counters.
 
Signature · 1 line
2.1.0
author maintainer
#12 lore raw

PATCH 12/12 perf tools: Fix find_perf_probe_point_from_map() which incorrectly returns success

In reply to Arnaldo Carvalho de Melo

From: Wang Nan <[email protected]>

It is possible that find_perf_probe_point_from_map() fails to find a symbol but still returns 0 because of an small error when coding:
find_perf_probe_point_from_map() set 'ret' to error code at first, but also use it to hold return value of kernel_get_symbol_address_by_name().

This patch resets 'ret' to error even kernel_get_symbol_address_by_name() success, so if !sym, the whole function returns error correctly.

---
 tools/perf/util/probe-event.c | 3 +++
 1 file changed, 3 insertions(+)
tools/perf/util/probe-event.c +3 -0
index b51a8bfb40f9..e659c4faddec 100644
@@ -1905,6 +1905,9 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
 			sym = __find_kernel_function(addr, &map);
 		}
 	}
+
+	/* ret may has be overwritten so reset it */
+	ret = -ENOENT;
 	if (!sym)
 		goto out;
 
Signature · 1 line
2.1.0