diff options
Diffstat (limited to 'tools')
29 files changed, 280 insertions, 107 deletions
diff --git a/tools/lib/subcmd/parse-options.c b/tools/lib/subcmd/parse-options.c index 3284bb14ae78..8aad81151d50 100644 --- a/tools/lib/subcmd/parse-options.c +++ b/tools/lib/subcmd/parse-options.c | |||
@@ -213,6 +213,9 @@ static int get_value(struct parse_opt_ctx_t *p, | |||
213 | else | 213 | else |
214 | err = get_arg(p, opt, flags, (const char **)opt->value); | 214 | err = get_arg(p, opt, flags, (const char **)opt->value); |
215 | 215 | ||
216 | if (opt->set) | ||
217 | *(bool *)opt->set = true; | ||
218 | |||
216 | /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */ | 219 | /* PARSE_OPT_NOEMPTY: Allow NULL but disallow empty string. */ |
217 | if (opt->flags & PARSE_OPT_NOEMPTY) { | 220 | if (opt->flags & PARSE_OPT_NOEMPTY) { |
218 | const char *val = *(const char **)opt->value; | 221 | const char *val = *(const char **)opt->value; |
diff --git a/tools/lib/subcmd/parse-options.h b/tools/lib/subcmd/parse-options.h index 8866ac438b34..11c3be3bcce7 100644 --- a/tools/lib/subcmd/parse-options.h +++ b/tools/lib/subcmd/parse-options.h | |||
@@ -137,6 +137,11 @@ struct option { | |||
137 | { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ | 137 | { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ |
138 | .value = check_vtype(v, const char **), (a), .help = (h), \ | 138 | .value = check_vtype(v, const char **), (a), .help = (h), \ |
139 | .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } | 139 | .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d) } |
140 | #define OPT_STRING_OPTARG_SET(s, l, v, os, a, h, d) \ | ||
141 | { .type = OPTION_STRING, .short_name = (s), .long_name = (l), \ | ||
142 | .value = check_vtype(v, const char **), (a), .help = (h), \ | ||
143 | .flags = PARSE_OPT_OPTARG, .defval = (intptr_t)(d), \ | ||
144 | .set = check_vtype(os, bool *)} | ||
140 | #define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} | 145 | #define OPT_STRING_NOEMPTY(s, l, v, a, h) { .type = OPTION_STRING, .short_name = (s), .long_name = (l), .value = check_vtype(v, const char **), (a), .help = (h), .flags = PARSE_OPT_NOEMPTY} |
141 | #define OPT_DATE(s, l, v, h) \ | 146 | #define OPT_DATE(s, l, v, h) \ |
142 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } | 147 | { .type = OPTION_CALLBACK, .short_name = (s), .long_name = (l), .value = (v), .argh = "time", .help = (h), .callback = parse_opt_approxidate_cb } |
diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c index f1ce60065258..ec30c2fcbac0 100644 --- a/tools/lib/traceevent/plugin_sched_switch.c +++ b/tools/lib/traceevent/plugin_sched_switch.c | |||
@@ -111,7 +111,7 @@ static int sched_switch_handler(struct trace_seq *s, | |||
111 | trace_seq_printf(s, "%lld ", val); | 111 | trace_seq_printf(s, "%lld ", val); |
112 | 112 | ||
113 | if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) | 113 | if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0) |
114 | trace_seq_printf(s, "[%lld] ", val); | 114 | trace_seq_printf(s, "[%d] ", (int) val); |
115 | 115 | ||
116 | if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0) | 116 | if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0) |
117 | write_state(s, val); | 117 | write_state(s, val); |
@@ -129,7 +129,7 @@ static int sched_switch_handler(struct trace_seq *s, | |||
129 | trace_seq_printf(s, "%lld", val); | 129 | trace_seq_printf(s, "%lld", val); |
130 | 130 | ||
131 | if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0) | 131 | if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0) |
132 | trace_seq_printf(s, " [%lld]", val); | 132 | trace_seq_printf(s, " [%d]", (int) val); |
133 | 133 | ||
134 | return 0; | 134 | return 0; |
135 | } | 135 | } |
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c index 5e0dea2cdc01..039636ffb6c8 100644 --- a/tools/objtool/arch/x86/decode.c +++ b/tools/objtool/arch/x86/decode.c | |||
@@ -150,9 +150,9 @@ int arch_decode_instruction(struct elf *elf, struct section *sec, | |||
150 | *type = INSN_RETURN; | 150 | *type = INSN_RETURN; |
151 | break; | 151 | break; |
152 | 152 | ||
153 | case 0xc5: /* iret */ | ||
154 | case 0xca: /* retf */ | 153 | case 0xca: /* retf */ |
155 | case 0xcb: /* retf */ | 154 | case 0xcb: /* retf */ |
155 | case 0xcf: /* iret */ | ||
156 | *type = INSN_CONTEXT_SWITCH; | 156 | *type = INSN_CONTEXT_SWITCH; |
157 | break; | 157 | break; |
158 | 158 | ||
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 27fc3617c6a4..5054d9147f0f 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -430,6 +430,10 @@ that gets then processed, possibly via a perf script, to decide if that | |||
430 | particular perf.data snapshot should be kept or not. | 430 | particular perf.data snapshot should be kept or not. |
431 | 431 | ||
432 | Implies --timestamp-filename, --no-buildid and --no-buildid-cache. | 432 | Implies --timestamp-filename, --no-buildid and --no-buildid-cache. |
433 | The reason for the latter two is to reduce the data file switching | ||
434 | overhead. You can still switch them on with: | ||
435 | |||
436 | --switch-output --no-no-buildid --no-no-buildid-cache | ||
433 | 437 | ||
434 | --dry-run:: | 438 | --dry-run:: |
435 | Parse options then exit. --dry-run can be used to detect errors in cmdline | 439 | Parse options then exit. --dry-run can be used to detect errors in cmdline |
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 8fc24824705e..8bb16aa9d661 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf | |||
@@ -704,9 +704,9 @@ install-tests: all install-gtk | |||
704 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ | 704 | $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \ |
705 | $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' | 705 | $(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr' |
706 | 706 | ||
707 | install-bin: install-tools install-tests | 707 | install-bin: install-tools install-tests install-traceevent-plugins |
708 | 708 | ||
709 | install: install-bin try-install-man install-traceevent-plugins | 709 | install: install-bin try-install-man |
710 | 710 | ||
711 | install-python_ext: | 711 | install-python_ext: |
712 | $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' | 712 | $(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)' |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 9ff0db4e2d0c..933aeec46f4a 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -1199,7 +1199,7 @@ static int ui_init(void) | |||
1199 | BUG_ON(1); | 1199 | BUG_ON(1); |
1200 | } | 1200 | } |
1201 | 1201 | ||
1202 | perf_hpp__register_sort_field(fmt); | 1202 | perf_hpp__prepend_sort_field(fmt); |
1203 | return 0; | 1203 | return 0; |
1204 | } | 1204 | } |
1205 | 1205 | ||
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c index 35a02f8e5a4a..915869e00d86 100644 --- a/tools/perf/builtin-kmem.c +++ b/tools/perf/builtin-kmem.c | |||
@@ -655,7 +655,6 @@ static const struct { | |||
655 | { "__GFP_RECLAIM", "R" }, | 655 | { "__GFP_RECLAIM", "R" }, |
656 | { "__GFP_DIRECT_RECLAIM", "DR" }, | 656 | { "__GFP_DIRECT_RECLAIM", "DR" }, |
657 | { "__GFP_KSWAPD_RECLAIM", "KR" }, | 657 | { "__GFP_KSWAPD_RECLAIM", "KR" }, |
658 | { "__GFP_OTHER_NODE", "ON" }, | ||
659 | }; | 658 | }; |
660 | 659 | ||
661 | static size_t max_gfp_len; | 660 | static size_t max_gfp_len; |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 74d6a035133a..4ec10e9427d9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -1405,7 +1405,7 @@ static bool dry_run; | |||
1405 | * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', | 1405 | * perf_evlist__prepare_workload, etc instead of fork+exec'in 'perf record', |
1406 | * using pipes, etc. | 1406 | * using pipes, etc. |
1407 | */ | 1407 | */ |
1408 | struct option __record_options[] = { | 1408 | static struct option __record_options[] = { |
1409 | OPT_CALLBACK('e', "event", &record.evlist, "event", | 1409 | OPT_CALLBACK('e', "event", &record.evlist, "event", |
1410 | "event selector. use 'perf list' to list available events", | 1410 | "event selector. use 'perf list' to list available events", |
1411 | parse_events_option), | 1411 | parse_events_option), |
@@ -1636,7 +1636,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1636 | * overhead. Still generate buildid if they are required | 1636 | * overhead. Still generate buildid if they are required |
1637 | * explicitly using | 1637 | * explicitly using |
1638 | * | 1638 | * |
1639 | * perf record --signal-trigger --no-no-buildid \ | 1639 | * perf record --switch-output --no-no-buildid \ |
1640 | * --no-no-buildid-cache | 1640 | * --no-no-buildid-cache |
1641 | * | 1641 | * |
1642 | * Following code equals to: | 1642 | * Following code equals to: |
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c index d53e706a6f17..5b134b0d1ff3 100644 --- a/tools/perf/builtin-sched.c +++ b/tools/perf/builtin-sched.c | |||
@@ -209,6 +209,7 @@ struct perf_sched { | |||
209 | u64 skipped_samples; | 209 | u64 skipped_samples; |
210 | const char *time_str; | 210 | const char *time_str; |
211 | struct perf_time_interval ptime; | 211 | struct perf_time_interval ptime; |
212 | struct perf_time_interval hist_time; | ||
212 | }; | 213 | }; |
213 | 214 | ||
214 | /* per thread run time data */ | 215 | /* per thread run time data */ |
@@ -2460,6 +2461,11 @@ static int timehist_sched_change_event(struct perf_tool *tool, | |||
2460 | timehist_print_sample(sched, sample, &al, thread, t); | 2461 | timehist_print_sample(sched, sample, &al, thread, t); |
2461 | 2462 | ||
2462 | out: | 2463 | out: |
2464 | if (sched->hist_time.start == 0 && t >= ptime->start) | ||
2465 | sched->hist_time.start = t; | ||
2466 | if (ptime->end == 0 || t <= ptime->end) | ||
2467 | sched->hist_time.end = t; | ||
2468 | |||
2463 | if (tr) { | 2469 | if (tr) { |
2464 | /* time of this sched_switch event becomes last time task seen */ | 2470 | /* time of this sched_switch event becomes last time task seen */ |
2465 | tr->last_time = sample->time; | 2471 | tr->last_time = sample->time; |
@@ -2624,6 +2630,7 @@ static void timehist_print_summary(struct perf_sched *sched, | |||
2624 | struct thread *t; | 2630 | struct thread *t; |
2625 | struct thread_runtime *r; | 2631 | struct thread_runtime *r; |
2626 | int i; | 2632 | int i; |
2633 | u64 hist_time = sched->hist_time.end - sched->hist_time.start; | ||
2627 | 2634 | ||
2628 | memset(&totals, 0, sizeof(totals)); | 2635 | memset(&totals, 0, sizeof(totals)); |
2629 | 2636 | ||
@@ -2665,7 +2672,7 @@ static void timehist_print_summary(struct perf_sched *sched, | |||
2665 | totals.sched_count += r->run_stats.n; | 2672 | totals.sched_count += r->run_stats.n; |
2666 | printf(" CPU %2d idle for ", i); | 2673 | printf(" CPU %2d idle for ", i); |
2667 | print_sched_time(r->total_run_time, 6); | 2674 | print_sched_time(r->total_run_time, 6); |
2668 | printf(" msec\n"); | 2675 | printf(" msec (%6.2f%%)\n", 100.0 * r->total_run_time / hist_time); |
2669 | } else | 2676 | } else |
2670 | printf(" CPU %2d idle entire time window\n", i); | 2677 | printf(" CPU %2d idle entire time window\n", i); |
2671 | } | 2678 | } |
@@ -2701,12 +2708,16 @@ static void timehist_print_summary(struct perf_sched *sched, | |||
2701 | 2708 | ||
2702 | printf("\n" | 2709 | printf("\n" |
2703 | " Total number of unique tasks: %" PRIu64 "\n" | 2710 | " Total number of unique tasks: %" PRIu64 "\n" |
2704 | "Total number of context switches: %" PRIu64 "\n" | 2711 | "Total number of context switches: %" PRIu64 "\n", |
2705 | " Total run time (msec): ", | ||
2706 | totals.task_count, totals.sched_count); | 2712 | totals.task_count, totals.sched_count); |
2707 | 2713 | ||
2714 | printf(" Total run time (msec): "); | ||
2708 | print_sched_time(totals.total_run_time, 2); | 2715 | print_sched_time(totals.total_run_time, 2); |
2709 | printf("\n"); | 2716 | printf("\n"); |
2717 | |||
2718 | printf(" Total scheduling time (msec): "); | ||
2719 | print_sched_time(hist_time, 2); | ||
2720 | printf(" (x %d)\n", sched->max_cpu); | ||
2710 | } | 2721 | } |
2711 | 2722 | ||
2712 | typedef int (*sched_handler)(struct perf_tool *tool, | 2723 | typedef int (*sched_handler)(struct perf_tool *tool, |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 37388397b5bc..18cfcdc90356 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -521,6 +521,12 @@ void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, | |||
521 | list_add_tail(&format->sort_list, &list->sorts); | 521 | list_add_tail(&format->sort_list, &list->sorts); |
522 | } | 522 | } |
523 | 523 | ||
524 | void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list, | ||
525 | struct perf_hpp_fmt *format) | ||
526 | { | ||
527 | list_add(&format->sort_list, &list->sorts); | ||
528 | } | ||
529 | |||
524 | void perf_hpp__column_unregister(struct perf_hpp_fmt *format) | 530 | void perf_hpp__column_unregister(struct perf_hpp_fmt *format) |
525 | { | 531 | { |
526 | list_del(&format->list); | 532 | list_del(&format->list); |
@@ -560,6 +566,10 @@ void perf_hpp__setup_output_field(struct perf_hpp_list *list) | |||
560 | perf_hpp_list__for_each_sort_list(list, fmt) { | 566 | perf_hpp_list__for_each_sort_list(list, fmt) { |
561 | struct perf_hpp_fmt *pos; | 567 | struct perf_hpp_fmt *pos; |
562 | 568 | ||
569 | /* skip sort-only fields ("sort_compute" in perf diff) */ | ||
570 | if (!fmt->entry && !fmt->color) | ||
571 | continue; | ||
572 | |||
563 | perf_hpp_list__for_each_format(list, pos) { | 573 | perf_hpp_list__for_each_format(list, pos) { |
564 | if (fmt_equal(fmt, pos)) | 574 | if (fmt_equal(fmt, pos)) |
565 | goto next; | 575 | goto next; |
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c index 42922512c1c6..8b610dd9e2f6 100644 --- a/tools/perf/util/callchain.c +++ b/tools/perf/util/callchain.c | |||
@@ -437,7 +437,7 @@ fill_node(struct callchain_node *node, struct callchain_cursor *cursor) | |||
437 | } | 437 | } |
438 | call->ip = cursor_node->ip; | 438 | call->ip = cursor_node->ip; |
439 | call->ms.sym = cursor_node->sym; | 439 | call->ms.sym = cursor_node->sym; |
440 | call->ms.map = cursor_node->map; | 440 | call->ms.map = map__get(cursor_node->map); |
441 | 441 | ||
442 | if (cursor_node->branch) { | 442 | if (cursor_node->branch) { |
443 | call->branch_count = 1; | 443 | call->branch_count = 1; |
@@ -477,6 +477,7 @@ add_child(struct callchain_node *parent, | |||
477 | 477 | ||
478 | list_for_each_entry_safe(call, tmp, &new->val, list) { | 478 | list_for_each_entry_safe(call, tmp, &new->val, list) { |
479 | list_del(&call->list); | 479 | list_del(&call->list); |
480 | map__zput(call->ms.map); | ||
480 | free(call); | 481 | free(call); |
481 | } | 482 | } |
482 | free(new); | 483 | free(new); |
@@ -761,6 +762,7 @@ merge_chain_branch(struct callchain_cursor *cursor, | |||
761 | list->ms.map, list->ms.sym, | 762 | list->ms.map, list->ms.sym, |
762 | false, NULL, 0, 0); | 763 | false, NULL, 0, 0); |
763 | list_del(&list->list); | 764 | list_del(&list->list); |
765 | map__zput(list->ms.map); | ||
764 | free(list); | 766 | free(list); |
765 | } | 767 | } |
766 | 768 | ||
@@ -811,7 +813,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor, | |||
811 | } | 813 | } |
812 | 814 | ||
813 | node->ip = ip; | 815 | node->ip = ip; |
814 | node->map = map; | 816 | map__zput(node->map); |
817 | node->map = map__get(map); | ||
815 | node->sym = sym; | 818 | node->sym = sym; |
816 | node->branch = branch; | 819 | node->branch = branch; |
817 | node->nr_loop_iter = nr_loop_iter; | 820 | node->nr_loop_iter = nr_loop_iter; |
@@ -1142,11 +1145,13 @@ static void free_callchain_node(struct callchain_node *node) | |||
1142 | 1145 | ||
1143 | list_for_each_entry_safe(list, tmp, &node->parent_val, list) { | 1146 | list_for_each_entry_safe(list, tmp, &node->parent_val, list) { |
1144 | list_del(&list->list); | 1147 | list_del(&list->list); |
1148 | map__zput(list->ms.map); | ||
1145 | free(list); | 1149 | free(list); |
1146 | } | 1150 | } |
1147 | 1151 | ||
1148 | list_for_each_entry_safe(list, tmp, &node->val, list) { | 1152 | list_for_each_entry_safe(list, tmp, &node->val, list) { |
1149 | list_del(&list->list); | 1153 | list_del(&list->list); |
1154 | map__zput(list->ms.map); | ||
1150 | free(list); | 1155 | free(list); |
1151 | } | 1156 | } |
1152 | 1157 | ||
@@ -1210,6 +1215,7 @@ int callchain_node__make_parent_list(struct callchain_node *node) | |||
1210 | goto out; | 1215 | goto out; |
1211 | *new = *chain; | 1216 | *new = *chain; |
1212 | new->has_children = false; | 1217 | new->has_children = false; |
1218 | map__get(new->ms.map); | ||
1213 | list_add_tail(&new->list, &head); | 1219 | list_add_tail(&new->list, &head); |
1214 | } | 1220 | } |
1215 | parent = parent->parent; | 1221 | parent = parent->parent; |
@@ -1230,6 +1236,7 @@ int callchain_node__make_parent_list(struct callchain_node *node) | |||
1230 | out: | 1236 | out: |
1231 | list_for_each_entry_safe(chain, new, &head, list) { | 1237 | list_for_each_entry_safe(chain, new, &head, list) { |
1232 | list_del(&chain->list); | 1238 | list_del(&chain->list); |
1239 | map__zput(chain->ms.map); | ||
1233 | free(chain); | 1240 | free(chain); |
1234 | } | 1241 | } |
1235 | return -ENOMEM; | 1242 | return -ENOMEM; |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index 35c8e379530f..4f4b60f1558a 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/list.h> | 5 | #include <linux/list.h> |
6 | #include <linux/rbtree.h> | 6 | #include <linux/rbtree.h> |
7 | #include "event.h" | 7 | #include "event.h" |
8 | #include "map.h" | ||
8 | #include "symbol.h" | 9 | #include "symbol.h" |
9 | 10 | ||
10 | #define HELP_PAD "\t\t\t\t" | 11 | #define HELP_PAD "\t\t\t\t" |
@@ -184,8 +185,13 @@ int callchain_merge(struct callchain_cursor *cursor, | |||
184 | */ | 185 | */ |
185 | static inline void callchain_cursor_reset(struct callchain_cursor *cursor) | 186 | static inline void callchain_cursor_reset(struct callchain_cursor *cursor) |
186 | { | 187 | { |
188 | struct callchain_cursor_node *node; | ||
189 | |||
187 | cursor->nr = 0; | 190 | cursor->nr = 0; |
188 | cursor->last = &cursor->first; | 191 | cursor->last = &cursor->first; |
192 | |||
193 | for (node = cursor->first; node != NULL; node = node->next) | ||
194 | map__zput(node->map); | ||
189 | } | 195 | } |
190 | 196 | ||
191 | int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, | 197 | int callchain_cursor_append(struct callchain_cursor *cursor, u64 ip, |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 6770a9645609..7d1b7d33e644 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include "util.h" | 1 | #include "util.h" |
2 | #include "build-id.h" | 2 | #include "build-id.h" |
3 | #include "hist.h" | 3 | #include "hist.h" |
4 | #include "map.h" | ||
4 | #include "session.h" | 5 | #include "session.h" |
5 | #include "sort.h" | 6 | #include "sort.h" |
6 | #include "evlist.h" | 7 | #include "evlist.h" |
@@ -1019,6 +1020,10 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, | |||
1019 | int max_stack_depth, void *arg) | 1020 | int max_stack_depth, void *arg) |
1020 | { | 1021 | { |
1021 | int err, err2; | 1022 | int err, err2; |
1023 | struct map *alm = NULL; | ||
1024 | |||
1025 | if (al && al->map) | ||
1026 | alm = map__get(al->map); | ||
1022 | 1027 | ||
1023 | err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, | 1028 | err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent, |
1024 | iter->evsel, al, max_stack_depth); | 1029 | iter->evsel, al, max_stack_depth); |
@@ -1058,6 +1063,8 @@ out: | |||
1058 | if (!err) | 1063 | if (!err) |
1059 | err = err2; | 1064 | err = err2; |
1060 | 1065 | ||
1066 | map__put(alm); | ||
1067 | |||
1061 | return err; | 1068 | return err; |
1062 | } | 1069 | } |
1063 | 1070 | ||
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index d4b6514eeef5..28c216e3d5b7 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -283,6 +283,8 @@ void perf_hpp_list__column_register(struct perf_hpp_list *list, | |||
283 | struct perf_hpp_fmt *format); | 283 | struct perf_hpp_fmt *format); |
284 | void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, | 284 | void perf_hpp_list__register_sort_field(struct perf_hpp_list *list, |
285 | struct perf_hpp_fmt *format); | 285 | struct perf_hpp_fmt *format); |
286 | void perf_hpp_list__prepend_sort_field(struct perf_hpp_list *list, | ||
287 | struct perf_hpp_fmt *format); | ||
286 | 288 | ||
287 | static inline void perf_hpp__column_register(struct perf_hpp_fmt *format) | 289 | static inline void perf_hpp__column_register(struct perf_hpp_fmt *format) |
288 | { | 290 | { |
@@ -294,6 +296,11 @@ static inline void perf_hpp__register_sort_field(struct perf_hpp_fmt *format) | |||
294 | perf_hpp_list__register_sort_field(&perf_hpp_list, format); | 296 | perf_hpp_list__register_sort_field(&perf_hpp_list, format); |
295 | } | 297 | } |
296 | 298 | ||
299 | static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format) | ||
300 | { | ||
301 | perf_hpp_list__prepend_sort_field(&perf_hpp_list, format); | ||
302 | } | ||
303 | |||
297 | #define perf_hpp_list__for_each_format(_list, format) \ | 304 | #define perf_hpp_list__for_each_format(_list, format) \ |
298 | list_for_each_entry(format, &(_list)->fields, list) | 305 | list_for_each_entry(format, &(_list)->fields, list) |
299 | 306 | ||
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index d281ae2b54e8..6a6f44dd594b 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -163,7 +163,7 @@ static struct map *kernel_get_module_map(const char *module) | |||
163 | 163 | ||
164 | /* A file path -- this is an offline module */ | 164 | /* A file path -- this is an offline module */ |
165 | if (module && strchr(module, '/')) | 165 | if (module && strchr(module, '/')) |
166 | return machine__findnew_module_map(host_machine, 0, module); | 166 | return dso__new_map(module); |
167 | 167 | ||
168 | if (!module) | 168 | if (!module) |
169 | module = "kernel"; | 169 | module = "kernel"; |
@@ -173,6 +173,7 @@ static struct map *kernel_get_module_map(const char *module) | |||
173 | if (strncmp(pos->dso->short_name + 1, module, | 173 | if (strncmp(pos->dso->short_name + 1, module, |
174 | pos->dso->short_name_len - 2) == 0 && | 174 | pos->dso->short_name_len - 2) == 0 && |
175 | module[pos->dso->short_name_len - 2] == '\0') { | 175 | module[pos->dso->short_name_len - 2] == '\0') { |
176 | map__get(pos); | ||
176 | return pos; | 177 | return pos; |
177 | } | 178 | } |
178 | } | 179 | } |
@@ -188,15 +189,6 @@ struct map *get_target_map(const char *target, bool user) | |||
188 | return kernel_get_module_map(target); | 189 | return kernel_get_module_map(target); |
189 | } | 190 | } |
190 | 191 | ||
191 | static void put_target_map(struct map *map, bool user) | ||
192 | { | ||
193 | if (map && user) { | ||
194 | /* Only the user map needs to be released */ | ||
195 | map__put(map); | ||
196 | } | ||
197 | } | ||
198 | |||
199 | |||
200 | static int convert_exec_to_group(const char *exec, char **result) | 192 | static int convert_exec_to_group(const char *exec, char **result) |
201 | { | 193 | { |
202 | char *ptr1, *ptr2, *exec_copy; | 194 | char *ptr1, *ptr2, *exec_copy; |
@@ -268,21 +260,6 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address) | |||
268 | } | 260 | } |
269 | 261 | ||
270 | /* | 262 | /* |
271 | * NOTE: | ||
272 | * '.gnu.linkonce.this_module' section of kernel module elf directly | ||
273 | * maps to 'struct module' from linux/module.h. This section contains | ||
274 | * actual module name which will be used by kernel after loading it. | ||
275 | * But, we cannot use 'struct module' here since linux/module.h is not | ||
276 | * exposed to user-space. Offset of 'name' has remained same from long | ||
277 | * time, so hardcoding it here. | ||
278 | */ | ||
279 | #ifdef __LP64__ | ||
280 | #define MOD_NAME_OFFSET 24 | ||
281 | #else | ||
282 | #define MOD_NAME_OFFSET 12 | ||
283 | #endif | ||
284 | |||
285 | /* | ||
286 | * @module can be module name of module file path. In case of path, | 263 | * @module can be module name of module file path. In case of path, |
287 | * inspect elf and find out what is actual module name. | 264 | * inspect elf and find out what is actual module name. |
288 | * Caller has to free mod_name after using it. | 265 | * Caller has to free mod_name after using it. |
@@ -296,6 +273,7 @@ static char *find_module_name(const char *module) | |||
296 | Elf_Data *data; | 273 | Elf_Data *data; |
297 | Elf_Scn *sec; | 274 | Elf_Scn *sec; |
298 | char *mod_name = NULL; | 275 | char *mod_name = NULL; |
276 | int name_offset; | ||
299 | 277 | ||
300 | fd = open(module, O_RDONLY); | 278 | fd = open(module, O_RDONLY); |
301 | if (fd < 0) | 279 | if (fd < 0) |
@@ -317,7 +295,21 @@ static char *find_module_name(const char *module) | |||
317 | if (!data || !data->d_buf) | 295 | if (!data || !data->d_buf) |
318 | goto ret_err; | 296 | goto ret_err; |
319 | 297 | ||
320 | mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET); | 298 | /* |
299 | * NOTE: | ||
300 | * '.gnu.linkonce.this_module' section of kernel module elf directly | ||
301 | * maps to 'struct module' from linux/module.h. This section contains | ||
302 | * actual module name which will be used by kernel after loading it. | ||
303 | * But, we cannot use 'struct module' here since linux/module.h is not | ||
304 | * exposed to user-space. Offset of 'name' has remained same from long | ||
305 | * time, so hardcoding it here. | ||
306 | */ | ||
307 | if (ehdr.e_ident[EI_CLASS] == ELFCLASS32) | ||
308 | name_offset = 12; | ||
309 | else /* expect ELFCLASS64 by default */ | ||
310 | name_offset = 24; | ||
311 | |||
312 | mod_name = strdup((char *)data->d_buf + name_offset); | ||
321 | 313 | ||
322 | ret_err: | 314 | ret_err: |
323 | elf_end(elf); | 315 | elf_end(elf); |
@@ -412,7 +404,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, | |||
412 | } | 404 | } |
413 | 405 | ||
414 | out: | 406 | out: |
415 | put_target_map(map, uprobes); | 407 | map__put(map); |
416 | return ret; | 408 | return ret; |
417 | 409 | ||
418 | } | 410 | } |
@@ -618,6 +610,67 @@ error: | |||
618 | return ret ? : -ENOENT; | 610 | return ret ? : -ENOENT; |
619 | } | 611 | } |
620 | 612 | ||
613 | /* Adjust symbol name and address */ | ||
614 | static int post_process_probe_trace_point(struct probe_trace_point *tp, | ||
615 | struct map *map, unsigned long offs) | ||
616 | { | ||
617 | struct symbol *sym; | ||
618 | u64 addr = tp->address + tp->offset - offs; | ||
619 | |||
620 | sym = map__find_symbol(map, addr); | ||
621 | if (!sym) | ||
622 | return -ENOENT; | ||
623 | |||
624 | if (strcmp(sym->name, tp->symbol)) { | ||
625 | /* If we have no realname, use symbol for it */ | ||
626 | if (!tp->realname) | ||
627 | tp->realname = tp->symbol; | ||
628 | else | ||
629 | free(tp->symbol); | ||
630 | tp->symbol = strdup(sym->name); | ||
631 | if (!tp->symbol) | ||
632 | return -ENOMEM; | ||
633 | } | ||
634 | tp->offset = addr - sym->start; | ||
635 | tp->address -= offs; | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Rename DWARF symbols to ELF symbols -- gcc sometimes optimizes functions | ||
642 | * and generate new symbols with suffixes such as .constprop.N or .isra.N | ||
643 | * etc. Since those symbols are not recorded in DWARF, we have to find | ||
644 | * correct generated symbols from offline ELF binary. | ||
645 | * For online kernel or uprobes we don't need this because those are | ||
646 | * rebased on _text, or already a section relative address. | ||
647 | */ | ||
648 | static int | ||
649 | post_process_offline_probe_trace_events(struct probe_trace_event *tevs, | ||
650 | int ntevs, const char *pathname) | ||
651 | { | ||
652 | struct map *map; | ||
653 | unsigned long stext = 0; | ||
654 | int i, ret = 0; | ||
655 | |||
656 | /* Prepare a map for offline binary */ | ||
657 | map = dso__new_map(pathname); | ||
658 | if (!map || get_text_start_address(pathname, &stext) < 0) { | ||
659 | pr_warning("Failed to get ELF symbols for %s\n", pathname); | ||
660 | return -EINVAL; | ||
661 | } | ||
662 | |||
663 | for (i = 0; i < ntevs; i++) { | ||
664 | ret = post_process_probe_trace_point(&tevs[i].point, | ||
665 | map, stext); | ||
666 | if (ret < 0) | ||
667 | break; | ||
668 | } | ||
669 | map__put(map); | ||
670 | |||
671 | return ret; | ||
672 | } | ||
673 | |||
621 | static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, | 674 | static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, |
622 | int ntevs, const char *exec) | 675 | int ntevs, const char *exec) |
623 | { | 676 | { |
@@ -645,18 +698,31 @@ static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs, | |||
645 | return ret; | 698 | return ret; |
646 | } | 699 | } |
647 | 700 | ||
648 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | 701 | static int |
649 | int ntevs, const char *module) | 702 | post_process_module_probe_trace_events(struct probe_trace_event *tevs, |
703 | int ntevs, const char *module, | ||
704 | struct debuginfo *dinfo) | ||
650 | { | 705 | { |
706 | Dwarf_Addr text_offs = 0; | ||
651 | int i, ret = 0; | 707 | int i, ret = 0; |
652 | char *mod_name = NULL; | 708 | char *mod_name = NULL; |
709 | struct map *map; | ||
653 | 710 | ||
654 | if (!module) | 711 | if (!module) |
655 | return 0; | 712 | return 0; |
656 | 713 | ||
657 | mod_name = find_module_name(module); | 714 | map = get_target_map(module, false); |
715 | if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) { | ||
716 | pr_warning("Failed to get ELF symbols for %s\n", module); | ||
717 | return -EINVAL; | ||
718 | } | ||
658 | 719 | ||
720 | mod_name = find_module_name(module); | ||
659 | for (i = 0; i < ntevs; i++) { | 721 | for (i = 0; i < ntevs; i++) { |
722 | ret = post_process_probe_trace_point(&tevs[i].point, | ||
723 | map, (unsigned long)text_offs); | ||
724 | if (ret < 0) | ||
725 | break; | ||
660 | tevs[i].point.module = | 726 | tevs[i].point.module = |
661 | strdup(mod_name ? mod_name : module); | 727 | strdup(mod_name ? mod_name : module); |
662 | if (!tevs[i].point.module) { | 728 | if (!tevs[i].point.module) { |
@@ -666,6 +732,8 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | |||
666 | } | 732 | } |
667 | 733 | ||
668 | free(mod_name); | 734 | free(mod_name); |
735 | map__put(map); | ||
736 | |||
669 | return ret; | 737 | return ret; |
670 | } | 738 | } |
671 | 739 | ||
@@ -679,7 +747,8 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs, | |||
679 | 747 | ||
680 | /* Skip post process if the target is an offline kernel */ | 748 | /* Skip post process if the target is an offline kernel */ |
681 | if (symbol_conf.ignore_vmlinux_buildid) | 749 | if (symbol_conf.ignore_vmlinux_buildid) |
682 | return 0; | 750 | return post_process_offline_probe_trace_events(tevs, ntevs, |
751 | symbol_conf.vmlinux_name); | ||
683 | 752 | ||
684 | reloc_sym = kernel_get_ref_reloc_sym(); | 753 | reloc_sym = kernel_get_ref_reloc_sym(); |
685 | if (!reloc_sym) { | 754 | if (!reloc_sym) { |
@@ -722,7 +791,7 @@ arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unuse | |||
722 | static int post_process_probe_trace_events(struct perf_probe_event *pev, | 791 | static int post_process_probe_trace_events(struct perf_probe_event *pev, |
723 | struct probe_trace_event *tevs, | 792 | struct probe_trace_event *tevs, |
724 | int ntevs, const char *module, | 793 | int ntevs, const char *module, |
725 | bool uprobe) | 794 | bool uprobe, struct debuginfo *dinfo) |
726 | { | 795 | { |
727 | int ret; | 796 | int ret; |
728 | 797 | ||
@@ -730,7 +799,8 @@ static int post_process_probe_trace_events(struct perf_probe_event *pev, | |||
730 | ret = add_exec_to_probe_trace_events(tevs, ntevs, module); | 799 | ret = add_exec_to_probe_trace_events(tevs, ntevs, module); |
731 | else if (module) | 800 | else if (module) |
732 | /* Currently ref_reloc_sym based probe is not for drivers */ | 801 | /* Currently ref_reloc_sym based probe is not for drivers */ |
733 | ret = add_module_to_probe_trace_events(tevs, ntevs, module); | 802 | ret = post_process_module_probe_trace_events(tevs, ntevs, |
803 | module, dinfo); | ||
734 | else | 804 | else |
735 | ret = post_process_kernel_probe_trace_events(tevs, ntevs); | 805 | ret = post_process_kernel_probe_trace_events(tevs, ntevs); |
736 | 806 | ||
@@ -774,30 +844,27 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, | |||
774 | } | 844 | } |
775 | } | 845 | } |
776 | 846 | ||
777 | debuginfo__delete(dinfo); | ||
778 | |||
779 | if (ntevs > 0) { /* Succeeded to find trace events */ | 847 | if (ntevs > 0) { /* Succeeded to find trace events */ |
780 | pr_debug("Found %d probe_trace_events.\n", ntevs); | 848 | pr_debug("Found %d probe_trace_events.\n", ntevs); |
781 | ret = post_process_probe_trace_events(pev, *tevs, ntevs, | 849 | ret = post_process_probe_trace_events(pev, *tevs, ntevs, |
782 | pev->target, pev->uprobes); | 850 | pev->target, pev->uprobes, dinfo); |
783 | if (ret < 0 || ret == ntevs) { | 851 | if (ret < 0 || ret == ntevs) { |
852 | pr_debug("Post processing failed or all events are skipped. (%d)\n", ret); | ||
784 | clear_probe_trace_events(*tevs, ntevs); | 853 | clear_probe_trace_events(*tevs, ntevs); |
785 | zfree(tevs); | 854 | zfree(tevs); |
855 | ntevs = 0; | ||
786 | } | 856 | } |
787 | if (ret != ntevs) | ||
788 | return ret < 0 ? ret : ntevs; | ||
789 | ntevs = 0; | ||
790 | /* Fall through */ | ||
791 | } | 857 | } |
792 | 858 | ||
859 | debuginfo__delete(dinfo); | ||
860 | |||
793 | if (ntevs == 0) { /* No error but failed to find probe point. */ | 861 | if (ntevs == 0) { /* No error but failed to find probe point. */ |
794 | pr_warning("Probe point '%s' not found.\n", | 862 | pr_warning("Probe point '%s' not found.\n", |
795 | synthesize_perf_probe_point(&pev->point)); | 863 | synthesize_perf_probe_point(&pev->point)); |
796 | return -ENOENT; | 864 | return -ENOENT; |
797 | } | 865 | } else if (ntevs < 0) { |
798 | /* Error path : ntevs < 0 */ | 866 | /* Error path : ntevs < 0 */ |
799 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); | 867 | pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); |
800 | if (ntevs < 0) { | ||
801 | if (ntevs == -EBADF) | 868 | if (ntevs == -EBADF) |
802 | pr_warning("Warning: No dwarf info found in the vmlinux - " | 869 | pr_warning("Warning: No dwarf info found in the vmlinux - " |
803 | "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); | 870 | "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); |
@@ -2869,7 +2936,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, | |||
2869 | } | 2936 | } |
2870 | 2937 | ||
2871 | out: | 2938 | out: |
2872 | put_target_map(map, pev->uprobes); | 2939 | map__put(map); |
2873 | free(syms); | 2940 | free(syms); |
2874 | return ret; | 2941 | return ret; |
2875 | 2942 | ||
@@ -3362,10 +3429,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter, | |||
3362 | return ret; | 3429 | return ret; |
3363 | 3430 | ||
3364 | /* Get a symbol map */ | 3431 | /* Get a symbol map */ |
3365 | if (user) | 3432 | map = get_target_map(target, user); |
3366 | map = dso__new_map(target); | ||
3367 | else | ||
3368 | map = kernel_get_module_map(target); | ||
3369 | if (!map) { | 3433 | if (!map) { |
3370 | pr_err("Failed to get a map for %s\n", (target) ? : "kernel"); | 3434 | pr_err("Failed to get a map for %s\n", (target) ? : "kernel"); |
3371 | return -EINVAL; | 3435 | return -EINVAL; |
@@ -3397,9 +3461,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter, | |||
3397 | } | 3461 | } |
3398 | 3462 | ||
3399 | end: | 3463 | end: |
3400 | if (user) { | 3464 | map__put(map); |
3401 | map__put(map); | ||
3402 | } | ||
3403 | exit_probe_symbol_maps(); | 3465 | exit_probe_symbol_maps(); |
3404 | 3466 | ||
3405 | return ret; | 3467 | return ret; |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index df4debe564da..0d9d6e0803b8 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -1501,7 +1501,8 @@ int debuginfo__find_available_vars_at(struct debuginfo *dbg, | |||
1501 | } | 1501 | } |
1502 | 1502 | ||
1503 | /* For the kernel module, we need a special code to get a DIE */ | 1503 | /* For the kernel module, we need a special code to get a DIE */ |
1504 | static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs) | 1504 | int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, |
1505 | bool adjust_offset) | ||
1505 | { | 1506 | { |
1506 | int n, i; | 1507 | int n, i; |
1507 | Elf32_Word shndx; | 1508 | Elf32_Word shndx; |
@@ -1530,6 +1531,8 @@ static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs) | |||
1530 | if (!shdr) | 1531 | if (!shdr) |
1531 | return -ENOENT; | 1532 | return -ENOENT; |
1532 | *offs = shdr->sh_addr; | 1533 | *offs = shdr->sh_addr; |
1534 | if (adjust_offset) | ||
1535 | *offs -= shdr->sh_offset; | ||
1533 | } | 1536 | } |
1534 | } | 1537 | } |
1535 | return 0; | 1538 | return 0; |
@@ -1543,16 +1546,12 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | |||
1543 | Dwarf_Addr _addr = 0, baseaddr = 0; | 1546 | Dwarf_Addr _addr = 0, baseaddr = 0; |
1544 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; | 1547 | const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; |
1545 | int baseline = 0, lineno = 0, ret = 0; | 1548 | int baseline = 0, lineno = 0, ret = 0; |
1546 | bool reloc = false; | ||
1547 | 1549 | ||
1548 | retry: | 1550 | /* We always need to relocate the address for aranges */ |
1551 | if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0) | ||
1552 | addr += baseaddr; | ||
1549 | /* Find cu die */ | 1553 | /* Find cu die */ |
1550 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { | 1554 | if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { |
1551 | if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) { | ||
1552 | addr += baseaddr; | ||
1553 | reloc = true; | ||
1554 | goto retry; | ||
1555 | } | ||
1556 | pr_warning("Failed to find debug information for address %lx\n", | 1555 | pr_warning("Failed to find debug information for address %lx\n", |
1557 | addr); | 1556 | addr); |
1558 | ret = -EINVAL; | 1557 | ret = -EINVAL; |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index f1d8558f498e..2956c5198652 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -46,6 +46,9 @@ int debuginfo__find_trace_events(struct debuginfo *dbg, | |||
46 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, | 46 | int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, |
47 | struct perf_probe_point *ppt); | 47 | struct perf_probe_point *ppt); |
48 | 48 | ||
49 | int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs, | ||
50 | bool adjust_offset); | ||
51 | |||
49 | /* Find a line range */ | 52 | /* Find a line range */ |
50 | int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); | 53 | int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr); |
51 | 54 | ||
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 99400b0e8f2a..adbc6c02c3aa 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -537,6 +537,12 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size) | |||
537 | break; | 537 | break; |
538 | } else { | 538 | } else { |
539 | int n = namesz + descsz; | 539 | int n = namesz + descsz; |
540 | |||
541 | if (n > (int)sizeof(bf)) { | ||
542 | n = sizeof(bf); | ||
543 | pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n", | ||
544 | __func__, filename, nhdr.n_namesz, nhdr.n_descsz); | ||
545 | } | ||
540 | if (read(fd, bf, n) != n) | 546 | if (read(fd, bf, n) != n) |
541 | break; | 547 | break; |
542 | } | 548 | } |
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index 71b05891a6a1..831022b12848 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile | |||
@@ -90,7 +90,7 @@ ifdef INSTALL_PATH | |||
90 | done; | 90 | done; |
91 | 91 | ||
92 | @# Ask all targets to emit their test scripts | 92 | @# Ask all targets to emit their test scripts |
93 | echo "#!/bin/bash" > $(ALL_SCRIPT) | 93 | echo "#!/bin/sh" > $(ALL_SCRIPT) |
94 | echo "cd \$$(dirname \$$0)" >> $(ALL_SCRIPT) | 94 | echo "cd \$$(dirname \$$0)" >> $(ALL_SCRIPT) |
95 | echo "ROOT=\$$PWD" >> $(ALL_SCRIPT) | 95 | echo "ROOT=\$$PWD" >> $(ALL_SCRIPT) |
96 | 96 | ||
diff --git a/tools/testing/selftests/bpf/test_kmod.sh b/tools/testing/selftests/bpf/test_kmod.sh index 92e627adf354..6d58cca8e235 100755 --- a/tools/testing/selftests/bpf/test_kmod.sh +++ b/tools/testing/selftests/bpf/test_kmod.sh | |||
@@ -1,4 +1,4 @@ | |||
1 | #!/bin/bash | 1 | #!/bin/sh |
2 | 2 | ||
3 | SRC_TREE=../../../../ | 3 | SRC_TREE=../../../../ |
4 | 4 | ||
diff --git a/tools/testing/selftests/bpf/test_lru_map.c b/tools/testing/selftests/bpf/test_lru_map.c index b13fed534d76..9f7bd1915c21 100644 --- a/tools/testing/selftests/bpf/test_lru_map.c +++ b/tools/testing/selftests/bpf/test_lru_map.c | |||
@@ -67,21 +67,23 @@ static int map_equal(int lru_map, int expected) | |||
67 | return map_subset(lru_map, expected) && map_subset(expected, lru_map); | 67 | return map_subset(lru_map, expected) && map_subset(expected, lru_map); |
68 | } | 68 | } |
69 | 69 | ||
70 | static int sched_next_online(int pid, int next_to_try) | 70 | static int sched_next_online(int pid, int *next_to_try) |
71 | { | 71 | { |
72 | cpu_set_t cpuset; | 72 | cpu_set_t cpuset; |
73 | int next = *next_to_try; | ||
74 | int ret = -1; | ||
73 | 75 | ||
74 | if (next_to_try == nr_cpus) | 76 | while (next < nr_cpus) { |
75 | return -1; | ||
76 | |||
77 | while (next_to_try < nr_cpus) { | ||
78 | CPU_ZERO(&cpuset); | 77 | CPU_ZERO(&cpuset); |
79 | CPU_SET(next_to_try++, &cpuset); | 78 | CPU_SET(next++, &cpuset); |
80 | if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) | 79 | if (!sched_setaffinity(pid, sizeof(cpuset), &cpuset)) { |
80 | ret = 0; | ||
81 | break; | 81 | break; |
82 | } | ||
82 | } | 83 | } |
83 | 84 | ||
84 | return next_to_try; | 85 | *next_to_try = next; |
86 | return ret; | ||
85 | } | 87 | } |
86 | 88 | ||
87 | /* Size of the LRU amp is 2 | 89 | /* Size of the LRU amp is 2 |
@@ -96,11 +98,12 @@ static void test_lru_sanity0(int map_type, int map_flags) | |||
96 | { | 98 | { |
97 | unsigned long long key, value[nr_cpus]; | 99 | unsigned long long key, value[nr_cpus]; |
98 | int lru_map_fd, expected_map_fd; | 100 | int lru_map_fd, expected_map_fd; |
101 | int next_cpu = 0; | ||
99 | 102 | ||
100 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 103 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
101 | map_flags); | 104 | map_flags); |
102 | 105 | ||
103 | assert(sched_next_online(0, 0) != -1); | 106 | assert(sched_next_online(0, &next_cpu) != -1); |
104 | 107 | ||
105 | if (map_flags & BPF_F_NO_COMMON_LRU) | 108 | if (map_flags & BPF_F_NO_COMMON_LRU) |
106 | lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus); | 109 | lru_map_fd = create_map(map_type, map_flags, 2 * nr_cpus); |
@@ -183,6 +186,7 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free) | |||
183 | int lru_map_fd, expected_map_fd; | 186 | int lru_map_fd, expected_map_fd; |
184 | unsigned int batch_size; | 187 | unsigned int batch_size; |
185 | unsigned int map_size; | 188 | unsigned int map_size; |
189 | int next_cpu = 0; | ||
186 | 190 | ||
187 | if (map_flags & BPF_F_NO_COMMON_LRU) | 191 | if (map_flags & BPF_F_NO_COMMON_LRU) |
188 | /* Ther percpu lru list (i.e each cpu has its own LRU | 192 | /* Ther percpu lru list (i.e each cpu has its own LRU |
@@ -196,7 +200,7 @@ static void test_lru_sanity1(int map_type, int map_flags, unsigned int tgt_free) | |||
196 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 200 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
197 | map_flags); | 201 | map_flags); |
198 | 202 | ||
199 | assert(sched_next_online(0, 0) != -1); | 203 | assert(sched_next_online(0, &next_cpu) != -1); |
200 | 204 | ||
201 | batch_size = tgt_free / 2; | 205 | batch_size = tgt_free / 2; |
202 | assert(batch_size * 2 == tgt_free); | 206 | assert(batch_size * 2 == tgt_free); |
@@ -262,6 +266,7 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free) | |||
262 | int lru_map_fd, expected_map_fd; | 266 | int lru_map_fd, expected_map_fd; |
263 | unsigned int batch_size; | 267 | unsigned int batch_size; |
264 | unsigned int map_size; | 268 | unsigned int map_size; |
269 | int next_cpu = 0; | ||
265 | 270 | ||
266 | if (map_flags & BPF_F_NO_COMMON_LRU) | 271 | if (map_flags & BPF_F_NO_COMMON_LRU) |
267 | /* Ther percpu lru list (i.e each cpu has its own LRU | 272 | /* Ther percpu lru list (i.e each cpu has its own LRU |
@@ -275,7 +280,7 @@ static void test_lru_sanity2(int map_type, int map_flags, unsigned int tgt_free) | |||
275 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 280 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
276 | map_flags); | 281 | map_flags); |
277 | 282 | ||
278 | assert(sched_next_online(0, 0) != -1); | 283 | assert(sched_next_online(0, &next_cpu) != -1); |
279 | 284 | ||
280 | batch_size = tgt_free / 2; | 285 | batch_size = tgt_free / 2; |
281 | assert(batch_size * 2 == tgt_free); | 286 | assert(batch_size * 2 == tgt_free); |
@@ -370,11 +375,12 @@ static void test_lru_sanity3(int map_type, int map_flags, unsigned int tgt_free) | |||
370 | int lru_map_fd, expected_map_fd; | 375 | int lru_map_fd, expected_map_fd; |
371 | unsigned int batch_size; | 376 | unsigned int batch_size; |
372 | unsigned int map_size; | 377 | unsigned int map_size; |
378 | int next_cpu = 0; | ||
373 | 379 | ||
374 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 380 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
375 | map_flags); | 381 | map_flags); |
376 | 382 | ||
377 | assert(sched_next_online(0, 0) != -1); | 383 | assert(sched_next_online(0, &next_cpu) != -1); |
378 | 384 | ||
379 | batch_size = tgt_free / 2; | 385 | batch_size = tgt_free / 2; |
380 | assert(batch_size * 2 == tgt_free); | 386 | assert(batch_size * 2 == tgt_free); |
@@ -430,11 +436,12 @@ static void test_lru_sanity4(int map_type, int map_flags, unsigned int tgt_free) | |||
430 | int lru_map_fd, expected_map_fd; | 436 | int lru_map_fd, expected_map_fd; |
431 | unsigned long long key, value[nr_cpus]; | 437 | unsigned long long key, value[nr_cpus]; |
432 | unsigned long long end_key; | 438 | unsigned long long end_key; |
439 | int next_cpu = 0; | ||
433 | 440 | ||
434 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, | 441 | printf("%s (map_type:%d map_flags:0x%X): ", __func__, map_type, |
435 | map_flags); | 442 | map_flags); |
436 | 443 | ||
437 | assert(sched_next_online(0, 0) != -1); | 444 | assert(sched_next_online(0, &next_cpu) != -1); |
438 | 445 | ||
439 | if (map_flags & BPF_F_NO_COMMON_LRU) | 446 | if (map_flags & BPF_F_NO_COMMON_LRU) |
440 | lru_map_fd = create_map(map_type, map_flags, | 447 | lru_map_fd = create_map(map_type, map_flags, |
@@ -502,9 +509,8 @@ static void do_test_lru_sanity5(unsigned long long last_key, int map_fd) | |||
502 | static void test_lru_sanity5(int map_type, int map_flags) | 509 | static void test_lru_sanity5(int map_type, int map_flags) |
503 | { | 510 | { |
504 | unsigned long long key, value[nr_cpus]; | 511 | unsigned long long key, value[nr_cpus]; |
505 | int next_sched_cpu = 0; | 512 | int next_cpu = 0; |
506 | int map_fd; | 513 | int map_fd; |
507 | int i; | ||
508 | 514 | ||
509 | if (map_flags & BPF_F_NO_COMMON_LRU) | 515 | if (map_flags & BPF_F_NO_COMMON_LRU) |
510 | return; | 516 | return; |
@@ -519,27 +525,20 @@ static void test_lru_sanity5(int map_type, int map_flags) | |||
519 | key = 0; | 525 | key = 0; |
520 | assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST)); | 526 | assert(!bpf_map_update(map_fd, &key, value, BPF_NOEXIST)); |
521 | 527 | ||
522 | for (i = 0; i < nr_cpus; i++) { | 528 | while (sched_next_online(0, &next_cpu) != -1) { |
523 | pid_t pid; | 529 | pid_t pid; |
524 | 530 | ||
525 | pid = fork(); | 531 | pid = fork(); |
526 | if (pid == 0) { | 532 | if (pid == 0) { |
527 | next_sched_cpu = sched_next_online(0, next_sched_cpu); | 533 | do_test_lru_sanity5(key, map_fd); |
528 | if (next_sched_cpu != -1) | ||
529 | do_test_lru_sanity5(key, map_fd); | ||
530 | exit(0); | 534 | exit(0); |
531 | } else if (pid == -1) { | 535 | } else if (pid == -1) { |
532 | printf("couldn't spawn #%d process\n", i); | 536 | printf("couldn't spawn process to test key:%llu\n", |
537 | key); | ||
533 | exit(1); | 538 | exit(1); |
534 | } else { | 539 | } else { |
535 | int status; | 540 | int status; |
536 | 541 | ||
537 | /* It is mostly redundant and just allow the parent | ||
538 | * process to update next_shced_cpu for the next child | ||
539 | * process | ||
540 | */ | ||
541 | next_sched_cpu = sched_next_online(pid, next_sched_cpu); | ||
542 | |||
543 | assert(waitpid(pid, &status, 0) == pid); | 542 | assert(waitpid(pid, &status, 0) == pid); |
544 | assert(status == 0); | 543 | assert(status == 0); |
545 | key++; | 544 | key++; |
@@ -547,6 +546,8 @@ static void test_lru_sanity5(int map_type, int map_flags) | |||
547 | } | 546 | } |
548 | 547 | ||
549 | close(map_fd); | 548 | close(map_fd); |
549 | /* At least one key should be tested */ | ||
550 | assert(key > 0); | ||
550 | 551 | ||
551 | printf("Pass\n"); | 552 | printf("Pass\n"); |
552 | } | 553 | } |
diff --git a/tools/testing/selftests/drivers/gpu/drm_mm.sh b/tools/testing/selftests/drivers/gpu/drm_mm.sh new file mode 100755 index 000000000000..96dd55c92799 --- /dev/null +++ b/tools/testing/selftests/drivers/gpu/drm_mm.sh | |||
@@ -0,0 +1,15 @@ | |||
1 | #!/bin/sh | ||
2 | # Runs API tests for struct drm_mm (DRM range manager) | ||
3 | |||
4 | if ! /sbin/modprobe -n -q test-drm_mm; then | ||
5 | echo "drivers/gpu/drm_mm: [skip]" | ||
6 | exit 77 | ||
7 | fi | ||
8 | |||
9 | if /sbin/modprobe -q test-drm_mm; then | ||
10 | /sbin/modprobe -q -r test-drm_mm | ||
11 | echo "drivers/gpu/drm_mm: ok" | ||
12 | else | ||
13 | echo "drivers/gpu/drm_mm: [FAIL]" | ||
14 | exit 1 | ||
15 | fi | ||
diff --git a/tools/testing/selftests/lib/prime_numbers.sh b/tools/testing/selftests/lib/prime_numbers.sh new file mode 100755 index 000000000000..da4cbcd766f5 --- /dev/null +++ b/tools/testing/selftests/lib/prime_numbers.sh | |||
@@ -0,0 +1,15 @@ | |||
1 | #!/bin/sh | ||
2 | # Checks fast/slow prime_number generation for inconsistencies | ||
3 | |||
4 | if ! /sbin/modprobe -q -r prime_numbers; then | ||
5 | echo "prime_numbers: [SKIP]" | ||
6 | exit 77 | ||
7 | fi | ||
8 | |||
9 | if /sbin/modprobe -q prime_numbers selftest=65536; then | ||
10 | /sbin/modprobe -q -r prime_numbers | ||
11 | echo "prime_numbers: ok" | ||
12 | else | ||
13 | echo "prime_numbers: [FAIL]" | ||
14 | exit 1 | ||
15 | fi | ||
diff --git a/tools/testing/selftests/net/run_netsocktests b/tools/testing/selftests/net/run_netsocktests index c09a682df56a..16058bbea7a8 100755 --- a/tools/testing/selftests/net/run_netsocktests +++ b/tools/testing/selftests/net/run_netsocktests | |||
@@ -1,4 +1,4 @@ | |||
1 | #!/bin/bash | 1 | #!/bin/sh |
2 | 2 | ||
3 | echo "--------------------" | 3 | echo "--------------------" |
4 | echo "running socket test" | 4 | echo "running socket test" |
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c b/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c index c22860ab9733..30e1ac62e8cb 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c +++ b/tools/testing/selftests/powerpc/pmu/ebb/pmc56_overflow_test.c | |||
@@ -66,7 +66,7 @@ int pmc56_overflow(void) | |||
66 | 66 | ||
67 | FAIL_IF(ebb_event_enable(&event)); | 67 | FAIL_IF(ebb_event_enable(&event)); |
68 | 68 | ||
69 | mtspr(SPRN_PMC1, pmc_sample_period(sample_period)); | 69 | mtspr(SPRN_PMC2, pmc_sample_period(sample_period)); |
70 | mtspr(SPRN_PMC5, 0); | 70 | mtspr(SPRN_PMC5, 0); |
71 | mtspr(SPRN_PMC6, 0); | 71 | mtspr(SPRN_PMC6, 0); |
72 | 72 | ||
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c index bdd58c78902e..df9e0a0cdf29 100644 --- a/tools/testing/selftests/x86/protection_keys.c +++ b/tools/testing/selftests/x86/protection_keys.c | |||
@@ -1367,7 +1367,7 @@ void run_tests_once(void) | |||
1367 | tracing_off(); | 1367 | tracing_off(); |
1368 | close_test_fds(); | 1368 | close_test_fds(); |
1369 | 1369 | ||
1370 | printf("test %2d PASSED (itertation %d)\n", test_nr, iteration_nr); | 1370 | printf("test %2d PASSED (iteration %d)\n", test_nr, iteration_nr); |
1371 | dprintf1("======================\n\n"); | 1371 | dprintf1("======================\n\n"); |
1372 | } | 1372 | } |
1373 | iteration_nr++; | 1373 | iteration_nr++; |
diff --git a/tools/virtio/ringtest/main.h b/tools/virtio/ringtest/main.h index 34e63cc4c572..14142faf040b 100644 --- a/tools/virtio/ringtest/main.h +++ b/tools/virtio/ringtest/main.h | |||
@@ -26,6 +26,16 @@ static inline void wait_cycles(unsigned long long cycles) | |||
26 | #define VMEXIT_CYCLES 500 | 26 | #define VMEXIT_CYCLES 500 |
27 | #define VMENTRY_CYCLES 500 | 27 | #define VMENTRY_CYCLES 500 |
28 | 28 | ||
29 | #elif defined(__s390x__) | ||
30 | static inline void wait_cycles(unsigned long long cycles) | ||
31 | { | ||
32 | asm volatile("0: brctg %0,0b" : : "d" (cycles)); | ||
33 | } | ||
34 | |||
35 | /* tweak me */ | ||
36 | #define VMEXIT_CYCLES 200 | ||
37 | #define VMENTRY_CYCLES 200 | ||
38 | |||
29 | #else | 39 | #else |
30 | static inline void wait_cycles(unsigned long long cycles) | 40 | static inline void wait_cycles(unsigned long long cycles) |
31 | { | 41 | { |
@@ -81,6 +91,8 @@ extern unsigned ring_size; | |||
81 | /* Is there a portable way to do this? */ | 91 | /* Is there a portable way to do this? */ |
82 | #if defined(__x86_64__) || defined(__i386__) | 92 | #if defined(__x86_64__) || defined(__i386__) |
83 | #define cpu_relax() asm ("rep; nop" ::: "memory") | 93 | #define cpu_relax() asm ("rep; nop" ::: "memory") |
94 | #elif defined(__s390x__) | ||
95 | #define cpu_relax() barrier() | ||
84 | #else | 96 | #else |
85 | #define cpu_relax() assert(0) | 97 | #define cpu_relax() assert(0) |
86 | #endif | 98 | #endif |
diff --git a/tools/virtio/ringtest/run-on-all.sh b/tools/virtio/ringtest/run-on-all.sh index 2e69ca812b4c..29b0d3920bfc 100755 --- a/tools/virtio/ringtest/run-on-all.sh +++ b/tools/virtio/ringtest/run-on-all.sh | |||
@@ -1,12 +1,13 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | CPUS_ONLINE=$(lscpu --online -p=cpu|grep -v -e '#') | ||
3 | #use last CPU for host. Why not the first? | 4 | #use last CPU for host. Why not the first? |
4 | #many devices tend to use cpu0 by default so | 5 | #many devices tend to use cpu0 by default so |
5 | #it tends to be busier | 6 | #it tends to be busier |
6 | HOST_AFFINITY=$(lscpu -p=cpu | tail -1) | 7 | HOST_AFFINITY=$(echo "${CPUS_ONLINE}"|tail -n 1) |
7 | 8 | ||
8 | #run command on all cpus | 9 | #run command on all cpus |
9 | for cpu in $(seq 0 $HOST_AFFINITY) | 10 | for cpu in $CPUS_ONLINE |
10 | do | 11 | do |
11 | #Don't run guest and host on same CPU | 12 | #Don't run guest and host on same CPU |
12 | #It actually works ok if using signalling | 13 | #It actually works ok if using signalling |