summaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2018-06-26 02:37:57 -0400
committerIngo Molnar <mingo@kernel.org>2018-06-26 02:37:57 -0400
commit79598041079827a22b33dd3edcb0dd827b70e204 (patch)
tree6335808b7d51fe4a0e7502a4459a3dc7ba39aa30 /tools/perf
parent6f0d349d922ba44e4348a17a78ea51b7135965b1 (diff)
parent92ead7ee30c80f8852d28735cbcb9d79bc85f715 (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.c2
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl2
-rw-r--r--tools/perf/bench/numa.c5
-rw-r--r--tools/perf/builtin-annotate.c11
-rw-r--r--tools/perf/builtin-report.c3
-rw-r--r--tools/perf/builtin-script.c30
-rw-r--r--tools/perf/tests/parse-events.c25
-rw-r--r--tools/perf/tests/topology.c1
-rw-r--r--tools/perf/util/c++/clang.cpp11
-rw-r--r--tools/perf/util/header.c12
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c2
-rw-r--r--tools/perf/util/pmu.c99
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 @@
341330 common pkey_alloc __x64_sys_pkey_alloc 341330 common pkey_alloc __x64_sys_pkey_alloc
342331 common pkey_free __x64_sys_pkey_free 342331 common pkey_free __x64_sys_pkey_free
343332 common statx __x64_sys_statx 343332 common statx __x64_sys_statx
344333 common io_pgetevents __x64_sys_io_pgetevents
345334 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
286static 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
286static int hist_entry__tty_annotate(struct hist_entry *he, 295static 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
3047static 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
3034static int perf_script__process_auxtrace_info(struct perf_tool *tool, 3057static 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
1312static bool test__intel_pt_valid(void)
1313{
1314 return !!perf_pmu__find("intel_pt");
1315}
1316
1312static int test__intel_pt(struct perf_evlist *evlist) 1317static 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
1687static int test_event(struct evlist_test *e) 1694static 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
237static 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;
250set_new:
251 *old_str = *new_str;
252 *new_str = NULL;
253}
254
255static 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. */
274static 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 */
290static 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
237static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, 305static 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}