aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2013-08-12 04:14:47 -0400
committerIngo Molnar <mingo@kernel.org>2013-08-12 04:14:47 -0400
commit0a3d23a2568ed5e73bd4fb532dc672fa9f03b1f1 (patch)
treee1b8974fc17cf810209d2b76d4d76ce1ab46d0b0 /tools/perf
parent93786a5f6aeb9c032c1c240246c5aabcf457b38f (diff)
parentcecb977e24da1465cdb0ff2d10d22e5891dc3e6c (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Do annotation using /proc/kcore and /proc/kallsyms, removing the need for a vmlinux file kernel assembly annotation. This also improves this use case because vmlinux has just the initial kernel image, not what is actually in use after various code patchings by things like alternatives, etc. From Adrian Hunter. * Add various improvements and fixes to the "vmlinux matches kallsyms" 'perf test' entry, related to the /proc/kcore annotation feature. * Add --initial-delay option to 'perf stat' to skip measuring for the startup phase, from Andi Kleen. * Add perf kvm stat live mode that combines aspects of 'perf kvm stat' record and report, from David Ahern. * Add option to analyze specific VM in perf kvm stat report, from David Ahern. * Do not require /lib/modules/* on a guest, fix from Jason Wessel. * Group leader sampling, that allows just one event in a group to sample while the other events have just its values read, from Jiri Olsa. * Add support for a new modifier "D", which requests that the event, or group of events, be pinned to the PMU, from Michael Ellerman. * Fix segmentation fault on the gtk browser, from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Documentation/perf-list.txt2
-rw-r--r--tools/perf/Documentation/perf-stat.txt5
-rw-r--r--tools/perf/Makefile1
-rw-r--r--tools/perf/arch/x86/util/tsc.c8
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-kvm.c732
-rw-r--r--tools/perf/builtin-script.c4
-rw-r--r--tools/perf/builtin-stat.c24
-rw-r--r--tools/perf/builtin-top.c5
-rw-r--r--tools/perf/builtin-trace.c1
-rwxr-xr-xtools/perf/python/twatch.py2
-rw-r--r--tools/perf/tests/attr/test-record-group-sampling36
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/code-reading.c573
-rw-r--r--tools/perf/tests/parse-events.c168
-rw-r--r--tools/perf/tests/tests.h1
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c36
-rw-r--r--tools/perf/ui/browsers/annotate.c20
-rw-r--r--tools/perf/ui/gtk/hists.c2
-rw-r--r--tools/perf/util/annotate.c60
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/dso.c10
-rw-r--r--tools/perf/util/dso.h17
-rw-r--r--tools/perf/util/event.c18
-rw-r--r--tools/perf/util/event.h18
-rw-r--r--tools/perf/util/evlist.c77
-rw-r--r--tools/perf/util/evlist.h4
-rw-r--r--tools/perf/util/evsel.c80
-rw-r--r--tools/perf/util/evsel.h5
-rw-r--r--tools/perf/util/machine.c25
-rw-r--r--tools/perf/util/map.c67
-rw-r--r--tools/perf/util/map.h13
-rw-r--r--tools/perf/util/parse-events.c17
-rw-r--r--tools/perf/util/parse-events.l3
-rw-r--r--tools/perf/util/session.c123
-rw-r--r--tools/perf/util/session.h5
-rw-r--r--tools/perf/util/stat.c6
-rw-r--r--tools/perf/util/stat.h9
-rw-r--r--tools/perf/util/symbol-elf.c174
-rw-r--r--tools/perf/util/symbol-minimal.c7
-rw-r--r--tools/perf/util/symbol.c273
-rw-r--r--tools/perf/util/symbol.h5
-rw-r--r--tools/perf/util/thread.h2
-rw-r--r--tools/perf/util/top.h2
-rw-r--r--tools/perf/util/unwind.c4
-rw-r--r--tools/perf/util/util.c33
-rw-r--r--tools/perf/util/util.h2
47 files changed, 2511 insertions, 176 deletions
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index 826f3d6d1d28..6fce6a622206 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -29,6 +29,8 @@ counted. The following modifiers exist:
29 G - guest counting (in KVM guests) 29 G - guest counting (in KVM guests)
30 H - host counting (not in KVM guests) 30 H - host counting (not in KVM guests)
31 p - precise level 31 p - precise level
32 S - read sample value (PERF_SAMPLE_READ)
33 D - pin the event to the PMU
32 34
33The 'p' modifier can be used for specifying how precise the instruction 35The 'p' modifier can be used for specifying how precise the instruction
34address should be. The 'p' modifier can be specified multiple times: 36address should be. The 'p' modifier can be specified multiple times:
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 2fe87fb558f0..73c9759005a3 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -132,6 +132,11 @@ is a useful mode to detect imbalance between physical cores. To enable this mod
132use --per-core in addition to -a. (system-wide). The output includes the 132use --per-core in addition to -a. (system-wide). The output includes the
133core number and the number of online logical processors on that physical processor. 133core number and the number of online logical processors on that physical processor.
134 134
135-D msecs::
136--initial-delay msecs::
137After starting the program, wait msecs before measuring. This is useful to
138filter out the startup phase of the program, which is often very different.
139
135EXAMPLES 140EXAMPLES
136-------- 141--------
137 142
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index bfd12d02a304..e0d3d9f96771 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -392,6 +392,7 @@ LIB_OBJS += $(OUTPUT)tests/sw-clock.o
392ifeq ($(ARCH),x86) 392ifeq ($(ARCH),x86)
393LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o 393LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o
394endif 394endif
395LIB_OBJS += $(OUTPUT)tests/code-reading.o
395 396
396BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o 397BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
397BUILTIN_OBJS += $(OUTPUT)builtin-bench.o 398BUILTIN_OBJS += $(OUTPUT)builtin-bench.o
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index f1117441cdcd..9570c2b0f83c 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -10,11 +10,11 @@
10 10
11u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc) 11u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc)
12{ 12{
13 u64 time, quot, rem; 13 u64 t, quot, rem;
14 14
15 time = ns - tc->time_zero; 15 t = ns - tc->time_zero;
16 quot = time / tc->time_mult; 16 quot = t / tc->time_mult;
17 rem = time % tc->time_mult; 17 rem = t % tc->time_mult;
18 return (quot << tc->time_shift) + 18 return (quot << tc->time_shift) +
19 (rem << tc->time_shift) / tc->time_mult; 19 (rem << tc->time_shift) / tc->time_mult;
20} 20}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 1d8de2e4a407..f012a98c726c 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -206,7 +206,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
206 } 206 }
207 207
208 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 208 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
209 event->ip.ip, &al); 209 event->ip.ip, &al, NULL);
210 210
211 if (al.map != NULL) { 211 if (al.map != NULL) {
212 if (!al.map->dso->hit) { 212 if (!al.map->dso->hit) {
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 24b78aecc928..2ceec817a2fb 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -2,22 +2,26 @@
2#include "perf.h" 2#include "perf.h"
3 3
4#include "util/evsel.h" 4#include "util/evsel.h"
5#include "util/evlist.h"
5#include "util/util.h" 6#include "util/util.h"
6#include "util/cache.h" 7#include "util/cache.h"
7#include "util/symbol.h" 8#include "util/symbol.h"
8#include "util/thread.h" 9#include "util/thread.h"
9#include "util/header.h" 10#include "util/header.h"
10#include "util/session.h" 11#include "util/session.h"
11 12#include "util/intlist.h"
12#include "util/parse-options.h" 13#include "util/parse-options.h"
13#include "util/trace-event.h" 14#include "util/trace-event.h"
14#include "util/debug.h" 15#include "util/debug.h"
15#include <lk/debugfs.h> 16#include <lk/debugfs.h>
16#include "util/tool.h" 17#include "util/tool.h"
17#include "util/stat.h" 18#include "util/stat.h"
19#include "util/top.h"
18 20
19#include <sys/prctl.h> 21#include <sys/prctl.h>
22#include <sys/timerfd.h>
20 23
24#include <termios.h>
21#include <semaphore.h> 25#include <semaphore.h>
22#include <pthread.h> 26#include <pthread.h>
23#include <math.h> 27#include <math.h>
@@ -82,6 +86,8 @@ struct exit_reasons_table {
82 86
83struct perf_kvm_stat { 87struct perf_kvm_stat {
84 struct perf_tool tool; 88 struct perf_tool tool;
89 struct perf_record_opts opts;
90 struct perf_evlist *evlist;
85 struct perf_session *session; 91 struct perf_session *session;
86 92
87 const char *file_name; 93 const char *file_name;
@@ -96,10 +102,19 @@ struct perf_kvm_stat {
96 struct kvm_events_ops *events_ops; 102 struct kvm_events_ops *events_ops;
97 key_cmp_fun compare; 103 key_cmp_fun compare;
98 struct list_head kvm_events_cache[EVENTS_CACHE_SIZE]; 104 struct list_head kvm_events_cache[EVENTS_CACHE_SIZE];
105
99 u64 total_time; 106 u64 total_time;
100 u64 total_count; 107 u64 total_count;
108 u64 lost_events;
109
110 const char *pid_str;
111 struct intlist *pid_list;
101 112
102 struct rb_root result; 113 struct rb_root result;
114
115 int timerfd;
116 unsigned int display_time;
117 bool live;
103}; 118};
104 119
105 120
@@ -320,6 +335,28 @@ static void init_kvm_event_record(struct perf_kvm_stat *kvm)
320 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]); 335 INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
321} 336}
322 337
338static void clear_events_cache_stats(struct list_head *kvm_events_cache)
339{
340 struct list_head *head;
341 struct kvm_event *event;
342 unsigned int i;
343 int j;
344
345 for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
346 head = &kvm_events_cache[i];
347 list_for_each_entry(event, head, hash_entry) {
348 /* reset stats for event */
349 event->total.time = 0;
350 init_stats(&event->total.stats);
351
352 for (j = 0; j < event->max_vcpu; ++j) {
353 event->vcpu[j].time = 0;
354 init_stats(&event->vcpu[j].stats);
355 }
356 }
357 }
358}
359
323static int kvm_events_hash_fn(u64 key) 360static int kvm_events_hash_fn(u64 key)
324{ 361{
325 return key & (EVENTS_CACHE_SIZE - 1); 362 return key & (EVENTS_CACHE_SIZE - 1);
@@ -472,7 +509,11 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
472 vcpu_record->last_event = NULL; 509 vcpu_record->last_event = NULL;
473 vcpu_record->start_time = 0; 510 vcpu_record->start_time = 0;
474 511
475 BUG_ON(timestamp < time_begin); 512 /* seems to happen once in a while during live mode */
513 if (timestamp < time_begin) {
514 pr_debug("End time before begin time; skipping event.\n");
515 return true;
516 }
476 517
477 time_diff = timestamp - time_begin; 518 time_diff = timestamp - time_begin;
478 return update_kvm_event(event, vcpu, time_diff); 519 return update_kvm_event(event, vcpu, time_diff);
@@ -550,6 +591,8 @@ static int compare_kvm_event_ ## func(struct kvm_event *one, \
550GET_EVENT_KEY(time, time); 591GET_EVENT_KEY(time, time);
551COMPARE_EVENT_KEY(count, stats.n); 592COMPARE_EVENT_KEY(count, stats.n);
552COMPARE_EVENT_KEY(mean, stats.mean); 593COMPARE_EVENT_KEY(mean, stats.mean);
594GET_EVENT_KEY(max, stats.max);
595GET_EVENT_KEY(min, stats.min);
553 596
554#define DEF_SORT_NAME_KEY(name, compare_key) \ 597#define DEF_SORT_NAME_KEY(name, compare_key) \
555 { #name, compare_kvm_event_ ## compare_key } 598 { #name, compare_kvm_event_ ## compare_key }
@@ -639,43 +682,81 @@ static struct kvm_event *pop_from_result(struct rb_root *result)
639 return container_of(node, struct kvm_event, rb); 682 return container_of(node, struct kvm_event, rb);
640} 683}
641 684
642static void print_vcpu_info(int vcpu) 685static void print_vcpu_info(struct perf_kvm_stat *kvm)
643{ 686{
687 int vcpu = kvm->trace_vcpu;
688
644 pr_info("Analyze events for "); 689 pr_info("Analyze events for ");
645 690
691 if (kvm->live) {
692 if (kvm->opts.target.system_wide)
693 pr_info("all VMs, ");
694 else if (kvm->opts.target.pid)
695 pr_info("pid(s) %s, ", kvm->opts.target.pid);
696 else
697 pr_info("dazed and confused on what is monitored, ");
698 }
699
646 if (vcpu == -1) 700 if (vcpu == -1)
647 pr_info("all VCPUs:\n\n"); 701 pr_info("all VCPUs:\n\n");
648 else 702 else
649 pr_info("VCPU %d:\n\n", vcpu); 703 pr_info("VCPU %d:\n\n", vcpu);
650} 704}
651 705
706static void show_timeofday(void)
707{
708 char date[64];
709 struct timeval tv;
710 struct tm ltime;
711
712 gettimeofday(&tv, NULL);
713 if (localtime_r(&tv.tv_sec, &ltime)) {
714 strftime(date, sizeof(date), "%H:%M:%S", &ltime);
715 pr_info("%s.%06ld", date, tv.tv_usec);
716 } else
717 pr_info("00:00:00.000000");
718
719 return;
720}
721
652static void print_result(struct perf_kvm_stat *kvm) 722static void print_result(struct perf_kvm_stat *kvm)
653{ 723{
654 char decode[20]; 724 char decode[20];
655 struct kvm_event *event; 725 struct kvm_event *event;
656 int vcpu = kvm->trace_vcpu; 726 int vcpu = kvm->trace_vcpu;
657 727
728 if (kvm->live) {
729 puts(CONSOLE_CLEAR);
730 show_timeofday();
731 }
732
658 pr_info("\n\n"); 733 pr_info("\n\n");
659 print_vcpu_info(vcpu); 734 print_vcpu_info(kvm);
660 pr_info("%20s ", kvm->events_ops->name); 735 pr_info("%20s ", kvm->events_ops->name);
661 pr_info("%10s ", "Samples"); 736 pr_info("%10s ", "Samples");
662 pr_info("%9s ", "Samples%"); 737 pr_info("%9s ", "Samples%");
663 738
664 pr_info("%9s ", "Time%"); 739 pr_info("%9s ", "Time%");
740 pr_info("%10s ", "Min Time");
741 pr_info("%10s ", "Max Time");
665 pr_info("%16s ", "Avg time"); 742 pr_info("%16s ", "Avg time");
666 pr_info("\n\n"); 743 pr_info("\n\n");
667 744
668 while ((event = pop_from_result(&kvm->result))) { 745 while ((event = pop_from_result(&kvm->result))) {
669 u64 ecount, etime; 746 u64 ecount, etime, max, min;
670 747
671 ecount = get_event_count(event, vcpu); 748 ecount = get_event_count(event, vcpu);
672 etime = get_event_time(event, vcpu); 749 etime = get_event_time(event, vcpu);
750 max = get_event_max(event, vcpu);
751 min = get_event_min(event, vcpu);
673 752
674 kvm->events_ops->decode_key(kvm, &event->key, decode); 753 kvm->events_ops->decode_key(kvm, &event->key, decode);
675 pr_info("%20s ", decode); 754 pr_info("%20s ", decode);
676 pr_info("%10llu ", (unsigned long long)ecount); 755 pr_info("%10llu ", (unsigned long long)ecount);
677 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 756 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
678 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 757 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
758 pr_info("%8" PRIu64 "us ", min / 1000);
759 pr_info("%8" PRIu64 "us ", max / 1000);
679 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 760 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3,
680 kvm_event_rel_stddev(vcpu, event)); 761 kvm_event_rel_stddev(vcpu, event));
681 pr_info("\n"); 762 pr_info("\n");
@@ -683,6 +764,29 @@ static void print_result(struct perf_kvm_stat *kvm)
683 764
684 pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n", 765 pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
685 kvm->total_count, kvm->total_time / 1e3); 766 kvm->total_count, kvm->total_time / 1e3);
767
768 if (kvm->lost_events)
769 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
770}
771
772static int process_lost_event(struct perf_tool *tool,
773 union perf_event *event __maybe_unused,
774 struct perf_sample *sample __maybe_unused,
775 struct machine *machine __maybe_unused)
776{
777 struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat, tool);
778
779 kvm->lost_events++;
780 return 0;
781}
782
783static bool skip_sample(struct perf_kvm_stat *kvm,
784 struct perf_sample *sample)
785{
786 if (kvm->pid_list && intlist__find(kvm->pid_list, sample->pid) == NULL)
787 return true;
788
789 return false;
686} 790}
687 791
688static int process_sample_event(struct perf_tool *tool, 792static int process_sample_event(struct perf_tool *tool,
@@ -691,10 +795,14 @@ static int process_sample_event(struct perf_tool *tool,
691 struct perf_evsel *evsel, 795 struct perf_evsel *evsel,
692 struct machine *machine) 796 struct machine *machine)
693{ 797{
694 struct thread *thread = machine__findnew_thread(machine, sample->tid); 798 struct thread *thread;
695 struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat, 799 struct perf_kvm_stat *kvm = container_of(tool, struct perf_kvm_stat,
696 tool); 800 tool);
697 801
802 if (skip_sample(kvm, sample))
803 return 0;
804
805 thread = machine__findnew_thread(machine, sample->tid);
698 if (thread == NULL) { 806 if (thread == NULL) {
699 pr_debug("problem processing %d event, skipping it.\n", 807 pr_debug("problem processing %d event, skipping it.\n",
700 event->header.type); 808 event->header.type);
@@ -707,10 +815,20 @@ static int process_sample_event(struct perf_tool *tool,
707 return 0; 815 return 0;
708} 816}
709 817
710static int get_cpu_isa(struct perf_session *session) 818static int cpu_isa_config(struct perf_kvm_stat *kvm)
711{ 819{
712 char *cpuid = session->header.env.cpuid; 820 char buf[64], *cpuid;
713 int isa; 821 int err, isa;
822
823 if (kvm->live) {
824 err = get_cpuid(buf, sizeof(buf));
825 if (err != 0) {
826 pr_err("Failed to look up CPU type (Intel or AMD)\n");
827 return err;
828 }
829 cpuid = buf;
830 } else
831 cpuid = kvm->session->header.env.cpuid;
714 832
715 if (strstr(cpuid, "Intel")) 833 if (strstr(cpuid, "Intel"))
716 isa = 1; 834 isa = 1;
@@ -718,10 +836,361 @@ static int get_cpu_isa(struct perf_session *session)
718 isa = 0; 836 isa = 0;
719 else { 837 else {
720 pr_err("CPU %s is not supported.\n", cpuid); 838 pr_err("CPU %s is not supported.\n", cpuid);
721 isa = -ENOTSUP; 839 return -ENOTSUP;
840 }
841
842 if (isa == 1) {
843 kvm->exit_reasons = vmx_exit_reasons;
844 kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
845 kvm->exit_reasons_isa = "VMX";
846 }
847
848 return 0;
849}
850
851static bool verify_vcpu(int vcpu)
852{
853 if (vcpu != -1 && vcpu < 0) {
854 pr_err("Invalid vcpu:%d.\n", vcpu);
855 return false;
856 }
857
858 return true;
859}
860
861/* keeping the max events to a modest level to keep
862 * the processing of samples per mmap smooth.
863 */
864#define PERF_KVM__MAX_EVENTS_PER_MMAP 25
865
866static s64 perf_kvm__mmap_read_idx(struct perf_kvm_stat *kvm, int idx,
867 u64 *mmap_time)
868{
869 union perf_event *event;
870 struct perf_sample sample;
871 s64 n = 0;
872 int err;
873
874 *mmap_time = ULLONG_MAX;
875 while ((event = perf_evlist__mmap_read(kvm->evlist, idx)) != NULL) {
876 err = perf_evlist__parse_sample(kvm->evlist, event, &sample);
877 if (err) {
878 pr_err("Failed to parse sample\n");
879 return -1;
880 }
881
882 err = perf_session_queue_event(kvm->session, event, &sample, 0);
883 if (err) {
884 pr_err("Failed to enqueue sample: %d\n", err);
885 return -1;
886 }
887
888 /* save time stamp of our first sample for this mmap */
889 if (n == 0)
890 *mmap_time = sample.time;
891
892 /* limit events per mmap handled all at once */
893 n++;
894 if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
895 break;
896 }
897
898 return n;
899}
900
901static int perf_kvm__mmap_read(struct perf_kvm_stat *kvm)
902{
903 int i, err, throttled = 0;
904 s64 n, ntotal = 0;
905 u64 flush_time = ULLONG_MAX, mmap_time;
906
907 for (i = 0; i < kvm->evlist->nr_mmaps; i++) {
908 n = perf_kvm__mmap_read_idx(kvm, i, &mmap_time);
909 if (n < 0)
910 return -1;
911
912 /* flush time is going to be the minimum of all the individual
913 * mmap times. Essentially, we flush all the samples queued up
914 * from the last pass under our minimal start time -- that leaves
915 * a very small race for samples to come in with a lower timestamp.
916 * The ioctl to return the perf_clock timestamp should close the
917 * race entirely.
918 */
919 if (mmap_time < flush_time)
920 flush_time = mmap_time;
921
922 ntotal += n;
923 if (n == PERF_KVM__MAX_EVENTS_PER_MMAP)
924 throttled = 1;
925 }
926
927 /* flush queue after each round in which we processed events */
928 if (ntotal) {
929 kvm->session->ordered_samples.next_flush = flush_time;
930 err = kvm->tool.finished_round(&kvm->tool, NULL, kvm->session);
931 if (err) {
932 if (kvm->lost_events)
933 pr_info("\nLost events: %" PRIu64 "\n\n",
934 kvm->lost_events);
935 return err;
936 }
937 }
938
939 return throttled;
940}
941
942static volatile int done;
943
944static void sig_handler(int sig __maybe_unused)
945{
946 done = 1;
947}
948
949static int perf_kvm__timerfd_create(struct perf_kvm_stat *kvm)
950{
951 struct itimerspec new_value;
952 int rc = -1;
953
954 kvm->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
955 if (kvm->timerfd < 0) {
956 pr_err("timerfd_create failed\n");
957 goto out;
958 }
959
960 new_value.it_value.tv_sec = kvm->display_time;
961 new_value.it_value.tv_nsec = 0;
962 new_value.it_interval.tv_sec = kvm->display_time;
963 new_value.it_interval.tv_nsec = 0;
964
965 if (timerfd_settime(kvm->timerfd, 0, &new_value, NULL) != 0) {
966 pr_err("timerfd_settime failed: %d\n", errno);
967 close(kvm->timerfd);
968 goto out;
969 }
970
971 rc = 0;
972out:
973 return rc;
974}
975
976static int perf_kvm__handle_timerfd(struct perf_kvm_stat *kvm)
977{
978 uint64_t c;
979 int rc;
980
981 rc = read(kvm->timerfd, &c, sizeof(uint64_t));
982 if (rc < 0) {
983 if (errno == EAGAIN)
984 return 0;
985
986 pr_err("Failed to read timer fd: %d\n", errno);
987 return -1;
988 }
989
990 if (rc != sizeof(uint64_t)) {
991 pr_err("Error reading timer fd - invalid size returned\n");
992 return -1;
993 }
994
995 if (c != 1)
996 pr_debug("Missed timer beats: %" PRIu64 "\n", c-1);
997
998 /* update display */
999 sort_result(kvm);
1000 print_result(kvm);
1001
1002 /* reset counts */
1003 clear_events_cache_stats(kvm->kvm_events_cache);
1004 kvm->total_count = 0;
1005 kvm->total_time = 0;
1006 kvm->lost_events = 0;
1007
1008 return 0;
1009}
1010
1011static int fd_set_nonblock(int fd)
1012{
1013 long arg = 0;
1014
1015 arg = fcntl(fd, F_GETFL);
1016 if (arg < 0) {
1017 pr_err("Failed to get current flags for fd %d\n", fd);
1018 return -1;
1019 }
1020
1021 if (fcntl(fd, F_SETFL, arg | O_NONBLOCK) < 0) {
1022 pr_err("Failed to set non-block option on fd %d\n", fd);
1023 return -1;
1024 }
1025
1026 return 0;
1027}
1028
1029static
1030int perf_kvm__handle_stdin(struct termios *tc_now, struct termios *tc_save)
1031{
1032 int c;
1033
1034 tcsetattr(0, TCSANOW, tc_now);
1035 c = getc(stdin);
1036 tcsetattr(0, TCSAFLUSH, tc_save);
1037
1038 if (c == 'q')
1039 return 1;
1040
1041 return 0;
1042}
1043
1044static int kvm_events_live_report(struct perf_kvm_stat *kvm)
1045{
1046 struct pollfd *pollfds = NULL;
1047 int nr_fds, nr_stdin, ret, err = -EINVAL;
1048 struct termios tc, save;
1049
1050 /* live flag must be set first */
1051 kvm->live = true;
1052
1053 ret = cpu_isa_config(kvm);
1054 if (ret < 0)
1055 return ret;
1056
1057 if (!verify_vcpu(kvm->trace_vcpu) ||
1058 !select_key(kvm) ||
1059 !register_kvm_events_ops(kvm)) {
1060 goto out;
1061 }
1062
1063 init_kvm_event_record(kvm);
1064
1065 tcgetattr(0, &save);
1066 tc = save;
1067 tc.c_lflag &= ~(ICANON | ECHO);
1068 tc.c_cc[VMIN] = 0;
1069 tc.c_cc[VTIME] = 0;
1070
1071 signal(SIGINT, sig_handler);
1072 signal(SIGTERM, sig_handler);
1073
1074 /* copy pollfds -- need to add timerfd and stdin */
1075 nr_fds = kvm->evlist->nr_fds;
1076 pollfds = zalloc(sizeof(struct pollfd) * (nr_fds + 2));
1077 if (!pollfds) {
1078 err = -ENOMEM;
1079 goto out;
1080 }
1081 memcpy(pollfds, kvm->evlist->pollfd,
1082 sizeof(struct pollfd) * kvm->evlist->nr_fds);
1083
1084 /* add timer fd */
1085 if (perf_kvm__timerfd_create(kvm) < 0) {
1086 err = -1;
1087 goto out;
722 } 1088 }
723 1089
724 return isa; 1090 pollfds[nr_fds].fd = kvm->timerfd;
1091 pollfds[nr_fds].events = POLLIN;
1092 nr_fds++;
1093
1094 pollfds[nr_fds].fd = fileno(stdin);
1095 pollfds[nr_fds].events = POLLIN;
1096 nr_stdin = nr_fds;
1097 nr_fds++;
1098 if (fd_set_nonblock(fileno(stdin)) != 0)
1099 goto out;
1100
1101 /* everything is good - enable the events and process */
1102 perf_evlist__enable(kvm->evlist);
1103
1104 while (!done) {
1105 int rc;
1106
1107 rc = perf_kvm__mmap_read(kvm);
1108 if (rc < 0)
1109 break;
1110
1111 err = perf_kvm__handle_timerfd(kvm);
1112 if (err)
1113 goto out;
1114
1115 if (pollfds[nr_stdin].revents & POLLIN)
1116 done = perf_kvm__handle_stdin(&tc, &save);
1117
1118 if (!rc && !done)
1119 err = poll(pollfds, nr_fds, 100);
1120 }
1121
1122 perf_evlist__disable(kvm->evlist);
1123
1124 if (err == 0) {
1125 sort_result(kvm);
1126 print_result(kvm);
1127 }
1128
1129out:
1130 if (kvm->timerfd >= 0)
1131 close(kvm->timerfd);
1132
1133 if (pollfds)
1134 free(pollfds);
1135
1136 return err;
1137}
1138
1139static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1140{
1141 int err, rc = -1;
1142 struct perf_evsel *pos;
1143 struct perf_evlist *evlist = kvm->evlist;
1144
1145 perf_evlist__config(evlist, &kvm->opts);
1146
1147 /*
1148 * Note: exclude_{guest,host} do not apply here.
1149 * This command processes KVM tracepoints from host only
1150 */
1151 list_for_each_entry(pos, &evlist->entries, node) {
1152 struct perf_event_attr *attr = &pos->attr;
1153
1154 /* make sure these *are* set */
1155 attr->sample_type |= PERF_SAMPLE_TID;
1156 attr->sample_type |= PERF_SAMPLE_TIME;
1157 attr->sample_type |= PERF_SAMPLE_CPU;
1158 attr->sample_type |= PERF_SAMPLE_RAW;
1159 /* make sure these are *not*; want as small a sample as possible */
1160 attr->sample_type &= ~PERF_SAMPLE_PERIOD;
1161 attr->sample_type &= ~PERF_SAMPLE_IP;
1162 attr->sample_type &= ~PERF_SAMPLE_CALLCHAIN;
1163 attr->sample_type &= ~PERF_SAMPLE_ADDR;
1164 attr->sample_type &= ~PERF_SAMPLE_READ;
1165 attr->mmap = 0;
1166 attr->comm = 0;
1167 attr->task = 0;
1168
1169 attr->sample_period = 1;
1170
1171 attr->watermark = 0;
1172 attr->wakeup_events = 1000;
1173
1174 /* will enable all once we are ready */
1175 attr->disabled = 1;
1176 }
1177
1178 err = perf_evlist__open(evlist);
1179 if (err < 0) {
1180 printf("Couldn't create the events: %s\n", strerror(errno));
1181 goto out;
1182 }
1183
1184 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
1185 ui__error("Failed to mmap the events: %s\n", strerror(errno));
1186 perf_evlist__close(evlist);
1187 goto out;
1188 }
1189
1190 rc = 0;
1191
1192out:
1193 return rc;
725} 1194}
726 1195
727static int read_events(struct perf_kvm_stat *kvm) 1196static int read_events(struct perf_kvm_stat *kvm)
@@ -749,28 +1218,24 @@ static int read_events(struct perf_kvm_stat *kvm)
749 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not 1218 * Do not use 'isa' recorded in kvm_exit tracepoint since it is not
750 * traced in the old kernel. 1219 * traced in the old kernel.
751 */ 1220 */
752 ret = get_cpu_isa(kvm->session); 1221 ret = cpu_isa_config(kvm);
753
754 if (ret < 0) 1222 if (ret < 0)
755 return ret; 1223 return ret;
756 1224
757 if (ret == 1) {
758 kvm->exit_reasons = vmx_exit_reasons;
759 kvm->exit_reasons_size = ARRAY_SIZE(vmx_exit_reasons);
760 kvm->exit_reasons_isa = "VMX";
761 }
762
763 return perf_session__process_events(kvm->session, &kvm->tool); 1225 return perf_session__process_events(kvm->session, &kvm->tool);
764} 1226}
765 1227
766static bool verify_vcpu(int vcpu) 1228static int parse_target_str(struct perf_kvm_stat *kvm)
767{ 1229{
768 if (vcpu != -1 && vcpu < 0) { 1230 if (kvm->pid_str) {
769 pr_err("Invalid vcpu:%d.\n", vcpu); 1231 kvm->pid_list = intlist__new(kvm->pid_str);
770 return false; 1232 if (kvm->pid_list == NULL) {
1233 pr_err("Error parsing process id string\n");
1234 return -EINVAL;
1235 }
771 } 1236 }
772 1237
773 return true; 1238 return 0;
774} 1239}
775 1240
776static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm) 1241static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
@@ -778,6 +1243,9 @@ static int kvm_events_report_vcpu(struct perf_kvm_stat *kvm)
778 int ret = -EINVAL; 1243 int ret = -EINVAL;
779 int vcpu = kvm->trace_vcpu; 1244 int vcpu = kvm->trace_vcpu;
780 1245
1246 if (parse_target_str(kvm) != 0)
1247 goto exit;
1248
781 if (!verify_vcpu(vcpu)) 1249 if (!verify_vcpu(vcpu))
782 goto exit; 1250 goto exit;
783 1251
@@ -801,16 +1269,11 @@ exit:
801 return ret; 1269 return ret;
802} 1270}
803 1271
804static const char * const record_args[] = { 1272static const char * const kvm_events_tp[] = {
805 "record", 1273 "kvm:kvm_entry",
806 "-R", 1274 "kvm:kvm_exit",
807 "-f", 1275 "kvm:kvm_mmio",
808 "-m", "1024", 1276 "kvm:kvm_pio",
809 "-c", "1",
810 "-e", "kvm:kvm_entry",
811 "-e", "kvm:kvm_exit",
812 "-e", "kvm:kvm_mmio",
813 "-e", "kvm:kvm_pio",
814}; 1277};
815 1278
816#define STRDUP_FAIL_EXIT(s) \ 1279#define STRDUP_FAIL_EXIT(s) \
@@ -826,8 +1289,16 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
826{ 1289{
827 unsigned int rec_argc, i, j; 1290 unsigned int rec_argc, i, j;
828 const char **rec_argv; 1291 const char **rec_argv;
1292 const char * const record_args[] = {
1293 "record",
1294 "-R",
1295 "-f",
1296 "-m", "1024",
1297 "-c", "1",
1298 };
829 1299
830 rec_argc = ARRAY_SIZE(record_args) + argc + 2; 1300 rec_argc = ARRAY_SIZE(record_args) + argc + 2 +
1301 2 * ARRAY_SIZE(kvm_events_tp);
831 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 1302 rec_argv = calloc(rec_argc + 1, sizeof(char *));
832 1303
833 if (rec_argv == NULL) 1304 if (rec_argv == NULL)
@@ -836,6 +1307,11 @@ kvm_events_record(struct perf_kvm_stat *kvm, int argc, const char **argv)
836 for (i = 0; i < ARRAY_SIZE(record_args); i++) 1307 for (i = 0; i < ARRAY_SIZE(record_args); i++)
837 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]); 1308 rec_argv[i] = STRDUP_FAIL_EXIT(record_args[i]);
838 1309
1310 for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) {
1311 rec_argv[i++] = "-e";
1312 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm_events_tp[j]);
1313 }
1314
839 rec_argv[i++] = STRDUP_FAIL_EXIT("-o"); 1315 rec_argv[i++] = STRDUP_FAIL_EXIT("-o");
840 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name); 1316 rec_argv[i++] = STRDUP_FAIL_EXIT(kvm->file_name);
841 1317
@@ -856,6 +1332,8 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
856 OPT_STRING('k', "key", &kvm->sort_key, "sort-key", 1332 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
857 "key for sorting: sample(sort by samples number)" 1333 "key for sorting: sample(sort by samples number)"
858 " time (sort by avg time)"), 1334 " time (sort by avg time)"),
1335 OPT_STRING('p', "pid", &kvm->pid_str, "pid",
1336 "analyze events only for given process id(s)"),
859 OPT_END() 1337 OPT_END()
860 }; 1338 };
861 1339
@@ -878,6 +1356,186 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
878 return kvm_events_report_vcpu(kvm); 1356 return kvm_events_report_vcpu(kvm);
879} 1357}
880 1358
1359static struct perf_evlist *kvm_live_event_list(void)
1360{
1361 struct perf_evlist *evlist;
1362 char *tp, *name, *sys;
1363 unsigned int j;
1364 int err = -1;
1365
1366 evlist = perf_evlist__new();
1367 if (evlist == NULL)
1368 return NULL;
1369
1370 for (j = 0; j < ARRAY_SIZE(kvm_events_tp); j++) {
1371
1372 tp = strdup(kvm_events_tp[j]);
1373 if (tp == NULL)
1374 goto out;
1375
1376 /* split tracepoint into subsystem and name */
1377 sys = tp;
1378 name = strchr(tp, ':');
1379 if (name == NULL) {
1380 pr_err("Error parsing %s tracepoint: subsystem delimiter not found\n",
1381 kvm_events_tp[j]);
1382 free(tp);
1383 goto out;
1384 }
1385 *name = '\0';
1386 name++;
1387
1388 if (perf_evlist__add_newtp(evlist, sys, name, NULL)) {
1389 pr_err("Failed to add %s tracepoint to the list\n", kvm_events_tp[j]);
1390 free(tp);
1391 goto out;
1392 }
1393
1394 free(tp);
1395 }
1396
1397 err = 0;
1398
1399out:
1400 if (err) {
1401 perf_evlist__delete(evlist);
1402 evlist = NULL;
1403 }
1404
1405 return evlist;
1406}
1407
1408static int kvm_events_live(struct perf_kvm_stat *kvm,
1409 int argc, const char **argv)
1410{
1411 char errbuf[BUFSIZ];
1412 int err;
1413
1414 const struct option live_options[] = {
1415 OPT_STRING('p', "pid", &kvm->opts.target.pid, "pid",
1416 "record events on existing process id"),
1417 OPT_UINTEGER('m', "mmap-pages", &kvm->opts.mmap_pages,
1418 "number of mmap data pages"),
1419 OPT_INCR('v', "verbose", &verbose,
1420 "be more verbose (show counter open errors, etc)"),
1421 OPT_BOOLEAN('a', "all-cpus", &kvm->opts.target.system_wide,
1422 "system-wide collection from all CPUs"),
1423 OPT_UINTEGER('d', "display", &kvm->display_time,
1424 "time in seconds between display updates"),
1425 OPT_STRING(0, "event", &kvm->report_event, "report event",
1426 "event for reporting: vmexit, mmio, ioport"),
1427 OPT_INTEGER(0, "vcpu", &kvm->trace_vcpu,
1428 "vcpu id to report"),
1429 OPT_STRING('k', "key", &kvm->sort_key, "sort-key",
1430 "key for sorting: sample(sort by samples number)"
1431 " time (sort by avg time)"),
1432 OPT_END()
1433 };
1434 const char * const live_usage[] = {
1435 "perf kvm stat live [<options>]",
1436 NULL
1437 };
1438
1439
1440 /* event handling */
1441 kvm->tool.sample = process_sample_event;
1442 kvm->tool.comm = perf_event__process_comm;
1443 kvm->tool.exit = perf_event__process_exit;
1444 kvm->tool.fork = perf_event__process_fork;
1445 kvm->tool.lost = process_lost_event;
1446 kvm->tool.ordered_samples = true;
1447 perf_tool__fill_defaults(&kvm->tool);
1448
1449 /* set defaults */
1450 kvm->display_time = 1;
1451 kvm->opts.user_interval = 1;
1452 kvm->opts.mmap_pages = 512;
1453 kvm->opts.target.uses_mmap = false;
1454 kvm->opts.target.uid_str = NULL;
1455 kvm->opts.target.uid = UINT_MAX;
1456
1457 symbol__init();
1458 disable_buildid_cache();
1459
1460 use_browser = 0;
1461 setup_browser(false);
1462
1463 if (argc) {
1464 argc = parse_options(argc, argv, live_options,
1465 live_usage, 0);
1466 if (argc)
1467 usage_with_options(live_usage, live_options);
1468 }
1469
1470 /*
1471 * target related setups
1472 */
1473 err = perf_target__validate(&kvm->opts.target);
1474 if (err) {
1475 perf_target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ);
1476 ui__warning("%s", errbuf);
1477 }
1478
1479 if (perf_target__none(&kvm->opts.target))
1480 kvm->opts.target.system_wide = true;
1481
1482
1483 /*
1484 * generate the event list
1485 */
1486 kvm->evlist = kvm_live_event_list();
1487 if (kvm->evlist == NULL) {
1488 err = -1;
1489 goto out;
1490 }
1491
1492 symbol_conf.nr_events = kvm->evlist->nr_entries;
1493
1494 if (perf_evlist__create_maps(kvm->evlist, &kvm->opts.target) < 0)
1495 usage_with_options(live_usage, live_options);
1496
1497 /*
1498 * perf session
1499 */
1500 kvm->session = perf_session__new(NULL, O_WRONLY, false, false, &kvm->tool);
1501 if (kvm->session == NULL) {
1502 err = -ENOMEM;
1503 goto out;
1504 }
1505 kvm->session->evlist = kvm->evlist;
1506 perf_session__set_id_hdr_size(kvm->session);
1507
1508
1509 if (perf_target__has_task(&kvm->opts.target))
1510 perf_event__synthesize_thread_map(&kvm->tool,
1511 kvm->evlist->threads,
1512 perf_event__process,
1513 &kvm->session->machines.host);
1514 else
1515 perf_event__synthesize_threads(&kvm->tool, perf_event__process,
1516 &kvm->session->machines.host);
1517
1518
1519 err = kvm_live_open_events(kvm);
1520 if (err)
1521 goto out;
1522
1523 err = kvm_events_live_report(kvm);
1524
1525out:
1526 exit_browser(0);
1527
1528 if (kvm->session)
1529 perf_session__delete(kvm->session);
1530 kvm->session = NULL;
1531 if (kvm->evlist) {
1532 perf_evlist__delete_maps(kvm->evlist);
1533 perf_evlist__delete(kvm->evlist);
1534 }
1535
1536 return err;
1537}
1538
881static void print_kvm_stat_usage(void) 1539static void print_kvm_stat_usage(void)
882{ 1540{
883 printf("Usage: perf kvm stat <command>\n\n"); 1541 printf("Usage: perf kvm stat <command>\n\n");
@@ -885,6 +1543,7 @@ static void print_kvm_stat_usage(void)
885 printf("# Available commands:\n"); 1543 printf("# Available commands:\n");
886 printf("\trecord: record kvm events\n"); 1544 printf("\trecord: record kvm events\n");
887 printf("\treport: report statistical data of kvm events\n"); 1545 printf("\treport: report statistical data of kvm events\n");
1546 printf("\tlive: live reporting of statistical data of kvm events\n");
888 1547
889 printf("\nOtherwise, it is the alias of 'perf stat':\n"); 1548 printf("\nOtherwise, it is the alias of 'perf stat':\n");
890} 1549}
@@ -914,6 +1573,9 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
914 if (!strncmp(argv[1], "rep", 3)) 1573 if (!strncmp(argv[1], "rep", 3))
915 return kvm_events_report(&kvm, argc - 1 , argv + 1); 1574 return kvm_events_report(&kvm, argc - 1 , argv + 1);
916 1575
1576 if (!strncmp(argv[1], "live", 4))
1577 return kvm_events_live(&kvm, argc - 1 , argv + 1);
1578
917perf_stat: 1579perf_stat:
918 return cmd_stat(argc, argv, NULL); 1580 return cmd_stat(argc, argv, NULL);
919} 1581}
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 1cad37014673..cd616ff5d221 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -341,10 +341,10 @@ static void print_sample_addr(union perf_event *event,
341 return; 341 return;
342 342
343 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 343 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
344 sample->addr, &al); 344 sample->addr, &al, NULL);
345 if (!al.map) 345 if (!al.map)
346 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE, 346 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
347 sample->addr, &al); 347 sample->addr, &al, NULL);
348 348
349 al.cpu = sample->cpu; 349 al.cpu = sample->cpu;
350 al.sym = NULL; 350 al.sym = NULL;
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 352fbd7ff4a1..f686d5ff594e 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -100,6 +100,7 @@ static const char *pre_cmd = NULL;
100static const char *post_cmd = NULL; 100static const char *post_cmd = NULL;
101static bool sync_run = false; 101static bool sync_run = false;
102static unsigned int interval = 0; 102static unsigned int interval = 0;
103static unsigned int initial_delay = 0;
103static bool forever = false; 104static bool forever = false;
104static struct timespec ref_time; 105static struct timespec ref_time;
105static struct cpu_map *aggr_map; 106static struct cpu_map *aggr_map;
@@ -254,7 +255,8 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
254 if (!perf_target__has_task(&target) && 255 if (!perf_target__has_task(&target) &&
255 perf_evsel__is_group_leader(evsel)) { 256 perf_evsel__is_group_leader(evsel)) {
256 attr->disabled = 1; 257 attr->disabled = 1;
257 attr->enable_on_exec = 1; 258 if (!initial_delay)
259 attr->enable_on_exec = 1;
258 } 260 }
259 261
260 return perf_evsel__open_per_thread(evsel, evsel_list->threads); 262 return perf_evsel__open_per_thread(evsel, evsel_list->threads);
@@ -414,6 +416,22 @@ static void print_interval(void)
414 list_for_each_entry(counter, &evsel_list->entries, node) 416 list_for_each_entry(counter, &evsel_list->entries, node)
415 print_counter_aggr(counter, prefix); 417 print_counter_aggr(counter, prefix);
416 } 418 }
419
420 fflush(output);
421}
422
423static void handle_initial_delay(void)
424{
425 struct perf_evsel *counter;
426
427 if (initial_delay) {
428 const int ncpus = cpu_map__nr(evsel_list->cpus),
429 nthreads = thread_map__nr(evsel_list->threads);
430
431 usleep(initial_delay * 1000);
432 list_for_each_entry(counter, &evsel_list->entries, node)
433 perf_evsel__enable(counter, ncpus, nthreads);
434 }
417} 435}
418 436
419static int __run_perf_stat(int argc, const char **argv) 437static int __run_perf_stat(int argc, const char **argv)
@@ -486,6 +504,7 @@ static int __run_perf_stat(int argc, const char **argv)
486 504
487 if (forks) { 505 if (forks) {
488 perf_evlist__start_workload(evsel_list); 506 perf_evlist__start_workload(evsel_list);
507 handle_initial_delay();
489 508
490 if (interval) { 509 if (interval) {
491 while (!waitpid(child_pid, &status, WNOHANG)) { 510 while (!waitpid(child_pid, &status, WNOHANG)) {
@@ -497,6 +516,7 @@ static int __run_perf_stat(int argc, const char **argv)
497 if (WIFSIGNALED(status)) 516 if (WIFSIGNALED(status))
498 psignal(WTERMSIG(status), argv[0]); 517 psignal(WTERMSIG(status), argv[0]);
499 } else { 518 } else {
519 handle_initial_delay();
500 while (!done) { 520 while (!done) {
501 nanosleep(&ts, NULL); 521 nanosleep(&ts, NULL);
502 if (interval) 522 if (interval)
@@ -1419,6 +1439,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
1419 "aggregate counts per processor socket", AGGR_SOCKET), 1439 "aggregate counts per processor socket", AGGR_SOCKET),
1420 OPT_SET_UINT(0, "per-core", &aggr_mode, 1440 OPT_SET_UINT(0, "per-core", &aggr_mode,
1421 "aggregate counts per physical processor core", AGGR_CORE), 1441 "aggregate counts per physical processor core", AGGR_CORE),
1442 OPT_UINTEGER('D', "delay", &initial_delay,
1443 "ms to wait before starting measurement after program start"),
1422 OPT_END() 1444 OPT_END()
1423 }; 1445 };
1424 const char * const stat_usage[] = { 1446 const char * const stat_usage[] = {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index bbf463572777..440c3b371401 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -103,7 +103,8 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
103 /* 103 /*
104 * We can't annotate with just /proc/kallsyms 104 * We can't annotate with just /proc/kallsyms
105 */ 105 */
106 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) { 106 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
107 !dso__is_kcore(map->dso)) {
107 pr_err("Can't annotate %s: No vmlinux file was found in the " 108 pr_err("Can't annotate %s: No vmlinux file was found in the "
108 "path\n", sym->name); 109 "path\n", sym->name);
109 sleep(1); 110 sleep(1);
@@ -238,8 +239,6 @@ out_unlock:
238 pthread_mutex_unlock(&notes->lock); 239 pthread_mutex_unlock(&notes->lock);
239} 240}
240 241
241static const char CONSOLE_CLEAR[] = "";
242
243static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, 242static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
244 struct addr_location *al, 243 struct addr_location *al,
245 struct perf_sample *sample) 244 struct perf_sample *sample)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 0e4b67f6bbd1..da7ae01c8394 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -18,6 +18,7 @@ static struct syscall_fmt {
18} syscall_fmts[] = { 18} syscall_fmts[] = {
19 { .name = "access", .errmsg = true, }, 19 { .name = "access", .errmsg = true, },
20 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 20 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
21 { .name = "connect", .errmsg = true, },
21 { .name = "fstat", .errmsg = true, .alias = "newfstat", }, 22 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
22 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", }, 23 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
23 { .name = "futex", .errmsg = true, }, 24 { .name = "futex", .errmsg = true, },
diff --git a/tools/perf/python/twatch.py b/tools/perf/python/twatch.py
index b11cca584238..2225162ee1fc 100755
--- a/tools/perf/python/twatch.py
+++ b/tools/perf/python/twatch.py
@@ -21,7 +21,7 @@ def main():
21 evsel = perf.evsel(task = 1, comm = 1, mmap = 0, 21 evsel = perf.evsel(task = 1, comm = 1, mmap = 0,
22 wakeup_events = 1, watermark = 1, 22 wakeup_events = 1, watermark = 1,
23 sample_id_all = 1, 23 sample_id_all = 1,
24 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_TID) 24 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU)
25 evsel.open(cpus = cpus, threads = threads); 25 evsel.open(cpus = cpus, threads = threads);
26 evlist = perf.evlist(cpus, threads) 26 evlist = perf.evlist(cpus, threads)
27 evlist.add(evsel) 27 evlist.add(evsel)
diff --git a/tools/perf/tests/attr/test-record-group-sampling b/tools/perf/tests/attr/test-record-group-sampling
new file mode 100644
index 000000000000..658f5d60c873
--- /dev/null
+++ b/tools/perf/tests/attr/test-record-group-sampling
@@ -0,0 +1,36 @@
1[config]
2command = record
3args = -e '{cycles,cache-misses}:S' kill >/dev/null 2>&1
4
5[event-1:base-record]
6fd=1
7group_fd=-1
8sample_type=343
9read_format=12
10inherit=0
11
12[event-2:base-record]
13fd=2
14group_fd=1
15
16# cache-misses
17type=0
18config=3
19
20# default | PERF_SAMPLE_READ
21sample_type=343
22
23# PERF_FORMAT_ID | PERF_FORMAT_GROUP
24read_format=12
25
26mmap=0
27comm=0
28enable_on_exec=0
29disabled=0
30
31# inherit is disabled for group sampling
32inherit=0
33
34# sampling disabled
35sample_freq=0
36sample_period=0
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index b7b4049fabbb..f5af19244a05 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -100,6 +100,10 @@ static struct test {
100 }, 100 },
101#endif 101#endif
102 { 102 {
103 .desc = "Test object code reading",
104 .func = test__code_reading,
105 },
106 {
103 .func = NULL, 107 .func = NULL,
104 }, 108 },
105}; 109};
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
new file mode 100644
index 000000000000..8e0943b966d7
--- /dev/null
+++ b/tools/perf/tests/code-reading.c
@@ -0,0 +1,573 @@
1#include <sys/types.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <inttypes.h>
6#include <ctype.h>
7#include <string.h>
8
9#include "parse-events.h"
10#include "evlist.h"
11#include "evsel.h"
12#include "thread_map.h"
13#include "cpumap.h"
14#include "machine.h"
15#include "event.h"
16#include "thread.h"
17
18#include "tests.h"
19
20#define BUFSZ 1024
21#define READLEN 128
22
23struct state {
24 u64 done[1024];
25 size_t done_cnt;
26};
27
28static unsigned int hex(char c)
29{
30 if (c >= '0' && c <= '9')
31 return c - '0';
32 if (c >= 'a' && c <= 'f')
33 return c - 'a' + 10;
34 return c - 'A' + 10;
35}
36
37static void read_objdump_line(const char *line, size_t line_len, void **buf,
38 size_t *len)
39{
40 const char *p;
41 size_t i;
42
43 /* Skip to a colon */
44 p = strchr(line, ':');
45 if (!p)
46 return;
47 i = p + 1 - line;
48
49 /* Read bytes */
50 while (*len) {
51 char c1, c2;
52
53 /* Skip spaces */
54 for (; i < line_len; i++) {
55 if (!isspace(line[i]))
56 break;
57 }
58 /* Get 2 hex digits */
59 if (i >= line_len || !isxdigit(line[i]))
60 break;
61 c1 = line[i++];
62 if (i >= line_len || !isxdigit(line[i]))
63 break;
64 c2 = line[i++];
65 /* Followed by a space */
66 if (i < line_len && line[i] && !isspace(line[i]))
67 break;
68 /* Store byte */
69 *(unsigned char *)*buf = (hex(c1) << 4) | hex(c2);
70 *buf += 1;
71 *len -= 1;
72 }
73}
74
75static int read_objdump_output(FILE *f, void **buf, size_t *len)
76{
77 char *line = NULL;
78 size_t line_len;
79 ssize_t ret;
80 int err = 0;
81
82 while (1) {
83 ret = getline(&line, &line_len, f);
84 if (feof(f))
85 break;
86 if (ret < 0) {
87 pr_debug("getline failed\n");
88 err = -1;
89 break;
90 }
91 read_objdump_line(line, ret, buf, len);
92 }
93
94 free(line);
95
96 return err;
97}
98
99static int read_via_objdump(const char *filename, u64 addr, void *buf,
100 size_t len)
101{
102 char cmd[PATH_MAX * 2];
103 const char *fmt;
104 FILE *f;
105 int ret;
106
107 fmt = "%s -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
108 ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
109 filename);
110 if (ret <= 0 || (size_t)ret >= sizeof(cmd))
111 return -1;
112
113 pr_debug("Objdump command is: %s\n", cmd);
114
115 /* Ignore objdump errors */
116 strcat(cmd, " 2>/dev/null");
117
118 f = popen(cmd, "r");
119 if (!f) {
120 pr_debug("popen failed\n");
121 return -1;
122 }
123
124 ret = read_objdump_output(f, &buf, &len);
125 if (len) {
126 pr_debug("objdump read too few bytes\n");
127 if (!ret)
128 ret = len;
129 }
130
131 pclose(f);
132
133 return ret;
134}
135
136static int read_object_code(u64 addr, size_t len, u8 cpumode,
137 struct thread *thread, struct machine *machine,
138 struct state *state)
139{
140 struct addr_location al;
141 unsigned char buf1[BUFSZ];
142 unsigned char buf2[BUFSZ];
143 size_t ret_len;
144 u64 objdump_addr;
145 int ret;
146
147 pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
148
149 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr,
150 &al, NULL);
151 if (!al.map || !al.map->dso) {
152 pr_debug("thread__find_addr_map failed\n");
153 return -1;
154 }
155
156 pr_debug("File is: %s\n", al.map->dso->long_name);
157
158 if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
159 !dso__is_kcore(al.map->dso)) {
160 pr_debug("Unexpected kernel address - skipping\n");
161 return 0;
162 }
163
164 pr_debug("On file address is: %#"PRIx64"\n", al.addr);
165
166 if (len > BUFSZ)
167 len = BUFSZ;
168
169 /* Do not go off the map */
170 if (addr + len > al.map->end)
171 len = al.map->end - addr;
172
173 /* Read the object code using perf */
174 ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1,
175 len);
176 if (ret_len != len) {
177 pr_debug("dso__data_read_offset failed\n");
178 return -1;
179 }
180
181 /*
182 * Converting addresses for use by objdump requires more information.
183 * map__load() does that. See map__rip_2objdump() for details.
184 */
185 if (map__load(al.map, NULL))
186 return -1;
187
188 /* objdump struggles with kcore - try each map only once */
189 if (dso__is_kcore(al.map->dso)) {
190 size_t d;
191
192 for (d = 0; d < state->done_cnt; d++) {
193 if (state->done[d] == al.map->start) {
194 pr_debug("kcore map tested already");
195 pr_debug(" - skipping\n");
196 return 0;
197 }
198 }
199 if (state->done_cnt >= ARRAY_SIZE(state->done)) {
200 pr_debug("Too many kcore maps - skipping\n");
201 return 0;
202 }
203 state->done[state->done_cnt++] = al.map->start;
204 }
205
206 /* Read the object code using objdump */
207 objdump_addr = map__rip_2objdump(al.map, al.addr);
208 ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len);
209 if (ret > 0) {
210 /*
211 * The kernel maps are inaccurate - assume objdump is right in
212 * that case.
213 */
214 if (cpumode == PERF_RECORD_MISC_KERNEL ||
215 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
216 len -= ret;
217 if (len) {
218 pr_debug("Reducing len to %zu\n", len);
219 } else if (dso__is_kcore(al.map->dso)) {
220 /*
221 * objdump cannot handle very large segments
222 * that may be found in kcore.
223 */
224 pr_debug("objdump failed for kcore");
225 pr_debug(" - skipping\n");
226 return 0;
227 } else {
228 return -1;
229 }
230 }
231 }
232 if (ret < 0) {
233 pr_debug("read_via_objdump failed\n");
234 return -1;
235 }
236
237 /* The results should be identical */
238 if (memcmp(buf1, buf2, len)) {
239 pr_debug("Bytes read differ from those read by objdump\n");
240 return -1;
241 }
242 pr_debug("Bytes read match those read by objdump\n");
243
244 return 0;
245}
246
247static int process_sample_event(struct machine *machine,
248 struct perf_evlist *evlist,
249 union perf_event *event, struct state *state)
250{
251 struct perf_sample sample;
252 struct thread *thread;
253 u8 cpumode;
254
255 if (perf_evlist__parse_sample(evlist, event, &sample)) {
256 pr_debug("perf_evlist__parse_sample failed\n");
257 return -1;
258 }
259
260 thread = machine__findnew_thread(machine, sample.pid);
261 if (!thread) {
262 pr_debug("machine__findnew_thread failed\n");
263 return -1;
264 }
265
266 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
267
268 return read_object_code(sample.ip, READLEN, cpumode, thread, machine,
269 state);
270}
271
272static int process_event(struct machine *machine, struct perf_evlist *evlist,
273 union perf_event *event, struct state *state)
274{
275 if (event->header.type == PERF_RECORD_SAMPLE)
276 return process_sample_event(machine, evlist, event, state);
277
278 if (event->header.type < PERF_RECORD_MAX)
279 return machine__process_event(machine, event);
280
281 return 0;
282}
283
284static int process_events(struct machine *machine, struct perf_evlist *evlist,
285 struct state *state)
286{
287 union perf_event *event;
288 int i, ret;
289
290 for (i = 0; i < evlist->nr_mmaps; i++) {
291 while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
292 ret = process_event(machine, evlist, event, state);
293 if (ret < 0)
294 return ret;
295 }
296 }
297 return 0;
298}
299
300static int comp(const void *a, const void *b)
301{
302 return *(int *)a - *(int *)b;
303}
304
305static void do_sort_something(void)
306{
307 size_t sz = 40960;
308 int buf[sz], i;
309
310 for (i = 0; i < (int)sz; i++)
311 buf[i] = sz - i - 1;
312
313 qsort(buf, sz, sizeof(int), comp);
314
315 for (i = 0; i < (int)sz; i++) {
316 if (buf[i] != i) {
317 pr_debug("qsort failed\n");
318 break;
319 }
320 }
321}
322
323static void sort_something(void)
324{
325 int i;
326
327 for (i = 0; i < 10; i++)
328 do_sort_something();
329}
330
331static void syscall_something(void)
332{
333 int pipefd[2];
334 int i;
335
336 for (i = 0; i < 1000; i++) {
337 if (pipe(pipefd) < 0) {
338 pr_debug("pipe failed\n");
339 break;
340 }
341 close(pipefd[1]);
342 close(pipefd[0]);
343 }
344}
345
346static void fs_something(void)
347{
348 const char *test_file_name = "temp-perf-code-reading-test-file--";
349 FILE *f;
350 int i;
351
352 for (i = 0; i < 1000; i++) {
353 f = fopen(test_file_name, "w+");
354 if (f) {
355 fclose(f);
356 unlink(test_file_name);
357 }
358 }
359}
360
361static void do_something(void)
362{
363 fs_something();
364
365 sort_something();
366
367 syscall_something();
368}
369
370enum {
371 TEST_CODE_READING_OK,
372 TEST_CODE_READING_NO_VMLINUX,
373 TEST_CODE_READING_NO_KCORE,
374 TEST_CODE_READING_NO_ACCESS,
375 TEST_CODE_READING_NO_KERNEL_OBJ,
376};
377
378static int do_test_code_reading(bool try_kcore)
379{
380 struct machines machines;
381 struct machine *machine;
382 struct thread *thread;
383 struct perf_record_opts opts = {
384 .mmap_pages = UINT_MAX,
385 .user_freq = UINT_MAX,
386 .user_interval = ULLONG_MAX,
387 .freq = 4000,
388 .target = {
389 .uses_mmap = true,
390 },
391 };
392 struct state state = {
393 .done_cnt = 0,
394 };
395 struct thread_map *threads = NULL;
396 struct cpu_map *cpus = NULL;
397 struct perf_evlist *evlist = NULL;
398 struct perf_evsel *evsel = NULL;
399 int err = -1, ret;
400 pid_t pid;
401 struct map *map;
402 bool have_vmlinux, have_kcore, excl_kernel = false;
403
404 pid = getpid();
405
406 machines__init(&machines);
407 machine = &machines.host;
408
409 ret = machine__create_kernel_maps(machine);
410 if (ret < 0) {
411 pr_debug("machine__create_kernel_maps failed\n");
412 goto out_err;
413 }
414
415 /* Force the use of kallsyms instead of vmlinux to try kcore */
416 if (try_kcore)
417 symbol_conf.kallsyms_name = "/proc/kallsyms";
418
419 /* Load kernel map */
420 map = machine->vmlinux_maps[MAP__FUNCTION];
421 ret = map__load(map, NULL);
422 if (ret < 0) {
423 pr_debug("map__load failed\n");
424 goto out_err;
425 }
426 have_vmlinux = dso__is_vmlinux(map->dso);
427 have_kcore = dso__is_kcore(map->dso);
428
429 /* 2nd time through we just try kcore */
430 if (try_kcore && !have_kcore)
431 return TEST_CODE_READING_NO_KCORE;
432
433 /* No point getting kernel events if there is no kernel object */
434 if (!have_vmlinux && !have_kcore)
435 excl_kernel = true;
436
437 threads = thread_map__new_by_tid(pid);
438 if (!threads) {
439 pr_debug("thread_map__new_by_tid failed\n");
440 goto out_err;
441 }
442
443 ret = perf_event__synthesize_thread_map(NULL, threads,
444 perf_event__process, machine);
445 if (ret < 0) {
446 pr_debug("perf_event__synthesize_thread_map failed\n");
447 goto out_err;
448 }
449
450 thread = machine__findnew_thread(machine, pid);
451 if (!thread) {
452 pr_debug("machine__findnew_thread failed\n");
453 goto out_err;
454 }
455
456 cpus = cpu_map__new(NULL);
457 if (!cpus) {
458 pr_debug("cpu_map__new failed\n");
459 goto out_err;
460 }
461
462 while (1) {
463 const char *str;
464
465 evlist = perf_evlist__new();
466 if (!evlist) {
467 pr_debug("perf_evlist__new failed\n");
468 goto out_err;
469 }
470
471 perf_evlist__set_maps(evlist, cpus, threads);
472
473 if (excl_kernel)
474 str = "cycles:u";
475 else
476 str = "cycles";
477 pr_debug("Parsing event '%s'\n", str);
478 ret = parse_events(evlist, str);
479 if (ret < 0) {
480 pr_debug("parse_events failed\n");
481 goto out_err;
482 }
483
484 perf_evlist__config(evlist, &opts);
485
486 evsel = perf_evlist__first(evlist);
487
488 evsel->attr.comm = 1;
489 evsel->attr.disabled = 1;
490 evsel->attr.enable_on_exec = 0;
491
492 ret = perf_evlist__open(evlist);
493 if (ret < 0) {
494 if (!excl_kernel) {
495 excl_kernel = true;
496 perf_evlist__delete(evlist);
497 evlist = NULL;
498 continue;
499 }
500 pr_debug("perf_evlist__open failed\n");
501 goto out_err;
502 }
503 break;
504 }
505
506 ret = perf_evlist__mmap(evlist, UINT_MAX, false);
507 if (ret < 0) {
508 pr_debug("perf_evlist__mmap failed\n");
509 goto out_err;
510 }
511
512 perf_evlist__enable(evlist);
513
514 do_something();
515
516 perf_evlist__disable(evlist);
517
518 ret = process_events(machine, evlist, &state);
519 if (ret < 0)
520 goto out_err;
521
522 if (!have_vmlinux && !have_kcore && !try_kcore)
523 err = TEST_CODE_READING_NO_KERNEL_OBJ;
524 else if (!have_vmlinux && !try_kcore)
525 err = TEST_CODE_READING_NO_VMLINUX;
526 else if (excl_kernel)
527 err = TEST_CODE_READING_NO_ACCESS;
528 else
529 err = TEST_CODE_READING_OK;
530out_err:
531 if (evlist) {
532 perf_evlist__munmap(evlist);
533 perf_evlist__close(evlist);
534 perf_evlist__delete(evlist);
535 }
536 if (cpus)
537 cpu_map__delete(cpus);
538 if (threads)
539 thread_map__delete(threads);
540 machines__destroy_kernel_maps(&machines);
541 machine__delete_threads(machine);
542 machines__exit(&machines);
543
544 return err;
545}
546
547int test__code_reading(void)
548{
549 int ret;
550
551 ret = do_test_code_reading(false);
552 if (!ret)
553 ret = do_test_code_reading(true);
554
555 switch (ret) {
556 case TEST_CODE_READING_OK:
557 return 0;
558 case TEST_CODE_READING_NO_VMLINUX:
559 fprintf(stderr, " (no vmlinux)");
560 return 0;
561 case TEST_CODE_READING_NO_KCORE:
562 fprintf(stderr, " (no kcore)");
563 return 0;
564 case TEST_CODE_READING_NO_ACCESS:
565 fprintf(stderr, " (no access)");
566 return 0;
567 case TEST_CODE_READING_NO_KERNEL_OBJ:
568 fprintf(stderr, " (no kernel obj)");
569 return 0;
570 default:
571 return -1;
572 };
573}
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 344c844ffc1e..48114d164e9f 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -452,6 +452,7 @@ static int test__checkevent_pmu_events(struct perf_evlist *evlist)
452 evsel->attr.exclude_kernel); 452 evsel->attr.exclude_kernel);
453 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv); 453 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
454 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 454 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
455 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
455 456
456 return 0; 457 return 0;
457} 458}
@@ -520,6 +521,7 @@ static int test__group1(struct perf_evlist *evlist)
520 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); 521 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
521 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); 522 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
522 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); 523 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
524 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
523 525
524 /* cycles:upp */ 526 /* cycles:upp */
525 evsel = perf_evsel__next(evsel); 527 evsel = perf_evsel__next(evsel);
@@ -535,6 +537,7 @@ static int test__group1(struct perf_evlist *evlist)
535 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); 537 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
536 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 538 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
537 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); 539 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
540 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
538 541
539 return 0; 542 return 0;
540} 543}
@@ -560,6 +563,7 @@ static int test__group2(struct perf_evlist *evlist)
560 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); 563 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
561 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); 564 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
562 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); 565 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
566 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
563 567
564 /* cache-references + :u modifier */ 568 /* cache-references + :u modifier */
565 evsel = perf_evsel__next(evsel); 569 evsel = perf_evsel__next(evsel);
@@ -574,6 +578,7 @@ static int test__group2(struct perf_evlist *evlist)
574 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 578 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
575 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 579 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
576 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); 580 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
581 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
577 582
578 /* cycles:k */ 583 /* cycles:k */
579 evsel = perf_evsel__next(evsel); 584 evsel = perf_evsel__next(evsel);
@@ -587,6 +592,7 @@ static int test__group2(struct perf_evlist *evlist)
587 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 592 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
588 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 593 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
589 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); 594 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
595 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
590 596
591 return 0; 597 return 0;
592} 598}
@@ -615,6 +621,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
615 !strcmp(leader->group_name, "group1")); 621 !strcmp(leader->group_name, "group1"));
616 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); 622 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
617 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); 623 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
624 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
618 625
619 /* group1 cycles:kppp */ 626 /* group1 cycles:kppp */
620 evsel = perf_evsel__next(evsel); 627 evsel = perf_evsel__next(evsel);
@@ -631,6 +638,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
631 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 638 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
632 TEST_ASSERT_VAL("wrong group name", !evsel->group_name); 639 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
633 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); 640 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
641 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
634 642
635 /* group2 cycles + G modifier */ 643 /* group2 cycles + G modifier */
636 evsel = leader = perf_evsel__next(evsel); 644 evsel = leader = perf_evsel__next(evsel);
@@ -648,6 +656,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
648 !strcmp(leader->group_name, "group2")); 656 !strcmp(leader->group_name, "group2"));
649 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); 657 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
650 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); 658 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
659 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
651 660
652 /* group2 1:3 + G modifier */ 661 /* group2 1:3 + G modifier */
653 evsel = perf_evsel__next(evsel); 662 evsel = perf_evsel__next(evsel);
@@ -661,6 +670,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
661 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 670 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
662 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 671 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
663 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); 672 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
673 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
664 674
665 /* instructions:u */ 675 /* instructions:u */
666 evsel = perf_evsel__next(evsel); 676 evsel = perf_evsel__next(evsel);
@@ -674,6 +684,7 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
674 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host); 684 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
675 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 685 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
676 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); 686 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
687 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
677 688
678 return 0; 689 return 0;
679} 690}
@@ -701,6 +712,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
701 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); 712 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
702 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); 713 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
703 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); 714 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
715 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
704 716
705 /* instructions:kp + p */ 717 /* instructions:kp + p */
706 evsel = perf_evsel__next(evsel); 718 evsel = perf_evsel__next(evsel);
@@ -716,6 +728,7 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
716 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2); 728 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
717 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 729 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
718 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); 730 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
731 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
719 732
720 return 0; 733 return 0;
721} 734}
@@ -742,6 +755,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
742 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); 755 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
743 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); 756 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
744 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); 757 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
758 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
745 759
746 /* instructions + G */ 760 /* instructions + G */
747 evsel = perf_evsel__next(evsel); 761 evsel = perf_evsel__next(evsel);
@@ -756,6 +770,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
756 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip); 770 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
757 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader); 771 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
758 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1); 772 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 1);
773 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
759 774
760 /* cycles:G */ 775 /* cycles:G */
761 evsel = leader = perf_evsel__next(evsel); 776 evsel = leader = perf_evsel__next(evsel);
@@ -772,6 +787,7 @@ static int test__group5(struct perf_evlist *evlist __maybe_unused)
772 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel)); 787 TEST_ASSERT_VAL("wrong leader", perf_evsel__is_group_leader(evsel));
773 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2); 788 TEST_ASSERT_VAL("wrong nr_members", evsel->nr_members == 2);
774 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0); 789 TEST_ASSERT_VAL("wrong group_idx", perf_evsel__group_idx(evsel) == 0);
790 TEST_ASSERT_VAL("wrong sample_read", !evsel->sample_read);
775 791
776 /* instructions:G */ 792 /* instructions:G */
777 evsel = perf_evsel__next(evsel); 793 evsel = perf_evsel__next(evsel);
@@ -963,6 +979,142 @@ static int test__group_gh4(struct perf_evlist *evlist)
963 return 0; 979 return 0;
964} 980}
965 981
982static int test__leader_sample1(struct perf_evlist *evlist)
983{
984 struct perf_evsel *evsel, *leader;
985
986 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
987
988 /* cycles - sampling group leader */
989 evsel = leader = perf_evlist__first(evlist);
990 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
991 TEST_ASSERT_VAL("wrong config",
992 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
993 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
994 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
995 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
996 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
997 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
998 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
999 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
1000 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
1001 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
1002
1003 /* cache-misses - not sampling */
1004 evsel = perf_evsel__next(evsel);
1005 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
1006 TEST_ASSERT_VAL("wrong config",
1007 PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
1008 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
1009 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
1010 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
1011 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
1012 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
1013 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
1014 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
1015 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
1016
1017 /* branch-misses - not sampling */
1018 evsel = perf_evsel__next(evsel);
1019 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
1020 TEST_ASSERT_VAL("wrong config",
1021 PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config);
1022 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
1023 TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
1024 TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
1025 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
1026 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
1027 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
1028 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
1029 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
1030 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
1031
1032 return 0;
1033}
1034
1035static int test__leader_sample2(struct perf_evlist *evlist __maybe_unused)
1036{
1037 struct perf_evsel *evsel, *leader;
1038
1039 TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
1040
1041 /* instructions - sampling group leader */
1042 evsel = leader = perf_evlist__first(evlist);
1043 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
1044 TEST_ASSERT_VAL("wrong config",
1045 PERF_COUNT_HW_INSTRUCTIONS == evsel->attr.config);
1046 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
1047 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
1048 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
1049 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
1050 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
1051 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
1052 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
1053 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
1054 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
1055
1056 /* branch-misses - not sampling */
1057 evsel = perf_evsel__next(evsel);
1058 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
1059 TEST_ASSERT_VAL("wrong config",
1060 PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config);
1061 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
1062 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
1063 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
1064 TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
1065 TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
1066 TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
1067 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
1068 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
1069 TEST_ASSERT_VAL("wrong sample_read", evsel->sample_read);
1070
1071 return 0;
1072}
1073
1074static int test__checkevent_pinned_modifier(struct perf_evlist *evlist)
1075{
1076 struct perf_evsel *evsel = perf_evlist__first(evlist);
1077
1078 TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
1079 TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
1080 TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
1081 TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
1082 TEST_ASSERT_VAL("wrong pinned", evsel->attr.pinned);
1083
1084 return test__checkevent_symbolic_name(evlist);
1085}
1086
1087static int test__pinned_group(struct perf_evlist *evlist)
1088{
1089 struct perf_evsel *evsel, *leader;
1090
1091 TEST_ASSERT_VAL("wrong number of entries", 3 == evlist->nr_entries);
1092
1093 /* cycles - group leader */
1094 evsel = leader = perf_evlist__first(evlist);
1095 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
1096 TEST_ASSERT_VAL("wrong config",
1097 PERF_COUNT_HW_CPU_CYCLES == evsel->attr.config);
1098 TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
1099 TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
1100 TEST_ASSERT_VAL("wrong pinned", evsel->attr.pinned);
1101
1102 /* cache-misses - can not be pinned, but will go on with the leader */
1103 evsel = perf_evsel__next(evsel);
1104 TEST_ASSERT_VAL("wrong type", PERF_TYPE_HARDWARE == evsel->attr.type);
1105 TEST_ASSERT_VAL("wrong config",
1106 PERF_COUNT_HW_CACHE_MISSES == evsel->attr.config);
1107 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
1108
1109 /* branch-misses - ditto */
1110 evsel = perf_evsel__next(evsel);
1111 TEST_ASSERT_VAL("wrong config",
1112 PERF_COUNT_HW_BRANCH_MISSES == evsel->attr.config);
1113 TEST_ASSERT_VAL("wrong pinned", !evsel->attr.pinned);
1114
1115 return 0;
1116}
1117
966static int count_tracepoints(void) 1118static int count_tracepoints(void)
967{ 1119{
968 char events_path[PATH_MAX]; 1120 char events_path[PATH_MAX];
@@ -1179,6 +1331,22 @@ static struct evlist_test test__events[] = {
1179 .name = "{cycles:G,cache-misses:H}:uG", 1331 .name = "{cycles:G,cache-misses:H}:uG",
1180 .check = test__group_gh4, 1332 .check = test__group_gh4,
1181 }, 1333 },
1334 [38] = {
1335 .name = "{cycles,cache-misses,branch-misses}:S",
1336 .check = test__leader_sample1,
1337 },
1338 [39] = {
1339 .name = "{instructions,branch-misses}:Su",
1340 .check = test__leader_sample2,
1341 },
1342 [40] = {
1343 .name = "instructions:uDp",
1344 .check = test__checkevent_pinned_modifier,
1345 },
1346 [41] = {
1347 .name = "{cycles,cache-misses,branch-misses}:D",
1348 .check = test__pinned_group,
1349 },
1182}; 1350};
1183 1351
1184static struct evlist_test test__events_pmu[] = { 1352static struct evlist_test test__events_pmu[] = {
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index d22202aa16e9..c748f532b20f 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -36,5 +36,6 @@ int test__bp_signal_overflow(void);
36int test__task_exit(void); 36int test__task_exit(void);
37int test__sw_clock_freq(void); 37int test__sw_clock_freq(void);
38int test__perf_time_to_tsc(void); 38int test__perf_time_to_tsc(void);
39int test__code_reading(void);
39 40
40#endif /* TESTS_H */ 41#endif /* TESTS_H */
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index add15392c622..2bd13edcbc17 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -16,6 +16,8 @@ static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
16 return 0; 16 return 0;
17} 17}
18 18
19#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x))
20
19int test__vmlinux_matches_kallsyms(void) 21int test__vmlinux_matches_kallsyms(void)
20{ 22{
21 int err = -1; 23 int err = -1;
@@ -25,6 +27,7 @@ int test__vmlinux_matches_kallsyms(void)
25 struct machine kallsyms, vmlinux; 27 struct machine kallsyms, vmlinux;
26 enum map_type type = MAP__FUNCTION; 28 enum map_type type = MAP__FUNCTION;
27 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", }; 29 struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };
30 u64 mem_start, mem_end;
28 31
29 /* 32 /*
30 * Step 1: 33 * Step 1:
@@ -73,7 +76,7 @@ int test__vmlinux_matches_kallsyms(void)
73 goto out; 76 goto out;
74 } 77 }
75 78
76 ref_reloc_sym.addr = sym->start; 79 ref_reloc_sym.addr = UM(sym->start);
77 80
78 /* 81 /*
79 * Step 5: 82 * Step 5:
@@ -123,10 +126,14 @@ int test__vmlinux_matches_kallsyms(void)
123 if (sym->start == sym->end) 126 if (sym->start == sym->end)
124 continue; 127 continue;
125 128
126 first_pair = machine__find_kernel_symbol(&kallsyms, type, sym->start, NULL, NULL); 129 mem_start = vmlinux_map->unmap_ip(vmlinux_map, sym->start);
130 mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end);
131
132 first_pair = machine__find_kernel_symbol(&kallsyms, type,
133 mem_start, NULL, NULL);
127 pair = first_pair; 134 pair = first_pair;
128 135
129 if (pair && pair->start == sym->start) { 136 if (pair && UM(pair->start) == mem_start) {
130next_pair: 137next_pair:
131 if (strcmp(sym->name, pair->name) == 0) { 138 if (strcmp(sym->name, pair->name) == 0) {
132 /* 139 /*
@@ -138,10 +145,11 @@ next_pair:
138 * off the real size. More than that and we 145 * off the real size. More than that and we
139 * _really_ have a problem. 146 * _really_ have a problem.
140 */ 147 */
141 s64 skew = sym->end - pair->end; 148 s64 skew = mem_end - UM(pair->end);
142 if (llabs(skew) >= page_size) 149 if (llabs(skew) >= page_size)
143 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", 150 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
144 sym->start, sym->name, sym->end, pair->end); 151 mem_start, sym->name, mem_end,
152 UM(pair->end));
145 153
146 /* 154 /*
147 * Do not count this as a failure, because we 155 * Do not count this as a failure, because we
@@ -159,7 +167,7 @@ detour:
159 if (nnd) { 167 if (nnd) {
160 struct symbol *next = rb_entry(nnd, struct symbol, rb_node); 168 struct symbol *next = rb_entry(nnd, struct symbol, rb_node);
161 169
162 if (next->start == sym->start) { 170 if (UM(next->start) == mem_start) {
163 pair = next; 171 pair = next;
164 goto next_pair; 172 goto next_pair;
165 } 173 }
@@ -172,10 +180,11 @@ detour:
172 } 180 }
173 181
174 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", 182 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
175 sym->start, sym->name, pair->name); 183 mem_start, sym->name, pair->name);
176 } 184 }
177 } else 185 } else
178 pr_debug("%#" PRIx64 ": %s not on kallsyms\n", sym->start, sym->name); 186 pr_debug("%#" PRIx64 ": %s not on kallsyms\n",
187 mem_start, sym->name);
179 188
180 err = -1; 189 err = -1;
181 } 190 }
@@ -208,16 +217,19 @@ detour:
208 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) { 217 for (nd = rb_first(&vmlinux.kmaps.maps[type]); nd; nd = rb_next(nd)) {
209 struct map *pos = rb_entry(nd, struct map, rb_node), *pair; 218 struct map *pos = rb_entry(nd, struct map, rb_node), *pair;
210 219
211 pair = map_groups__find(&kallsyms.kmaps, type, pos->start); 220 mem_start = vmlinux_map->unmap_ip(vmlinux_map, pos->start);
221 mem_end = vmlinux_map->unmap_ip(vmlinux_map, pos->end);
222
223 pair = map_groups__find(&kallsyms.kmaps, type, mem_start);
212 if (pair == NULL || pair->priv) 224 if (pair == NULL || pair->priv)
213 continue; 225 continue;
214 226
215 if (pair->start == pos->start) { 227 if (pair->start == mem_start) {
216 pair->priv = 1; 228 pair->priv = 1;
217 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", 229 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
218 pos->start, pos->end, pos->pgoff, pos->dso->name); 230 pos->start, pos->end, pos->pgoff, pos->dso->name);
219 if (pos->pgoff != pair->pgoff || pos->end != pair->end) 231 if (mem_end != pair->end)
220 pr_info(": \n*%" PRIx64 "-%" PRIx64 " %" PRIx64 "", 232 pr_info(":\n*%" PRIx64 "-%" PRIx64 " %" PRIx64,
221 pair->start, pair->end, pair->pgoff); 233 pair->start, pair->end, pair->pgoff);
222 pr_info(" %s\n", pair->dso->name); 234 pr_info(" %s\n", pair->dso->name);
223 pair->priv = 1; 235 pair->priv = 1;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index cc64d3f7fc36..08545ae46992 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -428,6 +428,14 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser)
428 browser->b.nr_entries = browser->nr_asm_entries; 428 browser->b.nr_entries = browser->nr_asm_entries;
429} 429}
430 430
431#define SYM_TITLE_MAX_SIZE (PATH_MAX + 64)
432
433static int sym_title(struct symbol *sym, struct map *map, char *title,
434 size_t sz)
435{
436 return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name);
437}
438
431static bool annotate_browser__callq(struct annotate_browser *browser, 439static bool annotate_browser__callq(struct annotate_browser *browser,
432 struct perf_evsel *evsel, 440 struct perf_evsel *evsel,
433 struct hist_browser_timer *hbt) 441 struct hist_browser_timer *hbt)
@@ -438,6 +446,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
438 struct annotation *notes; 446 struct annotation *notes;
439 struct symbol *target; 447 struct symbol *target;
440 u64 ip; 448 u64 ip;
449 char title[SYM_TITLE_MAX_SIZE];
441 450
442 if (!ins__is_call(dl->ins)) 451 if (!ins__is_call(dl->ins))
443 return false; 452 return false;
@@ -461,7 +470,8 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
461 470
462 pthread_mutex_unlock(&notes->lock); 471 pthread_mutex_unlock(&notes->lock);
463 symbol__tui_annotate(target, ms->map, evsel, hbt); 472 symbol__tui_annotate(target, ms->map, evsel, hbt);
464 ui_browser__show_title(&browser->b, sym->name); 473 sym_title(sym, ms->map, title, sizeof(title));
474 ui_browser__show_title(&browser->b, title);
465 return true; 475 return true;
466} 476}
467 477
@@ -495,7 +505,7 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
495 505
496 dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx); 506 dl = annotate_browser__find_offset(browser, dl->ops.target.offset, &idx);
497 if (dl == NULL) { 507 if (dl == NULL) {
498 ui_helpline__puts("Invallid jump offset"); 508 ui_helpline__puts("Invalid jump offset");
499 return true; 509 return true;
500 } 510 }
501 511
@@ -653,8 +663,10 @@ static int annotate_browser__run(struct annotate_browser *browser,
653 const char *help = "Press 'h' for help on key bindings"; 663 const char *help = "Press 'h' for help on key bindings";
654 int delay_secs = hbt ? hbt->refresh : 0; 664 int delay_secs = hbt ? hbt->refresh : 0;
655 int key; 665 int key;
666 char title[SYM_TITLE_MAX_SIZE];
656 667
657 if (ui_browser__show(&browser->b, sym->name, help) < 0) 668 sym_title(sym, ms->map, title, sizeof(title));
669 if (ui_browser__show(&browser->b, title, help) < 0)
658 return -1; 670 return -1;
659 671
660 annotate_browser__calc_percent(browser, evsel); 672 annotate_browser__calc_percent(browser, evsel);
@@ -720,7 +732,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
720 "s Toggle source code view\n" 732 "s Toggle source code view\n"
721 "/ Search string\n" 733 "/ Search string\n"
722 "r Run available scripts\n" 734 "r Run available scripts\n"
723 "? Search previous string\n"); 735 "? Search string backwards\n");
724 continue; 736 continue;
725 case 'r': 737 case 'r':
726 { 738 {
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index cb2ed1980147..2ca66cc1160f 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -109,8 +109,6 @@ __HPP_COLOR_PERCENT_FN(overhead_guest_us, period_guest_us)
109 109
110void perf_gtk__init_hpp(void) 110void perf_gtk__init_hpp(void)
111{ 111{
112 perf_hpp__column_enable(PERF_HPP__OVERHEAD);
113
114 perf_hpp__init(); 112 perf_hpp__init();
115 113
116 perf_hpp__format[PERF_HPP__OVERHEAD].color = 114 perf_hpp__format[PERF_HPP__OVERHEAD].color =
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index d102716c43a1..bfc5a27597d6 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -110,10 +110,10 @@ static int jump__parse(struct ins_operands *ops)
110{ 110{
111 const char *s = strchr(ops->raw, '+'); 111 const char *s = strchr(ops->raw, '+');
112 112
113 ops->target.addr = strtoll(ops->raw, NULL, 16); 113 ops->target.addr = strtoull(ops->raw, NULL, 16);
114 114
115 if (s++ != NULL) 115 if (s++ != NULL)
116 ops->target.offset = strtoll(s, NULL, 16); 116 ops->target.offset = strtoull(s, NULL, 16);
117 else 117 else
118 ops->target.offset = UINT64_MAX; 118 ops->target.offset = UINT64_MAX;
119 119
@@ -821,11 +821,55 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
821 if (dl == NULL) 821 if (dl == NULL)
822 return -1; 822 return -1;
823 823
824 if (dl->ops.target.offset == UINT64_MAX)
825 dl->ops.target.offset = dl->ops.target.addr -
826 map__rip_2objdump(map, sym->start);
827
828 /*
829 * kcore has no symbols, so add the call target name if it is on the
830 * same map.
831 */
832 if (dl->ins && ins__is_call(dl->ins) && !dl->ops.target.name) {
833 struct symbol *s;
834 u64 ip = dl->ops.target.addr;
835
836 if (ip >= map->start && ip <= map->end) {
837 ip = map->map_ip(map, ip);
838 s = map__find_symbol(map, ip, NULL);
839 if (s && s->start == ip)
840 dl->ops.target.name = strdup(s->name);
841 }
842 }
843
824 disasm__add(&notes->src->source, dl); 844 disasm__add(&notes->src->source, dl);
825 845
826 return 0; 846 return 0;
827} 847}
828 848
849static void delete_last_nop(struct symbol *sym)
850{
851 struct annotation *notes = symbol__annotation(sym);
852 struct list_head *list = &notes->src->source;
853 struct disasm_line *dl;
854
855 while (!list_empty(list)) {
856 dl = list_entry(list->prev, struct disasm_line, node);
857
858 if (dl->ins && dl->ins->ops) {
859 if (dl->ins->ops != &nop_ops)
860 return;
861 } else {
862 if (!strstr(dl->line, " nop ") &&
863 !strstr(dl->line, " nopl ") &&
864 !strstr(dl->line, " nopw "))
865 return;
866 }
867
868 list_del(&dl->node);
869 disasm_line__free(dl);
870 }
871}
872
829int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) 873int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
830{ 874{
831 struct dso *dso = map->dso; 875 struct dso *dso = map->dso;
@@ -864,7 +908,8 @@ fallback:
864 free_filename = false; 908 free_filename = false;
865 } 909 }
866 910
867 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) { 911 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
912 !dso__is_kcore(dso)) {
868 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 913 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
869 char *build_id_msg = NULL; 914 char *build_id_msg = NULL;
870 915
@@ -898,7 +943,7 @@ fallback:
898 snprintf(command, sizeof(command), 943 snprintf(command, sizeof(command),
899 "%s %s%s --start-address=0x%016" PRIx64 944 "%s %s%s --start-address=0x%016" PRIx64
900 " --stop-address=0x%016" PRIx64 945 " --stop-address=0x%016" PRIx64
901 " -d %s %s -C %s|grep -v %s|expand", 946 " -d %s %s -C %s 2>/dev/null|grep -v %s|expand",
902 objdump_path ? objdump_path : "objdump", 947 objdump_path ? objdump_path : "objdump",
903 disassembler_style ? "-M " : "", 948 disassembler_style ? "-M " : "",
904 disassembler_style ? disassembler_style : "", 949 disassembler_style ? disassembler_style : "",
@@ -918,6 +963,13 @@ fallback:
918 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0) 963 if (symbol__parse_objdump_line(sym, map, file, privsize) < 0)
919 break; 964 break;
920 965
966 /*
967 * kallsyms does not have symbol sizes so there may a nop at the end.
968 * Remove it.
969 */
970 if (dso__is_kcore(dso))
971 delete_last_nop(sym);
972
921 pclose(file); 973 pclose(file);
922out_free_filename: 974out_free_filename:
923 if (free_filename) 975 if (free_filename)
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 5295625c0c00..3a0f5089379c 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -33,7 +33,7 @@ int build_id__mark_dso_hit(struct perf_tool *tool __maybe_unused,
33 } 33 }
34 34
35 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 35 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
36 event->ip.ip, &al); 36 event->ip.ip, &al, NULL);
37 37
38 if (al.map != NULL) 38 if (al.map != NULL)
39 al.map->dso->hit = 1; 39 al.map->dso->hit = 1;
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index c4374f07603c..e3c1ff8512c8 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -78,6 +78,8 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
78 symbol_conf.symfs, build_id_hex, build_id_hex + 2); 78 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
79 break; 79 break;
80 80
81 case DSO_BINARY_TYPE__VMLINUX:
82 case DSO_BINARY_TYPE__GUEST_VMLINUX:
81 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO: 83 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
82 snprintf(file, size, "%s%s", 84 snprintf(file, size, "%s%s",
83 symbol_conf.symfs, dso->long_name); 85 symbol_conf.symfs, dso->long_name);
@@ -93,11 +95,14 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
93 dso->long_name); 95 dso->long_name);
94 break; 96 break;
95 97
98 case DSO_BINARY_TYPE__KCORE:
99 case DSO_BINARY_TYPE__GUEST_KCORE:
100 snprintf(file, size, "%s", dso->long_name);
101 break;
102
96 default: 103 default:
97 case DSO_BINARY_TYPE__KALLSYMS: 104 case DSO_BINARY_TYPE__KALLSYMS:
98 case DSO_BINARY_TYPE__VMLINUX:
99 case DSO_BINARY_TYPE__GUEST_KALLSYMS: 105 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
100 case DSO_BINARY_TYPE__GUEST_VMLINUX:
101 case DSO_BINARY_TYPE__JAVA_JIT: 106 case DSO_BINARY_TYPE__JAVA_JIT:
102 case DSO_BINARY_TYPE__NOT_FOUND: 107 case DSO_BINARY_TYPE__NOT_FOUND:
103 ret = -1; 108 ret = -1;
@@ -419,6 +424,7 @@ struct dso *dso__new(const char *name)
419 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 424 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
420 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND; 425 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
421 dso->loaded = 0; 426 dso->loaded = 0;
427 dso->rel = 0;
422 dso->sorted_by_name = 0; 428 dso->sorted_by_name = 0;
423 dso->has_build_id = 0; 429 dso->has_build_id = 0;
424 dso->kernel = DSO_TYPE_USER; 430 dso->kernel = DSO_TYPE_USER;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index d51aaf272c68..b793053335d6 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -3,6 +3,7 @@
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include <stdbool.h>
6#include "types.h" 7#include "types.h"
7#include "map.h" 8#include "map.h"
8 9
@@ -20,6 +21,8 @@ enum dso_binary_type {
20 DSO_BINARY_TYPE__SYSTEM_PATH_DSO, 21 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
21 DSO_BINARY_TYPE__GUEST_KMODULE, 22 DSO_BINARY_TYPE__GUEST_KMODULE,
22 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, 23 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
24 DSO_BINARY_TYPE__KCORE,
25 DSO_BINARY_TYPE__GUEST_KCORE,
23 DSO_BINARY_TYPE__NOT_FOUND, 26 DSO_BINARY_TYPE__NOT_FOUND,
24}; 27};
25 28
@@ -84,6 +87,7 @@ struct dso {
84 u8 lname_alloc:1; 87 u8 lname_alloc:1;
85 u8 sorted_by_name; 88 u8 sorted_by_name;
86 u8 loaded; 89 u8 loaded;
90 u8 rel;
87 u8 build_id[BUILD_ID_SIZE]; 91 u8 build_id[BUILD_ID_SIZE];
88 const char *short_name; 92 const char *short_name;
89 char *long_name; 93 char *long_name;
@@ -146,4 +150,17 @@ size_t dso__fprintf_buildid(struct dso *dso, FILE *fp);
146size_t dso__fprintf_symbols_by_name(struct dso *dso, 150size_t dso__fprintf_symbols_by_name(struct dso *dso,
147 enum map_type type, FILE *fp); 151 enum map_type type, FILE *fp);
148size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); 152size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
153
154static inline bool dso__is_vmlinux(struct dso *dso)
155{
156 return dso->data_type == DSO_BINARY_TYPE__VMLINUX ||
157 dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX;
158}
159
160static inline bool dso__is_kcore(struct dso *dso)
161{
162 return dso->data_type == DSO_BINARY_TYPE__KCORE ||
163 dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE;
164}
165
149#endif /* __PERF_DSO */ 166#endif /* __PERF_DSO */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 95412705d0d2..cc7c0c9c9ea6 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -592,9 +592,10 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
592void thread__find_addr_map(struct thread *self, 592void thread__find_addr_map(struct thread *self,
593 struct machine *machine, u8 cpumode, 593 struct machine *machine, u8 cpumode,
594 enum map_type type, u64 addr, 594 enum map_type type, u64 addr,
595 struct addr_location *al) 595 struct addr_location *al, symbol_filter_t filter)
596{ 596{
597 struct map_groups *mg = &self->mg; 597 struct map_groups *mg = &self->mg;
598 bool load_map = false;
598 599
599 al->thread = self; 600 al->thread = self;
600 al->addr = addr; 601 al->addr = addr;
@@ -609,11 +610,13 @@ void thread__find_addr_map(struct thread *self,
609 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) { 610 if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
610 al->level = 'k'; 611 al->level = 'k';
611 mg = &machine->kmaps; 612 mg = &machine->kmaps;
613 load_map = true;
612 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) { 614 } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
613 al->level = '.'; 615 al->level = '.';
614 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 616 } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
615 al->level = 'g'; 617 al->level = 'g';
616 mg = &machine->kmaps; 618 mg = &machine->kmaps;
619 load_map = true;
617 } else { 620 } else {
618 /* 621 /*
619 * 'u' means guest os user space. 622 * 'u' means guest os user space.
@@ -654,8 +657,15 @@ try_again:
654 mg = &machine->kmaps; 657 mg = &machine->kmaps;
655 goto try_again; 658 goto try_again;
656 } 659 }
657 } else 660 } else {
661 /*
662 * Kernel maps might be changed when loading symbols so loading
663 * must be done prior to using kernel maps.
664 */
665 if (load_map)
666 map__load(al->map, filter);
658 al->addr = al->map->map_ip(al->map, al->addr); 667 al->addr = al->map->map_ip(al->map, al->addr);
668 }
659} 669}
660 670
661void thread__find_addr_location(struct thread *thread, struct machine *machine, 671void thread__find_addr_location(struct thread *thread, struct machine *machine,
@@ -663,7 +673,7 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine,
663 struct addr_location *al, 673 struct addr_location *al,
664 symbol_filter_t filter) 674 symbol_filter_t filter)
665{ 675{
666 thread__find_addr_map(thread, machine, cpumode, type, addr, al); 676 thread__find_addr_map(thread, machine, cpumode, type, addr, al, filter);
667 if (al->map != NULL) 677 if (al->map != NULL)
668 al->sym = map__find_symbol(al->map, al->addr, filter); 678 al->sym = map__find_symbol(al->map, al->addr, filter);
669 else 679 else
@@ -699,7 +709,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
699 machine__create_kernel_maps(machine); 709 machine__create_kernel_maps(machine);
700 710
701 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 711 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
702 event->ip.ip, al); 712 event->ip.ip, al, filter);
703 dump_printf(" ...... dso: %s\n", 713 dump_printf(" ...... dso: %s\n",
704 al->map ? al->map->dso->long_name : 714 al->map ? al->map->dso->long_name :
705 al->level == 'H' ? "[hypervisor]" : "<not found>"); 715 al->level == 'H' ? "[hypervisor]" : "<not found>");
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 1ebb8fb0178c..6119a649d861 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -80,6 +80,23 @@ struct stack_dump {
80 char *data; 80 char *data;
81}; 81};
82 82
83struct sample_read_value {
84 u64 value;
85 u64 id;
86};
87
88struct sample_read {
89 u64 time_enabled;
90 u64 time_running;
91 union {
92 struct {
93 u64 nr;
94 struct sample_read_value *values;
95 } group;
96 struct sample_read_value one;
97 };
98};
99
83struct perf_sample { 100struct perf_sample {
84 u64 ip; 101 u64 ip;
85 u32 pid, tid; 102 u32 pid, tid;
@@ -97,6 +114,7 @@ struct perf_sample {
97 struct branch_stack *branch_stack; 114 struct branch_stack *branch_stack;
98 struct regs_dump user_regs; 115 struct regs_dump user_regs;
99 struct stack_dump user_stack; 116 struct stack_dump user_stack;
117 struct sample_read read;
100}; 118};
101 119
102#define PERF_MEM_DATA_SRC_NONE \ 120#define PERF_MEM_DATA_SRC_NONE \
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 42ea4e947eb8..c7d111f74553 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -302,6 +302,24 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
302{ 302{
303 u64 read_data[4] = { 0, }; 303 u64 read_data[4] = { 0, };
304 int id_idx = 1; /* The first entry is the counter value */ 304 int id_idx = 1; /* The first entry is the counter value */
305 u64 id;
306 int ret;
307
308 ret = ioctl(fd, PERF_EVENT_IOC_ID, &id);
309 if (!ret)
310 goto add;
311
312 if (errno != ENOTTY)
313 return -1;
314
315 /* Legacy way to get event id.. All hail to old kernels! */
316
317 /*
318 * This way does not work with group format read, so bail
319 * out in that case.
320 */
321 if (perf_evlist__read_format(evlist) & PERF_FORMAT_GROUP)
322 return -1;
305 323
306 if (!(evsel->attr.read_format & PERF_FORMAT_ID) || 324 if (!(evsel->attr.read_format & PERF_FORMAT_ID) ||
307 read(fd, &read_data, sizeof(read_data)) == -1) 325 read(fd, &read_data, sizeof(read_data)) == -1)
@@ -312,25 +330,39 @@ static int perf_evlist__id_add_fd(struct perf_evlist *evlist,
312 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) 330 if (evsel->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
313 ++id_idx; 331 ++id_idx;
314 332
315 perf_evlist__id_add(evlist, evsel, cpu, thread, read_data[id_idx]); 333 id = read_data[id_idx];
334
335 add:
336 perf_evlist__id_add(evlist, evsel, cpu, thread, id);
316 return 0; 337 return 0;
317} 338}
318 339
319struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id) 340struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id)
320{ 341{
321 struct hlist_head *head; 342 struct hlist_head *head;
322 struct perf_sample_id *sid; 343 struct perf_sample_id *sid;
323 int hash; 344 int hash;
324 345
325 if (evlist->nr_entries == 1)
326 return perf_evlist__first(evlist);
327
328 hash = hash_64(id, PERF_EVLIST__HLIST_BITS); 346 hash = hash_64(id, PERF_EVLIST__HLIST_BITS);
329 head = &evlist->heads[hash]; 347 head = &evlist->heads[hash];
330 348
331 hlist_for_each_entry(sid, head, node) 349 hlist_for_each_entry(sid, head, node)
332 if (sid->id == id) 350 if (sid->id == id)
333 return sid->evsel; 351 return sid;
352
353 return NULL;
354}
355
356struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)
357{
358 struct perf_sample_id *sid;
359
360 if (evlist->nr_entries == 1)
361 return perf_evlist__first(evlist);
362
363 sid = perf_evlist__id2sid(evlist, id);
364 if (sid)
365 return sid->evsel;
334 366
335 if (!perf_evlist__sample_id_all(evlist)) 367 if (!perf_evlist__sample_id_all(evlist))
336 return perf_evlist__first(evlist); 368 return perf_evlist__first(evlist);
@@ -662,6 +694,32 @@ u64 perf_evlist__sample_type(struct perf_evlist *evlist)
662 return first->attr.sample_type; 694 return first->attr.sample_type;
663} 695}
664 696
697bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
698{
699 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
700 u64 read_format = first->attr.read_format;
701 u64 sample_type = first->attr.sample_type;
702
703 list_for_each_entry_continue(pos, &evlist->entries, node) {
704 if (read_format != pos->attr.read_format)
705 return false;
706 }
707
708 /* PERF_SAMPLE_READ imples PERF_FORMAT_ID. */
709 if ((sample_type & PERF_SAMPLE_READ) &&
710 !(read_format & PERF_FORMAT_ID)) {
711 return false;
712 }
713
714 return true;
715}
716
717u64 perf_evlist__read_format(struct perf_evlist *evlist)
718{
719 struct perf_evsel *first = perf_evlist__first(evlist);
720 return first->attr.read_format;
721}
722
665u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist) 723u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist)
666{ 724{
667 struct perf_evsel *first = perf_evlist__first(evlist); 725 struct perf_evsel *first = perf_evlist__first(evlist);
@@ -779,13 +837,6 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
779 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC); 837 fcntl(go_pipe[0], F_SETFD, FD_CLOEXEC);
780 838
781 /* 839 /*
782 * Do a dummy execvp to get the PLT entry resolved,
783 * so we avoid the resolver overhead on the real
784 * execvp call.
785 */
786 execvp("", (char **)argv);
787
788 /*
789 * Tell the parent we're ready to go 840 * Tell the parent we're ready to go
790 */ 841 */
791 close(child_ready_pipe[1]); 842 close(child_ready_pipe[1]);
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index 0583d36252be..327ababa67b6 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -78,6 +78,8 @@ void perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd);
78 78
79struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id); 79struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
80 80
81struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
82
81union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx); 83union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
82 84
83int perf_evlist__open(struct perf_evlist *evlist); 85int perf_evlist__open(struct perf_evlist *evlist);
@@ -118,6 +120,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist);
118void __perf_evlist__set_leader(struct list_head *list); 120void __perf_evlist__set_leader(struct list_head *list);
119void perf_evlist__set_leader(struct perf_evlist *evlist); 121void perf_evlist__set_leader(struct perf_evlist *evlist);
120 122
123u64 perf_evlist__read_format(struct perf_evlist *evlist);
121u64 perf_evlist__sample_type(struct perf_evlist *evlist); 124u64 perf_evlist__sample_type(struct perf_evlist *evlist);
122bool perf_evlist__sample_id_all(struct perf_evlist *evlist); 125bool perf_evlist__sample_id_all(struct perf_evlist *evlist);
123u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist); 126u16 perf_evlist__id_hdr_size(struct perf_evlist *evlist);
@@ -127,6 +130,7 @@ int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *even
127 130
128bool perf_evlist__valid_sample_type(struct perf_evlist *evlist); 131bool perf_evlist__valid_sample_type(struct perf_evlist *evlist);
129bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist); 132bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist);
133bool perf_evlist__valid_read_format(struct perf_evlist *evlist);
130 134
131void perf_evlist__splice_list_tail(struct perf_evlist *evlist, 135void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
132 struct list_head *list, 136 struct list_head *list,
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 8bed0c1a1399..960394ea1e3a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -490,6 +490,7 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
490void perf_evsel__config(struct perf_evsel *evsel, 490void perf_evsel__config(struct perf_evsel *evsel,
491 struct perf_record_opts *opts) 491 struct perf_record_opts *opts)
492{ 492{
493 struct perf_evsel *leader = evsel->leader;
493 struct perf_event_attr *attr = &evsel->attr; 494 struct perf_event_attr *attr = &evsel->attr;
494 int track = !evsel->idx; /* only the first counter needs these */ 495 int track = !evsel->idx; /* only the first counter needs these */
495 496
@@ -499,6 +500,25 @@ void perf_evsel__config(struct perf_evsel *evsel,
499 perf_evsel__set_sample_bit(evsel, IP); 500 perf_evsel__set_sample_bit(evsel, IP);
500 perf_evsel__set_sample_bit(evsel, TID); 501 perf_evsel__set_sample_bit(evsel, TID);
501 502
503 if (evsel->sample_read) {
504 perf_evsel__set_sample_bit(evsel, READ);
505
506 /*
507 * We need ID even in case of single event, because
508 * PERF_SAMPLE_READ process ID specific data.
509 */
510 perf_evsel__set_sample_id(evsel);
511
512 /*
513 * Apply group format only if we belong to group
514 * with more than one members.
515 */
516 if (leader->nr_members > 1) {
517 attr->read_format |= PERF_FORMAT_GROUP;
518 attr->inherit = 0;
519 }
520 }
521
502 /* 522 /*
503 * We default some events to a 1 default interval. But keep 523 * We default some events to a 1 default interval. But keep
504 * it a weak assumption overridable by the user. 524 * it a weak assumption overridable by the user.
@@ -514,6 +534,15 @@ void perf_evsel__config(struct perf_evsel *evsel,
514 } 534 }
515 } 535 }
516 536
537 /*
538 * Disable sampling for all group members other
539 * than leader in case leader 'leads' the sampling.
540 */
541 if ((leader != evsel) && leader->sample_read) {
542 attr->sample_freq = 0;
543 attr->sample_period = 0;
544 }
545
517 if (opts->no_samples) 546 if (opts->no_samples)
518 attr->sample_freq = 0; 547 attr->sample_freq = 0;
519 548
@@ -605,15 +634,15 @@ int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
605 return evsel->fd != NULL ? 0 : -ENOMEM; 634 return evsel->fd != NULL ? 0 : -ENOMEM;
606} 635}
607 636
608int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 637static int perf_evsel__run_ioctl(struct perf_evsel *evsel, int ncpus, int nthreads,
609 const char *filter) 638 int ioc, void *arg)
610{ 639{
611 int cpu, thread; 640 int cpu, thread;
612 641
613 for (cpu = 0; cpu < ncpus; cpu++) { 642 for (cpu = 0; cpu < ncpus; cpu++) {
614 for (thread = 0; thread < nthreads; thread++) { 643 for (thread = 0; thread < nthreads; thread++) {
615 int fd = FD(evsel, cpu, thread), 644 int fd = FD(evsel, cpu, thread),
616 err = ioctl(fd, PERF_EVENT_IOC_SET_FILTER, filter); 645 err = ioctl(fd, ioc, arg);
617 646
618 if (err) 647 if (err)
619 return err; 648 return err;
@@ -623,6 +652,21 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
623 return 0; 652 return 0;
624} 653}
625 654
655int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
656 const char *filter)
657{
658 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
659 PERF_EVENT_IOC_SET_FILTER,
660 (void *)filter);
661}
662
663int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
664{
665 return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
666 PERF_EVENT_IOC_ENABLE,
667 0);
668}
669
626int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads) 670int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
627{ 671{
628 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id)); 672 evsel->sample_id = xyarray__new(ncpus, nthreads, sizeof(struct perf_sample_id));
@@ -1096,8 +1140,34 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1096 } 1140 }
1097 1141
1098 if (type & PERF_SAMPLE_READ) { 1142 if (type & PERF_SAMPLE_READ) {
1099 fprintf(stderr, "PERF_SAMPLE_READ is unsupported for now\n"); 1143 u64 read_format = evsel->attr.read_format;
1100 return -1; 1144
1145 if (read_format & PERF_FORMAT_GROUP)
1146 data->read.group.nr = *array;
1147 else
1148 data->read.one.value = *array;
1149
1150 array++;
1151
1152 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
1153 data->read.time_enabled = *array;
1154 array++;
1155 }
1156
1157 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
1158 data->read.time_running = *array;
1159 array++;
1160 }
1161
1162 /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
1163 if (read_format & PERF_FORMAT_GROUP) {
1164 data->read.group.values = (struct sample_read_value *) array;
1165 array = (void *) array + data->read.group.nr *
1166 sizeof(struct sample_read_value);
1167 } else {
1168 data->read.one.id = *array;
1169 array++;
1170 }
1101 } 1171 }
1102 1172
1103 if (type & PERF_SAMPLE_CALLCHAIN) { 1173 if (type & PERF_SAMPLE_CALLCHAIN) {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 3f156ccc1acb..532a5f925da0 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -38,6 +38,9 @@ struct perf_sample_id {
38 struct hlist_node node; 38 struct hlist_node node;
39 u64 id; 39 u64 id;
40 struct perf_evsel *evsel; 40 struct perf_evsel *evsel;
41
42 /* Holds total ID period value for PERF_SAMPLE_READ processing. */
43 u64 period;
41}; 44};
42 45
43/** struct perf_evsel - event selector 46/** struct perf_evsel - event selector
@@ -76,6 +79,7 @@ struct perf_evsel {
76 /* parse modifier helper */ 79 /* parse modifier helper */
77 int exclude_GH; 80 int exclude_GH;
78 int nr_members; 81 int nr_members;
82 int sample_read;
79 struct perf_evsel *leader; 83 struct perf_evsel *leader;
80 char *group_name; 84 char *group_name;
81}; 85};
@@ -142,6 +146,7 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel);
142 146
143int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 147int perf_evsel__set_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
144 const char *filter); 148 const char *filter);
149int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads);
145 150
146int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 151int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
147 struct cpu_map *cpus); 152 struct cpu_map *cpus);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index f9f9d6381b9a..6fcc358138ae 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -628,10 +628,8 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
628 struct map *map = machine->vmlinux_maps[type]; 628 struct map *map = machine->vmlinux_maps[type];
629 int ret = dso__load_vmlinux_path(map->dso, map, filter); 629 int ret = dso__load_vmlinux_path(map->dso, map, filter);
630 630
631 if (ret > 0) { 631 if (ret > 0)
632 dso__set_loaded(map->dso, type); 632 dso__set_loaded(map->dso, type);
633 map__reloc_vmlinux(map);
634 }
635 633
636 return ret; 634 return ret;
637} 635}
@@ -808,7 +806,10 @@ static int machine__create_modules(struct machine *machine)
808 free(line); 806 free(line);
809 fclose(file); 807 fclose(file);
810 808
811 return machine__set_modules_path(machine); 809 if (machine__set_modules_path(machine) < 0) {
810 pr_debug("Problems setting modules path maps, continuing anyway...\n");
811 }
812 return 0;
812 813
813out_delete_line: 814out_delete_line:
814 free(line); 815 free(line);
@@ -858,6 +859,18 @@ static void machine__set_kernel_mmap_len(struct machine *machine,
858 } 859 }
859} 860}
860 861
862static bool machine__uses_kcore(struct machine *machine)
863{
864 struct dso *dso;
865
866 list_for_each_entry(dso, &machine->kernel_dsos, node) {
867 if (dso__is_kcore(dso))
868 return true;
869 }
870
871 return false;
872}
873
861static int machine__process_kernel_mmap_event(struct machine *machine, 874static int machine__process_kernel_mmap_event(struct machine *machine,
862 union perf_event *event) 875 union perf_event *event)
863{ 876{
@@ -866,6 +879,10 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
866 enum dso_kernel_type kernel_type; 879 enum dso_kernel_type kernel_type;
867 bool is_kernel_mmap; 880 bool is_kernel_mmap;
868 881
882 /* If we have maps from kcore then we do not need or want any others */
883 if (machine__uses_kcore(machine))
884 return 0;
885
869 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); 886 machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
870 if (machine__is_host(machine)) 887 if (machine__is_host(machine))
871 kernel_type = DSO_TYPE_KERNEL; 888 kernel_type = DSO_TYPE_KERNEL;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 8bcdf9e54089..9e8304ca343e 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -182,12 +182,6 @@ int map__load(struct map *map, symbol_filter_t filter)
182#endif 182#endif
183 return -1; 183 return -1;
184 } 184 }
185 /*
186 * Only applies to the kernel, as its symtabs aren't relative like the
187 * module ones.
188 */
189 if (map->dso->kernel)
190 map__reloc_vmlinux(map);
191 185
192 return 0; 186 return 0;
193} 187}
@@ -254,14 +248,18 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp)
254 248
255/* 249/*
256 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN. 250 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
257 * map->dso->adjust_symbols==1 for ET_EXEC-like cases. 251 * map->dso->adjust_symbols==1 for ET_EXEC-like cases except ET_REL which is
252 * relative to section start.
258 */ 253 */
259u64 map__rip_2objdump(struct map *map, u64 rip) 254u64 map__rip_2objdump(struct map *map, u64 rip)
260{ 255{
261 u64 addr = map->dso->adjust_symbols ? 256 if (!map->dso->adjust_symbols)
262 map->unmap_ip(map, rip) : /* RIP -> IP */ 257 return rip;
263 rip; 258
264 return addr; 259 if (map->dso->rel)
260 return rip - map->pgoff;
261
262 return map->unmap_ip(map, rip);
265} 263}
266 264
267void map_groups__init(struct map_groups *mg) 265void map_groups__init(struct map_groups *mg)
@@ -513,35 +511,6 @@ int map_groups__clone(struct map_groups *mg,
513 return 0; 511 return 0;
514} 512}
515 513
516static u64 map__reloc_map_ip(struct map *map, u64 ip)
517{
518 return ip + (s64)map->pgoff;
519}
520
521static u64 map__reloc_unmap_ip(struct map *map, u64 ip)
522{
523 return ip - (s64)map->pgoff;
524}
525
526void map__reloc_vmlinux(struct map *map)
527{
528 struct kmap *kmap = map__kmap(map);
529 s64 reloc;
530
531 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr)
532 return;
533
534 reloc = (kmap->ref_reloc_sym->unrelocated_addr -
535 kmap->ref_reloc_sym->addr);
536
537 if (!reloc)
538 return;
539
540 map->map_ip = map__reloc_map_ip;
541 map->unmap_ip = map__reloc_unmap_ip;
542 map->pgoff = reloc;
543}
544
545void maps__insert(struct rb_root *maps, struct map *map) 514void maps__insert(struct rb_root *maps, struct map *map)
546{ 515{
547 struct rb_node **p = &maps->rb_node; 516 struct rb_node **p = &maps->rb_node;
@@ -586,3 +555,21 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
586 555
587 return NULL; 556 return NULL;
588} 557}
558
559struct map *maps__first(struct rb_root *maps)
560{
561 struct rb_node *first = rb_first(maps);
562
563 if (first)
564 return rb_entry(first, struct map, rb_node);
565 return NULL;
566}
567
568struct map *maps__next(struct map *map)
569{
570 struct rb_node *next = rb_next(&map->rb_node);
571
572 if (next)
573 return rb_entry(next, struct map, rb_node);
574 return NULL;
575}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index a887f2c9dfbb..2cc93cbf0e17 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -112,6 +112,8 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg,
112void maps__insert(struct rb_root *maps, struct map *map); 112void maps__insert(struct rb_root *maps, struct map *map);
113void maps__remove(struct rb_root *maps, struct map *map); 113void maps__remove(struct rb_root *maps, struct map *map);
114struct map *maps__find(struct rb_root *maps, u64 addr); 114struct map *maps__find(struct rb_root *maps, u64 addr);
115struct map *maps__first(struct rb_root *maps);
116struct map *maps__next(struct map *map);
115void map_groups__init(struct map_groups *mg); 117void map_groups__init(struct map_groups *mg);
116void map_groups__exit(struct map_groups *mg); 118void map_groups__exit(struct map_groups *mg);
117int map_groups__clone(struct map_groups *mg, 119int map_groups__clone(struct map_groups *mg,
@@ -139,6 +141,17 @@ static inline struct map *map_groups__find(struct map_groups *mg,
139 return maps__find(&mg->maps[type], addr); 141 return maps__find(&mg->maps[type], addr);
140} 142}
141 143
144static inline struct map *map_groups__first(struct map_groups *mg,
145 enum map_type type)
146{
147 return maps__first(&mg->maps[type]);
148}
149
150static inline struct map *map_groups__next(struct map *map)
151{
152 return maps__next(map);
153}
154
142struct symbol *map_groups__find_symbol(struct map_groups *mg, 155struct symbol *map_groups__find_symbol(struct map_groups *mg,
143 enum map_type type, u64 addr, 156 enum map_type type, u64 addr,
144 struct map **mapp, 157 struct map **mapp,
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 2c460ede0a69..9cba92386a82 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -687,6 +687,8 @@ struct event_modifier {
687 int eG; 687 int eG;
688 int precise; 688 int precise;
689 int exclude_GH; 689 int exclude_GH;
690 int sample_read;
691 int pinned;
690}; 692};
691 693
692static int get_event_modifier(struct event_modifier *mod, char *str, 694static int get_event_modifier(struct event_modifier *mod, char *str,
@@ -698,6 +700,8 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
698 int eH = evsel ? evsel->attr.exclude_host : 0; 700 int eH = evsel ? evsel->attr.exclude_host : 0;
699 int eG = evsel ? evsel->attr.exclude_guest : 0; 701 int eG = evsel ? evsel->attr.exclude_guest : 0;
700 int precise = evsel ? evsel->attr.precise_ip : 0; 702 int precise = evsel ? evsel->attr.precise_ip : 0;
703 int sample_read = 0;
704 int pinned = evsel ? evsel->attr.pinned : 0;
701 705
702 int exclude = eu | ek | eh; 706 int exclude = eu | ek | eh;
703 int exclude_GH = evsel ? evsel->exclude_GH : 0; 707 int exclude_GH = evsel ? evsel->exclude_GH : 0;
@@ -730,6 +734,10 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
730 /* use of precise requires exclude_guest */ 734 /* use of precise requires exclude_guest */
731 if (!exclude_GH) 735 if (!exclude_GH)
732 eG = 1; 736 eG = 1;
737 } else if (*str == 'S') {
738 sample_read = 1;
739 } else if (*str == 'D') {
740 pinned = 1;
733 } else 741 } else
734 break; 742 break;
735 743
@@ -756,6 +764,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
756 mod->eG = eG; 764 mod->eG = eG;
757 mod->precise = precise; 765 mod->precise = precise;
758 mod->exclude_GH = exclude_GH; 766 mod->exclude_GH = exclude_GH;
767 mod->sample_read = sample_read;
768 mod->pinned = pinned;
769
759 return 0; 770 return 0;
760} 771}
761 772
@@ -768,7 +779,7 @@ static int check_modifier(char *str)
768 char *p = str; 779 char *p = str;
769 780
770 /* The sizeof includes 0 byte as well. */ 781 /* The sizeof includes 0 byte as well. */
771 if (strlen(str) > (sizeof("ukhGHppp") - 1)) 782 if (strlen(str) > (sizeof("ukhGHpppSD") - 1))
772 return -1; 783 return -1;
773 784
774 while (*p) { 785 while (*p) {
@@ -806,6 +817,10 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
806 evsel->attr.exclude_host = mod.eH; 817 evsel->attr.exclude_host = mod.eH;
807 evsel->attr.exclude_guest = mod.eG; 818 evsel->attr.exclude_guest = mod.eG;
808 evsel->exclude_GH = mod.exclude_GH; 819 evsel->exclude_GH = mod.exclude_GH;
820 evsel->sample_read = mod.sample_read;
821
822 if (perf_evsel__is_group_leader(evsel))
823 evsel->attr.pinned = mod.pinned;
809 } 824 }
810 825
811 return 0; 826 return 0;
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index e9d1134c2c68..0790452658b3 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -82,7 +82,8 @@ num_hex 0x[a-fA-F0-9]+
82num_raw_hex [a-fA-F0-9]+ 82num_raw_hex [a-fA-F0-9]+
83name [a-zA-Z_*?][a-zA-Z0-9_*?]* 83name [a-zA-Z_*?][a-zA-Z0-9_*?]*
84name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]* 84name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?]*
85modifier_event [ukhpGH]+ 85/* If you add a modifier you need to update check_modifier() */
86modifier_event [ukhpGHSD]+
86modifier_bp [rwx]{1,3} 87modifier_bp [rwx]{1,3}
87 88
88%% 89%%
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 272c9cf57122..dedaeb22b7b9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -71,6 +71,11 @@ static int perf_session__open(struct perf_session *self, bool force)
71 goto out_close; 71 goto out_close;
72 } 72 }
73 73
74 if (!perf_evlist__valid_read_format(self->evlist)) {
75 pr_err("non matching read_format");
76 goto out_close;
77 }
78
74 self->size = input_stat.st_size; 79 self->size = input_stat.st_size;
75 return 0; 80 return 0;
76 81
@@ -245,7 +250,7 @@ static int process_finished_round(struct perf_tool *tool,
245 union perf_event *event, 250 union perf_event *event,
246 struct perf_session *session); 251 struct perf_session *session);
247 252
248static void perf_tool__fill_defaults(struct perf_tool *tool) 253void perf_tool__fill_defaults(struct perf_tool *tool)
249{ 254{
250 if (tool->sample == NULL) 255 if (tool->sample == NULL)
251 tool->sample = process_event_sample_stub; 256 tool->sample = process_event_sample_stub;
@@ -490,7 +495,7 @@ static int perf_session_deliver_event(struct perf_session *session,
490 u64 file_offset); 495 u64 file_offset);
491 496
492static int flush_sample_queue(struct perf_session *s, 497static int flush_sample_queue(struct perf_session *s,
493 struct perf_tool *tool) 498 struct perf_tool *tool)
494{ 499{
495 struct ordered_samples *os = &s->ordered_samples; 500 struct ordered_samples *os = &s->ordered_samples;
496 struct list_head *head = &os->samples; 501 struct list_head *head = &os->samples;
@@ -638,7 +643,7 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
638 643
639#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue)) 644#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
640 645
641static int perf_session_queue_event(struct perf_session *s, union perf_event *event, 646int perf_session_queue_event(struct perf_session *s, union perf_event *event,
642 struct perf_sample *sample, u64 file_offset) 647 struct perf_sample *sample, u64 file_offset)
643{ 648{
644 struct ordered_samples *os = &s->ordered_samples; 649 struct ordered_samples *os = &s->ordered_samples;
@@ -749,6 +754,36 @@ static void perf_session__print_tstamp(struct perf_session *session,
749 printf("%" PRIu64 " ", sample->time); 754 printf("%" PRIu64 " ", sample->time);
750} 755}
751 756
757static void sample_read__printf(struct perf_sample *sample, u64 read_format)
758{
759 printf("... sample_read:\n");
760
761 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
762 printf("...... time enabled %016" PRIx64 "\n",
763 sample->read.time_enabled);
764
765 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
766 printf("...... time running %016" PRIx64 "\n",
767 sample->read.time_running);
768
769 if (read_format & PERF_FORMAT_GROUP) {
770 u64 i;
771
772 printf(".... group nr %" PRIu64 "\n", sample->read.group.nr);
773
774 for (i = 0; i < sample->read.group.nr; i++) {
775 struct sample_read_value *value;
776
777 value = &sample->read.group.values[i];
778 printf("..... id %016" PRIx64
779 ", value %016" PRIx64 "\n",
780 value->id, value->value);
781 }
782 } else
783 printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
784 sample->read.one.id, sample->read.one.value);
785}
786
752static void dump_event(struct perf_session *session, union perf_event *event, 787static void dump_event(struct perf_session *session, union perf_event *event,
753 u64 file_offset, struct perf_sample *sample) 788 u64 file_offset, struct perf_sample *sample)
754{ 789{
@@ -798,6 +833,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
798 833
799 if (sample_type & PERF_SAMPLE_DATA_SRC) 834 if (sample_type & PERF_SAMPLE_DATA_SRC)
800 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src); 835 printf(" . data_src: 0x%"PRIx64"\n", sample->data_src);
836
837 if (sample_type & PERF_SAMPLE_READ)
838 sample_read__printf(sample, evsel->attr.read_format);
801} 839}
802 840
803static struct machine * 841static struct machine *
@@ -822,6 +860,75 @@ static struct machine *
822 return &session->machines.host; 860 return &session->machines.host;
823} 861}
824 862
863static int deliver_sample_value(struct perf_session *session,
864 struct perf_tool *tool,
865 union perf_event *event,
866 struct perf_sample *sample,
867 struct sample_read_value *v,
868 struct machine *machine)
869{
870 struct perf_sample_id *sid;
871
872 sid = perf_evlist__id2sid(session->evlist, v->id);
873 if (sid) {
874 sample->id = v->id;
875 sample->period = v->value - sid->period;
876 sid->period = v->value;
877 }
878
879 if (!sid || sid->evsel == NULL) {
880 ++session->stats.nr_unknown_id;
881 return 0;
882 }
883
884 return tool->sample(tool, event, sample, sid->evsel, machine);
885}
886
887static int deliver_sample_group(struct perf_session *session,
888 struct perf_tool *tool,
889 union perf_event *event,
890 struct perf_sample *sample,
891 struct machine *machine)
892{
893 int ret = -EINVAL;
894 u64 i;
895
896 for (i = 0; i < sample->read.group.nr; i++) {
897 ret = deliver_sample_value(session, tool, event, sample,
898 &sample->read.group.values[i],
899 machine);
900 if (ret)
901 break;
902 }
903
904 return ret;
905}
906
907static int
908perf_session__deliver_sample(struct perf_session *session,
909 struct perf_tool *tool,
910 union perf_event *event,
911 struct perf_sample *sample,
912 struct perf_evsel *evsel,
913 struct machine *machine)
914{
915 /* We know evsel != NULL. */
916 u64 sample_type = evsel->attr.sample_type;
917 u64 read_format = evsel->attr.read_format;
918
919 /* Standard sample delievery. */
920 if (!(sample_type & PERF_SAMPLE_READ))
921 return tool->sample(tool, event, sample, evsel, machine);
922
923 /* For PERF_SAMPLE_READ we have either single or group mode. */
924 if (read_format & PERF_FORMAT_GROUP)
925 return deliver_sample_group(session, tool, event, sample,
926 machine);
927 else
928 return deliver_sample_value(session, tool, event, sample,
929 &sample->read.one, machine);
930}
931
825static int perf_session_deliver_event(struct perf_session *session, 932static int perf_session_deliver_event(struct perf_session *session,
826 union perf_event *event, 933 union perf_event *event,
827 struct perf_sample *sample, 934 struct perf_sample *sample,
@@ -864,7 +971,8 @@ static int perf_session_deliver_event(struct perf_session *session,
864 ++session->stats.nr_unprocessable_samples; 971 ++session->stats.nr_unprocessable_samples;
865 return 0; 972 return 0;
866 } 973 }
867 return tool->sample(tool, event, sample, evsel, machine); 974 return perf_session__deliver_sample(session, tool, event,
975 sample, evsel, machine);
868 case PERF_RECORD_MMAP: 976 case PERF_RECORD_MMAP:
869 return tool->mmap(tool, event, sample, machine); 977 return tool->mmap(tool, event, sample, machine);
870 case PERF_RECORD_COMM: 978 case PERF_RECORD_COMM:
@@ -1411,8 +1519,13 @@ void perf_evsel__print_ip(struct perf_evsel *evsel, union perf_event *event,
1411 printf("\t%16" PRIx64, node->ip); 1519 printf("\t%16" PRIx64, node->ip);
1412 if (print_sym) { 1520 if (print_sym) {
1413 printf(" "); 1521 printf(" ");
1414 symbol__fprintf_symname(node->sym, stdout); 1522 if (print_symoffset) {
1523 al.addr = node->ip;
1524 symbol__fprintf_symname_offs(node->sym, &al, stdout);
1525 } else
1526 symbol__fprintf_symname(node->sym, stdout);
1415 } 1527 }
1528
1416 if (print_dso) { 1529 if (print_dso) {
1417 printf(" ("); 1530 printf(" (");
1418 map__fprintf_dsoname(node->map, stdout); 1531 map__fprintf_dsoname(node->map, stdout);
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index ad8d3d4ef14e..8bed17e64a96 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -56,6 +56,11 @@ int __perf_session__process_events(struct perf_session *self,
56int perf_session__process_events(struct perf_session *self, 56int perf_session__process_events(struct perf_session *self,
57 struct perf_tool *tool); 57 struct perf_tool *tool);
58 58
59int perf_session_queue_event(struct perf_session *s, union perf_event *event,
60 struct perf_sample *sample, u64 file_offset);
61
62void perf_tool__fill_defaults(struct perf_tool *tool);
63
59int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel, 64int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
60 struct thread *thread, 65 struct thread *thread,
61 struct ip_callchain *chain, 66 struct ip_callchain *chain,
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 7c59c28afcc5..6506b3dfb605 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -10,6 +10,12 @@ void update_stats(struct stats *stats, u64 val)
10 delta = val - stats->mean; 10 delta = val - stats->mean;
11 stats->mean += delta / stats->n; 11 stats->mean += delta / stats->n;
12 stats->M2 += delta*(val - stats->mean); 12 stats->M2 += delta*(val - stats->mean);
13
14 if (val > stats->max)
15 stats->max = val;
16
17 if (val < stats->min)
18 stats->min = val;
13} 19}
14 20
15double avg_stats(struct stats *stats) 21double avg_stats(struct stats *stats)
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 588367c3c767..ae8ccd7227cf 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -6,6 +6,7 @@
6struct stats 6struct stats
7{ 7{
8 double n, mean, M2; 8 double n, mean, M2;
9 u64 max, min;
9}; 10};
10 11
11void update_stats(struct stats *stats, u64 val); 12void update_stats(struct stats *stats, u64 val);
@@ -13,4 +14,12 @@ double avg_stats(struct stats *stats);
13double stddev_stats(struct stats *stats); 14double stddev_stats(struct stats *stats);
14double rel_stddev_stats(double stddev, double avg); 15double rel_stddev_stats(double stddev, double avg);
15 16
17static inline void init_stats(struct stats *stats)
18{
19 stats->n = 0.0;
20 stats->mean = 0.0;
21 stats->M2 = 0.0;
22 stats->min = (u64) -1;
23 stats->max = 0;
24}
16#endif 25#endif
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 4b12bf850325..a7b9ab557380 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -599,11 +599,13 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
599 if (dso->kernel == DSO_TYPE_USER) { 599 if (dso->kernel == DSO_TYPE_USER) {
600 GElf_Shdr shdr; 600 GElf_Shdr shdr;
601 ss->adjust_symbols = (ehdr.e_type == ET_EXEC || 601 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
602 ehdr.e_type == ET_REL ||
602 elf_section_by_name(elf, &ehdr, &shdr, 603 elf_section_by_name(elf, &ehdr, &shdr,
603 ".gnu.prelink_undo", 604 ".gnu.prelink_undo",
604 NULL) != NULL); 605 NULL) != NULL);
605 } else { 606 } else {
606 ss->adjust_symbols = 0; 607 ss->adjust_symbols = ehdr.e_type == ET_EXEC ||
608 ehdr.e_type == ET_REL;
607 } 609 }
608 610
609 ss->name = strdup(name); 611 ss->name = strdup(name);
@@ -624,6 +626,37 @@ out_close:
624 return err; 626 return err;
625} 627}
626 628
629/**
630 * ref_reloc_sym_not_found - has kernel relocation symbol been found.
631 * @kmap: kernel maps and relocation reference symbol
632 *
633 * This function returns %true if we are dealing with the kernel maps and the
634 * relocation reference symbol has not yet been found. Otherwise %false is
635 * returned.
636 */
637static bool ref_reloc_sym_not_found(struct kmap *kmap)
638{
639 return kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
640 !kmap->ref_reloc_sym->unrelocated_addr;
641}
642
643/**
644 * ref_reloc - kernel relocation offset.
645 * @kmap: kernel maps and relocation reference symbol
646 *
647 * This function returns the offset of kernel addresses as determined by using
648 * the relocation reference symbol i.e. if the kernel has not been relocated
649 * then the return value is zero.
650 */
651static u64 ref_reloc(struct kmap *kmap)
652{
653 if (kmap && kmap->ref_reloc_sym &&
654 kmap->ref_reloc_sym->unrelocated_addr)
655 return kmap->ref_reloc_sym->addr -
656 kmap->ref_reloc_sym->unrelocated_addr;
657 return 0;
658}
659
627int dso__load_sym(struct dso *dso, struct map *map, 660int dso__load_sym(struct dso *dso, struct map *map,
628 struct symsrc *syms_ss, struct symsrc *runtime_ss, 661 struct symsrc *syms_ss, struct symsrc *runtime_ss,
629 symbol_filter_t filter, int kmodule) 662 symbol_filter_t filter, int kmodule)
@@ -642,8 +675,17 @@ int dso__load_sym(struct dso *dso, struct map *map,
642 Elf_Scn *sec, *sec_strndx; 675 Elf_Scn *sec, *sec_strndx;
643 Elf *elf; 676 Elf *elf;
644 int nr = 0; 677 int nr = 0;
678 bool remap_kernel = false, adjust_kernel_syms = false;
645 679
646 dso->symtab_type = syms_ss->type; 680 dso->symtab_type = syms_ss->type;
681 dso->rel = syms_ss->ehdr.e_type == ET_REL;
682
683 /*
684 * Modules may already have symbols from kallsyms, but those symbols
685 * have the wrong values for the dso maps, so remove them.
686 */
687 if (kmodule && syms_ss->symtab)
688 symbols__delete(&dso->symbols[map->type]);
647 689
648 if (!syms_ss->symtab) { 690 if (!syms_ss->symtab) {
649 syms_ss->symtab = syms_ss->dynsym; 691 syms_ss->symtab = syms_ss->dynsym;
@@ -681,7 +723,31 @@ int dso__load_sym(struct dso *dso, struct map *map,
681 nr_syms = shdr.sh_size / shdr.sh_entsize; 723 nr_syms = shdr.sh_size / shdr.sh_entsize;
682 724
683 memset(&sym, 0, sizeof(sym)); 725 memset(&sym, 0, sizeof(sym));
684 dso->adjust_symbols = runtime_ss->adjust_symbols; 726
727 /*
728 * The kernel relocation symbol is needed in advance in order to adjust
729 * kernel maps correctly.
730 */
731 if (ref_reloc_sym_not_found(kmap)) {
732 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
733 const char *elf_name = elf_sym__name(&sym, symstrs);
734
735 if (strcmp(elf_name, kmap->ref_reloc_sym->name))
736 continue;
737 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
738 break;
739 }
740 }
741
742 dso->adjust_symbols = runtime_ss->adjust_symbols || ref_reloc(kmap);
743 /*
744 * Initial kernel and module mappings do not map to the dso. For
745 * function mappings, flag the fixups.
746 */
747 if (map->type == MAP__FUNCTION && (dso->kernel || kmodule)) {
748 remap_kernel = true;
749 adjust_kernel_syms = dso->adjust_symbols;
750 }
685 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { 751 elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) {
686 struct symbol *f; 752 struct symbol *f;
687 const char *elf_name = elf_sym__name(&sym, symstrs); 753 const char *elf_name = elf_sym__name(&sym, symstrs);
@@ -690,10 +756,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
690 const char *section_name; 756 const char *section_name;
691 bool used_opd = false; 757 bool used_opd = false;
692 758
693 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
694 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
695 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
696
697 if (!is_label && !elf_sym__is_a(&sym, map->type)) 759 if (!is_label && !elf_sym__is_a(&sym, map->type))
698 continue; 760 continue;
699 761
@@ -745,20 +807,55 @@ int dso__load_sym(struct dso *dso, struct map *map,
745 (sym.st_value & 1)) 807 (sym.st_value & 1))
746 --sym.st_value; 808 --sym.st_value;
747 809
748 if (dso->kernel != DSO_TYPE_USER || kmodule) { 810 if (dso->kernel || kmodule) {
749 char dso_name[PATH_MAX]; 811 char dso_name[PATH_MAX];
750 812
813 /* Adjust symbol to map to file offset */
814 if (adjust_kernel_syms)
815 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
816
751 if (strcmp(section_name, 817 if (strcmp(section_name,
752 (curr_dso->short_name + 818 (curr_dso->short_name +
753 dso->short_name_len)) == 0) 819 dso->short_name_len)) == 0)
754 goto new_symbol; 820 goto new_symbol;
755 821
756 if (strcmp(section_name, ".text") == 0) { 822 if (strcmp(section_name, ".text") == 0) {
823 /*
824 * The initial kernel mapping is based on
825 * kallsyms and identity maps. Overwrite it to
826 * map to the kernel dso.
827 */
828 if (remap_kernel && dso->kernel) {
829 remap_kernel = false;
830 map->start = shdr.sh_addr +
831 ref_reloc(kmap);
832 map->end = map->start + shdr.sh_size;
833 map->pgoff = shdr.sh_offset;
834 map->map_ip = map__map_ip;
835 map->unmap_ip = map__unmap_ip;
836 /* Ensure maps are correctly ordered */
837 map_groups__remove(kmap->kmaps, map);
838 map_groups__insert(kmap->kmaps, map);
839 }
840
841 /*
842 * The initial module mapping is based on
843 * /proc/modules mapped to offset zero.
844 * Overwrite it to map to the module dso.
845 */
846 if (remap_kernel && kmodule) {
847 remap_kernel = false;
848 map->pgoff = shdr.sh_offset;
849 }
850
757 curr_map = map; 851 curr_map = map;
758 curr_dso = dso; 852 curr_dso = dso;
759 goto new_symbol; 853 goto new_symbol;
760 } 854 }
761 855
856 if (!kmap)
857 goto new_symbol;
858
762 snprintf(dso_name, sizeof(dso_name), 859 snprintf(dso_name, sizeof(dso_name),
763 "%s%s", dso->short_name, section_name); 860 "%s%s", dso->short_name, section_name);
764 861
@@ -781,8 +878,16 @@ int dso__load_sym(struct dso *dso, struct map *map,
781 dso__delete(curr_dso); 878 dso__delete(curr_dso);
782 goto out_elf_end; 879 goto out_elf_end;
783 } 880 }
784 curr_map->map_ip = identity__map_ip; 881 if (adjust_kernel_syms) {
785 curr_map->unmap_ip = identity__map_ip; 882 curr_map->start = shdr.sh_addr +
883 ref_reloc(kmap);
884 curr_map->end = curr_map->start +
885 shdr.sh_size;
886 curr_map->pgoff = shdr.sh_offset;
887 } else {
888 curr_map->map_ip = identity__map_ip;
889 curr_map->unmap_ip = identity__map_ip;
890 }
786 curr_dso->symtab_type = dso->symtab_type; 891 curr_dso->symtab_type = dso->symtab_type;
787 map_groups__insert(kmap->kmaps, curr_map); 892 map_groups__insert(kmap->kmaps, curr_map);
788 dsos__add(&dso->node, curr_dso); 893 dsos__add(&dso->node, curr_dso);
@@ -846,6 +951,57 @@ out_elf_end:
846 return err; 951 return err;
847} 952}
848 953
954static int elf_read_maps(Elf *elf, bool exe, mapfn_t mapfn, void *data)
955{
956 GElf_Phdr phdr;
957 size_t i, phdrnum;
958 int err;
959 u64 sz;
960
961 if (elf_getphdrnum(elf, &phdrnum))
962 return -1;
963
964 for (i = 0; i < phdrnum; i++) {
965 if (gelf_getphdr(elf, i, &phdr) == NULL)
966 return -1;
967 if (phdr.p_type != PT_LOAD)
968 continue;
969 if (exe) {
970 if (!(phdr.p_flags & PF_X))
971 continue;
972 } else {
973 if (!(phdr.p_flags & PF_R))
974 continue;
975 }
976 sz = min(phdr.p_memsz, phdr.p_filesz);
977 if (!sz)
978 continue;
979 err = mapfn(phdr.p_vaddr, sz, phdr.p_offset, data);
980 if (err)
981 return err;
982 }
983 return 0;
984}
985
986int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
987 bool *is_64_bit)
988{
989 int err;
990 Elf *elf;
991
992 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
993 if (elf == NULL)
994 return -1;
995
996 if (is_64_bit)
997 *is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
998
999 err = elf_read_maps(elf, exe, mapfn, data);
1000
1001 elf_end(elf);
1002 return err;
1003}
1004
849void symbol__elf_init(void) 1005void symbol__elf_init(void)
850{ 1006{
851 elf_version(EV_CURRENT); 1007 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index a7390cde63bc..3a802c300fc5 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -301,6 +301,13 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
301 return 0; 301 return 0;
302} 302}
303 303
304int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused,
305 mapfn_t mapfn __maybe_unused, void *data __maybe_unused,
306 bool *is_64_bit __maybe_unused)
307{
308 return -1;
309}
310
304void symbol__elf_init(void) 311void symbol__elf_init(void)
305{ 312{
306} 313}
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 02718e728d59..77f3b95bb46d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -87,6 +87,7 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
87{ 87{
88 s64 a; 88 s64 a;
89 s64 b; 89 s64 b;
90 size_t na, nb;
90 91
91 /* Prefer a symbol with non zero length */ 92 /* Prefer a symbol with non zero length */
92 a = syma->end - syma->start; 93 a = syma->end - syma->start;
@@ -120,11 +121,21 @@ static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
120 else if (a > b) 121 else if (a > b)
121 return SYMBOL_B; 122 return SYMBOL_B;
122 123
123 /* If all else fails, choose the symbol with the longest name */ 124 /* Choose the symbol with the longest name */
124 if (strlen(syma->name) >= strlen(symb->name)) 125 na = strlen(syma->name);
126 nb = strlen(symb->name);
127 if (na > nb)
125 return SYMBOL_A; 128 return SYMBOL_A;
126 else 129 else if (na < nb)
130 return SYMBOL_B;
131
132 /* Avoid "SyS" kernel syscall aliases */
133 if (na >= 3 && !strncmp(syma->name, "SyS", 3))
134 return SYMBOL_B;
135 if (na >= 10 && !strncmp(syma->name, "compat_SyS", 10))
127 return SYMBOL_B; 136 return SYMBOL_B;
137
138 return SYMBOL_A;
128} 139}
129 140
130void symbols__fixup_duplicate(struct rb_root *symbols) 141void symbols__fixup_duplicate(struct rb_root *symbols)
@@ -316,6 +327,16 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
316 return NULL; 327 return NULL;
317} 328}
318 329
330static struct symbol *symbols__first(struct rb_root *symbols)
331{
332 struct rb_node *n = rb_first(symbols);
333
334 if (n)
335 return rb_entry(n, struct symbol, rb_node);
336
337 return NULL;
338}
339
319struct symbol_name_rb_node { 340struct symbol_name_rb_node {
320 struct rb_node rb_node; 341 struct rb_node rb_node;
321 struct symbol sym; 342 struct symbol sym;
@@ -386,6 +407,11 @@ struct symbol *dso__find_symbol(struct dso *dso,
386 return symbols__find(&dso->symbols[type], addr); 407 return symbols__find(&dso->symbols[type], addr);
387} 408}
388 409
410struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
411{
412 return symbols__first(&dso->symbols[type]);
413}
414
389struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 415struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
390 const char *name) 416 const char *name)
391{ 417{
@@ -522,6 +548,53 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
522 return kallsyms__parse(filename, &args, map__process_kallsym_symbol); 548 return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
523} 549}
524 550
551static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
552 symbol_filter_t filter)
553{
554 struct map_groups *kmaps = map__kmap(map)->kmaps;
555 struct map *curr_map;
556 struct symbol *pos;
557 int count = 0, moved = 0;
558 struct rb_root *root = &dso->symbols[map->type];
559 struct rb_node *next = rb_first(root);
560
561 while (next) {
562 char *module;
563
564 pos = rb_entry(next, struct symbol, rb_node);
565 next = rb_next(&pos->rb_node);
566
567 module = strchr(pos->name, '\t');
568 if (module)
569 *module = '\0';
570
571 curr_map = map_groups__find(kmaps, map->type, pos->start);
572
573 if (!curr_map || (filter && filter(curr_map, pos))) {
574 rb_erase(&pos->rb_node, root);
575 symbol__delete(pos);
576 } else {
577 pos->start -= curr_map->start - curr_map->pgoff;
578 if (pos->end)
579 pos->end -= curr_map->start - curr_map->pgoff;
580 if (curr_map != map) {
581 rb_erase(&pos->rb_node, root);
582 symbols__insert(
583 &curr_map->dso->symbols[curr_map->type],
584 pos);
585 ++moved;
586 } else {
587 ++count;
588 }
589 }
590 }
591
592 /* Symbols have been adjusted */
593 dso->adjust_symbols = 1;
594
595 return count + moved;
596}
597
525/* 598/*
526 * Split the symbols into maps, making sure there are no overlaps, i.e. the 599 * Split the symbols into maps, making sure there are no overlaps, i.e. the
527 * kernel range is broken in several maps, named [kernel].N, as we don't have 600 * kernel range is broken in several maps, named [kernel].N, as we don't have
@@ -663,6 +736,161 @@ bool symbol__restricted_filename(const char *filename,
663 return restricted; 736 return restricted;
664} 737}
665 738
739struct kcore_mapfn_data {
740 struct dso *dso;
741 enum map_type type;
742 struct list_head maps;
743};
744
745static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data)
746{
747 struct kcore_mapfn_data *md = data;
748 struct map *map;
749
750 map = map__new2(start, md->dso, md->type);
751 if (map == NULL)
752 return -ENOMEM;
753
754 map->end = map->start + len;
755 map->pgoff = pgoff;
756
757 list_add(&map->node, &md->maps);
758
759 return 0;
760}
761
762/*
763 * If kallsyms is referenced by name then we look for kcore in the same
764 * directory.
765 */
766static bool kcore_filename_from_kallsyms_filename(char *kcore_filename,
767 const char *kallsyms_filename)
768{
769 char *name;
770
771 strcpy(kcore_filename, kallsyms_filename);
772 name = strrchr(kcore_filename, '/');
773 if (!name)
774 return false;
775
776 if (!strcmp(name, "/kallsyms")) {
777 strcpy(name, "/kcore");
778 return true;
779 }
780
781 return false;
782}
783
784static int dso__load_kcore(struct dso *dso, struct map *map,
785 const char *kallsyms_filename)
786{
787 struct map_groups *kmaps = map__kmap(map)->kmaps;
788 struct machine *machine = kmaps->machine;
789 struct kcore_mapfn_data md;
790 struct map *old_map, *new_map, *replacement_map = NULL;
791 bool is_64_bit;
792 int err, fd;
793 char kcore_filename[PATH_MAX];
794 struct symbol *sym;
795
796 /* This function requires that the map is the kernel map */
797 if (map != machine->vmlinux_maps[map->type])
798 return -EINVAL;
799
800 if (!kcore_filename_from_kallsyms_filename(kcore_filename,
801 kallsyms_filename))
802 return -EINVAL;
803
804 md.dso = dso;
805 md.type = map->type;
806 INIT_LIST_HEAD(&md.maps);
807
808 fd = open(kcore_filename, O_RDONLY);
809 if (fd < 0)
810 return -EINVAL;
811
812 /* Read new maps into temporary lists */
813 err = file__read_maps(fd, md.type == MAP__FUNCTION, kcore_mapfn, &md,
814 &is_64_bit);
815 if (err)
816 goto out_err;
817
818 if (list_empty(&md.maps)) {
819 err = -EINVAL;
820 goto out_err;
821 }
822
823 /* Remove old maps */
824 old_map = map_groups__first(kmaps, map->type);
825 while (old_map) {
826 struct map *next = map_groups__next(old_map);
827
828 if (old_map != map)
829 map_groups__remove(kmaps, old_map);
830 old_map = next;
831 }
832
833 /* Find the kernel map using the first symbol */
834 sym = dso__first_symbol(dso, map->type);
835 list_for_each_entry(new_map, &md.maps, node) {
836 if (sym && sym->start >= new_map->start &&
837 sym->start < new_map->end) {
838 replacement_map = new_map;
839 break;
840 }
841 }
842
843 if (!replacement_map)
844 replacement_map = list_entry(md.maps.next, struct map, node);
845
846 /* Add new maps */
847 while (!list_empty(&md.maps)) {
848 new_map = list_entry(md.maps.next, struct map, node);
849 list_del(&new_map->node);
850 if (new_map == replacement_map) {
851 map->start = new_map->start;
852 map->end = new_map->end;
853 map->pgoff = new_map->pgoff;
854 map->map_ip = new_map->map_ip;
855 map->unmap_ip = new_map->unmap_ip;
856 map__delete(new_map);
857 /* Ensure maps are correctly ordered */
858 map_groups__remove(kmaps, map);
859 map_groups__insert(kmaps, map);
860 } else {
861 map_groups__insert(kmaps, new_map);
862 }
863 }
864
865 /*
866 * Set the data type and long name so that kcore can be read via
867 * dso__data_read_addr().
868 */
869 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
870 dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE;
871 else
872 dso->data_type = DSO_BINARY_TYPE__KCORE;
873 dso__set_long_name(dso, strdup(kcore_filename));
874
875 close(fd);
876
877 if (map->type == MAP__FUNCTION)
878 pr_debug("Using %s for kernel object code\n", kcore_filename);
879 else
880 pr_debug("Using %s for kernel data\n", kcore_filename);
881
882 return 0;
883
884out_err:
885 while (!list_empty(&md.maps)) {
886 map = list_entry(md.maps.next, struct map, node);
887 list_del(&map->node);
888 map__delete(map);
889 }
890 close(fd);
891 return -EINVAL;
892}
893
666int dso__load_kallsyms(struct dso *dso, const char *filename, 894int dso__load_kallsyms(struct dso *dso, const char *filename,
667 struct map *map, symbol_filter_t filter) 895 struct map *map, symbol_filter_t filter)
668{ 896{
@@ -680,7 +908,10 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
680 else 908 else
681 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; 909 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
682 910
683 return dso__split_kallsyms(dso, map, filter); 911 if (!dso__load_kcore(dso, map, filename))
912 return dso__split_kallsyms_for_kcore(dso, map, filter);
913 else
914 return dso__split_kallsyms(dso, map, filter);
684} 915}
685 916
686static int dso__load_perf_map(struct dso *dso, struct map *map, 917static int dso__load_perf_map(struct dso *dso, struct map *map,
@@ -843,10 +1074,15 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
843 if (!runtime_ss && syms_ss) 1074 if (!runtime_ss && syms_ss)
844 runtime_ss = syms_ss; 1075 runtime_ss = syms_ss;
845 1076
846 if (syms_ss) 1077 if (syms_ss) {
847 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0); 1078 int km;
848 else 1079
1080 km = dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE ||
1081 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE;
1082 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, km);
1083 } else {
849 ret = -1; 1084 ret = -1;
1085 }
850 1086
851 if (ret > 0) { 1087 if (ret > 0) {
852 int nr_plt; 1088 int nr_plt;
@@ -906,6 +1142,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
906 symsrc__destroy(&ss); 1142 symsrc__destroy(&ss);
907 1143
908 if (err > 0) { 1144 if (err > 0) {
1145 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1146 dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
1147 else
1148 dso->data_type = DSO_BINARY_TYPE__VMLINUX;
909 dso__set_long_name(dso, (char *)vmlinux); 1149 dso__set_long_name(dso, (char *)vmlinux);
910 dso__set_loaded(dso, map->type); 1150 dso__set_loaded(dso, map->type);
911 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1151 pr_debug("Using %s for symbols\n", symfs_vmlinux);
@@ -978,7 +1218,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
978 dso__set_long_name(dso, 1218 dso__set_long_name(dso,
979 strdup(symbol_conf.vmlinux_name)); 1219 strdup(symbol_conf.vmlinux_name));
980 dso->lname_alloc = 1; 1220 dso->lname_alloc = 1;
981 goto out_fixup; 1221 return err;
982 } 1222 }
983 return err; 1223 return err;
984 } 1224 }
@@ -986,7 +1226,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
986 if (vmlinux_path != NULL) { 1226 if (vmlinux_path != NULL) {
987 err = dso__load_vmlinux_path(dso, map, filter); 1227 err = dso__load_vmlinux_path(dso, map, filter);
988 if (err > 0) 1228 if (err > 0)
989 goto out_fixup; 1229 return err;
990 } 1230 }
991 1231
992 /* do not try local files if a symfs was given */ 1232 /* do not try local files if a symfs was given */
@@ -1045,9 +1285,8 @@ do_kallsyms:
1045 pr_debug("Using %s for symbols\n", kallsyms_filename); 1285 pr_debug("Using %s for symbols\n", kallsyms_filename);
1046 free(kallsyms_allocated_filename); 1286 free(kallsyms_allocated_filename);
1047 1287
1048 if (err > 0) { 1288 if (err > 0 && !dso__is_kcore(dso)) {
1049 dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 1289 dso__set_long_name(dso, strdup("[kernel.kallsyms]"));
1050out_fixup:
1051 map__fixup_start(map); 1290 map__fixup_start(map);
1052 map__fixup_end(map); 1291 map__fixup_end(map);
1053 } 1292 }
@@ -1078,7 +1317,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1078 if (symbol_conf.default_guest_vmlinux_name != NULL) { 1317 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1079 err = dso__load_vmlinux(dso, map, 1318 err = dso__load_vmlinux(dso, map,
1080 symbol_conf.default_guest_vmlinux_name, filter); 1319 symbol_conf.default_guest_vmlinux_name, filter);
1081 goto out_try_fixup; 1320 return err;
1082 } 1321 }
1083 1322
1084 kallsyms_filename = symbol_conf.default_guest_kallsyms; 1323 kallsyms_filename = symbol_conf.default_guest_kallsyms;
@@ -1092,13 +1331,9 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1092 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1331 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter);
1093 if (err > 0) 1332 if (err > 0)
1094 pr_debug("Using %s for symbols\n", kallsyms_filename); 1333 pr_debug("Using %s for symbols\n", kallsyms_filename);
1095 1334 if (err > 0 && !dso__is_kcore(dso)) {
1096out_try_fixup: 1335 machine__mmap_name(machine, path, sizeof(path));
1097 if (err > 0) { 1336 dso__set_long_name(dso, strdup(path));
1098 if (kallsyms_filename != NULL) {
1099 machine__mmap_name(machine, path, sizeof(path));
1100 dso__set_long_name(dso, strdup(path));
1101 }
1102 map__fixup_start(map); 1337 map__fixup_start(map);
1103 map__fixup_end(map); 1338 map__fixup_end(map);
1104 } 1339 }
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5f720dc076da..fd5b70ea2981 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -215,6 +215,7 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
215 u64 addr); 215 u64 addr);
216struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 216struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
217 const char *name); 217 const char *name);
218struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
218 219
219int filename__read_build_id(const char *filename, void *bf, size_t size); 220int filename__read_build_id(const char *filename, void *bf, size_t size);
220int sysfs__read_build_id(const char *filename, void *bf, size_t size); 221int sysfs__read_build_id(const char *filename, void *bf, size_t size);
@@ -247,4 +248,8 @@ void symbols__fixup_duplicate(struct rb_root *symbols);
247void symbols__fixup_end(struct rb_root *symbols); 248void symbols__fixup_end(struct rb_root *symbols);
248void __map_groups__fixup_end(struct map_groups *mg, enum map_type type); 249void __map_groups__fixup_end(struct map_groups *mg, enum map_type type);
249 250
251typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data);
252int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
253 bool *is_64_bit);
254
250#endif /* __PERF_SYMBOL */ 255#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 0fe1f9c05865..f98d1d983547 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -41,7 +41,7 @@ static inline struct map *thread__find_map(struct thread *self,
41 41
42void thread__find_addr_map(struct thread *thread, struct machine *machine, 42void thread__find_addr_map(struct thread *thread, struct machine *machine,
43 u8 cpumode, enum map_type type, u64 addr, 43 u8 cpumode, enum map_type type, u64 addr,
44 struct addr_location *al); 44 struct addr_location *al, symbol_filter_t filter);
45 45
46void thread__find_addr_location(struct thread *thread, struct machine *machine, 46void thread__find_addr_location(struct thread *thread, struct machine *machine,
47 u8 cpumode, enum map_type type, u64 addr, 47 u8 cpumode, enum map_type type, u64 addr,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index df46be93d902..b554ffc462b6 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -39,6 +39,8 @@ struct perf_top {
39 float min_percent; 39 float min_percent;
40}; 40};
41 41
42#define CONSOLE_CLEAR ""
43
42size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size); 44size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size);
43void perf_top__reset_sample_counters(struct perf_top *top); 45void perf_top__reset_sample_counters(struct perf_top *top);
44#endif /* __PERF_TOP_H */ 46#endif /* __PERF_TOP_H */
diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
index 958723ba3d2e..5bbd4947c27d 100644
--- a/tools/perf/util/unwind.c
+++ b/tools/perf/util/unwind.c
@@ -272,7 +272,7 @@ static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
272 struct addr_location al; 272 struct addr_location al;
273 273
274 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 274 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
275 MAP__FUNCTION, ip, &al); 275 MAP__FUNCTION, ip, &al, NULL);
276 return al.map; 276 return al.map;
277} 277}
278 278
@@ -349,7 +349,7 @@ static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
349 ssize_t size; 349 ssize_t size;
350 350
351 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER, 351 thread__find_addr_map(ui->thread, ui->machine, PERF_RECORD_MISC_USER,
352 MAP__FUNCTION, addr, &al); 352 MAP__FUNCTION, addr, &al, NULL);
353 if (!al.map) { 353 if (!al.map) {
354 pr_debug("unwind: no map for %lx\n", (unsigned long)addr); 354 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
355 return -1; 355 return -1;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 9a0658405760..6d17b18e915d 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -328,3 +328,36 @@ void put_tracing_file(char *file)
328{ 328{
329 free(file); 329 free(file);
330} 330}
331
332int parse_nsec_time(const char *str, u64 *ptime)
333{
334 u64 time_sec, time_nsec;
335 char *end;
336
337 time_sec = strtoul(str, &end, 10);
338 if (*end != '.' && *end != '\0')
339 return -1;
340
341 if (*end == '.') {
342 int i;
343 char nsec_buf[10];
344
345 if (strlen(++end) > 9)
346 return -1;
347
348 strncpy(nsec_buf, end, 9);
349 nsec_buf[9] = '\0';
350
351 /* make it nsec precision */
352 for (i = strlen(nsec_buf); i < 9; i++)
353 nsec_buf[i] = '0';
354
355 time_nsec = strtoul(nsec_buf, &end, 10);
356 if (*end != '\0')
357 return -1;
358 } else
359 time_nsec = 0;
360
361 *ptime = time_sec * NSEC_PER_SEC + time_nsec;
362 return 0;
363}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index cc1574edcd9a..a53535949043 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -208,6 +208,8 @@ static inline int has_extension(const char *filename, const char *ext)
208#define NSEC_PER_MSEC 1000000L 208#define NSEC_PER_MSEC 1000000L
209#endif 209#endif
210 210
211int parse_nsec_time(const char *str, u64 *ptime);
212
211extern unsigned char sane_ctype[256]; 213extern unsigned char sane_ctype[256];
212#define GIT_SPACE 0x01 214#define GIT_SPACE 0x01
213#define GIT_DIGIT 0x02 215#define GIT_DIGIT 0x02