diff options
29 files changed, 381 insertions, 82 deletions
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 0abf6742a8b0..c62d88396ad5 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c | |||
@@ -124,6 +124,7 @@ static struct event_constraint intel_ivb_event_constraints[] __read_mostly = | |||
124 | INTEL_UEVENT_CONSTRAINT(0x0148, 0x4), /* L1D_PEND_MISS.PENDING */ | 124 | INTEL_UEVENT_CONSTRAINT(0x0148, 0x4), /* L1D_PEND_MISS.PENDING */ |
125 | INTEL_UEVENT_CONSTRAINT(0x0279, 0xf), /* IDQ.EMTPY */ | 125 | INTEL_UEVENT_CONSTRAINT(0x0279, 0xf), /* IDQ.EMTPY */ |
126 | INTEL_UEVENT_CONSTRAINT(0x019c, 0xf), /* IDQ_UOPS_NOT_DELIVERED.CORE */ | 126 | INTEL_UEVENT_CONSTRAINT(0x019c, 0xf), /* IDQ_UOPS_NOT_DELIVERED.CORE */ |
127 | INTEL_UEVENT_CONSTRAINT(0x02a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_LDM_PENDING */ | ||
127 | INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */ | 128 | INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_EXECUTE */ |
128 | INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */ | 129 | INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */ |
129 | INTEL_UEVENT_CONSTRAINT(0x06a3, 0xf), /* CYCLE_ACTIVITY.STALLS_LDM_PENDING */ | 130 | INTEL_UEVENT_CONSTRAINT(0x06a3, 0xf), /* CYCLE_ACTIVITY.STALLS_LDM_PENDING */ |
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index fd8011ed4dcd..8ed44589b0e4 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c | |||
@@ -2808,7 +2808,7 @@ uncore_get_event_constraint(struct intel_uncore_box *box, struct perf_event *eve | |||
2808 | return c; | 2808 | return c; |
2809 | } | 2809 | } |
2810 | 2810 | ||
2811 | if (event->hw.config == ~0ULL) | 2811 | if (event->attr.config == UNCORE_FIXED_EVENT) |
2812 | return &constraint_fixed; | 2812 | return &constraint_fixed; |
2813 | 2813 | ||
2814 | if (type->constraints) { | 2814 | if (type->constraints) { |
@@ -3112,7 +3112,9 @@ static int uncore_pmu_event_init(struct perf_event *event) | |||
3112 | */ | 3112 | */ |
3113 | if (pmu->type->single_fixed && pmu->pmu_idx > 0) | 3113 | if (pmu->type->single_fixed && pmu->pmu_idx > 0) |
3114 | return -EINVAL; | 3114 | return -EINVAL; |
3115 | hwc->config = ~0ULL; | 3115 | |
3116 | /* fixed counters have event field hardcoded to zero */ | ||
3117 | hwc->config = 0ULL; | ||
3116 | } else { | 3118 | } else { |
3117 | hwc->config = event->attr.config & pmu->type->event_mask; | 3119 | hwc->config = event->attr.config & pmu->type->event_mask; |
3118 | if (pmu->type->ops->hw_config) { | 3120 | if (pmu->type->ops->hw_config) { |
diff --git a/kernel/events/core.c b/kernel/events/core.c index 2207efc941d1..dd236b66ca3a 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -5039,6 +5039,7 @@ static void perf_event_mmap_output(struct perf_event *event, | |||
5039 | mmap_event->event_id.header.size += sizeof(mmap_event->maj); | 5039 | mmap_event->event_id.header.size += sizeof(mmap_event->maj); |
5040 | mmap_event->event_id.header.size += sizeof(mmap_event->min); | 5040 | mmap_event->event_id.header.size += sizeof(mmap_event->min); |
5041 | mmap_event->event_id.header.size += sizeof(mmap_event->ino); | 5041 | mmap_event->event_id.header.size += sizeof(mmap_event->ino); |
5042 | mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation); | ||
5042 | } | 5043 | } |
5043 | 5044 | ||
5044 | perf_event_header__init_id(&mmap_event->event_id.header, &sample, event); | 5045 | perf_event_header__init_id(&mmap_event->event_id.header, &sample, event); |
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index f3569747d629..ad8e1bdca70e 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1682,12 +1682,10 @@ static bool handle_trampoline(struct pt_regs *regs) | |||
1682 | tmp = ri; | 1682 | tmp = ri; |
1683 | ri = ri->next; | 1683 | ri = ri->next; |
1684 | kfree(tmp); | 1684 | kfree(tmp); |
1685 | utask->depth--; | ||
1685 | 1686 | ||
1686 | if (!chained) | 1687 | if (!chained) |
1687 | break; | 1688 | break; |
1688 | |||
1689 | utask->depth--; | ||
1690 | |||
1691 | BUG_ON(!ri); | 1689 | BUG_ON(!ri); |
1692 | } | 1690 | } |
1693 | 1691 | ||
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index c5dc1ad1b8d7..3a0ff7fb71b6 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -394,6 +394,8 @@ ifeq ($(ARCH),x86) | |||
394 | LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o | 394 | LIB_OBJS += $(OUTPUT)tests/perf-time-to-tsc.o |
395 | endif | 395 | endif |
396 | LIB_OBJS += $(OUTPUT)tests/code-reading.o | 396 | LIB_OBJS += $(OUTPUT)tests/code-reading.o |
397 | LIB_OBJS += $(OUTPUT)tests/sample-parsing.o | ||
398 | LIB_OBJS += $(OUTPUT)tests/parse-no-sample-id-all.o | ||
397 | 399 | ||
398 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o | 400 | BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o |
399 | BUILTIN_OBJS += $(OUTPUT)builtin-bench.o | 401 | BUILTIN_OBJS += $(OUTPUT)builtin-bench.o |
@@ -439,7 +441,6 @@ PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT) | |||
439 | ifneq ($(OUTPUT),) | 441 | ifneq ($(OUTPUT),) |
440 | CFLAGS += -I$(OUTPUT) | 442 | CFLAGS += -I$(OUTPUT) |
441 | endif | 443 | endif |
442 | LIB_OBJS += $(OUTPUT)tests/sample-parsing.o | ||
443 | 444 | ||
444 | ifdef NO_LIBELF | 445 | ifdef NO_LIBELF |
445 | EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) | 446 | EXTLIBS := $(filter-out -lelf,$(EXTLIBS)) |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index f988d380c52f..5ebd0c3b71b6 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -277,6 +277,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) | |||
277 | .tool = { | 277 | .tool = { |
278 | .sample = process_sample_event, | 278 | .sample = process_sample_event, |
279 | .mmap = perf_event__process_mmap, | 279 | .mmap = perf_event__process_mmap, |
280 | .mmap2 = perf_event__process_mmap2, | ||
280 | .comm = perf_event__process_comm, | 281 | .comm = perf_event__process_comm, |
281 | .exit = perf_event__process_exit, | 282 | .exit = perf_event__process_exit, |
282 | .fork = perf_event__process_fork, | 283 | .fork = perf_event__process_fork, |
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 9b336fdb6f71..423875c999b2 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c | |||
@@ -123,6 +123,19 @@ static int perf_event__repipe_mmap(struct perf_tool *tool, | |||
123 | return err; | 123 | return err; |
124 | } | 124 | } |
125 | 125 | ||
126 | static int perf_event__repipe_mmap2(struct perf_tool *tool, | ||
127 | union perf_event *event, | ||
128 | struct perf_sample *sample, | ||
129 | struct machine *machine) | ||
130 | { | ||
131 | int err; | ||
132 | |||
133 | err = perf_event__process_mmap2(tool, event, sample, machine); | ||
134 | perf_event__repipe(tool, event, sample, machine); | ||
135 | |||
136 | return err; | ||
137 | } | ||
138 | |||
126 | static int perf_event__repipe_fork(struct perf_tool *tool, | 139 | static int perf_event__repipe_fork(struct perf_tool *tool, |
127 | union perf_event *event, | 140 | union perf_event *event, |
128 | struct perf_sample *sample, | 141 | struct perf_sample *sample, |
@@ -339,6 +352,7 @@ static int __cmd_inject(struct perf_inject *inject) | |||
339 | 352 | ||
340 | if (inject->build_ids || inject->sched_stat) { | 353 | if (inject->build_ids || inject->sched_stat) { |
341 | inject->tool.mmap = perf_event__repipe_mmap; | 354 | inject->tool.mmap = perf_event__repipe_mmap; |
355 | inject->tool.mmap2 = perf_event__repipe_mmap2; | ||
342 | inject->tool.fork = perf_event__repipe_fork; | 356 | inject->tool.fork = perf_event__repipe_fork; |
343 | inject->tool.tracing_data = perf_event__repipe_tracing_data; | 357 | inject->tool.tracing_data = perf_event__repipe_tracing_data; |
344 | } | 358 | } |
@@ -390,6 +404,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) | |||
390 | .tool = { | 404 | .tool = { |
391 | .sample = perf_event__repipe_sample, | 405 | .sample = perf_event__repipe_sample, |
392 | .mmap = perf_event__repipe, | 406 | .mmap = perf_event__repipe, |
407 | .mmap2 = perf_event__repipe, | ||
393 | .comm = perf_event__repipe, | 408 | .comm = perf_event__repipe, |
394 | .fork = perf_event__repipe, | 409 | .fork = perf_event__repipe, |
395 | .exit = perf_event__repipe, | 410 | .exit = perf_event__repipe, |
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 47b35407c2f2..935d52216c89 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -1165,16 +1165,16 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) | |||
1165 | struct perf_event_attr *attr = &pos->attr; | 1165 | struct perf_event_attr *attr = &pos->attr; |
1166 | 1166 | ||
1167 | /* make sure these *are* set */ | 1167 | /* make sure these *are* set */ |
1168 | attr->sample_type |= PERF_SAMPLE_TID; | 1168 | perf_evsel__set_sample_bit(pos, TID); |
1169 | attr->sample_type |= PERF_SAMPLE_TIME; | 1169 | perf_evsel__set_sample_bit(pos, TIME); |
1170 | attr->sample_type |= PERF_SAMPLE_CPU; | 1170 | perf_evsel__set_sample_bit(pos, CPU); |
1171 | attr->sample_type |= PERF_SAMPLE_RAW; | 1171 | perf_evsel__set_sample_bit(pos, RAW); |
1172 | /* make sure these are *not*; want as small a sample as possible */ | 1172 | /* make sure these are *not*; want as small a sample as possible */ |
1173 | attr->sample_type &= ~PERF_SAMPLE_PERIOD; | 1173 | perf_evsel__reset_sample_bit(pos, PERIOD); |
1174 | attr->sample_type &= ~PERF_SAMPLE_IP; | 1174 | perf_evsel__reset_sample_bit(pos, IP); |
1175 | attr->sample_type &= ~PERF_SAMPLE_CALLCHAIN; | 1175 | perf_evsel__reset_sample_bit(pos, CALLCHAIN); |
1176 | attr->sample_type &= ~PERF_SAMPLE_ADDR; | 1176 | perf_evsel__reset_sample_bit(pos, ADDR); |
1177 | attr->sample_type &= ~PERF_SAMPLE_READ; | 1177 | perf_evsel__reset_sample_bit(pos, READ); |
1178 | attr->mmap = 0; | 1178 | attr->mmap = 0; |
1179 | attr->comm = 0; | 1179 | attr->comm = 0; |
1180 | attr->task = 0; | 1180 | attr->task = 0; |
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c index 791b432df847..253133a6251d 100644 --- a/tools/perf/builtin-mem.c +++ b/tools/perf/builtin-mem.c | |||
@@ -190,6 +190,7 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused) | |||
190 | .tool = { | 190 | .tool = { |
191 | .sample = process_sample_event, | 191 | .sample = process_sample_event, |
192 | .mmap = perf_event__process_mmap, | 192 | .mmap = perf_event__process_mmap, |
193 | .mmap2 = perf_event__process_mmap2, | ||
193 | .comm = perf_event__process_comm, | 194 | .comm = perf_event__process_comm, |
194 | .lost = perf_event__process_lost, | 195 | .lost = perf_event__process_lost, |
195 | .fork = perf_event__process_fork, | 196 | .fork = perf_event__process_fork, |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 9725aa375414..8e50d8d77419 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -744,6 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
744 | .tool = { | 744 | .tool = { |
745 | .sample = process_sample_event, | 745 | .sample = process_sample_event, |
746 | .mmap = perf_event__process_mmap, | 746 | .mmap = perf_event__process_mmap, |
747 | .mmap2 = perf_event__process_mmap2, | ||
747 | .comm = perf_event__process_comm, | 748 | .comm = perf_event__process_comm, |
748 | .exit = perf_event__process_exit, | 749 | .exit = perf_event__process_exit, |
749 | .fork = perf_event__process_fork, | 750 | .fork = perf_event__process_fork, |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 93a34cef9676..7f31a3ded1b6 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -542,6 +542,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, | |||
542 | static struct perf_tool perf_script = { | 542 | static struct perf_tool perf_script = { |
543 | .sample = process_sample_event, | 543 | .sample = process_sample_event, |
544 | .mmap = perf_event__process_mmap, | 544 | .mmap = perf_event__process_mmap, |
545 | .mmap2 = perf_event__process_mmap2, | ||
545 | .comm = perf_event__process_comm, | 546 | .comm = perf_event__process_comm, |
546 | .exit = perf_event__process_exit, | 547 | .exit = perf_event__process_exit, |
547 | .fork = perf_event__process_fork, | 548 | .fork = perf_event__process_fork, |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index b6f0725068bd..f5aa6375e3e9 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -100,7 +100,9 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, | |||
100 | 100 | ||
101 | P_MMAP_FLAG(SHARED); | 101 | P_MMAP_FLAG(SHARED); |
102 | P_MMAP_FLAG(PRIVATE); | 102 | P_MMAP_FLAG(PRIVATE); |
103 | #ifdef MAP_32BIT | ||
103 | P_MMAP_FLAG(32BIT); | 104 | P_MMAP_FLAG(32BIT); |
105 | #endif | ||
104 | P_MMAP_FLAG(ANONYMOUS); | 106 | P_MMAP_FLAG(ANONYMOUS); |
105 | P_MMAP_FLAG(DENYWRITE); | 107 | P_MMAP_FLAG(DENYWRITE); |
106 | P_MMAP_FLAG(EXECUTABLE); | 108 | P_MMAP_FLAG(EXECUTABLE); |
@@ -994,6 +996,9 @@ again: | |||
994 | 996 | ||
995 | handler = evsel->handler.func; | 997 | handler = evsel->handler.func; |
996 | handler(trace, evsel, &sample); | 998 | handler(trace, evsel, &sample); |
999 | |||
1000 | if (done) | ||
1001 | goto out_unmap_evlist; | ||
997 | } | 1002 | } |
998 | } | 1003 | } |
999 | 1004 | ||
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 8bbeba322df9..1e67437fb4ca 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -112,6 +112,10 @@ static struct test { | |||
112 | .func = test__keep_tracking, | 112 | .func = test__keep_tracking, |
113 | }, | 113 | }, |
114 | { | 114 | { |
115 | .desc = "Test parsing with no sample_id_all bit set", | ||
116 | .func = test__parse_no_sample_id_all, | ||
117 | }, | ||
118 | { | ||
115 | .func = NULL, | 119 | .func = NULL, |
116 | }, | 120 | }, |
117 | }; | 121 | }; |
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c new file mode 100644 index 000000000000..e117b6c6a248 --- /dev/null +++ b/tools/perf/tests/parse-no-sample-id-all.c | |||
@@ -0,0 +1,108 @@ | |||
1 | #include <sys/types.h> | ||
2 | #include <stddef.h> | ||
3 | |||
4 | #include "tests.h" | ||
5 | |||
6 | #include "event.h" | ||
7 | #include "evlist.h" | ||
8 | #include "header.h" | ||
9 | #include "util.h" | ||
10 | |||
11 | static int process_event(struct perf_evlist **pevlist, union perf_event *event) | ||
12 | { | ||
13 | struct perf_sample sample; | ||
14 | |||
15 | if (event->header.type == PERF_RECORD_HEADER_ATTR) { | ||
16 | if (perf_event__process_attr(NULL, event, pevlist)) { | ||
17 | pr_debug("perf_event__process_attr failed\n"); | ||
18 | return -1; | ||
19 | } | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | if (event->header.type >= PERF_RECORD_USER_TYPE_START) | ||
24 | return -1; | ||
25 | |||
26 | if (!*pevlist) | ||
27 | return -1; | ||
28 | |||
29 | if (perf_evlist__parse_sample(*pevlist, event, &sample)) { | ||
30 | pr_debug("perf_evlist__parse_sample failed\n"); | ||
31 | return -1; | ||
32 | } | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int process_events(union perf_event **events, size_t count) | ||
38 | { | ||
39 | struct perf_evlist *evlist = NULL; | ||
40 | int err = 0; | ||
41 | size_t i; | ||
42 | |||
43 | for (i = 0; i < count && !err; i++) | ||
44 | err = process_event(&evlist, events[i]); | ||
45 | |||
46 | if (evlist) | ||
47 | perf_evlist__delete(evlist); | ||
48 | |||
49 | return err; | ||
50 | } | ||
51 | |||
52 | struct test_attr_event { | ||
53 | struct attr_event attr; | ||
54 | u64 id; | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * test__parse_no_sample_id_all - test parsing with no sample_id_all bit set. | ||
59 | * | ||
60 | * This function tests parsing data produced on kernel's that do not support the | ||
61 | * sample_id_all bit. Without the sample_id_all bit, non-sample events (such as | ||
62 | * mmap events) do not have an id sample appended, and consequently logic | ||
63 | * designed to determine the id will not work. That case happens when there is | ||
64 | * more than one selected event, so this test processes three events: 2 | ||
65 | * attributes representing the selected events and one mmap event. | ||
66 | * | ||
67 | * Return: %0 on success, %-1 if the test fails. | ||
68 | */ | ||
69 | int test__parse_no_sample_id_all(void) | ||
70 | { | ||
71 | int err; | ||
72 | |||
73 | struct test_attr_event event1 = { | ||
74 | .attr = { | ||
75 | .header = { | ||
76 | .type = PERF_RECORD_HEADER_ATTR, | ||
77 | .size = sizeof(struct test_attr_event), | ||
78 | }, | ||
79 | }, | ||
80 | .id = 1, | ||
81 | }; | ||
82 | struct test_attr_event event2 = { | ||
83 | .attr = { | ||
84 | .header = { | ||
85 | .type = PERF_RECORD_HEADER_ATTR, | ||
86 | .size = sizeof(struct test_attr_event), | ||
87 | }, | ||
88 | }, | ||
89 | .id = 2, | ||
90 | }; | ||
91 | struct mmap_event event3 = { | ||
92 | .header = { | ||
93 | .type = PERF_RECORD_MMAP, | ||
94 | .size = sizeof(struct mmap_event), | ||
95 | }, | ||
96 | }; | ||
97 | union perf_event *events[] = { | ||
98 | (union perf_event *)&event1, | ||
99 | (union perf_event *)&event2, | ||
100 | (union perf_event *)&event3, | ||
101 | }; | ||
102 | |||
103 | err = process_events(events, ARRAY_SIZE(events)); | ||
104 | if (err) | ||
105 | return -1; | ||
106 | |||
107 | return 0; | ||
108 | } | ||
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c index 72d8881873b0..b8a7056519ac 100644 --- a/tools/perf/tests/perf-record.c +++ b/tools/perf/tests/perf-record.c | |||
@@ -50,7 +50,7 @@ int test__PERF_RECORD(void) | |||
50 | struct perf_sample sample; | 50 | struct perf_sample sample; |
51 | const char *cmd = "sleep"; | 51 | const char *cmd = "sleep"; |
52 | const char *argv[] = { cmd, "1", NULL, }; | 52 | const char *argv[] = { cmd, "1", NULL, }; |
53 | char *bname; | 53 | char *bname, *mmap_filename; |
54 | u64 prev_time = 0; | 54 | u64 prev_time = 0; |
55 | bool found_cmd_mmap = false, | 55 | bool found_cmd_mmap = false, |
56 | found_libc_mmap = false, | 56 | found_libc_mmap = false, |
@@ -212,6 +212,7 @@ int test__PERF_RECORD(void) | |||
212 | 212 | ||
213 | if ((type == PERF_RECORD_COMM || | 213 | if ((type == PERF_RECORD_COMM || |
214 | type == PERF_RECORD_MMAP || | 214 | type == PERF_RECORD_MMAP || |
215 | type == PERF_RECORD_MMAP2 || | ||
215 | type == PERF_RECORD_FORK || | 216 | type == PERF_RECORD_FORK || |
216 | type == PERF_RECORD_EXIT) && | 217 | type == PERF_RECORD_EXIT) && |
217 | (pid_t)event->comm.pid != evlist->workload.pid) { | 218 | (pid_t)event->comm.pid != evlist->workload.pid) { |
@@ -220,7 +221,8 @@ int test__PERF_RECORD(void) | |||
220 | } | 221 | } |
221 | 222 | ||
222 | if ((type == PERF_RECORD_COMM || | 223 | if ((type == PERF_RECORD_COMM || |
223 | type == PERF_RECORD_MMAP) && | 224 | type == PERF_RECORD_MMAP || |
225 | type == PERF_RECORD_MMAP2) && | ||
224 | event->comm.pid != event->comm.tid) { | 226 | event->comm.pid != event->comm.tid) { |
225 | pr_debug("%s with different pid/tid!\n", name); | 227 | pr_debug("%s with different pid/tid!\n", name); |
226 | ++errs; | 228 | ++errs; |
@@ -236,7 +238,12 @@ int test__PERF_RECORD(void) | |||
236 | case PERF_RECORD_EXIT: | 238 | case PERF_RECORD_EXIT: |
237 | goto found_exit; | 239 | goto found_exit; |
238 | case PERF_RECORD_MMAP: | 240 | case PERF_RECORD_MMAP: |
239 | bname = strrchr(event->mmap.filename, '/'); | 241 | mmap_filename = event->mmap.filename; |
242 | goto check_bname; | ||
243 | case PERF_RECORD_MMAP2: | ||
244 | mmap_filename = event->mmap2.filename; | ||
245 | check_bname: | ||
246 | bname = strrchr(mmap_filename, '/'); | ||
240 | if (bname != NULL) { | 247 | if (bname != NULL) { |
241 | if (!found_cmd_mmap) | 248 | if (!found_cmd_mmap) |
242 | found_cmd_mmap = !strcmp(bname + 1, cmd); | 249 | found_cmd_mmap = !strcmp(bname + 1, cmd); |
@@ -245,7 +252,7 @@ int test__PERF_RECORD(void) | |||
245 | if (!found_ld_mmap) | 252 | if (!found_ld_mmap) |
246 | found_ld_mmap = !strncmp(bname + 1, "ld", 2); | 253 | found_ld_mmap = !strncmp(bname + 1, "ld", 2); |
247 | } else if (!found_vdso_mmap) | 254 | } else if (!found_vdso_mmap) |
248 | found_vdso_mmap = !strcmp(event->mmap.filename, "[vdso]"); | 255 | found_vdso_mmap = !strcmp(mmap_filename, "[vdso]"); |
249 | break; | 256 | break; |
250 | 257 | ||
251 | case PERF_RECORD_SAMPLE: | 258 | case PERF_RECORD_SAMPLE: |
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index c048b589998a..e0ac713857ba 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
@@ -39,5 +39,6 @@ int test__perf_time_to_tsc(void); | |||
39 | int test__code_reading(void); | 39 | int test__code_reading(void); |
40 | int test__sample_parsing(void); | 40 | int test__sample_parsing(void); |
41 | int test__keep_tracking(void); | 41 | int test__keep_tracking(void); |
42 | int test__parse_no_sample_id_all(void); | ||
42 | 43 | ||
43 | #endif /* TESTS_H */ | 44 | #endif /* TESTS_H */ |
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 5b4fb330f656..194e2f42ff5d 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c | |||
@@ -350,9 +350,9 @@ static int hist_entry__period_snprintf(struct perf_hpp *hpp, | |||
350 | } | 350 | } |
351 | 351 | ||
352 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, | 352 | static int hist_entry__fprintf(struct hist_entry *he, size_t size, |
353 | struct hists *hists, FILE *fp) | 353 | struct hists *hists, |
354 | char *bf, size_t bfsz, FILE *fp) | ||
354 | { | 355 | { |
355 | char bf[512]; | ||
356 | int ret; | 356 | int ret; |
357 | struct perf_hpp hpp = { | 357 | struct perf_hpp hpp = { |
358 | .buf = bf, | 358 | .buf = bf, |
@@ -360,8 +360,8 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, | |||
360 | }; | 360 | }; |
361 | bool color = !symbol_conf.field_sep; | 361 | bool color = !symbol_conf.field_sep; |
362 | 362 | ||
363 | if (size == 0 || size > sizeof(bf)) | 363 | if (size == 0 || size > bfsz) |
364 | size = hpp.size = sizeof(bf); | 364 | size = hpp.size = bfsz; |
365 | 365 | ||
366 | ret = hist_entry__period_snprintf(&hpp, he, color); | 366 | ret = hist_entry__period_snprintf(&hpp, he, color); |
367 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); | 367 | hist_entry__sort_snprintf(he, bf + ret, size - ret, hists); |
@@ -392,6 +392,8 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | |||
392 | .ptr = hists_to_evsel(hists), | 392 | .ptr = hists_to_evsel(hists), |
393 | }; | 393 | }; |
394 | bool first = true; | 394 | bool first = true; |
395 | size_t linesz; | ||
396 | char *line = NULL; | ||
395 | 397 | ||
396 | init_rem_hits(); | 398 | init_rem_hits(); |
397 | 399 | ||
@@ -479,6 +481,13 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, | |||
479 | goto out; | 481 | goto out; |
480 | 482 | ||
481 | print_entries: | 483 | print_entries: |
484 | linesz = hists__sort_list_width(hists) + 3 + 1; | ||
485 | line = malloc(linesz); | ||
486 | if (line == NULL) { | ||
487 | ret = -1; | ||
488 | goto out; | ||
489 | } | ||
490 | |||
482 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { | 491 | for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) { |
483 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 492 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
484 | float percent = h->stat.period * 100.0 / | 493 | float percent = h->stat.period * 100.0 / |
@@ -490,10 +499,10 @@ print_entries: | |||
490 | if (percent < min_pcnt) | 499 | if (percent < min_pcnt) |
491 | continue; | 500 | continue; |
492 | 501 | ||
493 | ret += hist_entry__fprintf(h, max_cols, hists, fp); | 502 | ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp); |
494 | 503 | ||
495 | if (max_rows && ++nr_rows >= max_rows) | 504 | if (max_rows && ++nr_rows >= max_rows) |
496 | goto out; | 505 | break; |
497 | 506 | ||
498 | if (h->ms.map == NULL && verbose > 1) { | 507 | if (h->ms.map == NULL && verbose > 1) { |
499 | __map_groups__fprintf_maps(&h->thread->mg, | 508 | __map_groups__fprintf_maps(&h->thread->mg, |
@@ -501,6 +510,8 @@ print_entries: | |||
501 | fprintf(fp, "%.10s end\n", graph_dotted_line); | 510 | fprintf(fp, "%.10s end\n", graph_dotted_line); |
502 | } | 511 | } |
503 | } | 512 | } |
513 | |||
514 | free(line); | ||
504 | out: | 515 | out: |
505 | free(rem_sq_bracket); | 516 | free(rem_sq_bracket); |
506 | 517 | ||
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c index fb584092eb88..7ded71d19d75 100644 --- a/tools/perf/util/build-id.c +++ b/tools/perf/util/build-id.c | |||
@@ -67,6 +67,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused, | |||
67 | struct perf_tool build_id__mark_dso_hit_ops = { | 67 | struct perf_tool build_id__mark_dso_hit_ops = { |
68 | .sample = build_id__mark_dso_hit, | 68 | .sample = build_id__mark_dso_hit, |
69 | .mmap = perf_event__process_mmap, | 69 | .mmap = perf_event__process_mmap, |
70 | .mmap2 = perf_event__process_mmap2, | ||
70 | .fork = perf_event__process_fork, | 71 | .fork = perf_event__process_fork, |
71 | .exit = perf_event__exit_del_thread, | 72 | .exit = perf_event__exit_del_thread, |
72 | .attr = perf_event__process_attr, | 73 | .attr = perf_event__process_attr, |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 8d51f21107aa..9b393e7dca6f 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -11,6 +11,7 @@ | |||
11 | static const char *perf_event__names[] = { | 11 | static const char *perf_event__names[] = { |
12 | [0] = "TOTAL", | 12 | [0] = "TOTAL", |
13 | [PERF_RECORD_MMAP] = "MMAP", | 13 | [PERF_RECORD_MMAP] = "MMAP", |
14 | [PERF_RECORD_MMAP2] = "MMAP2", | ||
14 | [PERF_RECORD_LOST] = "LOST", | 15 | [PERF_RECORD_LOST] = "LOST", |
15 | [PERF_RECORD_COMM] = "COMM", | 16 | [PERF_RECORD_COMM] = "COMM", |
16 | [PERF_RECORD_EXIT] = "EXIT", | 17 | [PERF_RECORD_EXIT] = "EXIT", |
@@ -186,7 +187,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
186 | return -1; | 187 | return -1; |
187 | } | 188 | } |
188 | 189 | ||
189 | event->header.type = PERF_RECORD_MMAP; | 190 | event->header.type = PERF_RECORD_MMAP2; |
190 | /* | 191 | /* |
191 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | 192 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c |
192 | */ | 193 | */ |
@@ -197,7 +198,9 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
197 | char prot[5]; | 198 | char prot[5]; |
198 | char execname[PATH_MAX]; | 199 | char execname[PATH_MAX]; |
199 | char anonstr[] = "//anon"; | 200 | char anonstr[] = "//anon"; |
201 | unsigned int ino; | ||
200 | size_t size; | 202 | size_t size; |
203 | ssize_t n; | ||
201 | 204 | ||
202 | if (fgets(bf, sizeof(bf), fp) == NULL) | 205 | if (fgets(bf, sizeof(bf), fp) == NULL) |
203 | break; | 206 | break; |
@@ -206,9 +209,16 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
206 | strcpy(execname, ""); | 209 | strcpy(execname, ""); |
207 | 210 | ||
208 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ | 211 | /* 00400000-0040c000 r-xp 00000000 fd:01 41038 /bin/cat */ |
209 | sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %*x:%*x %*u %s\n", | 212 | n = sscanf(bf, "%"PRIx64"-%"PRIx64" %s %"PRIx64" %x:%x %u %s\n", |
210 | &event->mmap.start, &event->mmap.len, prot, | 213 | &event->mmap2.start, &event->mmap2.len, prot, |
211 | &event->mmap.pgoff, execname); | 214 | &event->mmap2.pgoff, &event->mmap2.maj, |
215 | &event->mmap2.min, | ||
216 | &ino, execname); | ||
217 | |||
218 | event->mmap2.ino = (u64)ino; | ||
219 | |||
220 | if (n != 8) | ||
221 | continue; | ||
212 | 222 | ||
213 | if (prot[2] != 'x') | 223 | if (prot[2] != 'x') |
214 | continue; | 224 | continue; |
@@ -217,15 +227,15 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
217 | strcpy(execname, anonstr); | 227 | strcpy(execname, anonstr); |
218 | 228 | ||
219 | size = strlen(execname) + 1; | 229 | size = strlen(execname) + 1; |
220 | memcpy(event->mmap.filename, execname, size); | 230 | memcpy(event->mmap2.filename, execname, size); |
221 | size = PERF_ALIGN(size, sizeof(u64)); | 231 | size = PERF_ALIGN(size, sizeof(u64)); |
222 | event->mmap.len -= event->mmap.start; | 232 | event->mmap2.len -= event->mmap.start; |
223 | event->mmap.header.size = (sizeof(event->mmap) - | 233 | event->mmap2.header.size = (sizeof(event->mmap2) - |
224 | (sizeof(event->mmap.filename) - size)); | 234 | (sizeof(event->mmap2.filename) - size)); |
225 | memset(event->mmap.filename + size, 0, machine->id_hdr_size); | 235 | memset(event->mmap2.filename + size, 0, machine->id_hdr_size); |
226 | event->mmap.header.size += machine->id_hdr_size; | 236 | event->mmap2.header.size += machine->id_hdr_size; |
227 | event->mmap.pid = tgid; | 237 | event->mmap2.pid = tgid; |
228 | event->mmap.tid = pid; | 238 | event->mmap2.tid = pid; |
229 | 239 | ||
230 | if (process(tool, event, &synth_sample, machine) != 0) { | 240 | if (process(tool, event, &synth_sample, machine) != 0) { |
231 | rc = -1; | 241 | rc = -1; |
@@ -527,6 +537,17 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) | |||
527 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); | 537 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); |
528 | } | 538 | } |
529 | 539 | ||
540 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) | ||
541 | { | ||
542 | return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 | ||
543 | " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n", | ||
544 | event->mmap2.pid, event->mmap2.tid, event->mmap2.start, | ||
545 | event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, | ||
546 | event->mmap2.min, event->mmap2.ino, | ||
547 | event->mmap2.ino_generation, | ||
548 | event->mmap2.filename); | ||
549 | } | ||
550 | |||
530 | int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, | 551 | int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, |
531 | union perf_event *event, | 552 | union perf_event *event, |
532 | struct perf_sample *sample __maybe_unused, | 553 | struct perf_sample *sample __maybe_unused, |
@@ -535,6 +556,14 @@ int perf_event__process_mmap(struct perf_tool *tool __maybe_unused, | |||
535 | return machine__process_mmap_event(machine, event); | 556 | return machine__process_mmap_event(machine, event); |
536 | } | 557 | } |
537 | 558 | ||
559 | int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused, | ||
560 | union perf_event *event, | ||
561 | struct perf_sample *sample __maybe_unused, | ||
562 | struct machine *machine) | ||
563 | { | ||
564 | return machine__process_mmap2_event(machine, event); | ||
565 | } | ||
566 | |||
538 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) | 567 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) |
539 | { | 568 | { |
540 | return fprintf(fp, "(%d:%d):(%d:%d)\n", | 569 | return fprintf(fp, "(%d:%d):(%d:%d)\n", |
@@ -574,6 +603,9 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp) | |||
574 | case PERF_RECORD_MMAP: | 603 | case PERF_RECORD_MMAP: |
575 | ret += perf_event__fprintf_mmap(event, fp); | 604 | ret += perf_event__fprintf_mmap(event, fp); |
576 | break; | 605 | break; |
606 | case PERF_RECORD_MMAP2: | ||
607 | ret += perf_event__fprintf_mmap2(event, fp); | ||
608 | break; | ||
577 | default: | 609 | default: |
578 | ret += fprintf(fp, "\n"); | 610 | ret += fprintf(fp, "\n"); |
579 | } | 611 | } |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 93130d856bf0..c67ecc457d29 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -17,6 +17,19 @@ struct mmap_event { | |||
17 | char filename[PATH_MAX]; | 17 | char filename[PATH_MAX]; |
18 | }; | 18 | }; |
19 | 19 | ||
20 | struct mmap2_event { | ||
21 | struct perf_event_header header; | ||
22 | u32 pid, tid; | ||
23 | u64 start; | ||
24 | u64 len; | ||
25 | u64 pgoff; | ||
26 | u32 maj; | ||
27 | u32 min; | ||
28 | u64 ino; | ||
29 | u64 ino_generation; | ||
30 | char filename[PATH_MAX]; | ||
31 | }; | ||
32 | |||
20 | struct comm_event { | 33 | struct comm_event { |
21 | struct perf_event_header header; | 34 | struct perf_event_header header; |
22 | u32 pid, tid; | 35 | u32 pid, tid; |
@@ -159,6 +172,7 @@ struct tracing_data_event { | |||
159 | union perf_event { | 172 | union perf_event { |
160 | struct perf_event_header header; | 173 | struct perf_event_header header; |
161 | struct mmap_event mmap; | 174 | struct mmap_event mmap; |
175 | struct mmap2_event mmap2; | ||
162 | struct comm_event comm; | 176 | struct comm_event comm; |
163 | struct fork_event fork; | 177 | struct fork_event fork; |
164 | struct lost_event lost; | 178 | struct lost_event lost; |
@@ -208,6 +222,10 @@ int perf_event__process_mmap(struct perf_tool *tool, | |||
208 | union perf_event *event, | 222 | union perf_event *event, |
209 | struct perf_sample *sample, | 223 | struct perf_sample *sample, |
210 | struct machine *machine); | 224 | struct machine *machine); |
225 | int perf_event__process_mmap2(struct perf_tool *tool, | ||
226 | union perf_event *event, | ||
227 | struct perf_sample *sample, | ||
228 | struct machine *machine); | ||
211 | int perf_event__process_fork(struct perf_tool *tool, | 229 | int perf_event__process_fork(struct perf_tool *tool, |
212 | union perf_event *event, | 230 | union perf_event *event, |
213 | struct perf_sample *sample, | 231 | struct perf_sample *sample, |
@@ -238,6 +256,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, | |||
238 | 256 | ||
239 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); | 257 | size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); |
240 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); | 258 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); |
259 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); | ||
241 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); | 260 | size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); |
242 | size_t perf_event__fprintf(union perf_event *event, FILE *fp); | 261 | size_t perf_event__fprintf(union perf_event *event, FILE *fp); |
243 | 262 | ||
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index b8727ae45e3b..f9f77bee0b1b 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c | |||
@@ -64,6 +64,16 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist) | |||
64 | evlist->is_pos = first->is_pos; | 64 | evlist->is_pos = first->is_pos; |
65 | } | 65 | } |
66 | 66 | ||
67 | static void perf_evlist__update_id_pos(struct perf_evlist *evlist) | ||
68 | { | ||
69 | struct perf_evsel *evsel; | ||
70 | |||
71 | list_for_each_entry(evsel, &evlist->entries, node) | ||
72 | perf_evsel__calc_id_pos(evsel); | ||
73 | |||
74 | perf_evlist__set_id_pos(evlist); | ||
75 | } | ||
76 | |||
67 | static void perf_evlist__purge(struct perf_evlist *evlist) | 77 | static void perf_evlist__purge(struct perf_evlist *evlist) |
68 | { | 78 | { |
69 | struct perf_evsel *pos, *n; | 79 | struct perf_evsel *pos, *n; |
@@ -446,20 +456,25 @@ static int perf_evlist__event2id(struct perf_evlist *evlist, | |||
446 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, | 456 | static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, |
447 | union perf_event *event) | 457 | union perf_event *event) |
448 | { | 458 | { |
459 | struct perf_evsel *first = perf_evlist__first(evlist); | ||
449 | struct hlist_head *head; | 460 | struct hlist_head *head; |
450 | struct perf_sample_id *sid; | 461 | struct perf_sample_id *sid; |
451 | int hash; | 462 | int hash; |
452 | u64 id; | 463 | u64 id; |
453 | 464 | ||
454 | if (evlist->nr_entries == 1) | 465 | if (evlist->nr_entries == 1) |
455 | return perf_evlist__first(evlist); | 466 | return first; |
467 | |||
468 | if (!first->attr.sample_id_all && | ||
469 | event->header.type != PERF_RECORD_SAMPLE) | ||
470 | return first; | ||
456 | 471 | ||
457 | if (perf_evlist__event2id(evlist, event, &id)) | 472 | if (perf_evlist__event2id(evlist, event, &id)) |
458 | return NULL; | 473 | return NULL; |
459 | 474 | ||
460 | /* Synthesized events have an id of zero */ | 475 | /* Synthesized events have an id of zero */ |
461 | if (!id) | 476 | if (!id) |
462 | return perf_evlist__first(evlist); | 477 | return first; |
463 | 478 | ||
464 | hash = hash_64(id, PERF_EVLIST__HLIST_BITS); | 479 | hash = hash_64(id, PERF_EVLIST__HLIST_BITS); |
465 | head = &evlist->heads[hash]; | 480 | head = &evlist->heads[hash]; |
@@ -915,6 +930,8 @@ int perf_evlist__open(struct perf_evlist *evlist) | |||
915 | struct perf_evsel *evsel; | 930 | struct perf_evsel *evsel; |
916 | int err; | 931 | int err; |
917 | 932 | ||
933 | perf_evlist__update_id_pos(evlist); | ||
934 | |||
918 | list_for_each_entry(evsel, &evlist->entries, node) { | 935 | list_for_each_entry(evsel, &evlist->entries, node) { |
919 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); | 936 | err = perf_evsel__open(evsel, evlist->cpus, evlist->threads); |
920 | if (err < 0) | 937 | if (err < 0) |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 3612183e2cc5..0ce9febf1ba0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -27,6 +27,7 @@ | |||
27 | static struct { | 27 | static struct { |
28 | bool sample_id_all; | 28 | bool sample_id_all; |
29 | bool exclude_guest; | 29 | bool exclude_guest; |
30 | bool mmap2; | ||
30 | } perf_missing_features; | 31 | } perf_missing_features; |
31 | 32 | ||
32 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) | 33 | #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) |
@@ -676,8 +677,9 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
676 | if (opts->sample_weight) | 677 | if (opts->sample_weight) |
677 | attr->sample_type |= PERF_SAMPLE_WEIGHT; | 678 | attr->sample_type |= PERF_SAMPLE_WEIGHT; |
678 | 679 | ||
679 | attr->mmap = track; | 680 | attr->mmap = track; |
680 | attr->comm = track; | 681 | attr->mmap2 = track && !perf_missing_features.mmap2; |
682 | attr->comm = track; | ||
681 | 683 | ||
682 | /* | 684 | /* |
683 | * XXX see the function comment above | 685 | * XXX see the function comment above |
@@ -1016,6 +1018,8 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, | |||
1016 | } | 1018 | } |
1017 | 1019 | ||
1018 | fallback_missing_features: | 1020 | fallback_missing_features: |
1021 | if (perf_missing_features.mmap2) | ||
1022 | evsel->attr.mmap2 = 0; | ||
1019 | if (perf_missing_features.exclude_guest) | 1023 | if (perf_missing_features.exclude_guest) |
1020 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; | 1024 | evsel->attr.exclude_guest = evsel->attr.exclude_host = 0; |
1021 | retry_sample_id: | 1025 | retry_sample_id: |
@@ -1080,8 +1084,11 @@ try_fallback: | |||
1080 | if (err != -EINVAL || cpu > 0 || thread > 0) | 1084 | if (err != -EINVAL || cpu > 0 || thread > 0) |
1081 | goto out_close; | 1085 | goto out_close; |
1082 | 1086 | ||
1083 | if (!perf_missing_features.exclude_guest && | 1087 | if (!perf_missing_features.mmap2 && evsel->attr.mmap2) { |
1084 | (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { | 1088 | perf_missing_features.mmap2 = true; |
1089 | goto fallback_missing_features; | ||
1090 | } else if (!perf_missing_features.exclude_guest && | ||
1091 | (evsel->attr.exclude_guest || evsel->attr.exclude_host)) { | ||
1085 | perf_missing_features.exclude_guest = true; | 1092 | perf_missing_features.exclude_guest = true; |
1086 | goto fallback_missing_features; | 1093 | goto fallback_missing_features; |
1087 | } else if (!perf_missing_features.sample_id_all) { | 1094 | } else if (!perf_missing_features.sample_id_all) { |
@@ -1925,6 +1932,7 @@ int perf_evsel__fprintf(struct perf_evsel *evsel, | |||
1925 | if_print(exclude_hv); | 1932 | if_print(exclude_hv); |
1926 | if_print(exclude_idle); | 1933 | if_print(exclude_idle); |
1927 | if_print(mmap); | 1934 | if_print(mmap); |
1935 | if_print(mmap2); | ||
1928 | if_print(comm); | 1936 | if_print(comm); |
1929 | if_print(freq); | 1937 | if_print(freq); |
1930 | if_print(inherit_stat); | 1938 | if_print(inherit_stat); |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index a33197a4fd21..26441d0e571b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -1351,6 +1351,9 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp) | |||
1351 | 1351 | ||
1352 | fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); | 1352 | fprintf(fp, ", precise_ip = %d", evsel->attr.precise_ip); |
1353 | 1353 | ||
1354 | fprintf(fp, ", attr_mmap2 = %d", evsel->attr.mmap2); | ||
1355 | fprintf(fp, ", attr_mmap = %d", evsel->attr.mmap); | ||
1356 | fprintf(fp, ", attr_mmap_data = %d", evsel->attr.mmap_data); | ||
1354 | if (evsel->ids) { | 1357 | if (evsel->ids) { |
1355 | fprintf(fp, ", id = {"); | 1358 | fprintf(fp, ", id = {"); |
1356 | for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { | 1359 | for (j = 0, id = evsel->id; j < evsel->ids; j++, id++) { |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 1dca61f0512d..933d14f287ca 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -997,6 +997,54 @@ out_problem: | |||
997 | return -1; | 997 | return -1; |
998 | } | 998 | } |
999 | 999 | ||
1000 | int machine__process_mmap2_event(struct machine *machine, | ||
1001 | union perf_event *event) | ||
1002 | { | ||
1003 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | ||
1004 | struct thread *thread; | ||
1005 | struct map *map; | ||
1006 | enum map_type type; | ||
1007 | int ret = 0; | ||
1008 | |||
1009 | if (dump_trace) | ||
1010 | perf_event__fprintf_mmap2(event, stdout); | ||
1011 | |||
1012 | if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL || | ||
1013 | cpumode == PERF_RECORD_MISC_KERNEL) { | ||
1014 | ret = machine__process_kernel_mmap_event(machine, event); | ||
1015 | if (ret < 0) | ||
1016 | goto out_problem; | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | thread = machine__findnew_thread(machine, event->mmap2.pid, | ||
1021 | event->mmap2.pid); | ||
1022 | if (thread == NULL) | ||
1023 | goto out_problem; | ||
1024 | |||
1025 | if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) | ||
1026 | type = MAP__VARIABLE; | ||
1027 | else | ||
1028 | type = MAP__FUNCTION; | ||
1029 | |||
1030 | map = map__new(&machine->user_dsos, event->mmap2.start, | ||
1031 | event->mmap2.len, event->mmap2.pgoff, | ||
1032 | event->mmap2.pid, event->mmap2.maj, | ||
1033 | event->mmap2.min, event->mmap2.ino, | ||
1034 | event->mmap2.ino_generation, | ||
1035 | event->mmap2.filename, type); | ||
1036 | |||
1037 | if (map == NULL) | ||
1038 | goto out_problem; | ||
1039 | |||
1040 | thread__insert_map(thread, map); | ||
1041 | return 0; | ||
1042 | |||
1043 | out_problem: | ||
1044 | dump_printf("problem processing PERF_RECORD_MMAP2, skipping event.\n"); | ||
1045 | return 0; | ||
1046 | } | ||
1047 | |||
1000 | int machine__process_mmap_event(struct machine *machine, union perf_event *event) | 1048 | int machine__process_mmap_event(struct machine *machine, union perf_event *event) |
1001 | { | 1049 | { |
1002 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; | 1050 | u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; |
@@ -1028,7 +1076,8 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event | |||
1028 | 1076 | ||
1029 | map = map__new(&machine->user_dsos, event->mmap.start, | 1077 | map = map__new(&machine->user_dsos, event->mmap.start, |
1030 | event->mmap.len, event->mmap.pgoff, | 1078 | event->mmap.len, event->mmap.pgoff, |
1031 | event->mmap.pid, event->mmap.filename, | 1079 | event->mmap.pid, 0, 0, 0, 0, |
1080 | event->mmap.filename, | ||
1032 | type); | 1081 | type); |
1033 | 1082 | ||
1034 | if (map == NULL) | 1083 | if (map == NULL) |
@@ -1101,6 +1150,8 @@ int machine__process_event(struct machine *machine, union perf_event *event) | |||
1101 | ret = machine__process_comm_event(machine, event); break; | 1150 | ret = machine__process_comm_event(machine, event); break; |
1102 | case PERF_RECORD_MMAP: | 1151 | case PERF_RECORD_MMAP: |
1103 | ret = machine__process_mmap_event(machine, event); break; | 1152 | ret = machine__process_mmap_event(machine, event); break; |
1153 | case PERF_RECORD_MMAP2: | ||
1154 | ret = machine__process_mmap2_event(machine, event); break; | ||
1104 | case PERF_RECORD_FORK: | 1155 | case PERF_RECORD_FORK: |
1105 | ret = machine__process_fork_event(machine, event); break; | 1156 | ret = machine__process_fork_event(machine, event); break; |
1106 | case PERF_RECORD_EXIT: | 1157 | case PERF_RECORD_EXIT: |
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h index 0df925ba6a44..58a6be1fc739 100644 --- a/tools/perf/util/machine.h +++ b/tools/perf/util/machine.h | |||
@@ -45,6 +45,7 @@ int machine__process_exit_event(struct machine *machine, union perf_event *event | |||
45 | int machine__process_fork_event(struct machine *machine, union perf_event *event); | 45 | int machine__process_fork_event(struct machine *machine, union perf_event *event); |
46 | int machine__process_lost_event(struct machine *machine, union perf_event *event); | 46 | int machine__process_lost_event(struct machine *machine, union perf_event *event); |
47 | int machine__process_mmap_event(struct machine *machine, union perf_event *event); | 47 | int machine__process_mmap_event(struct machine *machine, union perf_event *event); |
48 | int machine__process_mmap2_event(struct machine *machine, union perf_event *event); | ||
48 | int machine__process_event(struct machine *machine, union perf_event *event); | 49 | int machine__process_event(struct machine *machine, union perf_event *event); |
49 | 50 | ||
50 | typedef void (*machine__process_t)(struct machine *machine, void *data); | 51 | typedef void (*machine__process_t)(struct machine *machine, void *data); |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 9e8304ca343e..4f6680d2043b 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -48,7 +48,8 @@ void map__init(struct map *map, enum map_type type, | |||
48 | } | 48 | } |
49 | 49 | ||
50 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 50 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
51 | u64 pgoff, u32 pid, char *filename, | 51 | u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, |
52 | u64 ino_gen, char *filename, | ||
52 | enum map_type type) | 53 | enum map_type type) |
53 | { | 54 | { |
54 | struct map *map = malloc(sizeof(*map)); | 55 | struct map *map = malloc(sizeof(*map)); |
@@ -62,6 +63,11 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | |||
62 | vdso = is_vdso_map(filename); | 63 | vdso = is_vdso_map(filename); |
63 | no_dso = is_no_dso_memory(filename); | 64 | no_dso = is_no_dso_memory(filename); |
64 | 65 | ||
66 | map->maj = d_maj; | ||
67 | map->min = d_min; | ||
68 | map->ino = ino; | ||
69 | map->ino_generation = ino_gen; | ||
70 | |||
65 | if (anon) { | 71 | if (anon) { |
66 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); | 72 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid); |
67 | filename = newfilename; | 73 | filename = newfilename; |
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 2cc93cbf0e17..4886ca280536 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -36,6 +36,9 @@ struct map { | |||
36 | bool erange_warned; | 36 | bool erange_warned; |
37 | u32 priv; | 37 | u32 priv; |
38 | u64 pgoff; | 38 | u64 pgoff; |
39 | u32 maj, min; /* only valid for MMAP2 record */ | ||
40 | u64 ino; /* only valid for MMAP2 record */ | ||
41 | u64 ino_generation;/* only valid for MMAP2 record */ | ||
39 | 42 | ||
40 | /* ip -> dso rip */ | 43 | /* ip -> dso rip */ |
41 | u64 (*map_ip)(struct map *, u64); | 44 | u64 (*map_ip)(struct map *, u64); |
@@ -88,8 +91,9 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym); | |||
88 | void map__init(struct map *map, enum map_type type, | 91 | void map__init(struct map *map, enum map_type type, |
89 | u64 start, u64 end, u64 pgoff, struct dso *dso); | 92 | u64 start, u64 end, u64 pgoff, struct dso *dso); |
90 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, | 93 | struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, |
91 | u64 pgoff, u32 pid, char *filename, | 94 | u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, |
92 | enum map_type type); | 95 | u64 ino_gen, |
96 | char *filename, enum map_type type); | ||
93 | struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 97 | struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
94 | void map__delete(struct map *map); | 98 | void map__delete(struct map *map); |
95 | struct map *map__clone(struct map *map); | 99 | struct map *map__clone(struct map *map); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 1fc0c628683e..51f5edf2a6d0 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -351,6 +351,25 @@ static void perf_event__mmap_swap(union perf_event *event, | |||
351 | } | 351 | } |
352 | } | 352 | } |
353 | 353 | ||
354 | static void perf_event__mmap2_swap(union perf_event *event, | ||
355 | bool sample_id_all) | ||
356 | { | ||
357 | event->mmap2.pid = bswap_32(event->mmap2.pid); | ||
358 | event->mmap2.tid = bswap_32(event->mmap2.tid); | ||
359 | event->mmap2.start = bswap_64(event->mmap2.start); | ||
360 | event->mmap2.len = bswap_64(event->mmap2.len); | ||
361 | event->mmap2.pgoff = bswap_64(event->mmap2.pgoff); | ||
362 | event->mmap2.maj = bswap_32(event->mmap2.maj); | ||
363 | event->mmap2.min = bswap_32(event->mmap2.min); | ||
364 | event->mmap2.ino = bswap_64(event->mmap2.ino); | ||
365 | |||
366 | if (sample_id_all) { | ||
367 | void *data = &event->mmap2.filename; | ||
368 | |||
369 | data += PERF_ALIGN(strlen(data) + 1, sizeof(u64)); | ||
370 | swap_sample_id_all(event, data); | ||
371 | } | ||
372 | } | ||
354 | static void perf_event__task_swap(union perf_event *event, bool sample_id_all) | 373 | static void perf_event__task_swap(union perf_event *event, bool sample_id_all) |
355 | { | 374 | { |
356 | event->fork.pid = bswap_32(event->fork.pid); | 375 | event->fork.pid = bswap_32(event->fork.pid); |
@@ -455,6 +474,7 @@ typedef void (*perf_event__swap_op)(union perf_event *event, | |||
455 | 474 | ||
456 | static perf_event__swap_op perf_event__swap_ops[] = { | 475 | static perf_event__swap_op perf_event__swap_ops[] = { |
457 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, | 476 | [PERF_RECORD_MMAP] = perf_event__mmap_swap, |
477 | [PERF_RECORD_MMAP2] = perf_event__mmap2_swap, | ||
458 | [PERF_RECORD_COMM] = perf_event__comm_swap, | 478 | [PERF_RECORD_COMM] = perf_event__comm_swap, |
459 | [PERF_RECORD_FORK] = perf_event__task_swap, | 479 | [PERF_RECORD_FORK] = perf_event__task_swap, |
460 | [PERF_RECORD_EXIT] = perf_event__task_swap, | 480 | [PERF_RECORD_EXIT] = perf_event__task_swap, |
@@ -504,6 +524,7 @@ static int flush_sample_queue(struct perf_session *s, | |||
504 | u64 limit = os->next_flush; | 524 | u64 limit = os->next_flush; |
505 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; | 525 | u64 last_ts = os->last_sample ? os->last_sample->timestamp : 0ULL; |
506 | unsigned idx = 0, progress_next = os->nr_samples / 16; | 526 | unsigned idx = 0, progress_next = os->nr_samples / 16; |
527 | bool show_progress = limit == ULLONG_MAX; | ||
507 | int ret; | 528 | int ret; |
508 | 529 | ||
509 | if (!tool->ordered_samples || !limit) | 530 | if (!tool->ordered_samples || !limit) |
@@ -526,7 +547,7 @@ static int flush_sample_queue(struct perf_session *s, | |||
526 | os->last_flush = iter->timestamp; | 547 | os->last_flush = iter->timestamp; |
527 | list_del(&iter->list); | 548 | list_del(&iter->list); |
528 | list_add(&iter->list, &os->sample_cache); | 549 | list_add(&iter->list, &os->sample_cache); |
529 | if (++idx >= progress_next) { | 550 | if (show_progress && (++idx >= progress_next)) { |
530 | progress_next += os->nr_samples / 16; | 551 | progress_next += os->nr_samples / 16; |
531 | ui_progress__update(idx, os->nr_samples, | 552 | ui_progress__update(idx, os->nr_samples, |
532 | "Processing time ordered events..."); | 553 | "Processing time ordered events..."); |
@@ -850,7 +871,8 @@ static struct machine * | |||
850 | (cpumode == PERF_RECORD_MISC_GUEST_USER))) { | 871 | (cpumode == PERF_RECORD_MISC_GUEST_USER))) { |
851 | u32 pid; | 872 | u32 pid; |
852 | 873 | ||
853 | if (event->header.type == PERF_RECORD_MMAP) | 874 | if (event->header.type == PERF_RECORD_MMAP |
875 | || event->header.type == PERF_RECORD_MMAP2) | ||
854 | pid = event->mmap.pid; | 876 | pid = event->mmap.pid; |
855 | else | 877 | else |
856 | pid = sample->pid; | 878 | pid = sample->pid; |
@@ -977,6 +999,8 @@ static int perf_session_deliver_event(struct perf_session *session, | |||
977 | sample, evsel, machine); | 999 | sample, evsel, machine); |
978 | case PERF_RECORD_MMAP: | 1000 | case PERF_RECORD_MMAP: |
979 | return tool->mmap(tool, event, sample, machine); | 1001 | return tool->mmap(tool, event, sample, machine); |
1002 | case PERF_RECORD_MMAP2: | ||
1003 | return tool->mmap2(tool, event, sample, machine); | ||
980 | case PERF_RECORD_COMM: | 1004 | case PERF_RECORD_COMM: |
981 | return tool->comm(tool, event, sample, machine); | 1005 | return tool->comm(tool, event, sample, machine); |
982 | case PERF_RECORD_FORK: | 1006 | case PERF_RECORD_FORK: |
@@ -1619,52 +1643,26 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, | |||
1619 | const struct perf_evsel_str_handler *assocs, | 1643 | const struct perf_evsel_str_handler *assocs, |
1620 | size_t nr_assocs) | 1644 | size_t nr_assocs) |
1621 | { | 1645 | { |
1622 | struct perf_evlist *evlist = session->evlist; | ||
1623 | struct event_format *format; | ||
1624 | struct perf_evsel *evsel; | 1646 | struct perf_evsel *evsel; |
1625 | char *tracepoint, *name; | ||
1626 | size_t i; | 1647 | size_t i; |
1627 | int err; | 1648 | int err; |
1628 | 1649 | ||
1629 | for (i = 0; i < nr_assocs; i++) { | 1650 | for (i = 0; i < nr_assocs; i++) { |
1630 | err = -ENOMEM; | 1651 | /* |
1631 | tracepoint = strdup(assocs[i].name); | 1652 | * Adding a handler for an event not in the session, |
1632 | if (tracepoint == NULL) | 1653 | * just ignore it. |
1633 | goto out; | 1654 | */ |
1634 | 1655 | evsel = perf_evlist__find_tracepoint_by_name(session->evlist, assocs[i].name); | |
1635 | err = -ENOENT; | ||
1636 | name = strchr(tracepoint, ':'); | ||
1637 | if (name == NULL) | ||
1638 | goto out_free; | ||
1639 | |||
1640 | *name++ = '\0'; | ||
1641 | format = pevent_find_event_by_name(session->pevent, | ||
1642 | tracepoint, name); | ||
1643 | if (format == NULL) { | ||
1644 | /* | ||
1645 | * Adding a handler for an event not in the session, | ||
1646 | * just ignore it. | ||
1647 | */ | ||
1648 | goto next; | ||
1649 | } | ||
1650 | |||
1651 | evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id); | ||
1652 | if (evsel == NULL) | 1656 | if (evsel == NULL) |
1653 | goto next; | 1657 | continue; |
1654 | 1658 | ||
1655 | err = -EEXIST; | 1659 | err = -EEXIST; |
1656 | if (evsel->handler.func != NULL) | 1660 | if (evsel->handler.func != NULL) |
1657 | goto out_free; | 1661 | goto out; |
1658 | evsel->handler.func = assocs[i].handler; | 1662 | evsel->handler.func = assocs[i].handler; |
1659 | next: | ||
1660 | free(tracepoint); | ||
1661 | } | 1663 | } |
1662 | 1664 | ||
1663 | err = 0; | 1665 | err = 0; |
1664 | out: | 1666 | out: |
1665 | return err; | 1667 | return err; |
1666 | |||
1667 | out_free: | ||
1668 | free(tracepoint); | ||
1669 | goto out; | ||
1670 | } | 1668 | } |
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h index 62b16b6165ba..4385816d3d49 100644 --- a/tools/perf/util/tool.h +++ b/tools/perf/util/tool.h | |||
@@ -29,6 +29,7 @@ struct perf_tool { | |||
29 | event_sample sample, | 29 | event_sample sample, |
30 | read; | 30 | read; |
31 | event_op mmap, | 31 | event_op mmap, |
32 | mmap2, | ||
32 | comm, | 33 | comm, |
33 | fork, | 34 | fork, |
34 | exit, | 35 | exit, |