From e69af4657e7764d03ad555f0b583d9c4217bcefa Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Wed, 2 Apr 2014 00:49:55 -0400 Subject: [PATCH 01/16] perf/x86: Enable DRAM RAPL support on Intel Haswell It turns out all Haswell processors (including the Desktop variant) support RAPL DRAM readings in addition to package, pp0, and pp1. I've confirmed RAPL DRAM readings on my model 60 Haswell desktop. See the 4th-gen-core-family-desktop-vol-2-datasheet.pdf available from the Intel website for confirmation. Signed-off-by: Vince Weaver Cc: Peter Zijlstra Cc: Paul Mackerras Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Link: http://lkml.kernel.org/r/alpine.DEB.2.10.1404020045290.17889@vincent-weaver-1.um.maine.edu Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event_intel_rapl.c | 33 +++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event_intel_rapl.c b/arch/x86/kernel/cpu/perf_event_intel_rapl.c index 5ad35ad94d0f..3cec947e3b98 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_rapl.c +++ b/arch/x86/kernel/cpu/perf_event_intel_rapl.c @@ -59,7 +59,7 @@ #define INTEL_RAPL_PKG 0x2 /* pseudo-encoding */ #define RAPL_IDX_RAM_NRG_STAT 2 /* DRAM */ #define INTEL_RAPL_RAM 0x3 /* pseudo-encoding */ -#define RAPL_IDX_PP1_NRG_STAT 3 /* DRAM */ +#define RAPL_IDX_PP1_NRG_STAT 3 /* gpu */ #define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */ /* Clients have PP0, PKG */ @@ -72,6 +72,12 @@ 1<config * any other bit is reserved @@ -425,6 +431,24 @@ static struct attribute *rapl_events_cln_attr[] = { NULL, }; +static struct attribute *rapl_events_hsw_attr[] = { + EVENT_PTR(rapl_cores), + EVENT_PTR(rapl_pkg), + EVENT_PTR(rapl_gpu), + EVENT_PTR(rapl_ram), + + EVENT_PTR(rapl_cores_unit), + EVENT_PTR(rapl_pkg_unit), + EVENT_PTR(rapl_gpu_unit), + EVENT_PTR(rapl_ram_unit), + + EVENT_PTR(rapl_cores_scale), + EVENT_PTR(rapl_pkg_scale), + EVENT_PTR(rapl_gpu_scale), + EVENT_PTR(rapl_ram_scale), + NULL, +}; + static struct attribute_group rapl_pmu_events_group = { .name = "events", .attrs = NULL, /* patched at runtime */ @@ -631,11 +655,14 @@ static int __init rapl_pmu_init(void) switch (boot_cpu_data.x86_model) { case 42: /* Sandy Bridge */ case 58: /* Ivy Bridge */ - case 60: /* Haswell */ - case 69: /* Haswell-Celeron */ rapl_cntr_mask = RAPL_IDX_CLN; rapl_pmu_events_group.attrs = rapl_events_cln_attr; break; + case 60: /* Haswell */ + case 69: /* Haswell-Celeron */ + rapl_cntr_mask = RAPL_IDX_HSW; + rapl_pmu_events_group.attrs = rapl_events_hsw_attr; + break; case 45: /* Sandy Bridge-EP */ case 62: /* IvyTown */ rapl_cntr_mask = RAPL_IDX_SRV; From 5e09714b0e877d5d062530aae4061074d864243f Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 19 Mar 2014 10:46:18 +0900 Subject: [PATCH 02/16] perf top: Fix documentation of invalid -s option On perf top, the -s option is used for --sort, but the man page contains invalid documentation of -s option for --sym-annotate. Signed-off-by: Namhyung Kim Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1395193578-27098-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa --- tools/perf/Documentation/perf-top.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index cdd8d4946dba..976b00c6cdb1 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt @@ -87,7 +87,6 @@ Default is to monitor all CPUS. --realtime=:: Collect data with this RT SCHED_FIFO priority. --s :: --sym-annotate=:: Annotate this symbol. From 3388cc3eb848154d0f2a0cd01542201d0d0fdad7 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 19 Mar 2014 10:22:53 +0900 Subject: [PATCH 03/16] tools lib traceevent: Print event name when show warning if possible It's sometimes useful to know where the parse failure was occurred. Add do_warning_event() macro to see the failing event. It now shows the messages like below: $ perf test 5 5: parse events tests : Warning: [kvmmmu:kvm_mmu_get_page] bad op token { Warning: [kvmmmu:kvm_mmu_sync_page] bad op token { Warning: [kvmmmu:kvm_mmu_unsync_page] bad op token { Warning: [kvmmmu:kvm_mmu_prepare_zap_page] bad op token { Warning: [kvmmmu:fast_page_fault] function is_writable_pte not defined Warning: [xen:xen_mmu_ptep_modify_prot_commit] function sizeof not defined Warning: [xen:xen_mmu_ptep_modify_prot_start] function sizeof not defined Warning: [xen:xen_mmu_set_pgd] function sizeof not defined Warning: [xen:xen_mmu_set_pud] function sizeof not defined Warning: [xen:xen_mmu_set_pmd] function sizeof not defined ... Signed-off-by: Namhyung Kim Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Ramkumar Ramachandra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1395192174-26273-1-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa --- tools/lib/traceevent/event-parse.c | 103 +++++++++++++++++------------ 1 file changed, 62 insertions(+), 41 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 1587ea392ad6..33803c0b94d6 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -50,6 +50,18 @@ static int show_warning = 1; warning(fmt, ##__VA_ARGS__); \ } while (0) +#define do_warning_event(event, fmt, ...) \ + do { \ + if (!show_warning) \ + continue; \ + \ + if (event) \ + warning("[%s:%s] " fmt, event->system, \ + event->name, ##__VA_ARGS__); \ + else \ + warning(fmt, ##__VA_ARGS__); \ + } while (0) + static void init_input_buf(const char *buf, unsigned long long size) { input_buf = buf; @@ -1355,7 +1367,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f } if (!field->type) { - do_warning("%s: no type found", __func__); + do_warning_event(event, "%s: no type found", __func__); goto fail; } field->name = last_token; @@ -1402,7 +1414,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f free_token(token); type = read_token(&token); if (type == EVENT_NONE) { - do_warning("failed to find token"); + do_warning_event(event, "failed to find token"); goto fail; } } @@ -1636,7 +1648,7 @@ process_cond(struct event_format *event, struct print_arg *top, char **tok) right = alloc_arg(); if (!arg || !left || !right) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); /* arg will be freed at out_free */ free_arg(left); free_arg(right); @@ -1686,7 +1698,7 @@ process_array(struct event_format *event, struct print_arg *top, char **tok) arg = alloc_arg(); if (!arg) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); /* '*tok' is set to top->op.op. No need to free. */ *tok = NULL; return EVENT_ERROR; @@ -1792,7 +1804,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) if (arg->type == PRINT_OP && !arg->op.left) { /* handle single op */ if (token[1]) { - do_warning("bad op token %s", token); + do_warning_event(event, "bad op token %s", token); goto out_free; } switch (token[0]) { @@ -1802,7 +1814,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) case '-': break; default: - do_warning("bad op token %s", token); + do_warning_event(event, "bad op token %s", token); goto out_free; } @@ -1888,7 +1900,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) char *new_atom; if (left->type != PRINT_ATOM) { - do_warning("bad pointer type"); + do_warning_event(event, "bad pointer type"); goto out_free; } new_atom = realloc(left->atom.atom, @@ -1930,7 +1942,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) type = process_array(event, arg, tok); } else { - do_warning("unknown op '%s'", token); + do_warning_event(event, "unknown op '%s'", token); event->flags |= EVENT_FL_FAILED; /* the arg is now the left side */ goto out_free; @@ -1951,7 +1963,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) return type; out_warn_free: - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); out_free: free_token(token); *tok = NULL; @@ -2385,7 +2397,7 @@ process_flags(struct event_format *event, struct print_arg *arg, char **tok) field = alloc_arg(); if (!field) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); goto out_free; } @@ -2438,7 +2450,7 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok) field = alloc_arg(); if (!field) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); goto out_free; } @@ -2477,7 +2489,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok) field = alloc_arg(); if (!field) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); goto out_free; } @@ -2492,7 +2504,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok) field = alloc_arg(); if (!field) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); *tok = NULL; return EVENT_ERROR; } @@ -2555,7 +2567,7 @@ process_dynamic_array(struct event_format *event, struct print_arg *arg, char ** free_token(token); arg = alloc_arg(); if (!arg) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", __func__); *tok = NULL; return EVENT_ERROR; } @@ -2614,13 +2626,14 @@ process_paren(struct event_format *event, struct print_arg *arg, char **tok) /* prevous must be an atom */ if (arg->type != PRINT_ATOM) { - do_warning("previous needed to be PRINT_ATOM"); + do_warning_event(event, "previous needed to be PRINT_ATOM"); goto out_free; } item_arg = alloc_arg(); if (!item_arg) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", + __func__); goto out_free; } @@ -2721,7 +2734,8 @@ process_func_handler(struct event_format *event, struct pevent_function_handler for (i = 0; i < func->nr_args; i++) { farg = alloc_arg(); if (!farg) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", + __func__); return EVENT_ERROR; } @@ -2792,7 +2806,7 @@ process_function(struct event_format *event, struct print_arg *arg, return process_func_handler(event, func, arg, tok); } - do_warning("function %s not defined", token); + do_warning_event(event, "function %s not defined", token); free_token(token); return EVENT_ERROR; } @@ -2878,7 +2892,7 @@ process_arg_token(struct event_format *event, struct print_arg *arg, case EVENT_ERROR ... EVENT_NEWLINE: default: - do_warning("unexpected type %d", type); + do_warning_event(event, "unexpected type %d", type); return EVENT_ERROR; } *tok = token; @@ -2901,7 +2915,8 @@ static int event_read_print_args(struct event_format *event, struct print_arg ** arg = alloc_arg(); if (!arg) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", + __func__); return -1; } @@ -3481,11 +3496,12 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg return val; out_warning_op: - do_warning("%s: unknown op '%s'", __func__, arg->op.op); + do_warning_event(event, "%s: unknown op '%s'", __func__, arg->op.op); return 0; out_warning_field: - do_warning("%s: field %s not found", __func__, arg->field.name); + do_warning_event(event, "%s: field %s not found", + __func__, arg->field.name); return 0; } @@ -3591,7 +3607,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, } str = malloc(len + 1); if (!str) { - do_warning("%s: not enough memory!", __func__); + do_warning_event(event, "%s: not enough memory!", + __func__); return; } memcpy(str, data + field->offset, len); @@ -3697,7 +3714,8 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, return; out_warning_field: - do_warning("%s: field %s not found", __func__, arg->field.name); + do_warning_event(event, "%s: field %s not found", + __func__, arg->field.name); } static unsigned long long @@ -3742,14 +3760,16 @@ process_defined_func(struct trace_seq *s, void *data, int size, trace_seq_terminate(&str); string = malloc(sizeof(*string)); if (!string) { - do_warning("%s(%d): malloc str", __func__, __LINE__); + do_warning_event(event, "%s(%d): malloc str", + __func__, __LINE__); goto out_free; } string->next = strings; string->str = strdup(str.buffer); if (!string->str) { free(string); - do_warning("%s(%d): malloc str", __func__, __LINE__); + do_warning_event(event, "%s(%d): malloc str", + __func__, __LINE__); goto out_free; } args[i] = (uintptr_t)string->str; @@ -3761,7 +3781,7 @@ process_defined_func(struct trace_seq *s, void *data, int size, * Something went totally wrong, this is not * an input error, something in this code broke. */ - do_warning("Unexpected end of arguments\n"); + do_warning_event(event, "Unexpected end of arguments\n"); goto out_free; } farg = farg->next; @@ -3811,12 +3831,12 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc if (!field) { field = pevent_find_field(event, "buf"); if (!field) { - do_warning("can't find buffer field for binary printk"); + do_warning_event(event, "can't find buffer field for binary printk"); return NULL; } ip_field = pevent_find_field(event, "ip"); if (!ip_field) { - do_warning("can't find ip field for binary printk"); + do_warning_event(event, "can't find ip field for binary printk"); return NULL; } pevent->bprint_buf_field = field; @@ -3830,7 +3850,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc */ args = alloc_arg(); if (!args) { - do_warning("%s(%d): not enough memory!", __func__, __LINE__); + do_warning_event(event, "%s(%d): not enough memory!", + __func__, __LINE__); return NULL; } arg = args; @@ -3896,7 +3917,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc bptr += vsize; arg = alloc_arg(); if (!arg) { - do_warning("%s(%d): not enough memory!", + do_warning_event(event, "%s(%d): not enough memory!", __func__, __LINE__); goto out_free; } @@ -3919,7 +3940,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc case 's': arg = alloc_arg(); if (!arg) { - do_warning("%s(%d): not enough memory!", + do_warning_event(event, "%s(%d): not enough memory!", __func__, __LINE__); goto out_free; } @@ -3959,7 +3980,7 @@ get_bprint_format(void *data, int size __maybe_unused, if (!field) { field = pevent_find_field(event, "fmt"); if (!field) { - do_warning("can't find format field for binary printk"); + do_warning_event(event, "can't find format field for binary printk"); return NULL; } pevent->bprint_fmt_field = field; @@ -4003,8 +4024,8 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size, arg->field.field = pevent_find_any_field(event, arg->field.name); if (!arg->field.field) { - do_warning("%s: field %s not found", - __func__, arg->field.name); + do_warning_event(event, "%s: field %s not found", + __func__, arg->field.name); return; } } @@ -4176,7 +4197,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event case '*': /* The argument is the length. */ if (!arg) { - do_warning("no argument match"); + do_warning_event(event, "no argument match"); event->flags |= EVENT_FL_FAILED; goto out_failed; } @@ -4213,7 +4234,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event case 'X': case 'u': if (!arg) { - do_warning("no argument match"); + do_warning_event(event, "no argument match"); event->flags |= EVENT_FL_FAILED; goto out_failed; } @@ -4223,7 +4244,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event /* should never happen */ if (len > 31) { - do_warning("bad format!"); + do_warning_event(event, "bad format!"); event->flags |= EVENT_FL_FAILED; len = 31; } @@ -4290,13 +4311,13 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event trace_seq_printf(s, format, (long long)val); break; default: - do_warning("bad count (%d)", ls); + do_warning_event(event, "bad count (%d)", ls); event->flags |= EVENT_FL_FAILED; } break; case 's': if (!arg) { - do_warning("no matching argument"); + do_warning_event(event, "no matching argument"); event->flags |= EVENT_FL_FAILED; goto out_failed; } @@ -4306,7 +4327,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event /* should never happen */ if (len > 31) { - do_warning("bad format!"); + do_warning_event(event, "bad format!"); event->flags |= EVENT_FL_FAILED; len = 31; } From 9e9e5dfd86b9fdea8c75bae42cba052901b94f78 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Wed, 19 Mar 2014 10:22:54 +0900 Subject: [PATCH 04/16] tools lib traceevent: Do not call warning() directly The patch 3a3ffa2e82205 ("tools lib traceevent: Report better error message on bad function args") added the error message but it seems there's no reason to call warning() directly. So change it to do_warning_event() to provide event information too. Signed-off-by: Namhyung Kim Acked-by: Steven Rostedt Cc: Frederic Weisbecker Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Steven Rostedt Link: http://lkml.kernel.org/r/1395192174-26273-2-git-send-email-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa --- tools/lib/traceevent/event-parse.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 33803c0b94d6..baec7d887da4 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -2742,14 +2742,16 @@ process_func_handler(struct event_format *event, struct pevent_function_handler type = process_arg(event, farg, &token); if (i < (func->nr_args - 1)) { if (type != EVENT_DELIM || strcmp(token, ",") != 0) { - warning("Error: function '%s()' expects %d arguments but event %s only uses %d", + do_warning_event(event, + "Error: function '%s()' expects %d arguments but event %s only uses %d", func->name, func->nr_args, event->name, i + 1); goto err; } } else { if (type != EVENT_DELIM || strcmp(token, ")") != 0) { - warning("Error: function '%s()' only expects %d arguments but event %s has more", + do_warning_event(event, + "Error: function '%s()' only expects %d arguments but event %s has more", func->name, func->nr_args, event->name); goto err; } From 945895574873101c72a2d90a8cf1e09922378968 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Tue, 25 Mar 2014 09:35:11 -0300 Subject: [PATCH 05/16] perf callchains: Disable unwind libraries when libelf isn't found I.e. do the same as when NO_LIBELF is explicitely passed in the 'make' command line, fixing this: Auto-detecting system features: ... dwarf: [ OFF ] ... glibc: [ on ] ... gtk2: [ OFF ] ... libaudit: [ OFF ] ... libbfd: [ OFF ] ... libelf: [ OFF ] ... libunwind: [ OFF ] ... libdw-dwarf-unwind: [ OFF ] ... DWARF post unwind library: libdw CC /tmp/build/perf/util/symbol-minimal.o CC /tmp/build/perf/util/unwind-libdw.o arch/x86/util/unwind-libdw.c:1:30: fatal error: elfutils/libdwfl.h: No such file or directory compilation terminated. CC /tmp/build/perf/tests/keep-tracking.o util/unwind-libdw.c:2:28: fatal error: elfutils/libdw.h: No such file or directory compilation terminated. Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-e39j1yxanltjx4t0msse63ax@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa --- tools/perf/config/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index c23418225c2c..5a3c452e8e77 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -278,6 +278,8 @@ else NO_LIBELF := 1 NO_DWARF := 1 NO_DEMANGLE := 1 + NO_LIBUNWIND := 1 + NO_LIBDW_DWARF_UNWIND := 1 else msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static); endif From f80c539323984257d62f7683b1262ce24c52ce26 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 27 Mar 2014 17:36:14 -0300 Subject: [PATCH 06/16] MAINTAINERS: Change e-mail to kernel.org one Leaving ghostprotocols.net for old networking stuff. Cc: Adrian Hunter Cc: David Ahern Cc: Don Zickus Cc: Frederic Weisbecker Cc: Jiri Olsa Cc: Mike Galbraith Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Stephane Eranian Link: http://lkml.kernel.org/n/tip-jott6d40nkjjc3vvh3vw53lp@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Jiri Olsa --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1ecfde109667..b06a9a8fed88 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6678,7 +6678,7 @@ PERFORMANCE EVENTS SUBSYSTEM M: Peter Zijlstra M: Paul Mackerras M: Ingo Molnar -M: Arnaldo Carvalho de Melo +M: Arnaldo Carvalho de Melo L: linux-kernel@vger.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core S: Supported From 2c529e4e6aab405aa52e8627cbd691ed28b56a0b Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Wed, 26 Mar 2014 18:44:05 -0400 Subject: [PATCH 07/16] perf tools: Pick up libdw without explicit LIBDW_DIR The Makefile logic sets FEATURE_CHECKS_CFLAGS-libdw-dwarf-unwind and FEATURE_CHECKS_LDFLAGS-libdw-dwarf-unwind only if LIBDW_DIR is defined. This means that under a normal setup, $ make NO_LIBUNWIND=1 won't automatically pick up libdw. Fix this. Signed-off-by: Ramkumar Ramachandra Acked-by: Jean Pihet Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1395873845-466-1-git-send-email-artagnon@gmail.com Signed-off-by: Jiri Olsa --- tools/perf/config/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile index 5a3c452e8e77..ee21fa95ebcf 100644 --- a/tools/perf/config/Makefile +++ b/tools/perf/config/Makefile @@ -65,10 +65,9 @@ ifndef NO_LIBELF ifdef LIBDW_DIR LIBDW_CFLAGS := -I$(LIBDW_DIR)/include LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib - - FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) - FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw endif + FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS) + FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw endif # include ARCH specific config From 202c7c123c96a1c193149b7fa2718d7fb143efb2 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 1 Apr 2014 13:47:57 +0900 Subject: [PATCH 08/16] perf probe: Fix --line option behavior The commit 5a62257a3ddd1 ("perf probe: Replace line_list with intlist") replaced line_list to intlist but it has a problem that if a same line was added again, it'd return -EEXIST rather than 1. Since line_range_walk_cb() only checks the result being negative, it resulted in failure or segfault sometimes. Signed-off-by: Namhyung Kim Acked-by: Masami Hiramatsu Cc: Masami Hiramatsu Link: http://lkml.kernel.org/r/1396327677-3657-1-git-send-email-namhyung@kernel.org Signed-off-by: Jiri Olsa --- tools/perf/util/probe-finder.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index df0238654698..3bf0c8cdccb7 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1441,13 +1441,15 @@ static int line_range_walk_cb(const char *fname, int lineno, void *data) { struct line_finder *lf = data; + int err; if ((strtailcmp(fname, lf->fname) != 0) || (lf->lno_s > lineno || lf->lno_e < lineno)) return 0; - if (line_range_add_line(fname, lineno, lf->lr) < 0) - return -EINVAL; + err = line_range_add_line(fname, lineno, lf->lr); + if (err < 0 && err != -EEXIST) + return err; return 0; } From 182c228ebcf1ac67a44e62236d8f7a8a9a3c5699 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Wed, 2 Apr 2014 14:48:31 +0900 Subject: [PATCH 09/16] perf probe: Fix to handle errors in line_range searching As Namhyung reported(https://lkml.org/lkml/2014/4/1/89), current perf-probe -L option doesn't handle errors in line-range searching correctly. It causes a SEGV if an error occured in the line-range searching. ---- $ perf probe -x ./perf -v -L map__load Open Debuginfo file: /home/namhyung/project/linux/tools/perf/perf fname: util/map.c, lineno:153 New line range: 153 to 2147483647 path: (null) Segmentation fault (core dumped) ---- This is because line_range_inline_cb() ignores errors from find_line_range_by_line() which means that lr->path is already freed on the error path in find_line_range_by_line(). As a result, get_real_path() accesses the lr->path and it causes a NULL pointer exception. This fixes line_range_inline_cb() to handle the error correctly, and report it to the caller. Anyway, this just fixes a possible SEGV bug, Namhyung's patch is also required. Reported-by: Namhyung Kim Signed-off-by: Masami Hiramatsu Acked-by: Namhyung Kim Cc: Arnaldo Carvalho de Melo Cc: Ingo Molnar Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/20140402054831.19080.27006.stgit@ltc230.yrl.intra.hitachi.co.jp Signed-off-by: Jiri Olsa --- tools/perf/util/probe-finder.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 3bf0c8cdccb7..fae274e72fe6 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1475,14 +1475,15 @@ static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) static int line_range_inline_cb(Dwarf_Die *in_die, void *data) { - find_line_range_by_line(in_die, data); + int ret = find_line_range_by_line(in_die, data); /* * We have to check all instances of inlined function, because * some execution paths can be optimized out depends on the - * function argument of instances + * function argument of instances. However, if an error occurs, + * it should be handled by the caller. */ - return 0; + return ret < 0 ? ret : 0; } /* Search function definition from function name */ From 03d89412981a7681971bc77edba1669595763030 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 7 Apr 2014 16:05:48 +0900 Subject: [PATCH 10/16] perf probe: Use dwarf_getcfi_elf() instead of dwarf_getcfi() The dwarf_getcfi() only checks .debug_frame section for CFI, but as most binaries only have .eh_frame it'd return NULL and it makes some variables inaccessible. Using dwarf_getcfi_elf (along with dwarf_getelf()) allows to show and add probe to more variables. Signed-off-by: Namhyung Kim Acked-by: Masami Hiramatsu Cc: Masami Hiramatsu Link: http://lkml.kernel.org/r/1396854348-9296-1-git-send-email-namhyung@kernel.org Signed-off-by: Jiri Olsa --- tools/perf/util/probe-finder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index fae274e72fe6..562762117639 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -985,7 +985,7 @@ static int debuginfo__find_probes(struct debuginfo *dbg, #if _ELFUTILS_PREREQ(0, 142) /* Get the call frame information from this dwarf */ - pf->cfi = dwarf_getcfi(dbg->dbg); + pf->cfi = dwarf_getcfi_elf(dwarf_getelf(dbg->dbg)); #endif off = 0; From 95a2b3c0a9e2a8038edbf3f9776d5a3d76146459 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 27 Mar 2014 19:50:18 -0400 Subject: [PATCH 11/16] perf bench: Update manpage to mention numa and futex Signed-off-by: Ramkumar Ramachandra Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1395964219-22173-3-git-send-email-artagnon@gmail.com Signed-off-by: Jiri Olsa --- tools/perf/Documentation/perf-bench.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tools/perf/Documentation/perf-bench.txt b/tools/perf/Documentation/perf-bench.txt index 7065cd6fbdfc..4464ad770d51 100644 --- a/tools/perf/Documentation/perf-bench.txt +++ b/tools/perf/Documentation/perf-bench.txt @@ -48,6 +48,12 @@ SUBSYSTEM 'mem':: Memory access performance. +'numa':: + NUMA scheduling and MM benchmarks. + +'futex':: + Futex stressing benchmarks. + 'all':: All benchmark subsystems. @@ -187,6 +193,22 @@ Show only the result with page faults before memset. --no-prefault:: Show only the result without page faults before memset. +SUITES FOR 'numa' +~~~~~~~~~~~~~~~~~ +*mem*:: +Suite for evaluating NUMA workloads. + +SUITES FOR 'futex' +~~~~~~~~~~~~~~~~~~ +*hash*:: +Suite for evaluating hash tables. + +*wake*:: +Suite for evaluating wake calls. + +*requeue*:: +Suite for evaluating requeue calls. + SEE ALSO -------- linkperf:perf[1] From 5673872d4afd2584e075cf2b1adb2cccec46a0f3 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 27 Mar 2014 19:50:19 -0400 Subject: [PATCH 12/16] perf bench: Fix segfault at the end of an 'all' execution At the end of $ perf bench all the program segfaults because it attempts to dereference a NULL pointer. Fix this fault. Signed-off-by: Ramkumar Ramachandra Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1395964219-22173-4-git-send-email-artagnon@gmail.com Signed-off-by: Jiri Olsa --- tools/perf/builtin-bench.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index f600b74216da..1e6e77710545 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c @@ -86,7 +86,7 @@ static struct collection collections[] = { /* Iterate over all benchmarks within a collection: */ #define for_each_bench(coll, bench) \ - for (bench = coll->benchmarks; bench->name; bench++) + for (bench = coll->benchmarks; bench && bench->name; bench++) static void dump_benchmarks(struct collection *coll) { From 40ba93e3aa001246110320edbe8cf2eb488c1fe7 Mon Sep 17 00:00:00 2001 From: Ramkumar Ramachandra Date: Thu, 27 Mar 2014 19:50:17 -0400 Subject: [PATCH 13/16] perf bench: Set more defaults in the 'numa' suite Currently, $ perf bench numa mem errors out with usage information. To make this more user-friendly, let us provide a minimum set of default values required for a test run. As an added bonus, $ perf bench all now goes all the way to completion. Signed-off-by: Ramkumar Ramachandra Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Ingo Molnar Cc: Jiri Olsa Link: http://lkml.kernel.org/r/1395964219-22173-2-git-send-email-artagnon@gmail.com Signed-off-by: Jiri Olsa --- tools/perf/bench/numa.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index d4c83c60b9b2..20697fbf2c98 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c @@ -1593,6 +1593,10 @@ static void init_params(struct params *p, const char *name, int argc, const char p->data_rand_walk = true; p->nr_loops = -1; p->init_random = true; + p->mb_global_str = "1"; + p->nr_proc = 1; + p->nr_threads = 1; + p->nr_secs = 5; } static int run_bench_numa(const char *name, const char **argv) From 90f6bb6c98ffef42125d7be6d4612505f561fbce Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 25 Mar 2014 10:31:38 -0700 Subject: [PATCH 14/16] perf stat: Initialize statistics correctly perf stat did initialize the stats structure used to compute stddev etc. incorrectly. It merely zeroes it. But one member (min) needs to be set to a non zero value. This causes min to be not computed at all. Call init_stats() correctly. It doesn't matter for stat currently because it doesn't use min, but it's still better to do it correctly. The other users of statistics are already correct. Signed-off-by: Andi Kleen Acked-by: Namhyung Kim Link: http://lkml.kernel.org/r/1395768699-16060-1-git-send-email-andi@firstfloor.org Signed-off-by: Jiri Olsa --- tools/perf/builtin-stat.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index 8b0e1c9234d9..65a151e36067 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -174,13 +174,20 @@ static inline int perf_evsel__nr_cpus(struct perf_evsel *evsel) static void perf_evsel__reset_stat_priv(struct perf_evsel *evsel) { - memset(evsel->priv, 0, sizeof(struct perf_stat)); + int i; + struct perf_stat *ps = evsel->priv; + + for (i = 0; i < 3; i++) + init_stats(&ps->res_stats[i]); } static int perf_evsel__alloc_stat_priv(struct perf_evsel *evsel) { evsel->priv = zalloc(sizeof(struct perf_stat)); - return evsel->priv == NULL ? -ENOMEM : 0; + if (evsel == NULL) + return -ENOMEM; + perf_evsel__reset_stat_priv(evsel); + return 0; } static void perf_evsel__free_stat_priv(struct perf_evsel *evsel) From ae450a7d054cd1fe8d003a085858ca5b90cc74d9 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 10 Apr 2014 12:02:54 +0300 Subject: [PATCH 15/16] perf tools: Fix double free in perf test 21 (code-reading.c) perf_evlist__delete() deletes attached cpu and thread maps but the test is still using them, so remove them from the evlist before deleting it. Signed-off-by: Adrian Hunter Link: http://lkml.kernel.org/r/53465E3E.8070201@intel.com Signed-off-by: Jiri Olsa --- tools/perf/tests/code-reading.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 653a8fe2db95..bfb186900ac0 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -504,6 +504,7 @@ static int do_test_code_reading(bool try_kcore) if (ret < 0) { if (!excl_kernel) { excl_kernel = true; + perf_evlist__set_maps(evlist, NULL, NULL); perf_evlist__delete(evlist); evlist = NULL; continue; From c9e87a472594fd237b2d19dcbe4a3424297f0b1a Mon Sep 17 00:00:00 2001 From: Cody P Schafer Date: Mon, 14 Apr 2014 12:47:01 +0200 Subject: [PATCH 16/16] perf tools: Instead of redirecting flex output, use -o This gives us a real filename instead of having '' show up all over the place when debugging. Signed-off-by: Cody P Schafer Link: http://lkml.kernel.org/r/1396652539-2416-1-git-send-email-cody@linux.vnet.ibm.com Signed-off-by: Jiri Olsa --- tools/perf/Makefile.perf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 50d875d970c4..e96923310d57 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -192,13 +192,13 @@ endif export PERL_PATH $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(OUTPUT)util/parse-events-bison.c - $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c + $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/parse-events-flex.h $(PARSER_DEBUG_FLEX) util/parse-events.l $(OUTPUT)util/parse-events-bison.c: util/parse-events.y $(QUIET_BISON)$(BISON) -v util/parse-events.y -d $(PARSER_DEBUG_BISON) -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(OUTPUT)util/pmu-bison.c - $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c + $(QUIET_FLEX)$(FLEX) -o $@ --header-file=$(OUTPUT)util/pmu-flex.h util/pmu.l $(OUTPUT)util/pmu-bison.c: util/pmu.y $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_