From 7375e151bb42dca0b1abedce0b1940ff6aad7c87 Mon Sep 17 00:00:00 2001 From: Michael Petlan Date: Fri, 27 Nov 2015 14:48:09 +0100 Subject: perf buildid-list: Show running kernel build id fix The --kernel option of perf buildid-list tool should show the running kernel buildid. The functionality has been lost during other changes of the related code. The build_id__sprintf() function should return length of the build-id string, but it was the length of the build-id raw data instead. Due to that, some return value checking caused that the final string was not printed out. With this patch the build_id__sprintf() returns the correct value, so the --kernel option works again. Before: # perf buildid-list --kernel # After: # perf buildid-list --kernel 972c1edab5bdc06cc224af45d510af662a3c6972 # Signed-off-by: Michael Petlan Cc: Jiri Olsa Cc: Masami Hiramatsu LPU-Reference: 1448632089.24573.114.camel@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/build-id.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index 217b5a60e2ab..6a7e273a514a 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c @@ -91,7 +91,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf) bid += 2; } - return raw - build_id; + return (bid - bf) + 1; } int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id) -- cgit v1.2.3 From c8319c9d0d4a61b346aa9b30fb93978f1a355606 Mon Sep 17 00:00:00 2001 From: Michael Petlan Date: Wed, 2 Dec 2015 19:27:51 +0100 Subject: perf buildid-list: Fix return value of perf buildid-list -k The buildid string length is returned by perf buildid-list -k command. Since a non-zero return value means an error, perf buildid-list -k cmd should return 0 when successful instead. Before: # perf buildid-list -k 39356d74e96e02346fe0ec1f3f162b6c522bac62 # echo $? 41 After: # perf buildid-list -k 39356d74e96e02346fe0ec1f3f162b6c522bac62 # echo $? 0 Signed-off-by: Michael Petlan Tested-by: Arnaldo Carvalho de Melo Cc: Masami Hiramatsu Fixes: 0b5a7935f3b5 ("perf buildid: Introduce sysfs/filename__sprintf_build_id") LPU-Reference: 1449080871.24573.145.camel@redhat.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-buildid-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c index 918b4de29de4..6419f57b0850 100644 --- a/tools/perf/builtin-buildid-list.c +++ b/tools/perf/builtin-buildid-list.c @@ -110,7 +110,7 @@ int cmd_buildid_list(int argc, const char **argv, setup_pager(); if (show_kernel) - return sysfs__fprintf_build_id(stdout); + return !(sysfs__fprintf_build_id(stdout) > 0); return perf_session__list_build_ids(force, with_hits); } -- cgit v1.2.3 From 837eeb7569bf2b3bd3b1b82e0e61edb19811036e Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 7 Dec 2015 02:35:45 +0000 Subject: perf hists browser: Add NULL pointer check to prevent crash Before this patch we can trigger a segfault by following steps: Step 0: Use 'perf record' to generate a perf.data without callchain Step 1: perf report Step 2: Use UP/DOWN to select an entry, don't press 'ENTER' Step 3: Use '/' to filter symbols, use a filter which returns empty result Step 4: Press 'ENTER' (notice here that the old selection is still there. This is another problem) Step 5: Press 'ENTER' to annotate that symbol Step 6: Press 'LEFT' to go out. Result: segfault: perf: Segmentation fault -------- backtrace -------- /home/wangnan/perf[0x53e568] /lib64/libc.so.6(+0x3545f)[0x7fba75d3245f] /home/wangnan/perf[0x537516] /home/wangnan/perf[0x533fef] /home/wangnan/perf[0x53b347] /home/wangnan/perf(perf_evlist__tui_browse_hists+0x96)[0x53d206] /home/wangnan/perf(cmd_report+0x1b9f)[0x442c7f] /home/wangnan/perf[0x47efa2] /home/wangnan/perf(main+0x5f5)[0x432fa5] /lib64/libc.so.6(__libc_start_main+0xf4)[0x7fba75d1ebd4] /home/wangnan/perf[0x4330d4] This is because in this case 'nd' could be NULL in ui_browser__hists_seek(), but that function never checks it. This patch adds checker for potential NULL pointer in that function. After this patch the above steps won't segfault. Signed-off-by: Wang Nan Tested-by: Arnaldo Carvalho de Melo Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1449455746-41952-3-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index fa9eb92c9e24..932e13d015b9 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1033,6 +1033,9 @@ static void ui_browser__hists_seek(struct ui_browser *browser, * and stop when we printed enough lines to fill the screen. */ do_offset: + if (!nd) + return; + if (offset > 0) { do { h = rb_entry(nd, struct hist_entry, rb_node); -- cgit v1.2.3 From 979d2cac1144da6b25334a8572c80cde9662105c Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 7 Dec 2015 02:35:46 +0000 Subject: perf hists browser: Reset selection when refresh With the following steps: Step 1: perf report Step 2: Use UP/DOWN to select an entry, don't press 'ENTER' Step 3: Use '/' to filter symbols, use a filter which returns empty result Step 4: Press 'ENTER' We see that, even if we have filtered all the symbols (and the main interface is empty), pressing 'ENTER' still selects one symbol. This behavior surprises the user. This patch resets browser->{he_,}selection in hist_browser__refresh() and lets it choose default selection. In this case browser->{he_,}selection keeps NULL so user won't see annotation item in menu. Signed-off-by: Wang Nan Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1449455746-41952-4-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 932e13d015b9..84c8251f39a1 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -928,6 +928,8 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser) } ui_browser__hists_init_top(browser); + hb->he_selection = NULL; + hb->selection = NULL; for (nd = browser->top; nd; nd = rb_next(nd)) { struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); -- cgit v1.2.3 From 4938cf0c7a62025bbfbf3db7bcdcc2c33312bedb Mon Sep 17 00:00:00 2001 From: Wang Nan Date: Mon, 7 Dec 2015 02:35:44 +0000 Subject: perf hists browser: Fix segfault if use symbol filter in cmdline If feed perf a symbol filter in cmdline and the result is empty, pressing 'Enter' in the hist browser causes crash: # ./perf report perf.data <-- Common mistake for beginners Then press 'Enter': perf: Segmentation fault -------- backtrace -------- /home/wangnan/perf[0x53e578] /lib64/libc.so.6(+0x3545f)[0x7f76bafe045f] /home/wangnan/perf[0x539dd4] /home/wangnan/perf(perf_evlist__tui_browse_hists+0x96)[0x53d216] /home/wangnan/perf(cmd_report+0x1b9f)[0x442c7f] /home/wangnan/perf[0x47efa2] /home/wangnan/perf(main+0x5f5)[0x432fa5] /lib64/libc.so.6(__libc_start_main+0xf4)[0x7f76bafccbd4] /home/wangnan/perf[0x4330d4] This is because 'perf.data' is interpreted as a symbol filter, and the result is empty, so selection is empty. However, hist_browser__toggle_fold() forgets to check it. This patch simply return false when selection is NULL. Signed-off-by: Wang Nan Acked-by: Namhyung Kim Tested-by: Arnaldo Carvalho de Melo Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1449455746-41952-2-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/ui/browsers/hists.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 84c8251f39a1..81def6c3f24b 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -298,6 +298,9 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser) struct callchain_list *cl = container_of(ms, struct callchain_list, ms); bool has_children; + if (!he || !ms) + return false; + if (ms == &he->ms) has_children = hist_entry__toggle_fold(he); else -- cgit v1.2.3 From d643b5aba84884de96d2ea4a902f8b0d9cf4b1b0 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 27 Nov 2015 15:54:33 -0300 Subject: perf list: Add support for PERF_COUNT_SW_BPF_OUT When PERF_COUNT_SW_BPF_OUTPUT was added to the kernel we should've added it to tools/perf, where it is used just to list events. This ended up causing a segfault in commands like "perf list stall". Fix it by adding that new software counter. A patch to robustify perf to not segfault when the next counter gets added in the kernel will follow this one. Reported-by: Ingo Molnar Cc: Adrian Hunter Cc: Alexei Starovoitov Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-uya354upi3eprsey6mi5962d@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index e48d9da75707..40ae92a8673c 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -124,6 +124,10 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = { .symbol = "dummy", .alias = "", }, + [PERF_COUNT_SW_BPF_OUTPUT] = { + .symbol = "bpf-output", + .alias = "", + }, }; #define __PERF_EVENT_FIELD(config, name) \ -- cgit v1.2.3 From fb202539e61b14bc63ac29af10fe5d758ecd880a Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 27 Nov 2015 16:04:58 -0300 Subject: perf list: Robustify event printing routine When a43eec304259 ("bpf: introduce bpf_perf_event_output() helper") added PERF_COUNT_SW_BPF_OUTPUT we ended up with a new entry in the event_symbols_sw array that wasn't initialized, thus set to NULL, fix print_symbol_events() to check for that case so that we don't crash if this happens again. (gdb) bt #0 __match_glob (ignore_space=false, pat=, str=) at util/string.c:198 #1 strglobmatch (str=, pat=pat@entry=0x7fffffffe61d "stall") at util/string.c:252 #2 0x00000000004993a5 in print_symbol_events (type=1, syms=0x872880 , max=11, name_only=false, event_glob=0x7fffffffe61d "stall") at util/parse-events.c:1615 #3 print_events (event_glob=event_glob@entry=0x7fffffffe61d "stall", name_only=false) at util/parse-events.c:1675 #4 0x000000000042c79e in cmd_list (argc=1, argv=0x7fffffffe390, prefix=) at builtin-list.c:68 #5 0x00000000004788a5 in run_builtin (p=p@entry=0x871758 , argc=argc@entry=2, argv=argv@entry=0x7fffffffe390) at perf.c:370 #6 0x0000000000420ab0 in handle_internal_command (argv=0x7fffffffe390, argc=2) at perf.c:429 #7 run_argv (argv=0x7fffffffe110, argcp=0x7fffffffe11c) at perf.c:473 #8 main (argc=2, argv=0x7fffffffe390) at perf.c:588 (gdb) p event_symbols_sw[PERF_COUNT_SW_BPF_OUTPUT] $4 = {symbol = 0x0, alias = 0x0} (gdb) A patch to robustify perf to not segfault when the next counter gets added in the kernel will follow this one. Reported-by: Ingo Molnar Cc: Adrian Hunter Cc: Alexei Starovoitov Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: http://lkml.kernel.org/n/tip-57wysblcjfrseb0zg5u7ek10@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/parse-events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 40ae92a8673c..6fc8cd753e1a 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -1883,7 +1883,7 @@ restart: for (i = 0; i < max; i++, syms++) { - if (event_glob != NULL && + if (event_glob != NULL && syms->symbol != NULL && !(strglobmatch(syms->symbol, event_glob) || (syms->alias && strglobmatch(syms->alias, event_glob)))) continue; -- cgit v1.2.3 From c127449944659543e5e2423002f08f0af98dba5c Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 10 Dec 2015 20:57:40 +0100 Subject: perf: Fix race in perf_event_exec() I managed to tickle this warning: [ 2338.884942] ------------[ cut here ]------------ [ 2338.890112] WARNING: CPU: 13 PID: 35162 at ../kernel/events/core.c:2702 task_ctx_sched_out+0x6b/0x80() [ 2338.900504] Modules linked in: [ 2338.903933] CPU: 13 PID: 35162 Comm: bash Not tainted 4.4.0-rc4-dirty #244 [ 2338.911610] Hardware name: Intel Corporation S2600GZ/S2600GZ, BIOS SE5C600.86B.02.02.0002.122320131210 12/23/2013 [ 2338.923071] ffffffff81f1468e ffff8807c6457cb8 ffffffff815c680c 0000000000000000 [ 2338.931382] ffff8807c6457cf0 ffffffff810c8a56 ffffe8ffff8c1bd0 ffff8808132ed400 [ 2338.939678] 0000000000000286 ffff880813170380 ffff8808132ed400 ffff8807c6457d00 [ 2338.947987] Call Trace: [ 2338.950726] [] dump_stack+0x4e/0x82 [ 2338.956474] [] warn_slowpath_common+0x86/0xc0 [ 2338.963195] [] warn_slowpath_null+0x1a/0x20 [ 2338.969720] [] task_ctx_sched_out+0x6b/0x80 [ 2338.976244] [] perf_event_exec+0xe2/0x180 [ 2338.982575] [] setup_new_exec+0x6f/0x1b0 [ 2338.988810] [] load_elf_binary+0x393/0x1660 [ 2338.995339] [] ? get_user_pages+0x52/0x60 [ 2339.001669] [] search_binary_handler+0x97/0x200 [ 2339.008581] [] do_execveat_common.isra.33+0x543/0x6e0 [ 2339.016072] [] SyS_execve+0x3a/0x50 [ 2339.021819] [] stub_execve+0x5/0x5 [ 2339.027469] [] ? entry_SYSCALL_64_fastpath+0x12/0x71 [ 2339.034860] ---[ end trace ee1337c59a0ddeac ]--- Which is a WARN_ON_ONCE() indicating that cpuctx->task_ctx is not what we expected it to be. This is because context switches can swap the task_struct::perf_event_ctxp[] pointer around. Therefore you have to either disable preemption when looking at current, or hold ctx->lock. Fix perf_event_enable_on_exec(), it loads current->perf_event_ctxp[] before disabling interrupts, therefore a preemption in the right place can swap contexts around and we're using the wrong one. Signed-off-by: Peter Zijlstra (Intel) Cc: Alexander Potapenko Cc: Arnaldo Carvalho de Melo Cc: Arnaldo Carvalho de Melo Cc: Dmitry Vyukov Cc: Eric Dumazet Cc: Jiri Olsa Cc: Kostya Serebryany Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Sasha Levin Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Cc: syzkaller Link: http://lkml.kernel.org/r/20151210195740.GG6357@twins.programming.kicks-ass.net Signed-off-by: Ingo Molnar --- kernel/events/core.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 39cf4a40aa4c..fd7de0418fbe 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3154,15 +3154,16 @@ static int event_enable_on_exec(struct perf_event *event, * Enable all of a task's events that have been marked enable-on-exec. * This expects task == current. */ -static void perf_event_enable_on_exec(struct perf_event_context *ctx) +static void perf_event_enable_on_exec(int ctxn) { - struct perf_event_context *clone_ctx = NULL; + struct perf_event_context *ctx, *clone_ctx = NULL; struct perf_event *event; unsigned long flags; int enabled = 0; int ret; local_irq_save(flags); + ctx = current->perf_event_ctxp[ctxn]; if (!ctx || !ctx->nr_events) goto out; @@ -3205,17 +3206,11 @@ out: void perf_event_exec(void) { - struct perf_event_context *ctx; int ctxn; rcu_read_lock(); - for_each_task_context_nr(ctxn) { - ctx = current->perf_event_ctxp[ctxn]; - if (!ctx) - continue; - - perf_event_enable_on_exec(ctx); - } + for_each_task_context_nr(ctxn) + perf_event_enable_on_exec(ctxn); rcu_read_unlock(); } -- cgit v1.2.3 From 12ca6ad2e3a896256f086497a7c7406a547ee373 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Tue, 15 Dec 2015 13:49:05 +0100 Subject: perf: Fix race in swevent hash There's a race on CPU unplug where we free the swevent hash array while it can still have events on. This will result in a use-after-free which is BAD. Simply do not free the hash array on unplug. This leaves the thing around and no use-after-free takes place. When the last swevent dies, we do a for_each_possible_cpu() iteration anyway to clean these up, at which time we'll free it, so no leakage will occur. Reported-by: Sasha Levin Tested-by: Sasha Levin Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Thomas Gleixner Cc: Vince Weaver Signed-off-by: Ingo Molnar --- kernel/events/core.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index fd7de0418fbe..0a791a2203dc 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6488,9 +6488,6 @@ struct swevent_htable { /* Recursion avoidance in each contexts */ int recursion[PERF_NR_CONTEXTS]; - - /* Keeps track of cpu being initialized/exited */ - bool online; }; static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); @@ -6748,14 +6745,8 @@ static int perf_swevent_add(struct perf_event *event, int flags) hwc->state = !(flags & PERF_EF_START); head = find_swevent_head(swhash, event); - if (!head) { - /* - * We can race with cpu hotplug code. Do not - * WARN if the cpu just got unplugged. - */ - WARN_ON_ONCE(swhash->online); + if (WARN_ON_ONCE(!head)) return -EINVAL; - } hlist_add_head_rcu(&event->hlist_entry, head); perf_event_update_userpage(event); @@ -6823,7 +6814,6 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu) int err = 0; mutex_lock(&swhash->hlist_mutex); - if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) { struct swevent_hlist *hlist; @@ -9286,7 +9276,6 @@ static void perf_event_init_cpu(int cpu) struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); mutex_lock(&swhash->hlist_mutex); - swhash->online = true; if (swhash->hlist_refcount > 0) { struct swevent_hlist *hlist; @@ -9328,14 +9317,7 @@ static void perf_event_exit_cpu_context(int cpu) static void perf_event_exit_cpu(int cpu) { - struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); - perf_event_exit_cpu_context(cpu); - - mutex_lock(&swhash->hlist_mutex); - swhash->online = false; - swevent_hlist_release(swhash); - mutex_unlock(&swhash->hlist_mutex); } #else static inline void perf_event_exit_cpu(int cpu) { } -- cgit v1.2.3