From 2932cffc89e9a1476b28a59896fa4f81e0d4f131 Mon Sep 17 00:00:00 2001 From: "Carlos R. Mafra" Date: Mon, 17 Aug 2009 00:36:21 +0200 Subject: [PATCH 1/7] perf: Rename perf-examples.txt to examples.txt Rename it to examples.txt to avoid the perf-*.txt pattern in the Makefile, otherwise 'make doc' fails because perf-examples.txt is not formatted to be a man page: ERROR: perf-examples.txt: line 1: manpage document title is mandatory Signed-off-by: Carlos R. Mafra Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: Signed-off-by: Ingo Molnar --- tools/perf/Documentation/{perf-examples.txt => examples.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tools/perf/Documentation/{perf-examples.txt => examples.txt} (100%) diff --git a/tools/perf/Documentation/perf-examples.txt b/tools/perf/Documentation/examples.txt similarity index 100% rename from tools/perf/Documentation/perf-examples.txt rename to tools/perf/Documentation/examples.txt From e1ac3614ff606ae03677f47459113f98a19af63c Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Fri, 14 Aug 2009 15:39:10 +1000 Subject: [PATCH 2/7] perf_counter: Check task on counter read IPI In general, code in perf_counter.c that is called through an IPI checks, for per-task counters, that the counter's task is still the current task. This is to handle the race condition where the cpu switches from the task we want to another task in the interval between sending the IPI and the IPI arriving and being handled on the target CPU. For some reason, __perf_counter_read is missing this check, yet there is no reason why the race condition can't occur. This adds a check that the current task is the one we want. If it isn't, we just return. In that case the counter->count value should be up to date, since it will have been updated when the counter was scheduled out, which must have happened since the IPI was sent. I don't have an example of an actual failure due to this race, but it seems obvious that it could occur and we need to guard against it. Signed-off-by: Paul Mackerras Acked-by: Peter Zijlstra LKML-Reference: <19076.63614.277861.368125@drongo.ozlabs.ibm.com> Signed-off-by: Ingo Molnar --- kernel/perf_counter.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 534e20d14d63..b8fe7397b902 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1503,10 +1503,21 @@ static void perf_counter_enable_on_exec(struct task_struct *task) */ static void __perf_counter_read(void *info) { + struct perf_cpu_context *cpuctx = &__get_cpu_var(perf_cpu_context); struct perf_counter *counter = info; struct perf_counter_context *ctx = counter->ctx; unsigned long flags; + /* + * If this is a task context, we need to check whether it is + * the current task context of this cpu. If not it has been + * scheduled out before the smp call arrived. In that case + * counter->count would have been updated to a recent sample + * when the counter was scheduled out. + */ + if (ctx->task && cpuctx->task_ctx != ctx) + return; + local_irq_save(flags); if (ctx->is_active) update_context_time(ctx); From f738eb1b63edf664da1b4ac76895d988749b2f07 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 18 Aug 2009 11:32:24 +0200 Subject: [PATCH 3/7] perf_counter: Fix the PARISC build PARISC does not build: /home/mingo/tip/kernel/perf_counter.c: In function 'perf_counter_index': /home/mingo/tip/kernel/perf_counter.c:2016: error: 'PERF_COUNTER_INDEX_OFFSET' undeclared (first use in this function) /home/mingo/tip/kernel/perf_counter.c:2016: error: (Each undeclared identifier is reported only once /home/mingo/tip/kernel/perf_counter.c:2016: error: for each function it appears in.) As PERF_COUNTER_INDEX_OFFSET is not defined. Now, we could define it in the architecture - but lets also provide a core default of 0 (which happens to be what all but one architecture uses at the moment). Architectures that need a different index offset should set this value in their asm/perf_counter.h files. Cc: Kyle McMartin Cc: Helge Deller Cc: linux-parisc@vger.kernel.org Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: Signed-off-by: Ingo Molnar --- kernel/perf_counter.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index b8fe7397b902..36f65e2b8b57 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -2019,6 +2019,10 @@ int perf_counter_task_disable(void) return 0; } +#ifndef PERF_COUNTER_INDEX_OFFSET +# define PERF_COUNTER_INDEX_OFFSET 0 +#endif + static int perf_counter_index(struct perf_counter *counter) { if (counter->state != PERF_COUNTER_STATE_ACTIVE) From 15f3fa4e7f608c5ce19187b3b4a953222fdfa751 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 18 Aug 2009 13:52:28 +0200 Subject: [PATCH 4/7] perf annotate: Fix segmentation fault Linus reported this perf annotate segfault: [torvalds@nehalem git]$ perf annotate unmap_vmas Segmentation fault #0 map__clone (self=) at builtin-annotate.c:236 #1 thread__fork (self=) at builtin-annotate.c:372 The bug here was that builtin-annotate.c was a copy of builtin-report.c and a threading related fix to builtin-report.c didnt get propagated to builtin-annotate.c ... Reported-by: Linus Torvalds Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: Signed-off-by: Ingo Molnar --- tools/perf/builtin-annotate.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 1dba568e1941..343e7b14bf01 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -980,6 +980,13 @@ process_fork_event(event_t *event, unsigned long offset, unsigned long head) (void *)(long)(event->header.size), event->fork.pid, event->fork.ppid); + /* + * A thread clone will have the same PID for both + * parent and child. + */ + if (thread == parent) + return 0; + if (!thread || !parent || thread__fork(thread, parent)) { dprintf("problem processing PERF_EVENT_FORK, skipping event.\n"); return -1; From b395cd8a74b4a8d943dd4b5585e676f62f7350b3 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Tue, 18 Aug 2009 12:41:25 -0400 Subject: [PATCH 5/7] perf tools: Make 'make html' work pushd tools/perf/Documentation make html popd is failing for me... ASCIIDOC perf-annotate.html ERROR: unsafe: include file: /etc/asciidoc/./stylesheets/xhtml11.css ERROR: unsafe: include file: /etc/asciidoc/./stylesheets/xhtml11-manpage.css ERROR: unsafe: include file: /etc/asciidoc/./stylesheets/xhtml11-quirks.css make: *** [perf-annotate.html] Error 1 Apparently asciidoc "unsafe" is the default mode of operation in practice. https://bugzilla.redhat.com/show_bug.cgi?id=506953 Works tidily now. Signed-off-by: Kyle McMartin Cc: Peter Zijlstra Cc: Mike Galbraith Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker LKML-Reference: <20090818164125.GM25206@bombadil.infradead.org> Signed-off-by: Ingo Molnar --- tools/perf/Documentation/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile index 5457192e1b41..bdd3b7ecad0a 100644 --- a/tools/perf/Documentation/Makefile +++ b/tools/perf/Documentation/Makefile @@ -35,7 +35,7 @@ man7dir=$(mandir)/man7 # DESTDIR= ASCIIDOC=asciidoc -ASCIIDOC_EXTRA = +ASCIIDOC_EXTRA = --unsafe MANPAGE_XSL = manpage-normal.xsl XMLTO_EXTRA = INSTALL?=install From fa6963b2481beff8b11f76006fbb63fdbbf2d2d7 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 19 Aug 2009 11:18:26 +0200 Subject: [PATCH 6/7] perf tools: Check perf.data owner Add an owner check to opening perf.data files and a switch to silence it. Because perf-report/perf-annotate are binary parsers reading another users' perf.data file could be a security risk if the file were explicitly engineered to trigger bugs in the parser (we hope of course there are non such bugs, but you never know). Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Mike Galbraith Cc: Peter Zijlstra Cc: Paul Mackerras LKML-Reference: <20090819092023.896648538@chello.nl> Signed-off-by: Ingo Molnar --- tools/perf/builtin-annotate.c | 7 +++++++ tools/perf/builtin-report.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 343e7b14bf01..5e17de984dc8 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -31,6 +31,7 @@ static char *vmlinux = "vmlinux"; static char default_sort_order[] = "comm,symbol"; static char *sort_order = default_sort_order; +static int force; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; @@ -1334,6 +1335,11 @@ static int __cmd_annotate(void) exit(-1); } + if (!force && (stat.st_uid != geteuid())) { + fprintf(stderr, "file: %s not owned by current user\n", input_name); + exit(-1); + } + if (!stat.st_size) { fprintf(stderr, "zero-sized file, nothing to do!\n"); exit(0); @@ -1439,6 +1445,7 @@ static const struct option options[] = { "input file name"), OPT_STRING('s', "symbol", &sym_hist_filter, "symbol", "symbol to annotate"), + OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), OPT_BOOLEAN('v', "verbose", &verbose, "be more verbose (show symbol address, etc)"), OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b53a60fc12de..8b2ec882e6e0 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -38,6 +38,7 @@ static char *dso_list_str, *comm_list_str, *sym_list_str, static struct strlist *dso_list, *comm_list, *sym_list; static char *field_sep; +static int force; static int input; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; @@ -1856,6 +1857,11 @@ static int __cmd_report(void) exit(-1); } + if (!force && (stat.st_uid != geteuid())) { + fprintf(stderr, "file: %s not owned by current user\n", input_name); + exit(-1); + } + if (!stat.st_size) { fprintf(stderr, "zero-sized file, nothing to do!\n"); exit(0); @@ -2064,6 +2070,7 @@ static const struct option options[] = { OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace, "dump raw trace in ASCII"), OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"), + OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), OPT_BOOLEAN('m', "modules", &modules, "load module symbols - WARNING: use only with -k and LIVE kernel"), OPT_BOOLEAN('n', "show-nr-samples", &show_nr_samples, From 4464fcaa9cbfc9c551956b48af203e2f775ca892 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 21 Aug 2009 17:19:36 +0200 Subject: [PATCH 7/7] perf_counter: Fix typo in read() output generation When you iterate a list, using the iterator is useful. Before: ID: 5 ID: 5 ID: 5 ID: 5 EVNT: 0x40088b scale: nan ID: 5 CNT: 1006252 ID: 6 CNT: 1011090 ID: 7 CNT: 1011196 ID: 8 CNT: 1011095 EVNT: 0x40088c scale: 1.000000 ID: 5 CNT: 2003065 ID: 6 CNT: 2011671 ID: 7 CNT: 2012620 ID: 8 CNT: 2013479 EVNT: 0x40088c scale: 1.000000 ID: 5 CNT: 3002390 ID: 6 CNT: 3015996 ID: 7 CNT: 3018019 ID: 8 CNT: 3020006 EVNT: 0x40088b scale: 1.000000 ID: 5 CNT: 4002406 ID: 6 CNT: 4021120 ID: 7 CNT: 4024241 ID: 8 CNT: 4027059 After: ID: 1 ID: 2 ID: 3 ID: 4 EVNT: 0x400889 scale: nan ID: 1 CNT: 1005270 ID: 2 CNT: 1009833 ID: 3 CNT: 1010065 ID: 4 CNT: 1010088 EVNT: 0x400898 scale: nan ID: 1 CNT: 2001531 ID: 2 CNT: 2022309 ID: 3 CNT: 2022470 ID: 4 CNT: 2022627 EVNT: 0x400888 scale: 0.489467 ID: 1 CNT: 3001261 ID: 2 CNT: 3027088 ID: 3 CNT: 3027941 ID: 4 CNT: 3028762 Reported-by: stephane eranian Signed-off-by: Peter Zijlstra Cc: Paul Mackerras Cc: Corey J Ashford Cc: perfmon2-devel LKML-Reference: <1250867976.7538.73.camel@twins> Signed-off-by: Ingo Molnar --- kernel/perf_counter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 36f65e2b8b57..f274e1959885 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c @@ -1791,7 +1791,7 @@ static int perf_counter_read_group(struct perf_counter *counter, size += err; list_for_each_entry(sub, &leader->sibling_list, list_entry) { - err = perf_counter_read_entry(counter, read_format, + err = perf_counter_read_entry(sub, read_format, buf + size); if (err < 0) return err;