diff options
author | Ingo Molnar <mingo@kernel.org> | 2018-06-26 02:37:57 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2018-06-26 02:37:57 -0400 |
commit | 79598041079827a22b33dd3edcb0dd827b70e204 (patch) | |
tree | 6335808b7d51fe4a0e7502a4459a3dc7ba39aa30 /tools/perf | |
parent | 6f0d349d922ba44e4348a17a78ea51b7135965b1 (diff) | |
parent | 92ead7ee30c80f8852d28735cbcb9d79bc85f715 (diff) |
Merge tag 'perf-urgent-for-mingo-4.18-20180625' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/urgent fixes from Arnaldo Carvalho de Melo:
perf bench: (Jiri Olsa):
- Fix NUMA report output code handling of less than 1s runtimes.
perf script: (Ravi Bangoria)
- Add missing output fields in a 'perf script -h' hint.
- Fix crash because of missing evsel->priv.
- Fix crash caused by accessing feat_ops[HEADER_LAST_FEATURE], which
is just a end of features header marker.
perf stat: (Thomas Richter)
- Remove duplicate event counting
perf test:
- Wire parsing error handling in 'parse events' test (Jiri Olsa)
- Fix 'session topology' test on s/390 (Thomas Richter)
eBPF: (Yonghong Song)
- Fix a clang 7.0 compilation error when building perf linking
with libclang
intel-pt: (Adrian Hunter)
- Fix packet decoding of CYC packets.
Copies of kernel files: (Arnaldo Carvalho de Melo)
- Synchronize drm/drm.h UAPI
- Update x86's syscall_64.tbl, adding support for 'io_pgetevents' and 'rseq'
in 'perf trace'.
- Update powerpc uapi/asm/unistd.h, adding support for the 'rseq' syscall.
- Update if_link.h and bpf.h, no effect on tool features.
PowerPC: (Sandipan Das)
- Fix crash if callchain is empty.
s/390: (Thomas Richter)
- Support random socked_id assignment in the perf header.
- Support s390 random socket_id assignment in perf.data file.
- Make PMU alias definitions taken from sysfs and JSON files comparable
by normalizing them wrt spaces and newlines.
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/arch/powerpc/util/skip-callchain-idx.c | 2 | ||||
-rw-r--r-- | tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | 2 | ||||
-rw-r--r-- | tools/perf/bench/numa.c | 5 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 11 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 3 | ||||
-rw-r--r-- | tools/perf/builtin-script.c | 30 | ||||
-rw-r--r-- | tools/perf/tests/parse-events.c | 25 | ||||
-rw-r--r-- | tools/perf/tests/topology.c | 1 | ||||
-rw-r--r-- | tools/perf/util/c++/clang.cpp | 11 | ||||
-rw-r--r-- | tools/perf/util/header.c | 12 | ||||
-rw-r--r-- | tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | 2 | ||||
-rw-r--r-- | tools/perf/util/pmu.c | 99 |
12 files changed, 183 insertions, 20 deletions
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c index 3598b8b75d27..ef5d59a5742e 100644 --- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c +++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c | |||
@@ -243,7 +243,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain) | |||
243 | u64 ip; | 243 | u64 ip; |
244 | u64 skip_slot = -1; | 244 | u64 skip_slot = -1; |
245 | 245 | ||
246 | if (chain->nr < 3) | 246 | if (!chain || chain->nr < 3) |
247 | return skip_slot; | 247 | return skip_slot; |
248 | 248 | ||
249 | ip = chain->ips[2]; | 249 | ip = chain->ips[2]; |
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl index 4dfe42666d0c..f0b1709a5ffb 100644 --- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl | |||
@@ -341,6 +341,8 @@ | |||
341 | 330 common pkey_alloc __x64_sys_pkey_alloc | 341 | 330 common pkey_alloc __x64_sys_pkey_alloc |
342 | 331 common pkey_free __x64_sys_pkey_free | 342 | 331 common pkey_free __x64_sys_pkey_free |
343 | 332 common statx __x64_sys_statx | 343 | 332 common statx __x64_sys_statx |
344 | 333 common io_pgetevents __x64_sys_io_pgetevents | ||
345 | 334 common rseq __x64_sys_rseq | ||
344 | 346 | ||
345 | # | 347 | # |
346 | # x32-specific system call numbers start at 512 to avoid cache impact | 348 | # x32-specific system call numbers start at 512 to avoid cache impact |
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c index 63eb49082774..44195514b19e 100644 --- a/tools/perf/bench/numa.c +++ b/tools/perf/bench/numa.c | |||
@@ -1098,7 +1098,7 @@ static void *worker_thread(void *__tdata) | |||
1098 | u8 *global_data; | 1098 | u8 *global_data; |
1099 | u8 *process_data; | 1099 | u8 *process_data; |
1100 | u8 *thread_data; | 1100 | u8 *thread_data; |
1101 | u64 bytes_done; | 1101 | u64 bytes_done, secs; |
1102 | long work_done; | 1102 | long work_done; |
1103 | u32 l; | 1103 | u32 l; |
1104 | struct rusage rusage; | 1104 | struct rusage rusage; |
@@ -1254,7 +1254,8 @@ static void *worker_thread(void *__tdata) | |||
1254 | timersub(&stop, &start0, &diff); | 1254 | timersub(&stop, &start0, &diff); |
1255 | td->runtime_ns = diff.tv_sec * NSEC_PER_SEC; | 1255 | td->runtime_ns = diff.tv_sec * NSEC_PER_SEC; |
1256 | td->runtime_ns += diff.tv_usec * NSEC_PER_USEC; | 1256 | td->runtime_ns += diff.tv_usec * NSEC_PER_USEC; |
1257 | td->speed_gbs = bytes_done / (td->runtime_ns / NSEC_PER_SEC) / 1e9; | 1257 | secs = td->runtime_ns / NSEC_PER_SEC; |
1258 | td->speed_gbs = secs ? bytes_done / secs / 1e9 : 0; | ||
1258 | 1259 | ||
1259 | getrusage(RUSAGE_THREAD, &rusage); | 1260 | getrusage(RUSAGE_THREAD, &rusage); |
1260 | td->system_time_ns = rusage.ru_stime.tv_sec * NSEC_PER_SEC; | 1261 | td->system_time_ns = rusage.ru_stime.tv_sec * NSEC_PER_SEC; |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5eb22cc56363..8180319285af 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -283,6 +283,15 @@ out_put: | |||
283 | return ret; | 283 | return ret; |
284 | } | 284 | } |
285 | 285 | ||
286 | static int process_feature_event(struct perf_tool *tool, | ||
287 | union perf_event *event, | ||
288 | struct perf_session *session) | ||
289 | { | ||
290 | if (event->feat.feat_id < HEADER_LAST_FEATURE) | ||
291 | return perf_event__process_feature(tool, event, session); | ||
292 | return 0; | ||
293 | } | ||
294 | |||
286 | static int hist_entry__tty_annotate(struct hist_entry *he, | 295 | static int hist_entry__tty_annotate(struct hist_entry *he, |
287 | struct perf_evsel *evsel, | 296 | struct perf_evsel *evsel, |
288 | struct perf_annotate *ann) | 297 | struct perf_annotate *ann) |
@@ -471,7 +480,7 @@ int cmd_annotate(int argc, const char **argv) | |||
471 | .attr = perf_event__process_attr, | 480 | .attr = perf_event__process_attr, |
472 | .build_id = perf_event__process_build_id, | 481 | .build_id = perf_event__process_build_id, |
473 | .tracing_data = perf_event__process_tracing_data, | 482 | .tracing_data = perf_event__process_tracing_data, |
474 | .feature = perf_event__process_feature, | 483 | .feature = process_feature_event, |
475 | .ordered_events = true, | 484 | .ordered_events = true, |
476 | .ordering_requires_timestamps = true, | 485 | .ordering_requires_timestamps = true, |
477 | }, | 486 | }, |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index cdb5b6949832..c04dc7b53797 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -217,7 +217,8 @@ static int process_feature_event(struct perf_tool *tool, | |||
217 | } | 217 | } |
218 | 218 | ||
219 | /* | 219 | /* |
220 | * All features are received, we can force the | 220 | * (feat_id = HEADER_LAST_FEATURE) is the end marker which |
221 | * means all features are received, now we can force the | ||
221 | * group if needed. | 222 | * group if needed. |
222 | */ | 223 | */ |
223 | setup_forced_leader(rep, session->evlist); | 224 | setup_forced_leader(rep, session->evlist); |
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index a31d7082188e..568ddfac3213 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c | |||
@@ -1834,6 +1834,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, | |||
1834 | struct perf_evlist *evlist; | 1834 | struct perf_evlist *evlist; |
1835 | struct perf_evsel *evsel, *pos; | 1835 | struct perf_evsel *evsel, *pos; |
1836 | int err; | 1836 | int err; |
1837 | static struct perf_evsel_script *es; | ||
1837 | 1838 | ||
1838 | err = perf_event__process_attr(tool, event, pevlist); | 1839 | err = perf_event__process_attr(tool, event, pevlist); |
1839 | if (err) | 1840 | if (err) |
@@ -1842,6 +1843,19 @@ static int process_attr(struct perf_tool *tool, union perf_event *event, | |||
1842 | evlist = *pevlist; | 1843 | evlist = *pevlist; |
1843 | evsel = perf_evlist__last(*pevlist); | 1844 | evsel = perf_evlist__last(*pevlist); |
1844 | 1845 | ||
1846 | if (!evsel->priv) { | ||
1847 | if (scr->per_event_dump) { | ||
1848 | evsel->priv = perf_evsel_script__new(evsel, | ||
1849 | scr->session->data); | ||
1850 | } else { | ||
1851 | es = zalloc(sizeof(*es)); | ||
1852 | if (!es) | ||
1853 | return -ENOMEM; | ||
1854 | es->fp = stdout; | ||
1855 | evsel->priv = es; | ||
1856 | } | ||
1857 | } | ||
1858 | |||
1845 | if (evsel->attr.type >= PERF_TYPE_MAX && | 1859 | if (evsel->attr.type >= PERF_TYPE_MAX && |
1846 | evsel->attr.type != PERF_TYPE_SYNTH) | 1860 | evsel->attr.type != PERF_TYPE_SYNTH) |
1847 | return 0; | 1861 | return 0; |
@@ -3030,6 +3044,15 @@ int process_cpu_map_event(struct perf_tool *tool __maybe_unused, | |||
3030 | return set_maps(script); | 3044 | return set_maps(script); |
3031 | } | 3045 | } |
3032 | 3046 | ||
3047 | static int process_feature_event(struct perf_tool *tool, | ||
3048 | union perf_event *event, | ||
3049 | struct perf_session *session) | ||
3050 | { | ||
3051 | if (event->feat.feat_id < HEADER_LAST_FEATURE) | ||
3052 | return perf_event__process_feature(tool, event, session); | ||
3053 | return 0; | ||
3054 | } | ||
3055 | |||
3033 | #ifdef HAVE_AUXTRACE_SUPPORT | 3056 | #ifdef HAVE_AUXTRACE_SUPPORT |
3034 | static int perf_script__process_auxtrace_info(struct perf_tool *tool, | 3057 | static int perf_script__process_auxtrace_info(struct perf_tool *tool, |
3035 | union perf_event *event, | 3058 | union perf_event *event, |
@@ -3074,7 +3097,7 @@ int cmd_script(int argc, const char **argv) | |||
3074 | .attr = process_attr, | 3097 | .attr = process_attr, |
3075 | .event_update = perf_event__process_event_update, | 3098 | .event_update = perf_event__process_event_update, |
3076 | .tracing_data = perf_event__process_tracing_data, | 3099 | .tracing_data = perf_event__process_tracing_data, |
3077 | .feature = perf_event__process_feature, | 3100 | .feature = process_feature_event, |
3078 | .build_id = perf_event__process_build_id, | 3101 | .build_id = perf_event__process_build_id, |
3079 | .id_index = perf_event__process_id_index, | 3102 | .id_index = perf_event__process_id_index, |
3080 | .auxtrace_info = perf_script__process_auxtrace_info, | 3103 | .auxtrace_info = perf_script__process_auxtrace_info, |
@@ -3125,8 +3148,9 @@ int cmd_script(int argc, const char **argv) | |||
3125 | "+field to add and -field to remove." | 3148 | "+field to add and -field to remove." |
3126 | "Valid types: hw,sw,trace,raw,synth. " | 3149 | "Valid types: hw,sw,trace,raw,synth. " |
3127 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," | 3150 | "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," |
3128 | "addr,symoff,period,iregs,uregs,brstack,brstacksym,flags," | 3151 | "addr,symoff,srcline,period,iregs,uregs,brstack," |
3129 | "bpf-output,callindent,insn,insnlen,brstackinsn,synth,phys_addr", | 3152 | "brstacksym,flags,bpf-output,brstackinsn,brstackoff," |
3153 | "callindent,insn,insnlen,synth,phys_addr,metric,misc", | ||
3130 | parse_output_fields), | 3154 | parse_output_fields), |
3131 | OPT_BOOLEAN('a', "all-cpus", &system_wide, | 3155 | OPT_BOOLEAN('a', "all-cpus", &system_wide, |
3132 | "system-wide collection from all CPUs"), | 3156 | "system-wide collection from all CPUs"), |
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c index 7d4077068454..61211918bfba 100644 --- a/tools/perf/tests/parse-events.c +++ b/tools/perf/tests/parse-events.c | |||
@@ -1309,6 +1309,11 @@ static int test__checkevent_config_cache(struct perf_evlist *evlist) | |||
1309 | return 0; | 1309 | return 0; |
1310 | } | 1310 | } |
1311 | 1311 | ||
1312 | static bool test__intel_pt_valid(void) | ||
1313 | { | ||
1314 | return !!perf_pmu__find("intel_pt"); | ||
1315 | } | ||
1316 | |||
1312 | static int test__intel_pt(struct perf_evlist *evlist) | 1317 | static int test__intel_pt(struct perf_evlist *evlist) |
1313 | { | 1318 | { |
1314 | struct perf_evsel *evsel = perf_evlist__first(evlist); | 1319 | struct perf_evsel *evsel = perf_evlist__first(evlist); |
@@ -1375,6 +1380,7 @@ struct evlist_test { | |||
1375 | const char *name; | 1380 | const char *name; |
1376 | __u32 type; | 1381 | __u32 type; |
1377 | const int id; | 1382 | const int id; |
1383 | bool (*valid)(void); | ||
1378 | int (*check)(struct perf_evlist *evlist); | 1384 | int (*check)(struct perf_evlist *evlist); |
1379 | }; | 1385 | }; |
1380 | 1386 | ||
@@ -1648,6 +1654,7 @@ static struct evlist_test test__events[] = { | |||
1648 | }, | 1654 | }, |
1649 | { | 1655 | { |
1650 | .name = "intel_pt//u", | 1656 | .name = "intel_pt//u", |
1657 | .valid = test__intel_pt_valid, | ||
1651 | .check = test__intel_pt, | 1658 | .check = test__intel_pt, |
1652 | .id = 52, | 1659 | .id = 52, |
1653 | }, | 1660 | }, |
@@ -1686,17 +1693,24 @@ static struct terms_test test__terms[] = { | |||
1686 | 1693 | ||
1687 | static int test_event(struct evlist_test *e) | 1694 | static int test_event(struct evlist_test *e) |
1688 | { | 1695 | { |
1696 | struct parse_events_error err = { .idx = 0, }; | ||
1689 | struct perf_evlist *evlist; | 1697 | struct perf_evlist *evlist; |
1690 | int ret; | 1698 | int ret; |
1691 | 1699 | ||
1700 | if (e->valid && !e->valid()) { | ||
1701 | pr_debug("... SKIP"); | ||
1702 | return 0; | ||
1703 | } | ||
1704 | |||
1692 | evlist = perf_evlist__new(); | 1705 | evlist = perf_evlist__new(); |
1693 | if (evlist == NULL) | 1706 | if (evlist == NULL) |
1694 | return -ENOMEM; | 1707 | return -ENOMEM; |
1695 | 1708 | ||
1696 | ret = parse_events(evlist, e->name, NULL); | 1709 | ret = parse_events(evlist, e->name, &err); |
1697 | if (ret) { | 1710 | if (ret) { |
1698 | pr_debug("failed to parse event '%s', err %d\n", | 1711 | pr_debug("failed to parse event '%s', err %d, str '%s'\n", |
1699 | e->name, ret); | 1712 | e->name, ret, err.str); |
1713 | parse_events_print_error(&err, e->name); | ||
1700 | } else { | 1714 | } else { |
1701 | ret = e->check(evlist); | 1715 | ret = e->check(evlist); |
1702 | } | 1716 | } |
@@ -1714,10 +1728,11 @@ static int test_events(struct evlist_test *events, unsigned cnt) | |||
1714 | for (i = 0; i < cnt; i++) { | 1728 | for (i = 0; i < cnt; i++) { |
1715 | struct evlist_test *e = &events[i]; | 1729 | struct evlist_test *e = &events[i]; |
1716 | 1730 | ||
1717 | pr_debug("running test %d '%s'\n", e->id, e->name); | 1731 | pr_debug("running test %d '%s'", e->id, e->name); |
1718 | ret1 = test_event(e); | 1732 | ret1 = test_event(e); |
1719 | if (ret1) | 1733 | if (ret1) |
1720 | ret2 = ret1; | 1734 | ret2 = ret1; |
1735 | pr_debug("\n"); | ||
1721 | } | 1736 | } |
1722 | 1737 | ||
1723 | return ret2; | 1738 | return ret2; |
@@ -1799,7 +1814,7 @@ static int test_pmu_events(void) | |||
1799 | } | 1814 | } |
1800 | 1815 | ||
1801 | while (!ret && (ent = readdir(dir))) { | 1816 | while (!ret && (ent = readdir(dir))) { |
1802 | struct evlist_test e; | 1817 | struct evlist_test e = { .id = 0, }; |
1803 | char name[2 * NAME_MAX + 1 + 12 + 3]; | 1818 | char name[2 * NAME_MAX + 1 + 12 + 3]; |
1804 | 1819 | ||
1805 | /* Names containing . are special and cannot be used directly */ | 1820 | /* Names containing . are special and cannot be used directly */ |
diff --git a/tools/perf/tests/topology.c b/tools/perf/tests/topology.c index 40e30a26b23c..9497d02f69e6 100644 --- a/tools/perf/tests/topology.c +++ b/tools/perf/tests/topology.c | |||
@@ -45,6 +45,7 @@ static int session_write_header(char *path) | |||
45 | 45 | ||
46 | perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); | 46 | perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY); |
47 | perf_header__set_feat(&session->header, HEADER_NRCPUS); | 47 | perf_header__set_feat(&session->header, HEADER_NRCPUS); |
48 | perf_header__set_feat(&session->header, HEADER_ARCH); | ||
48 | 49 | ||
49 | session->header.data_size += DATA_SIZE; | 50 | session->header.data_size += DATA_SIZE; |
50 | 51 | ||
diff --git a/tools/perf/util/c++/clang.cpp b/tools/perf/util/c++/clang.cpp index bf31ceab33bd..89512504551b 100644 --- a/tools/perf/util/c++/clang.cpp +++ b/tools/perf/util/c++/clang.cpp | |||
@@ -146,8 +146,15 @@ getBPFObjectFromModule(llvm::Module *Module) | |||
146 | raw_svector_ostream ostream(*Buffer); | 146 | raw_svector_ostream ostream(*Buffer); |
147 | 147 | ||
148 | legacy::PassManager PM; | 148 | legacy::PassManager PM; |
149 | if (TargetMachine->addPassesToEmitFile(PM, ostream, | 149 | bool NotAdded; |
150 | TargetMachine::CGFT_ObjectFile)) { | 150 | #if CLANG_VERSION_MAJOR < 7 |
151 | NotAdded = TargetMachine->addPassesToEmitFile(PM, ostream, | ||
152 | TargetMachine::CGFT_ObjectFile); | ||
153 | #else | ||
154 | NotAdded = TargetMachine->addPassesToEmitFile(PM, ostream, nullptr, | ||
155 | TargetMachine::CGFT_ObjectFile); | ||
156 | #endif | ||
157 | if (NotAdded) { | ||
151 | llvm::errs() << "TargetMachine can't emit a file of this type\n"; | 158 | llvm::errs() << "TargetMachine can't emit a file of this type\n"; |
152 | return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);; | 159 | return std::unique_ptr<llvm::SmallVectorImpl<char>>(nullptr);; |
153 | } | 160 | } |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 540cd2dcd3e7..653ff65aa2c3 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -2129,6 +2129,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) | |||
2129 | int cpu_nr = ff->ph->env.nr_cpus_avail; | 2129 | int cpu_nr = ff->ph->env.nr_cpus_avail; |
2130 | u64 size = 0; | 2130 | u64 size = 0; |
2131 | struct perf_header *ph = ff->ph; | 2131 | struct perf_header *ph = ff->ph; |
2132 | bool do_core_id_test = true; | ||
2132 | 2133 | ||
2133 | ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); | 2134 | ph->env.cpu = calloc(cpu_nr, sizeof(*ph->env.cpu)); |
2134 | if (!ph->env.cpu) | 2135 | if (!ph->env.cpu) |
@@ -2183,6 +2184,13 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) | |||
2183 | return 0; | 2184 | return 0; |
2184 | } | 2185 | } |
2185 | 2186 | ||
2187 | /* On s390 the socket_id number is not related to the numbers of cpus. | ||
2188 | * The socket_id number might be higher than the numbers of cpus. | ||
2189 | * This depends on the configuration. | ||
2190 | */ | ||
2191 | if (ph->env.arch && !strncmp(ph->env.arch, "s390", 4)) | ||
2192 | do_core_id_test = false; | ||
2193 | |||
2186 | for (i = 0; i < (u32)cpu_nr; i++) { | 2194 | for (i = 0; i < (u32)cpu_nr; i++) { |
2187 | if (do_read_u32(ff, &nr)) | 2195 | if (do_read_u32(ff, &nr)) |
2188 | goto free_cpu; | 2196 | goto free_cpu; |
@@ -2192,7 +2200,7 @@ static int process_cpu_topology(struct feat_fd *ff, void *data __maybe_unused) | |||
2192 | if (do_read_u32(ff, &nr)) | 2200 | if (do_read_u32(ff, &nr)) |
2193 | goto free_cpu; | 2201 | goto free_cpu; |
2194 | 2202 | ||
2195 | if (nr != (u32)-1 && nr > (u32)cpu_nr) { | 2203 | if (do_core_id_test && nr != (u32)-1 && nr > (u32)cpu_nr) { |
2196 | pr_debug("socket_id number is too big." | 2204 | pr_debug("socket_id number is too big." |
2197 | "You may need to upgrade the perf tool.\n"); | 2205 | "You may need to upgrade the perf tool.\n"); |
2198 | goto free_cpu; | 2206 | goto free_cpu; |
@@ -3456,7 +3464,7 @@ int perf_event__process_feature(struct perf_tool *tool, | |||
3456 | pr_warning("invalid record type %d in pipe-mode\n", type); | 3464 | pr_warning("invalid record type %d in pipe-mode\n", type); |
3457 | return 0; | 3465 | return 0; |
3458 | } | 3466 | } |
3459 | if (feat == HEADER_RESERVED || feat > HEADER_LAST_FEATURE) { | 3467 | if (feat == HEADER_RESERVED || feat >= HEADER_LAST_FEATURE) { |
3460 | pr_warning("invalid record type %d in pipe-mode\n", type); | 3468 | pr_warning("invalid record type %d in pipe-mode\n", type); |
3461 | return -1; | 3469 | return -1; |
3462 | } | 3470 | } |
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c index ba4c9dd18643..d426761a549d 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c | |||
@@ -366,7 +366,7 @@ static int intel_pt_get_cyc(unsigned int byte, const unsigned char *buf, | |||
366 | if (len < offs) | 366 | if (len < offs) |
367 | return INTEL_PT_NEED_MORE_BYTES; | 367 | return INTEL_PT_NEED_MORE_BYTES; |
368 | byte = buf[offs++]; | 368 | byte = buf[offs++]; |
369 | payload |= (byte >> 1) << shift; | 369 | payload |= ((uint64_t)byte >> 1) << shift; |
370 | } | 370 | } |
371 | 371 | ||
372 | packet->type = INTEL_PT_CYC; | 372 | packet->type = INTEL_PT_CYC; |
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c index d2fb597c9a8c..3ba6a1742f91 100644 --- a/tools/perf/util/pmu.c +++ b/tools/perf/util/pmu.c | |||
@@ -234,6 +234,74 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, | |||
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | static void perf_pmu_assign_str(char *name, const char *field, char **old_str, | ||
238 | char **new_str) | ||
239 | { | ||
240 | if (!*old_str) | ||
241 | goto set_new; | ||
242 | |||
243 | if (*new_str) { /* Have new string, check with old */ | ||
244 | if (strcasecmp(*old_str, *new_str)) | ||
245 | pr_debug("alias %s differs in field '%s'\n", | ||
246 | name, field); | ||
247 | zfree(old_str); | ||
248 | } else /* Nothing new --> keep old string */ | ||
249 | return; | ||
250 | set_new: | ||
251 | *old_str = *new_str; | ||
252 | *new_str = NULL; | ||
253 | } | ||
254 | |||
255 | static void perf_pmu_update_alias(struct perf_pmu_alias *old, | ||
256 | struct perf_pmu_alias *newalias) | ||
257 | { | ||
258 | perf_pmu_assign_str(old->name, "desc", &old->desc, &newalias->desc); | ||
259 | perf_pmu_assign_str(old->name, "long_desc", &old->long_desc, | ||
260 | &newalias->long_desc); | ||
261 | perf_pmu_assign_str(old->name, "topic", &old->topic, &newalias->topic); | ||
262 | perf_pmu_assign_str(old->name, "metric_expr", &old->metric_expr, | ||
263 | &newalias->metric_expr); | ||
264 | perf_pmu_assign_str(old->name, "metric_name", &old->metric_name, | ||
265 | &newalias->metric_name); | ||
266 | perf_pmu_assign_str(old->name, "value", &old->str, &newalias->str); | ||
267 | old->scale = newalias->scale; | ||
268 | old->per_pkg = newalias->per_pkg; | ||
269 | old->snapshot = newalias->snapshot; | ||
270 | memcpy(old->unit, newalias->unit, sizeof(old->unit)); | ||
271 | } | ||
272 | |||
273 | /* Delete an alias entry. */ | ||
274 | static void perf_pmu_free_alias(struct perf_pmu_alias *newalias) | ||
275 | { | ||
276 | zfree(&newalias->name); | ||
277 | zfree(&newalias->desc); | ||
278 | zfree(&newalias->long_desc); | ||
279 | zfree(&newalias->topic); | ||
280 | zfree(&newalias->str); | ||
281 | zfree(&newalias->metric_expr); | ||
282 | zfree(&newalias->metric_name); | ||
283 | parse_events_terms__purge(&newalias->terms); | ||
284 | free(newalias); | ||
285 | } | ||
286 | |||
287 | /* Merge an alias, search in alias list. If this name is already | ||
288 | * present merge both of them to combine all information. | ||
289 | */ | ||
290 | static bool perf_pmu_merge_alias(struct perf_pmu_alias *newalias, | ||
291 | struct list_head *alist) | ||
292 | { | ||
293 | struct perf_pmu_alias *a; | ||
294 | |||
295 | list_for_each_entry(a, alist, list) { | ||
296 | if (!strcasecmp(newalias->name, a->name)) { | ||
297 | perf_pmu_update_alias(a, newalias); | ||
298 | perf_pmu_free_alias(newalias); | ||
299 | return true; | ||
300 | } | ||
301 | } | ||
302 | return false; | ||
303 | } | ||
304 | |||
237 | static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, | 305 | static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, |
238 | char *desc, char *val, | 306 | char *desc, char *val, |
239 | char *long_desc, char *topic, | 307 | char *long_desc, char *topic, |
@@ -241,9 +309,11 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, | |||
241 | char *metric_expr, | 309 | char *metric_expr, |
242 | char *metric_name) | 310 | char *metric_name) |
243 | { | 311 | { |
312 | struct parse_events_term *term; | ||
244 | struct perf_pmu_alias *alias; | 313 | struct perf_pmu_alias *alias; |
245 | int ret; | 314 | int ret; |
246 | int num; | 315 | int num; |
316 | char newval[256]; | ||
247 | 317 | ||
248 | alias = malloc(sizeof(*alias)); | 318 | alias = malloc(sizeof(*alias)); |
249 | if (!alias) | 319 | if (!alias) |
@@ -262,6 +332,27 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, | |||
262 | return ret; | 332 | return ret; |
263 | } | 333 | } |
264 | 334 | ||
335 | /* Scan event and remove leading zeroes, spaces, newlines, some | ||
336 | * platforms have terms specified as | ||
337 | * event=0x0091 (read from files ../<PMU>/events/<FILE> | ||
338 | * and terms specified as event=0x91 (read from JSON files). | ||
339 | * | ||
340 | * Rebuild string to make alias->str member comparable. | ||
341 | */ | ||
342 | memset(newval, 0, sizeof(newval)); | ||
343 | ret = 0; | ||
344 | list_for_each_entry(term, &alias->terms, list) { | ||
345 | if (ret) | ||
346 | ret += scnprintf(newval + ret, sizeof(newval) - ret, | ||
347 | ","); | ||
348 | if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) | ||
349 | ret += scnprintf(newval + ret, sizeof(newval) - ret, | ||
350 | "%s=%#x", term->config, term->val.num); | ||
351 | else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) | ||
352 | ret += scnprintf(newval + ret, sizeof(newval) - ret, | ||
353 | "%s=%s", term->config, term->val.str); | ||
354 | } | ||
355 | |||
265 | alias->name = strdup(name); | 356 | alias->name = strdup(name); |
266 | if (dir) { | 357 | if (dir) { |
267 | /* | 358 | /* |
@@ -285,9 +376,10 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, | |||
285 | snprintf(alias->unit, sizeof(alias->unit), "%s", unit); | 376 | snprintf(alias->unit, sizeof(alias->unit), "%s", unit); |
286 | } | 377 | } |
287 | alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1; | 378 | alias->per_pkg = perpkg && sscanf(perpkg, "%d", &num) == 1 && num == 1; |
288 | alias->str = strdup(val); | 379 | alias->str = strdup(newval); |
289 | 380 | ||
290 | list_add_tail(&alias->list, list); | 381 | if (!perf_pmu_merge_alias(alias, list)) |
382 | list_add_tail(&alias->list, list); | ||
291 | 383 | ||
292 | return 0; | 384 | return 0; |
293 | } | 385 | } |
@@ -303,6 +395,9 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI | |||
303 | 395 | ||
304 | buf[ret] = 0; | 396 | buf[ret] = 0; |
305 | 397 | ||
398 | /* Remove trailing newline from sysfs file */ | ||
399 | rtrim(buf); | ||
400 | |||
306 | return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL, | 401 | return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL, NULL, |
307 | NULL, NULL, NULL); | 402 | NULL, NULL, NULL); |
308 | } | 403 | } |