aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2018-08-18 07:11:51 -0400
committerIngo Molnar <mingo@kernel.org>2018-08-18 07:11:51 -0400
commit5804b11034a21e4287daaf017c5ad60ad7af8d67 (patch)
tree79dd4998b58e3124bc2e5749914e4046afe5d0fd /tools/perf/util
parent13e091b6dd0e78a518a7d8756607d3acb8215768 (diff)
parent6855dc41b24619c3d1de3dbd27dd0546b0e45272 (diff)
Merge tag 'perf-core-for-mingo-4.19-20180815' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: kernel: - kallsyms, x86: Export addresses of PTI entry trampolines (Alexander Shishkin) - kallsyms: Simplify update_iter_mod() (Adrian Hunter) - x86: Add entry trampolines to kcore (Adrian Hunter) Hardware tracing: - Fix auxtrace queue resize (Adrian Hunter) Arch specific: - Fix uninitialized ARM SPE record error variable (Kim Phillips) - Fix trace event post-processing in powerpc (Sandipan Das) Build: - Fix check-headers.sh AND list path of execution (Alexander Kapshuk) - Remove -mcet and -fcf-protection when building the python binding with older clang versions (Arnaldo Carvalho de Melo) - Make check-headers.sh check based on kernel dir (Jiri Olsa) - Move syscall_64.tbl check into check-headers.sh (Jiri Olsa) Infrastructure: - Check for null when copying nsinfo. (Benno Evers) Libraries: - Rename libtraceevent prefixes, prep work for making it a shared library generaly available (Tzvetomir Stoyanov (VMware)) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/Build1
-rw-r--r--tools/perf/util/annotate.c301
-rw-r--r--tools/perf/util/annotate.h54
-rw-r--r--tools/perf/util/auxtrace.c6
-rw-r--r--tools/perf/util/auxtrace.h1
-rw-r--r--tools/perf/util/bpf-loader.c48
-rw-r--r--tools/perf/util/bpf-loader.h23
-rw-r--r--tools/perf/util/data-convert-bt.c6
-rw-r--r--tools/perf/util/event.c13
-rw-r--r--tools/perf/util/evsel.c2
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/header.c9
-rw-r--r--tools/perf/util/machine.h2
-rw-r--r--tools/perf/util/map.c44
-rw-r--r--tools/perf/util/map.h1
-rw-r--r--tools/perf/util/namespaces.c3
-rw-r--r--tools/perf/util/python.c10
-rw-r--r--tools/perf/util/s390-cpumsf-kernel.h71
-rw-r--r--tools/perf/util/s390-cpumsf.c945
-rw-r--r--tools/perf/util/s390-cpumsf.h21
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c2
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c6
-rw-r--r--tools/perf/util/setup.py10
-rw-r--r--tools/perf/util/sort.c16
-rw-r--r--tools/perf/util/sort.h2
-rw-r--r--tools/perf/util/trace-event-parse.c34
-rw-r--r--tools/perf/util/trace-event-read.c44
-rw-r--r--tools/perf/util/trace-event-scripting.c4
-rw-r--r--tools/perf/util/trace-event.c28
-rw-r--r--tools/perf/util/trace-event.h20
30 files changed, 1458 insertions, 276 deletions
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index b604ef334dc9..7efe15b9618d 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -87,6 +87,7 @@ libperf-$(CONFIG_AUXTRACE) += intel-pt.o
87libperf-$(CONFIG_AUXTRACE) += intel-bts.o 87libperf-$(CONFIG_AUXTRACE) += intel-bts.o
88libperf-$(CONFIG_AUXTRACE) += arm-spe.o 88libperf-$(CONFIG_AUXTRACE) += arm-spe.o
89libperf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o 89libperf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o
90libperf-$(CONFIG_AUXTRACE) += s390-cpumsf.o
90 91
91ifdef CONFIG_LIBOPENCSD 92ifdef CONFIG_LIBOPENCSD
92libperf-$(CONFIG_AUXTRACE) += cs-etm.o 93libperf-$(CONFIG_AUXTRACE) += cs-etm.o
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index f91775b4bc3c..e4268b948e0e 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -49,6 +49,7 @@ struct annotation_options annotation__default_options = {
49 .jump_arrows = true, 49 .jump_arrows = true,
50 .annotate_src = true, 50 .annotate_src = true,
51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS, 51 .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS,
52 .percent_type = PERCENT_PERIOD_LOCAL,
52}; 53};
53 54
54static regex_t file_lineno; 55static regex_t file_lineno;
@@ -1108,7 +1109,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
1108 if (perf_evsel__is_group_event(evsel)) 1109 if (perf_evsel__is_group_event(evsel))
1109 nr = evsel->nr_members; 1110 nr = evsel->nr_members;
1110 1111
1111 size += sizeof(al->samples[0]) * nr; 1112 size += sizeof(al->data[0]) * nr;
1112 1113
1113 al = zalloc(size); 1114 al = zalloc(size);
1114 if (al) { 1115 if (al) {
@@ -1117,7 +1118,7 @@ annotation_line__new(struct annotate_args *args, size_t privsize)
1117 al->offset = args->offset; 1118 al->offset = args->offset;
1118 al->line = strdup(args->line); 1119 al->line = strdup(args->line);
1119 al->line_nr = args->line_nr; 1120 al->line_nr = args->line_nr;
1120 al->samples_nr = nr; 1121 al->data_nr = nr;
1121 } 1122 }
1122 1123
1123 return al; 1124 return al;
@@ -1297,7 +1298,8 @@ static int disasm_line__print(struct disasm_line *dl, u64 start, int addr_fmt_wi
1297static int 1298static int
1298annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start, 1299annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start,
1299 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed, 1300 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
1300 int max_lines, struct annotation_line *queue, int addr_fmt_width) 1301 int max_lines, struct annotation_line *queue, int addr_fmt_width,
1302 int percent_type)
1301{ 1303{
1302 struct disasm_line *dl = container_of(al, struct disasm_line, al); 1304 struct disasm_line *dl = container_of(al, struct disasm_line, al);
1303 static const char *prev_line; 1305 static const char *prev_line;
@@ -1309,15 +1311,18 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1309 const char *color; 1311 const char *color;
1310 struct annotation *notes = symbol__annotation(sym); 1312 struct annotation *notes = symbol__annotation(sym);
1311 1313
1312 for (i = 0; i < al->samples_nr; i++) { 1314 for (i = 0; i < al->data_nr; i++) {
1313 struct annotation_data *sample = &al->samples[i]; 1315 double percent;
1314 1316
1315 if (sample->percent > max_percent) 1317 percent = annotation_data__percent(&al->data[i],
1316 max_percent = sample->percent; 1318 percent_type);
1319
1320 if (percent > max_percent)
1321 max_percent = percent;
1317 } 1322 }
1318 1323
1319 if (al->samples_nr > nr_percent) 1324 if (al->data_nr > nr_percent)
1320 nr_percent = al->samples_nr; 1325 nr_percent = al->data_nr;
1321 1326
1322 if (max_percent < min_pcnt) 1327 if (max_percent < min_pcnt)
1323 return -1; 1328 return -1;
@@ -1330,7 +1335,8 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1330 if (queue == al) 1335 if (queue == al)
1331 break; 1336 break;
1332 annotation_line__print(queue, sym, start, evsel, len, 1337 annotation_line__print(queue, sym, start, evsel, len,
1333 0, 0, 1, NULL, addr_fmt_width); 1338 0, 0, 1, NULL, addr_fmt_width,
1339 percent_type);
1334 } 1340 }
1335 } 1341 }
1336 1342
@@ -1351,18 +1357,20 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start
1351 } 1357 }
1352 1358
1353 for (i = 0; i < nr_percent; i++) { 1359 for (i = 0; i < nr_percent; i++) {
1354 struct annotation_data *sample = &al->samples[i]; 1360 struct annotation_data *data = &al->data[i];
1361 double percent;
1355 1362
1356 color = get_percent_color(sample->percent); 1363 percent = annotation_data__percent(data, percent_type);
1364 color = get_percent_color(percent);
1357 1365
1358 if (symbol_conf.show_total_period) 1366 if (symbol_conf.show_total_period)
1359 color_fprintf(stdout, color, " %11" PRIu64, 1367 color_fprintf(stdout, color, " %11" PRIu64,
1360 sample->he.period); 1368 data->he.period);
1361 else if (symbol_conf.show_nr_samples) 1369 else if (symbol_conf.show_nr_samples)
1362 color_fprintf(stdout, color, " %7" PRIu64, 1370 color_fprintf(stdout, color, " %7" PRIu64,
1363 sample->he.nr_samples); 1371 data->he.nr_samples);
1364 else 1372 else
1365 color_fprintf(stdout, color, " %7.2f", sample->percent); 1373 color_fprintf(stdout, color, " %7.2f", percent);
1366 } 1374 }
1367 1375
1368 printf(" : "); 1376 printf(" : ");
@@ -1753,34 +1761,45 @@ out_close_stdout:
1753 goto out_free_command; 1761 goto out_free_command;
1754} 1762}
1755 1763
1756static void calc_percent(struct sym_hist *hist, 1764static void calc_percent(struct sym_hist *sym_hist,
1757 struct annotation_data *sample, 1765 struct hists *hists,
1766 struct annotation_data *data,
1758 s64 offset, s64 end) 1767 s64 offset, s64 end)
1759{ 1768{
1760 unsigned int hits = 0; 1769 unsigned int hits = 0;
1761 u64 period = 0; 1770 u64 period = 0;
1762 1771
1763 while (offset < end) { 1772 while (offset < end) {
1764 hits += hist->addr[offset].nr_samples; 1773 hits += sym_hist->addr[offset].nr_samples;
1765 period += hist->addr[offset].period; 1774 period += sym_hist->addr[offset].period;
1766 ++offset; 1775 ++offset;
1767 } 1776 }
1768 1777
1769 if (hist->nr_samples) { 1778 if (sym_hist->nr_samples) {
1770 sample->he.period = period; 1779 data->he.period = period;
1771 sample->he.nr_samples = hits; 1780 data->he.nr_samples = hits;
1772 sample->percent = 100.0 * hits / hist->nr_samples; 1781 data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
1773 } 1782 }
1783
1784 if (hists->stats.nr_non_filtered_samples)
1785 data->percent[PERCENT_HITS_GLOBAL] = 100.0 * hits / hists->stats.nr_non_filtered_samples;
1786
1787 if (sym_hist->period)
1788 data->percent[PERCENT_PERIOD_LOCAL] = 100.0 * period / sym_hist->period;
1789
1790 if (hists->stats.total_period)
1791 data->percent[PERCENT_PERIOD_GLOBAL] = 100.0 * period / hists->stats.total_period;
1774} 1792}
1775 1793
1776static void annotation__calc_percent(struct annotation *notes, 1794static void annotation__calc_percent(struct annotation *notes,
1777 struct perf_evsel *evsel, s64 len) 1795 struct perf_evsel *leader, s64 len)
1778{ 1796{
1779 struct annotation_line *al, *next; 1797 struct annotation_line *al, *next;
1798 struct perf_evsel *evsel;
1780 1799
1781 list_for_each_entry(al, &notes->src->source, node) { 1800 list_for_each_entry(al, &notes->src->source, node) {
1782 s64 end; 1801 s64 end;
1783 int i; 1802 int i = 0;
1784 1803
1785 if (al->offset == -1) 1804 if (al->offset == -1)
1786 continue; 1805 continue;
@@ -1788,14 +1807,17 @@ static void annotation__calc_percent(struct annotation *notes,
1788 next = annotation_line__next(al, &notes->src->source); 1807 next = annotation_line__next(al, &notes->src->source);
1789 end = next ? next->offset : len; 1808 end = next ? next->offset : len;
1790 1809
1791 for (i = 0; i < al->samples_nr; i++) { 1810 for_each_group_evsel(evsel, leader) {
1792 struct annotation_data *sample; 1811 struct hists *hists = evsel__hists(evsel);
1793 struct sym_hist *hist; 1812 struct annotation_data *data;
1813 struct sym_hist *sym_hist;
1814
1815 BUG_ON(i >= al->data_nr);
1794 1816
1795 hist = annotation__histogram(notes, evsel->idx + i); 1817 sym_hist = annotation__histogram(notes, evsel->idx);
1796 sample = &al->samples[i]; 1818 data = &al->data[i++];
1797 1819
1798 calc_percent(hist, sample, al->offset, end); 1820 calc_percent(sym_hist, hists, data, al->offset, end);
1799 } 1821 }
1800 } 1822 }
1801} 1823}
@@ -1846,7 +1868,8 @@ int symbol__annotate(struct symbol *sym, struct map *map,
1846 return symbol__disassemble(sym, &args); 1868 return symbol__disassemble(sym, &args);
1847} 1869}
1848 1870
1849static void insert_source_line(struct rb_root *root, struct annotation_line *al) 1871static void insert_source_line(struct rb_root *root, struct annotation_line *al,
1872 struct annotation_options *opts)
1850{ 1873{
1851 struct annotation_line *iter; 1874 struct annotation_line *iter;
1852 struct rb_node **p = &root->rb_node; 1875 struct rb_node **p = &root->rb_node;
@@ -1859,8 +1882,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
1859 1882
1860 ret = strcmp(iter->path, al->path); 1883 ret = strcmp(iter->path, al->path);
1861 if (ret == 0) { 1884 if (ret == 0) {
1862 for (i = 0; i < al->samples_nr; i++) 1885 for (i = 0; i < al->data_nr; i++) {
1863 iter->samples[i].percent_sum += al->samples[i].percent; 1886 iter->data[i].percent_sum += annotation_data__percent(&al->data[i],
1887 opts->percent_type);
1888 }
1864 return; 1889 return;
1865 } 1890 }
1866 1891
@@ -1870,8 +1895,10 @@ static void insert_source_line(struct rb_root *root, struct annotation_line *al)
1870 p = &(*p)->rb_right; 1895 p = &(*p)->rb_right;
1871 } 1896 }
1872 1897
1873 for (i = 0; i < al->samples_nr; i++) 1898 for (i = 0; i < al->data_nr; i++) {
1874 al->samples[i].percent_sum = al->samples[i].percent; 1899 al->data[i].percent_sum = annotation_data__percent(&al->data[i],
1900 opts->percent_type);
1901 }
1875 1902
1876 rb_link_node(&al->rb_node, parent, p); 1903 rb_link_node(&al->rb_node, parent, p);
1877 rb_insert_color(&al->rb_node, root); 1904 rb_insert_color(&al->rb_node, root);
@@ -1881,10 +1908,10 @@ static int cmp_source_line(struct annotation_line *a, struct annotation_line *b)
1881{ 1908{
1882 int i; 1909 int i;
1883 1910
1884 for (i = 0; i < a->samples_nr; i++) { 1911 for (i = 0; i < a->data_nr; i++) {
1885 if (a->samples[i].percent_sum == b->samples[i].percent_sum) 1912 if (a->data[i].percent_sum == b->data[i].percent_sum)
1886 continue; 1913 continue;
1887 return a->samples[i].percent_sum > b->samples[i].percent_sum; 1914 return a->data[i].percent_sum > b->data[i].percent_sum;
1888 } 1915 }
1889 1916
1890 return 0; 1917 return 0;
@@ -1949,8 +1976,8 @@ static void print_summary(struct rb_root *root, const char *filename)
1949 int i; 1976 int i;
1950 1977
1951 al = rb_entry(node, struct annotation_line, rb_node); 1978 al = rb_entry(node, struct annotation_line, rb_node);
1952 for (i = 0; i < al->samples_nr; i++) { 1979 for (i = 0; i < al->data_nr; i++) {
1953 percent = al->samples[i].percent_sum; 1980 percent = al->data[i].percent_sum;
1954 color = get_percent_color(percent); 1981 color = get_percent_color(percent);
1955 color_fprintf(stdout, color, " %7.2f", percent); 1982 color_fprintf(stdout, color, " %7.2f", percent);
1956 1983
@@ -2029,10 +2056,12 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
2029 evsel_name = buf; 2056 evsel_name = buf;
2030 } 2057 }
2031 2058
2032 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n", 2059 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
2060 "percent: %s)\n",
2033 width, width, symbol_conf.show_total_period ? "Period" : 2061 width, width, symbol_conf.show_total_period ? "Period" :
2034 symbol_conf.show_nr_samples ? "Samples" : "Percent", 2062 symbol_conf.show_nr_samples ? "Samples" : "Percent",
2035 d_filename, evsel_name, h->nr_samples); 2063 d_filename, evsel_name, h->nr_samples,
2064 percent_type_str(opts->percent_type));
2036 2065
2037 printf("%-*.*s----\n", 2066 printf("%-*.*s----\n",
2038 graph_dotted_len, graph_dotted_len, graph_dotted_line); 2067 graph_dotted_len, graph_dotted_len, graph_dotted_line);
@@ -2052,7 +2081,7 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
2052 2081
2053 err = annotation_line__print(pos, sym, start, evsel, len, 2082 err = annotation_line__print(pos, sym, start, evsel, len,
2054 opts->min_pcnt, printed, opts->max_lines, 2083 opts->min_pcnt, printed, opts->max_lines,
2055 queue, addr_fmt_width); 2084 queue, addr_fmt_width, opts->percent_type);
2056 2085
2057 switch (err) { 2086 switch (err) {
2058 case 0: 2087 case 0:
@@ -2129,10 +2158,11 @@ static void FILE__write_graph(void *fp, int graph)
2129 fputs(s, fp); 2158 fputs(s, fp);
2130} 2159}
2131 2160
2132int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp) 2161static int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp,
2162 struct annotation_options *opts)
2133{ 2163{
2134 struct annotation *notes = symbol__annotation(sym); 2164 struct annotation *notes = symbol__annotation(sym);
2135 struct annotation_write_ops ops = { 2165 struct annotation_write_ops wops = {
2136 .first_line = true, 2166 .first_line = true,
2137 .obj = fp, 2167 .obj = fp,
2138 .set_color = FILE__set_color, 2168 .set_color = FILE__set_color,
@@ -2146,15 +2176,16 @@ int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
2146 list_for_each_entry(al, &notes->src->source, node) { 2176 list_for_each_entry(al, &notes->src->source, node) {
2147 if (annotation_line__filter(al, notes)) 2177 if (annotation_line__filter(al, notes))
2148 continue; 2178 continue;
2149 annotation_line__write(al, notes, &ops); 2179 annotation_line__write(al, notes, &wops, opts);
2150 fputc('\n', fp); 2180 fputc('\n', fp);
2151 ops.first_line = false; 2181 wops.first_line = false;
2152 } 2182 }
2153 2183
2154 return 0; 2184 return 0;
2155} 2185}
2156 2186
2157int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel) 2187int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
2188 struct annotation_options *opts)
2158{ 2189{
2159 const char *ev_name = perf_evsel__name(evsel); 2190 const char *ev_name = perf_evsel__name(evsel);
2160 char buf[1024]; 2191 char buf[1024];
@@ -2176,7 +2207,7 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel)
2176 2207
2177 fprintf(fp, "%s() %s\nEvent: %s\n\n", 2208 fprintf(fp, "%s() %s\nEvent: %s\n\n",
2178 ms->sym->name, ms->map->dso->long_name, ev_name); 2209 ms->sym->name, ms->map->dso->long_name, ev_name);
2179 symbol__annotate_fprintf2(ms->sym, fp); 2210 symbol__annotate_fprintf2(ms->sym, fp, opts);
2180 2211
2181 fclose(fp); 2212 fclose(fp);
2182 err = 0; 2213 err = 0;
@@ -2346,7 +2377,8 @@ void annotation__update_column_widths(struct annotation *notes)
2346} 2377}
2347 2378
2348static void annotation__calc_lines(struct annotation *notes, struct map *map, 2379static void annotation__calc_lines(struct annotation *notes, struct map *map,
2349 struct rb_root *root) 2380 struct rb_root *root,
2381 struct annotation_options *opts)
2350{ 2382{
2351 struct annotation_line *al; 2383 struct annotation_line *al;
2352 struct rb_root tmp_root = RB_ROOT; 2384 struct rb_root tmp_root = RB_ROOT;
@@ -2355,13 +2387,14 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
2355 double percent_max = 0.0; 2387 double percent_max = 0.0;
2356 int i; 2388 int i;
2357 2389
2358 for (i = 0; i < al->samples_nr; i++) { 2390 for (i = 0; i < al->data_nr; i++) {
2359 struct annotation_data *sample; 2391 double percent;
2360 2392
2361 sample = &al->samples[i]; 2393 percent = annotation_data__percent(&al->data[i],
2394 opts->percent_type);
2362 2395
2363 if (sample->percent > percent_max) 2396 if (percent > percent_max)
2364 percent_max = sample->percent; 2397 percent_max = percent;
2365 } 2398 }
2366 2399
2367 if (percent_max <= 0.5) 2400 if (percent_max <= 0.5)
@@ -2369,18 +2402,19 @@ static void annotation__calc_lines(struct annotation *notes, struct map *map,
2369 2402
2370 al->path = get_srcline(map->dso, notes->start + al->offset, NULL, 2403 al->path = get_srcline(map->dso, notes->start + al->offset, NULL,
2371 false, true, notes->start + al->offset); 2404 false, true, notes->start + al->offset);
2372 insert_source_line(&tmp_root, al); 2405 insert_source_line(&tmp_root, al, opts);
2373 } 2406 }
2374 2407
2375 resort_source_line(root, &tmp_root); 2408 resort_source_line(root, &tmp_root);
2376} 2409}
2377 2410
2378static void symbol__calc_lines(struct symbol *sym, struct map *map, 2411static void symbol__calc_lines(struct symbol *sym, struct map *map,
2379 struct rb_root *root) 2412 struct rb_root *root,
2413 struct annotation_options *opts)
2380{ 2414{
2381 struct annotation *notes = symbol__annotation(sym); 2415 struct annotation *notes = symbol__annotation(sym);
2382 2416
2383 annotation__calc_lines(notes, map, root); 2417 annotation__calc_lines(notes, map, root, opts);
2384} 2418}
2385 2419
2386int symbol__tty_annotate2(struct symbol *sym, struct map *map, 2420int symbol__tty_annotate2(struct symbol *sym, struct map *map,
@@ -2389,7 +2423,7 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2389{ 2423{
2390 struct dso *dso = map->dso; 2424 struct dso *dso = map->dso;
2391 struct rb_root source_line = RB_ROOT; 2425 struct rb_root source_line = RB_ROOT;
2392 struct annotation *notes = symbol__annotation(sym); 2426 struct hists *hists = evsel__hists(evsel);
2393 char buf[1024]; 2427 char buf[1024];
2394 2428
2395 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0) 2429 if (symbol__annotate2(sym, map, evsel, opts, NULL) < 0)
@@ -2397,13 +2431,14 @@ int symbol__tty_annotate2(struct symbol *sym, struct map *map,
2397 2431
2398 if (opts->print_lines) { 2432 if (opts->print_lines) {
2399 srcline_full_filename = opts->full_path; 2433 srcline_full_filename = opts->full_path;
2400 symbol__calc_lines(sym, map, &source_line); 2434 symbol__calc_lines(sym, map, &source_line, opts);
2401 print_summary(&source_line, dso->long_name); 2435 print_summary(&source_line, dso->long_name);
2402 } 2436 }
2403 2437
2404 annotation__scnprintf_samples_period(notes, buf, sizeof(buf), evsel); 2438 hists__scnprintf_title(hists, buf, sizeof(buf));
2405 fprintf(stdout, "%s\n%s() %s\n", buf, sym->name, dso->long_name); 2439 fprintf(stdout, "%s, [percent: %s]\n%s() %s\n",
2406 symbol__annotate_fprintf2(sym, stdout); 2440 buf, percent_type_str(opts->percent_type), sym->name, dso->long_name);
2441 symbol__annotate_fprintf2(sym, stdout, opts);
2407 2442
2408 annotated_source__purge(symbol__annotation(sym)->src); 2443 annotated_source__purge(symbol__annotation(sym)->src);
2409 2444
@@ -2424,7 +2459,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
2424 2459
2425 if (opts->print_lines) { 2460 if (opts->print_lines) {
2426 srcline_full_filename = opts->full_path; 2461 srcline_full_filename = opts->full_path;
2427 symbol__calc_lines(sym, map, &source_line); 2462 symbol__calc_lines(sym, map, &source_line, opts);
2428 print_summary(&source_line, dso->long_name); 2463 print_summary(&source_line, dso->long_name);
2429 } 2464 }
2430 2465
@@ -2441,14 +2476,21 @@ bool ui__has_annotation(void)
2441} 2476}
2442 2477
2443 2478
2444double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes) 2479static double annotation_line__max_percent(struct annotation_line *al,
2480 struct annotation *notes,
2481 unsigned int percent_type)
2445{ 2482{
2446 double percent_max = 0.0; 2483 double percent_max = 0.0;
2447 int i; 2484 int i;
2448 2485
2449 for (i = 0; i < notes->nr_events; i++) { 2486 for (i = 0; i < notes->nr_events; i++) {
2450 if (al->samples[i].percent > percent_max) 2487 double percent;
2451 percent_max = al->samples[i].percent; 2488
2489 percent = annotation_data__percent(&al->data[i],
2490 percent_type);
2491
2492 if (percent > percent_max)
2493 percent_max = percent;
2452 } 2494 }
2453 2495
2454 return percent_max; 2496 return percent_max;
@@ -2487,7 +2529,7 @@ call_like:
2487 2529
2488static void __annotation_line__write(struct annotation_line *al, struct annotation *notes, 2530static void __annotation_line__write(struct annotation_line *al, struct annotation *notes,
2489 bool first_line, bool current_entry, bool change_color, int width, 2531 bool first_line, bool current_entry, bool change_color, int width,
2490 void *obj, 2532 void *obj, unsigned int percent_type,
2491 int (*obj__set_color)(void *obj, int color), 2533 int (*obj__set_color)(void *obj, int color),
2492 void (*obj__set_percent_color)(void *obj, double percent, bool current), 2534 void (*obj__set_percent_color)(void *obj, double percent, bool current),
2493 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current), 2535 int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current),
@@ -2495,7 +2537,7 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
2495 void (*obj__write_graph)(void *obj, int graph)) 2537 void (*obj__write_graph)(void *obj, int graph))
2496 2538
2497{ 2539{
2498 double percent_max = annotation_line__max_percent(al, notes); 2540 double percent_max = annotation_line__max_percent(al, notes, percent_type);
2499 int pcnt_width = annotation__pcnt_width(notes), 2541 int pcnt_width = annotation__pcnt_width(notes),
2500 cycles_width = annotation__cycles_width(notes); 2542 cycles_width = annotation__cycles_width(notes);
2501 bool show_title = false; 2543 bool show_title = false;
@@ -2514,15 +2556,18 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati
2514 int i; 2556 int i;
2515 2557
2516 for (i = 0; i < notes->nr_events; i++) { 2558 for (i = 0; i < notes->nr_events; i++) {
2517 obj__set_percent_color(obj, al->samples[i].percent, current_entry); 2559 double percent;
2560
2561 percent = annotation_data__percent(&al->data[i], percent_type);
2562
2563 obj__set_percent_color(obj, percent, current_entry);
2518 if (notes->options->show_total_period) { 2564 if (notes->options->show_total_period) {
2519 obj__printf(obj, "%11" PRIu64 " ", al->samples[i].he.period); 2565 obj__printf(obj, "%11" PRIu64 " ", al->data[i].he.period);
2520 } else if (notes->options->show_nr_samples) { 2566 } else if (notes->options->show_nr_samples) {
2521 obj__printf(obj, "%6" PRIu64 " ", 2567 obj__printf(obj, "%6" PRIu64 " ",
2522 al->samples[i].he.nr_samples); 2568 al->data[i].he.nr_samples);
2523 } else { 2569 } else {
2524 obj__printf(obj, "%6.2f ", 2570 obj__printf(obj, "%6.2f ", percent);
2525 al->samples[i].percent);
2526 } 2571 }
2527 } 2572 }
2528 } else { 2573 } else {
@@ -2640,13 +2685,15 @@ print_addr:
2640} 2685}
2641 2686
2642void annotation_line__write(struct annotation_line *al, struct annotation *notes, 2687void annotation_line__write(struct annotation_line *al, struct annotation *notes,
2643 struct annotation_write_ops *ops) 2688 struct annotation_write_ops *wops,
2689 struct annotation_options *opts)
2644{ 2690{
2645 __annotation_line__write(al, notes, ops->first_line, ops->current_entry, 2691 __annotation_line__write(al, notes, wops->first_line, wops->current_entry,
2646 ops->change_color, ops->width, ops->obj, 2692 wops->change_color, wops->width, wops->obj,
2647 ops->set_color, ops->set_percent_color, 2693 opts->percent_type,
2648 ops->set_jumps_percent_color, ops->printf, 2694 wops->set_color, wops->set_percent_color,
2649 ops->write_graph); 2695 wops->set_jumps_percent_color, wops->printf,
2696 wops->write_graph);
2650} 2697}
2651 2698
2652int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel, 2699int symbol__annotate2(struct symbol *sym, struct map *map, struct perf_evsel *evsel,
@@ -2688,46 +2735,6 @@ out_free_offsets:
2688 return -1; 2735 return -1;
2689} 2736}
2690 2737
2691int __annotation__scnprintf_samples_period(struct annotation *notes,
2692 char *bf, size_t size,
2693 struct perf_evsel *evsel,
2694 bool show_freq)
2695{
2696 const char *ev_name = perf_evsel__name(evsel);
2697 char buf[1024], ref[30] = " show reference callgraph, ";
2698 char sample_freq_str[64] = "";
2699 unsigned long nr_samples = 0;
2700 int nr_members = 1;
2701 bool enable_ref = false;
2702 u64 nr_events = 0;
2703 char unit;
2704 int i;
2705
2706 if (perf_evsel__is_group_event(evsel)) {
2707 perf_evsel__group_desc(evsel, buf, sizeof(buf));
2708 ev_name = buf;
2709 nr_members = evsel->nr_members;
2710 }
2711
2712 for (i = 0; i < nr_members; i++) {
2713 struct sym_hist *ah = annotation__histogram(notes, evsel->idx + i);
2714
2715 nr_samples += ah->nr_samples;
2716 nr_events += ah->period;
2717 }
2718
2719 if (symbol_conf.show_ref_callgraph && strstr(ev_name, "call-graph=no"))
2720 enable_ref = true;
2721
2722 if (show_freq)
2723 scnprintf(sample_freq_str, sizeof(sample_freq_str), " %d Hz,", evsel->attr.sample_freq);
2724
2725 nr_samples = convert_unit(nr_samples, &unit);
2726 return scnprintf(bf, size, "Samples: %lu%c of event%s '%s',%s%sEvent count (approx.): %" PRIu64,
2727 nr_samples, unit, evsel->nr_members > 1 ? "s" : "",
2728 ev_name, sample_freq_str, enable_ref ? ref : " ", nr_events);
2729}
2730
2731#define ANNOTATION__CFG(n) \ 2738#define ANNOTATION__CFG(n) \
2732 { .name = #n, .value = &annotation__default_options.n, } 2739 { .name = #n, .value = &annotation__default_options.n, }
2733 2740
@@ -2792,3 +2799,55 @@ void annotation_config__init(void)
2792 annotation__default_options.show_total_period = symbol_conf.show_total_period; 2799 annotation__default_options.show_total_period = symbol_conf.show_total_period;
2793 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples; 2800 annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples;
2794} 2801}
2802
2803static unsigned int parse_percent_type(char *str1, char *str2)
2804{
2805 unsigned int type = (unsigned int) -1;
2806
2807 if (!strcmp("period", str1)) {
2808 if (!strcmp("local", str2))
2809 type = PERCENT_PERIOD_LOCAL;
2810 else if (!strcmp("global", str2))
2811 type = PERCENT_PERIOD_GLOBAL;
2812 }
2813
2814 if (!strcmp("hits", str1)) {
2815 if (!strcmp("local", str2))
2816 type = PERCENT_HITS_LOCAL;
2817 else if (!strcmp("global", str2))
2818 type = PERCENT_HITS_GLOBAL;
2819 }
2820
2821 return type;
2822}
2823
2824int annotate_parse_percent_type(const struct option *opt, const char *_str,
2825 int unset __maybe_unused)
2826{
2827 struct annotation_options *opts = opt->value;
2828 unsigned int type;
2829 char *str1, *str2;
2830 int err = -1;
2831
2832 str1 = strdup(_str);
2833 if (!str1)
2834 return -ENOMEM;
2835
2836 str2 = strchr(str1, '-');
2837 if (!str2)
2838 goto out;
2839
2840 *str2++ = 0;
2841
2842 type = parse_percent_type(str1, str2);
2843 if (type == (unsigned int) -1)
2844 type = parse_percent_type(str2, str1);
2845 if (type != (unsigned int) -1) {
2846 opts->percent_type = type;
2847 err = 0;
2848 }
2849
2850out:
2851 free(str1);
2852 return err;
2853}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index a4c0d91907e6..005a5fe8a8c6 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -11,6 +11,7 @@
11#include <linux/list.h> 11#include <linux/list.h>
12#include <linux/rbtree.h> 12#include <linux/rbtree.h>
13#include <pthread.h> 13#include <pthread.h>
14#include <asm/bug.h>
14 15
15struct ins_ops; 16struct ins_ops;
16 17
@@ -82,6 +83,7 @@ struct annotation_options {
82 int context; 83 int context;
83 const char *objdump_path; 84 const char *objdump_path;
84 const char *disassembler_style; 85 const char *disassembler_style;
86 unsigned int percent_type;
85}; 87};
86 88
87enum { 89enum {
@@ -101,8 +103,16 @@ struct sym_hist_entry {
101 u64 period; 103 u64 period;
102}; 104};
103 105
106enum {
107 PERCENT_HITS_LOCAL,
108 PERCENT_HITS_GLOBAL,
109 PERCENT_PERIOD_LOCAL,
110 PERCENT_PERIOD_GLOBAL,
111 PERCENT_MAX,
112};
113
104struct annotation_data { 114struct annotation_data {
105 double percent; 115 double percent[PERCENT_MAX];
106 double percent_sum; 116 double percent_sum;
107 struct sym_hist_entry he; 117 struct sym_hist_entry he;
108}; 118};
@@ -122,8 +132,8 @@ struct annotation_line {
122 char *path; 132 char *path;
123 u32 idx; 133 u32 idx;
124 int idx_asm; 134 int idx_asm;
125 int samples_nr; 135 int data_nr;
126 struct annotation_data samples[0]; 136 struct annotation_data data[0];
127}; 137};
128 138
129struct disasm_line { 139struct disasm_line {
@@ -134,6 +144,27 @@ struct disasm_line {
134 struct annotation_line al; 144 struct annotation_line al;
135}; 145};
136 146
147static inline double annotation_data__percent(struct annotation_data *data,
148 unsigned int which)
149{
150 return which < PERCENT_MAX ? data->percent[which] : -1;
151}
152
153static inline const char *percent_type_str(unsigned int type)
154{
155 static const char *str[PERCENT_MAX] = {
156 "local hits",
157 "global hits",
158 "local period",
159 "global period",
160 };
161
162 if (WARN_ON(type >= PERCENT_MAX))
163 return "N/A";
164
165 return str[type];
166}
167
137static inline struct disasm_line *disasm_line(struct annotation_line *al) 168static inline struct disasm_line *disasm_line(struct annotation_line *al)
138{ 169{
139 return al ? container_of(al, struct disasm_line, al) : NULL; 170 return al ? container_of(al, struct disasm_line, al) : NULL;
@@ -169,22 +200,15 @@ struct annotation_write_ops {
169 void (*write_graph)(void *obj, int graph); 200 void (*write_graph)(void *obj, int graph);
170}; 201};
171 202
172double annotation_line__max_percent(struct annotation_line *al, struct annotation *notes);
173void annotation_line__write(struct annotation_line *al, struct annotation *notes, 203void annotation_line__write(struct annotation_line *al, struct annotation *notes,
174 struct annotation_write_ops *ops); 204 struct annotation_write_ops *ops,
205 struct annotation_options *opts);
175 206
176int __annotation__scnprintf_samples_period(struct annotation *notes, 207int __annotation__scnprintf_samples_period(struct annotation *notes,
177 char *bf, size_t size, 208 char *bf, size_t size,
178 struct perf_evsel *evsel, 209 struct perf_evsel *evsel,
179 bool show_freq); 210 bool show_freq);
180 211
181static inline int annotation__scnprintf_samples_period(struct annotation *notes,
182 char *bf, size_t size,
183 struct perf_evsel *evsel)
184{
185 return __annotation__scnprintf_samples_period(notes, bf, size, evsel, true);
186}
187
188int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw); 212int disasm_line__scnprintf(struct disasm_line *dl, char *bf, size_t size, bool raw);
189size_t disasm__fprintf(struct list_head *head, FILE *fp); 213size_t disasm__fprintf(struct list_head *head, FILE *fp);
190void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel); 214void symbol__calc_percent(struct symbol *sym, struct perf_evsel *evsel);
@@ -340,12 +364,12 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
340int symbol__annotate_printf(struct symbol *sym, struct map *map, 364int symbol__annotate_printf(struct symbol *sym, struct map *map,
341 struct perf_evsel *evsel, 365 struct perf_evsel *evsel,
342 struct annotation_options *options); 366 struct annotation_options *options);
343int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
344void symbol__annotate_zero_histogram(struct symbol *sym, int evidx); 367void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
345void symbol__annotate_decay_histogram(struct symbol *sym, int evidx); 368void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
346void annotated_source__purge(struct annotated_source *as); 369void annotated_source__purge(struct annotated_source *as);
347 370
348int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel); 371int map_symbol__annotation_dump(struct map_symbol *ms, struct perf_evsel *evsel,
372 struct annotation_options *opts);
349 373
350bool ui__has_annotation(void); 374bool ui__has_annotation(void);
351 375
@@ -373,4 +397,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused,
373 397
374void annotation_config__init(void); 398void annotation_config__init(void);
375 399
400int annotate_parse_percent_type(const struct option *opt, const char *_str,
401 int unset);
376#endif /* __PERF_ANNOTATE_H */ 402#endif /* __PERF_ANNOTATE_H */
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index d056447520a2..db1511359c5e 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -56,6 +56,7 @@
56#include "intel-pt.h" 56#include "intel-pt.h"
57#include "intel-bts.h" 57#include "intel-bts.h"
58#include "arm-spe.h" 58#include "arm-spe.h"
59#include "s390-cpumsf.h"
59 60
60#include "sane_ctype.h" 61#include "sane_ctype.h"
61#include "symbol/kallsyms.h" 62#include "symbol/kallsyms.h"
@@ -202,6 +203,9 @@ static int auxtrace_queues__grow(struct auxtrace_queues *queues,
202 for (i = 0; i < queues->nr_queues; i++) { 203 for (i = 0; i < queues->nr_queues; i++) {
203 list_splice_tail(&queues->queue_array[i].head, 204 list_splice_tail(&queues->queue_array[i].head,
204 &queue_array[i].head); 205 &queue_array[i].head);
206 queue_array[i].tid = queues->queue_array[i].tid;
207 queue_array[i].cpu = queues->queue_array[i].cpu;
208 queue_array[i].set = queues->queue_array[i].set;
205 queue_array[i].priv = queues->queue_array[i].priv; 209 queue_array[i].priv = queues->queue_array[i].priv;
206 } 210 }
207 211
@@ -920,6 +924,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
920 return arm_spe_process_auxtrace_info(event, session); 924 return arm_spe_process_auxtrace_info(event, session);
921 case PERF_AUXTRACE_CS_ETM: 925 case PERF_AUXTRACE_CS_ETM:
922 return cs_etm__process_auxtrace_info(event, session); 926 return cs_etm__process_auxtrace_info(event, session);
927 case PERF_AUXTRACE_S390_CPUMSF:
928 return s390_cpumsf_process_auxtrace_info(event, session);
923 case PERF_AUXTRACE_UNKNOWN: 929 case PERF_AUXTRACE_UNKNOWN:
924 default: 930 default:
925 return -EINVAL; 931 return -EINVAL;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index e731f55da072..71fc3bd74299 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -44,6 +44,7 @@ enum auxtrace_type {
44 PERF_AUXTRACE_INTEL_BTS, 44 PERF_AUXTRACE_INTEL_BTS,
45 PERF_AUXTRACE_CS_ETM, 45 PERF_AUXTRACE_CS_ETM,
46 PERF_AUXTRACE_ARM_SPE, 46 PERF_AUXTRACE_ARM_SPE,
47 PERF_AUXTRACE_S390_CPUMSF,
47}; 48};
48 49
49enum itrace_period_type { 50enum itrace_period_type {
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 3d02ae38ec56..47aac41349a2 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -1529,13 +1529,13 @@ int bpf__apply_obj_config(void)
1529 bpf_object__for_each_safe(obj, objtmp) \ 1529 bpf_object__for_each_safe(obj, objtmp) \
1530 bpf_map__for_each(pos, obj) 1530 bpf_map__for_each(pos, obj)
1531 1531
1532#define bpf__for_each_stdout_map(pos, obj, objtmp) \ 1532#define bpf__for_each_map_named(pos, obj, objtmp, name) \
1533 bpf__for_each_map(pos, obj, objtmp) \ 1533 bpf__for_each_map(pos, obj, objtmp) \
1534 if (bpf_map__name(pos) && \ 1534 if (bpf_map__name(pos) && \
1535 (strcmp("__bpf_stdout__", \ 1535 (strcmp(name, \
1536 bpf_map__name(pos)) == 0)) 1536 bpf_map__name(pos)) == 0))
1537 1537
1538int bpf__setup_stdout(struct perf_evlist *evlist) 1538struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name)
1539{ 1539{
1540 struct bpf_map_priv *tmpl_priv = NULL; 1540 struct bpf_map_priv *tmpl_priv = NULL;
1541 struct bpf_object *obj, *tmp; 1541 struct bpf_object *obj, *tmp;
@@ -1544,11 +1544,11 @@ int bpf__setup_stdout(struct perf_evlist *evlist)
1544 int err; 1544 int err;
1545 bool need_init = false; 1545 bool need_init = false;
1546 1546
1547 bpf__for_each_stdout_map(map, obj, tmp) { 1547 bpf__for_each_map_named(map, obj, tmp, name) {
1548 struct bpf_map_priv *priv = bpf_map__priv(map); 1548 struct bpf_map_priv *priv = bpf_map__priv(map);
1549 1549
1550 if (IS_ERR(priv)) 1550 if (IS_ERR(priv))
1551 return -BPF_LOADER_ERRNO__INTERNAL; 1551 return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL);
1552 1552
1553 /* 1553 /*
1554 * No need to check map type: type should have been 1554 * No need to check map type: type should have been
@@ -1561,49 +1561,61 @@ int bpf__setup_stdout(struct perf_evlist *evlist)
1561 } 1561 }
1562 1562
1563 if (!need_init) 1563 if (!need_init)
1564 return 0; 1564 return NULL;
1565 1565
1566 if (!tmpl_priv) { 1566 if (!tmpl_priv) {
1567 err = parse_events(evlist, "bpf-output/no-inherit=1,name=__bpf_stdout__/", 1567 char *event_definition = NULL;
1568 NULL); 1568
1569 if (asprintf(&event_definition, "bpf-output/no-inherit=1,name=%s/", name) < 0)
1570 return ERR_PTR(-ENOMEM);
1571
1572 err = parse_events(evlist, event_definition, NULL);
1573 free(event_definition);
1574
1569 if (err) { 1575 if (err) {
1570 pr_debug("ERROR: failed to create bpf-output event\n"); 1576 pr_debug("ERROR: failed to create the \"%s\" bpf-output event\n", name);
1571 return -err; 1577 return ERR_PTR(-err);
1572 } 1578 }
1573 1579
1574 evsel = perf_evlist__last(evlist); 1580 evsel = perf_evlist__last(evlist);
1575 } 1581 }
1576 1582
1577 bpf__for_each_stdout_map(map, obj, tmp) { 1583 bpf__for_each_map_named(map, obj, tmp, name) {
1578 struct bpf_map_priv *priv = bpf_map__priv(map); 1584 struct bpf_map_priv *priv = bpf_map__priv(map);
1579 1585
1580 if (IS_ERR(priv)) 1586 if (IS_ERR(priv))
1581 return -BPF_LOADER_ERRNO__INTERNAL; 1587 return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL);
1582 if (priv) 1588 if (priv)
1583 continue; 1589 continue;
1584 1590
1585 if (tmpl_priv) { 1591 if (tmpl_priv) {
1586 priv = bpf_map_priv__clone(tmpl_priv); 1592 priv = bpf_map_priv__clone(tmpl_priv);
1587 if (!priv) 1593 if (!priv)
1588 return -ENOMEM; 1594 return ERR_PTR(-ENOMEM);
1589 1595
1590 err = bpf_map__set_priv(map, priv, bpf_map_priv__clear); 1596 err = bpf_map__set_priv(map, priv, bpf_map_priv__clear);
1591 if (err) { 1597 if (err) {
1592 bpf_map_priv__clear(map, priv); 1598 bpf_map_priv__clear(map, priv);
1593 return err; 1599 return ERR_PTR(err);
1594 } 1600 }
1595 } else if (evsel) { 1601 } else if (evsel) {
1596 struct bpf_map_op *op; 1602 struct bpf_map_op *op;
1597 1603
1598 op = bpf_map__add_newop(map, NULL); 1604 op = bpf_map__add_newop(map, NULL);
1599 if (IS_ERR(op)) 1605 if (IS_ERR(op))
1600 return PTR_ERR(op); 1606 return ERR_PTR(PTR_ERR(op));
1601 op->op_type = BPF_MAP_OP_SET_EVSEL; 1607 op->op_type = BPF_MAP_OP_SET_EVSEL;
1602 op->v.evsel = evsel; 1608 op->v.evsel = evsel;
1603 } 1609 }
1604 } 1610 }
1605 1611
1606 return 0; 1612 return evsel;
1613}
1614
1615int bpf__setup_stdout(struct perf_evlist *evlist)
1616{
1617 struct perf_evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__");
1618 return IS_ERR(evsel) ? PTR_ERR(evsel) : 0;
1607} 1619}
1608 1620
1609#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) 1621#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
@@ -1780,8 +1792,8 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
1780 return 0; 1792 return 0;
1781} 1793}
1782 1794
1783int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused, 1795int bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
1784 int err, char *buf, size_t size) 1796 int err, char *buf, size_t size)
1785{ 1797{
1786 bpf__strerror_head(err, buf, size); 1798 bpf__strerror_head(err, buf, size);
1787 bpf__strerror_end(buf, size); 1799 bpf__strerror_end(buf, size);
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 5d3aefd6fae7..62d245a90e1d 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -43,6 +43,7 @@ enum bpf_loader_errno {
43 __BPF_LOADER_ERRNO__END, 43 __BPF_LOADER_ERRNO__END,
44}; 44};
45 45
46struct perf_evsel;
46struct bpf_object; 47struct bpf_object;
47struct parse_events_term; 48struct parse_events_term;
48#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" 49#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
@@ -82,9 +83,8 @@ int bpf__apply_obj_config(void);
82int bpf__strerror_apply_obj_config(int err, char *buf, size_t size); 83int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);
83 84
84int bpf__setup_stdout(struct perf_evlist *evlist); 85int bpf__setup_stdout(struct perf_evlist *evlist);
85int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, 86struct perf_evsel *bpf__setup_output_event(struct perf_evlist *evlist, const char *name);
86 char *buf, size_t size); 87int bpf__strerror_setup_output_event(struct perf_evlist *evlist, int err, char *buf, size_t size);
87
88#else 88#else
89#include <errno.h> 89#include <errno.h>
90 90
@@ -138,6 +138,12 @@ bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
138 return 0; 138 return 0;
139} 139}
140 140
141static inline struct perf_evsel *
142bpf__setup_output_event(struct perf_evlist *evlist __maybe_unused, const char *name __maybe_unused)
143{
144 return NULL;
145}
146
141static inline int 147static inline int
142__bpf_strerror(char *buf, size_t size) 148__bpf_strerror(char *buf, size_t size)
143{ 149{
@@ -193,11 +199,16 @@ bpf__strerror_apply_obj_config(int err __maybe_unused,
193} 199}
194 200
195static inline int 201static inline int
196bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused, 202bpf__strerror_setup_output_event(struct perf_evlist *evlist __maybe_unused,
197 int err __maybe_unused, char *buf, 203 int err __maybe_unused, char *buf, size_t size)
198 size_t size)
199{ 204{
200 return __bpf_strerror(buf, size); 205 return __bpf_strerror(buf, size);
201} 206}
207
202#endif 208#endif
209
210static inline int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err, char *buf, size_t size)
211{
212 return bpf__strerror_setup_output_event(evlist, err, buf, size);
213}
203#endif 214#endif
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 5744c12641a5..abd38abf1d91 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -310,8 +310,8 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
310 if (flags & FIELD_IS_DYNAMIC) { 310 if (flags & FIELD_IS_DYNAMIC) {
311 unsigned long long tmp_val; 311 unsigned long long tmp_val;
312 312
313 tmp_val = pevent_read_number(fmtf->event->pevent, 313 tmp_val = tep_read_number(fmtf->event->pevent,
314 data + offset, len); 314 data + offset, len);
315 offset = tmp_val; 315 offset = tmp_val;
316 len = offset >> 16; 316 len = offset >> 16;
317 offset &= 0xffff; 317 offset &= 0xffff;
@@ -353,7 +353,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
353 else { 353 else {
354 unsigned long long value_int; 354 unsigned long long value_int;
355 355
356 value_int = pevent_read_number( 356 value_int = tep_read_number(
357 fmtf->event->pevent, 357 fmtf->event->pevent,
358 data + offset + i * len, len); 358 data + offset + i * len, len);
359 359
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 0c8ecf0c78a4..0cd42150f712 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -541,10 +541,17 @@ static int __event__synthesize_thread(union perf_event *comm_event,
541 tgid, process, machine) < 0) 541 tgid, process, machine) < 0)
542 return -1; 542 return -1;
543 543
544 /*
545 * send mmap only for thread group leader
546 * see thread__init_map_groups
547 */
548 if (pid == tgid &&
549 perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
550 process, machine, mmap_data,
551 proc_map_timeout))
552 return -1;
544 553
545 return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 554 return 0;
546 process, machine, mmap_data,
547 proc_map_timeout);
548 } 555 }
549 556
550 if (machine__is_default_guest(machine)) 557 if (machine__is_default_guest(machine))
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index ddf84b941abf..c980bbff6353 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2683,7 +2683,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
2683 2683
2684struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name) 2684struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name)
2685{ 2685{
2686 return pevent_find_field(evsel->tp_format, name); 2686 return tep_find_field(evsel->tp_format, name);
2687} 2687}
2688 2688
2689void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample, 2689void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 973c03167947..163c960614d3 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -452,11 +452,18 @@ static inline int perf_evsel__group_idx(struct perf_evsel *evsel)
452 return evsel->idx - evsel->leader->idx; 452 return evsel->idx - evsel->leader->idx;
453} 453}
454 454
455/* Iterates group WITHOUT the leader. */
455#define for_each_group_member(_evsel, _leader) \ 456#define for_each_group_member(_evsel, _leader) \
456for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \ 457for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
457 (_evsel) && (_evsel)->leader == (_leader); \ 458 (_evsel) && (_evsel)->leader == (_leader); \
458 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 459 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
459 460
461/* Iterates group WITH the leader. */
462#define for_each_group_evsel(_evsel, _leader) \
463for ((_evsel) = _leader; \
464 (_evsel) && (_evsel)->leader == (_leader); \
465 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
466
460static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel) 467static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
461{ 468{
462 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; 469 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 5af58aac91ad..3cadc252dd89 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -279,8 +279,6 @@ static int do_read_bitmap(struct feat_fd *ff, unsigned long **pset, u64 *psize)
279 if (!set) 279 if (!set)
280 return -ENOMEM; 280 return -ENOMEM;
281 281
282 bitmap_zero(set, size);
283
284 p = (u64 *) set; 282 p = (u64 *) set;
285 283
286 for (i = 0; (u64) i < BITS_TO_U64(size); i++) { 284 for (i = 0; (u64) i < BITS_TO_U64(size); i++) {
@@ -1285,7 +1283,6 @@ static int memory_node__read(struct memory_node *n, unsigned long idx)
1285 return -ENOMEM; 1283 return -ENOMEM;
1286 } 1284 }
1287 1285
1288 bitmap_zero(n->set, size);
1289 n->node = idx; 1286 n->node = idx;
1290 n->size = size; 1287 n->size = size;
1291 1288
@@ -3207,7 +3204,7 @@ static int read_attr(int fd, struct perf_header *ph,
3207} 3204}
3208 3205
3209static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel, 3206static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3210 struct pevent *pevent) 3207 struct tep_handle *pevent)
3211{ 3208{
3212 struct event_format *event; 3209 struct event_format *event;
3213 char bf[128]; 3210 char bf[128];
@@ -3221,7 +3218,7 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3221 return -1; 3218 return -1;
3222 } 3219 }
3223 3220
3224 event = pevent_find_event(pevent, evsel->attr.config); 3221 event = tep_find_event(pevent, evsel->attr.config);
3225 if (event == NULL) { 3222 if (event == NULL) {
3226 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config); 3223 pr_debug("cannot find event format for %d\n", (int)evsel->attr.config);
3227 return -1; 3224 return -1;
@@ -3239,7 +3236,7 @@ static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
3239} 3236}
3240 3237
3241static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist, 3238static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
3242 struct pevent *pevent) 3239 struct tep_handle *pevent)
3243{ 3240{
3244 struct perf_evsel *pos; 3241 struct perf_evsel *pos;
3245 3242
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 1de7660d93e9..d856b85862e2 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -265,7 +265,7 @@ pid_t machine__get_current_tid(struct machine *machine, int cpu);
265int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid, 265int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
266 pid_t tid); 266 pid_t tid);
267/* 267/*
268 * For use with libtraceevent's pevent_set_function_resolver() 268 * For use with libtraceevent's tep_set_function_resolver()
269 */ 269 */
270char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp); 270char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp);
271 271
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 89ac5b5dc218..36d0763311ef 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -381,20 +381,6 @@ struct map *map__clone(struct map *from)
381 return map; 381 return map;
382} 382}
383 383
384int map__overlap(struct map *l, struct map *r)
385{
386 if (l->start > r->start) {
387 struct map *t = l;
388 l = r;
389 r = t;
390 }
391
392 if (l->end > r->start)
393 return 1;
394
395 return 0;
396}
397
398size_t map__fprintf(struct map *map, FILE *fp) 384size_t map__fprintf(struct map *map, FILE *fp)
399{ 385{
400 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n", 386 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s\n",
@@ -675,20 +661,42 @@ static void __map_groups__insert(struct map_groups *mg, struct map *map)
675static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) 661static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
676{ 662{
677 struct rb_root *root; 663 struct rb_root *root;
678 struct rb_node *next; 664 struct rb_node *next, *first;
679 int err = 0; 665 int err = 0;
680 666
681 down_write(&maps->lock); 667 down_write(&maps->lock);
682 668
683 root = &maps->entries; 669 root = &maps->entries;
684 next = rb_first(root);
685 670
671 /*
672 * Find first map where end > map->start.
673 * Same as find_vma() in kernel.
674 */
675 next = root->rb_node;
676 first = NULL;
677 while (next) {
678 struct map *pos = rb_entry(next, struct map, rb_node);
679
680 if (pos->end > map->start) {
681 first = next;
682 if (pos->start <= map->start)
683 break;
684 next = next->rb_left;
685 } else
686 next = next->rb_right;
687 }
688
689 next = first;
686 while (next) { 690 while (next) {
687 struct map *pos = rb_entry(next, struct map, rb_node); 691 struct map *pos = rb_entry(next, struct map, rb_node);
688 next = rb_next(&pos->rb_node); 692 next = rb_next(&pos->rb_node);
689 693
690 if (!map__overlap(pos, map)) 694 /*
691 continue; 695 * Stop if current map starts after map->end.
696 * Maps are ordered by start: next will not overlap for sure.
697 */
698 if (pos->start >= map->end)
699 break;
692 700
693 if (verbose >= 2) { 701 if (verbose >= 2) {
694 702
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 4cb90f242bed..e0f327b51e66 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -166,7 +166,6 @@ static inline void __map__zput(struct map **map)
166 166
167#define map__zput(map) __map__zput(&map) 167#define map__zput(map) __map__zput(&map)
168 168
169int map__overlap(struct map *l, struct map *r);
170size_t map__fprintf(struct map *map, FILE *fp); 169size_t map__fprintf(struct map *map, FILE *fp);
171size_t map__fprintf_dsoname(struct map *map, FILE *fp); 170size_t map__fprintf_dsoname(struct map *map, FILE *fp);
172char *map__srcline(struct map *map, u64 addr, struct symbol *sym); 171char *map__srcline(struct map *map, u64 addr, struct symbol *sym);
diff --git a/tools/perf/util/namespaces.c b/tools/perf/util/namespaces.c
index 5be021701f34..cf8bd123cf73 100644
--- a/tools/perf/util/namespaces.c
+++ b/tools/perf/util/namespaces.c
@@ -139,6 +139,9 @@ struct nsinfo *nsinfo__copy(struct nsinfo *nsi)
139{ 139{
140 struct nsinfo *nnsi; 140 struct nsinfo *nnsi;
141 141
142 if (nsi == NULL)
143 return NULL;
144
142 nnsi = calloc(1, sizeof(*nnsi)); 145 nnsi = calloc(1, sizeof(*nnsi));
143 if (nnsi != NULL) { 146 if (nnsi != NULL) {
144 nnsi->pid = nsi->pid; 147 nnsi->pid = nsi->pid;
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 863b61478edd..f74fbb652a4f 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -341,7 +341,7 @@ static bool is_tracepoint(struct pyrf_event *pevent)
341static PyObject* 341static PyObject*
342tracepoint_field(struct pyrf_event *pe, struct format_field *field) 342tracepoint_field(struct pyrf_event *pe, struct format_field *field)
343{ 343{
344 struct pevent *pevent = field->event->pevent; 344 struct tep_handle *pevent = field->event->pevent;
345 void *data = pe->sample.raw_data; 345 void *data = pe->sample.raw_data;
346 PyObject *ret = NULL; 346 PyObject *ret = NULL;
347 unsigned long long val; 347 unsigned long long val;
@@ -351,7 +351,7 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
351 offset = field->offset; 351 offset = field->offset;
352 len = field->size; 352 len = field->size;
353 if (field->flags & FIELD_IS_DYNAMIC) { 353 if (field->flags & FIELD_IS_DYNAMIC) {
354 val = pevent_read_number(pevent, data + offset, len); 354 val = tep_read_number(pevent, data + offset, len);
355 offset = val; 355 offset = val;
356 len = offset >> 16; 356 len = offset >> 16;
357 offset &= 0xffff; 357 offset &= 0xffff;
@@ -364,8 +364,8 @@ tracepoint_field(struct pyrf_event *pe, struct format_field *field)
364 field->flags &= ~FIELD_IS_STRING; 364 field->flags &= ~FIELD_IS_STRING;
365 } 365 }
366 } else { 366 } else {
367 val = pevent_read_number(pevent, data + field->offset, 367 val = tep_read_number(pevent, data + field->offset,
368 field->size); 368 field->size);
369 if (field->flags & FIELD_IS_POINTER) 369 if (field->flags & FIELD_IS_POINTER)
370 ret = PyLong_FromUnsignedLong((unsigned long) val); 370 ret = PyLong_FromUnsignedLong((unsigned long) val);
371 else if (field->flags & FIELD_IS_SIGNED) 371 else if (field->flags & FIELD_IS_SIGNED)
@@ -394,7 +394,7 @@ get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
394 evsel->tp_format = tp_format; 394 evsel->tp_format = tp_format;
395 } 395 }
396 396
397 field = pevent_find_any_field(evsel->tp_format, str); 397 field = tep_find_any_field(evsel->tp_format, str);
398 if (!field) 398 if (!field)
399 return NULL; 399 return NULL;
400 400
diff --git a/tools/perf/util/s390-cpumsf-kernel.h b/tools/perf/util/s390-cpumsf-kernel.h
new file mode 100644
index 000000000000..de8c7ad0eca8
--- /dev/null
+++ b/tools/perf/util/s390-cpumsf-kernel.h
@@ -0,0 +1,71 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Auxtrace support for s390 CPU measurement sampling facility
4 *
5 * Copyright IBM Corp. 2018
6 * Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
7 * Thomas Richter <tmricht@linux.ibm.com>
8 */
9#ifndef S390_CPUMSF_KERNEL_H
10#define S390_CPUMSF_KERNEL_H
11
12#define S390_CPUMSF_PAGESZ 4096 /* Size of sample block units */
13#define S390_CPUMSF_DIAG_DEF_FIRST 0x8001 /* Diagnostic entry lowest id */
14
15struct hws_basic_entry {
16 unsigned int def:16; /* 0-15 Data Entry Format */
17 unsigned int R:4; /* 16-19 reserved */
18 unsigned int U:4; /* 20-23 Number of unique instruct. */
19 unsigned int z:2; /* zeros */
20 unsigned int T:1; /* 26 PSW DAT mode */
21 unsigned int W:1; /* 27 PSW wait state */
22 unsigned int P:1; /* 28 PSW Problem state */
23 unsigned int AS:2; /* 29-30 PSW address-space control */
24 unsigned int I:1; /* 31 entry valid or invalid */
25 unsigned int CL:2; /* 32-33 Configuration Level */
26 unsigned int:14;
27 unsigned int prim_asn:16; /* primary ASN */
28 unsigned long long ia; /* Instruction Address */
29 unsigned long long gpp; /* Guest Program Parameter */
30 unsigned long long hpp; /* Host Program Parameter */
31};
32
33struct hws_diag_entry {
34 unsigned int def:16; /* 0-15 Data Entry Format */
35 unsigned int R:15; /* 16-19 and 20-30 reserved */
36 unsigned int I:1; /* 31 entry valid or invalid */
37 u8 data[]; /* Machine-dependent sample data */
38};
39
40struct hws_combined_entry {
41 struct hws_basic_entry basic; /* Basic-sampling data entry */
42 struct hws_diag_entry diag; /* Diagnostic-sampling data entry */
43};
44
45struct hws_trailer_entry {
46 union {
47 struct {
48 unsigned int f:1; /* 0 - Block Full Indicator */
49 unsigned int a:1; /* 1 - Alert request control */
50 unsigned int t:1; /* 2 - Timestamp format */
51 unsigned int:29; /* 3 - 31: Reserved */
52 unsigned int bsdes:16; /* 32-47: size of basic SDE */
53 unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
54 };
55 unsigned long long flags; /* 0 - 64: All indicators */
56 };
57 unsigned long long overflow; /* 64 - sample Overflow count */
58 unsigned char timestamp[16]; /* 16 - 31 timestamp */
59 unsigned long long reserved1; /* 32 -Reserved */
60 unsigned long long reserved2; /* */
61 union { /* 48 - reserved for programming use */
62 struct {
63 unsigned long long clock_base:1; /* in progusage2 */
64 unsigned long long progusage1:63;
65 unsigned long long progusage2;
66 };
67 unsigned long long progusage[2];
68 };
69};
70
71#endif
diff --git a/tools/perf/util/s390-cpumsf.c b/tools/perf/util/s390-cpumsf.c
new file mode 100644
index 000000000000..d2c78ffd9fee
--- /dev/null
+++ b/tools/perf/util/s390-cpumsf.c
@@ -0,0 +1,945 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright IBM Corp. 2018
4 * Auxtrace support for s390 CPU-Measurement Sampling Facility
5 *
6 * Author(s): Thomas Richter <tmricht@linux.ibm.com>
7 *
8 * Auxiliary traces are collected during 'perf record' using rbd000 event.
9 * Several PERF_RECORD_XXX are generated during recording:
10 *
11 * PERF_RECORD_AUX:
12 * Records that new data landed in the AUX buffer part.
13 * PERF_RECORD_AUXTRACE:
14 * Defines auxtrace data. Followed by the actual data. The contents of
15 * the auxtrace data is dependent on the event and the CPU.
16 * This record is generated by perf record command. For details
17 * see Documentation/perf.data-file-format.txt.
18 * PERF_RECORD_AUXTRACE_INFO:
19 * Defines a table of contains for PERF_RECORD_AUXTRACE records. This
20 * record is generated during 'perf record' command. Each record contains up
21 * to 256 entries describing offset and size of the AUXTRACE data in the
22 * perf.data file.
23 * PERF_RECORD_AUXTRACE_ERROR:
24 * Indicates an error during AUXTRACE collection such as buffer overflow.
25 * PERF_RECORD_FINISHED_ROUND:
26 * Perf events are not necessarily in time stamp order, as they can be
27 * collected in parallel on different CPUs. If the events should be
28 * processed in time order they need to be sorted first.
29 * Perf report guarantees that there is no reordering over a
30 * PERF_RECORD_FINISHED_ROUND boundary event. All perf records with a
31 * time stamp lower than this record are processed (and displayed) before
32 * the succeeding perf record are processed.
33 *
34 * These records are evaluated during perf report command.
35 *
36 * 1. PERF_RECORD_AUXTRACE_INFO is used to set up the infrastructure for
37 * auxiliary trace data processing. See s390_cpumsf_process_auxtrace_info()
38 * below.
39 * Auxiliary trace data is collected per CPU. To merge the data into the report
40 * an auxtrace_queue is created for each CPU. It is assumed that the auxtrace
41 * data is in ascending order.
42 *
43 * Each queue has a double linked list of auxtrace_buffers. This list contains
44 * the offset and size of a CPU's auxtrace data. During auxtrace processing
45 * the data portion is mmap()'ed.
46 *
47 * To sort the queues in chronological order, all queue access is controlled
48 * by the auxtrace_heap. This is basicly a stack, each stack element has two
49 * entries, the queue number and a time stamp. However the stack is sorted by
50 * the time stamps. The highest time stamp is at the bottom the lowest
51 * (nearest) time stamp is at the top. That sort order is maintained at all
52 * times!
53 *
54 * After the auxtrace infrastructure has been setup, the auxtrace queues are
55 * filled with data (offset/size pairs) and the auxtrace_heap is populated.
56 *
57 * 2. PERF_RECORD_XXX processing triggers access to the auxtrace_queues.
58 * Each record is handled by s390_cpumsf_process_event(). The time stamp of
59 * the perf record is compared with the time stamp located on the auxtrace_heap
60 * top element. If that time stamp is lower than the time stamp from the
61 * record sample, the auxtrace queues will be processed. As auxtrace queues
62 * control many auxtrace_buffers and each buffer can be quite large, the
63 * auxtrace buffer might be processed only partially. In this case the
64 * position in the auxtrace_buffer of that queue is remembered and the time
65 * stamp of the last processed entry of the auxtrace_buffer replaces the
66 * current auxtrace_heap top.
67 *
68 * 3. Auxtrace_queues might run of out data and are feeded by the
69 * PERF_RECORD_AUXTRACE handling, see s390_cpumsf_process_auxtrace_event().
70 *
71 * Event Generation
72 * Each sampling-data entry in the auxilary trace data generates a perf sample.
73 * This sample is filled
74 * with data from the auxtrace such as PID/TID, instruction address, CPU state,
75 * etc. This sample is processed with perf_session__deliver_synth_event() to
76 * be included into the GUI.
77 *
78 * 4. PERF_RECORD_FINISHED_ROUND event is used to process all the remaining
79 * auxiliary traces entries until the time stamp of this record is reached
80 * auxtrace_heap top. This is triggered by ordered_event->deliver().
81 *
82 *
83 * Perf event processing.
84 * Event processing of PERF_RECORD_XXX entries relies on time stamp entries.
85 * This is the function call sequence:
86 *
87 * __cmd_report()
88 * |
89 * perf_session__process_events()
90 * |
91 * __perf_session__process_events()
92 * |
93 * perf_session__process_event()
94 * | This functions splits the PERF_RECORD_XXX records.
95 * | - Those generated by perf record command (type number equal or higher
96 * | than PERF_RECORD_USER_TYPE_START) are handled by
97 * | perf_session__process_user_event(see below)
98 * | - Those generated by the kernel are handled by
99 * | perf_evlist__parse_sample_timestamp()
100 * |
101 * perf_evlist__parse_sample_timestamp()
102 * | Extract time stamp from sample data.
103 * |
104 * perf_session__queue_event()
105 * | If timestamp is positive the sample is entered into an ordered_event
106 * | list, sort order is the timestamp. The event processing is deferred until
107 * | later (see perf_session__process_user_event()).
108 * | Other timestamps (0 or -1) are handled immediately by
109 * | perf_session__deliver_event(). These are events generated at start up
110 * | of command perf record. They create PERF_RECORD_COMM and PERF_RECORD_MMAP*
111 * | records. They are needed to create a list of running processes and its
112 * | memory mappings and layout. They are needed at the beginning to enable
113 * | command perf report to create process trees and memory mappings.
114 * |
115 * perf_session__deliver_event()
116 * | Delivers a PERF_RECORD_XXX entry for handling.
117 * |
118 * auxtrace__process_event()
119 * | The timestamp of the PERF_RECORD_XXX entry is taken to correlate with
120 * | time stamps from the auxiliary trace buffers. This enables
121 * | synchronization between auxiliary trace data and the events on the
122 * | perf.data file.
123 * |
124 * machine__deliver_event()
125 * | Handles the PERF_RECORD_XXX event. This depends on the record type.
126 * It might update the process tree, update a process memory map or enter
127 * a sample with IP and call back chain data into GUI data pool.
128 *
129 *
130 * Deferred processing determined by perf_session__process_user_event() is
131 * finally processed when a PERF_RECORD_FINISHED_ROUND is encountered. These
132 * are generated during command perf record.
133 * The timestamp of PERF_RECORD_FINISHED_ROUND event is taken to process all
134 * PERF_RECORD_XXX entries stored in the ordered_event list. This list was
135 * built up while reading the perf.data file.
136 * Each event is now processed by calling perf_session__deliver_event().
137 * This enables time synchronization between the data in the perf.data file and
138 * the data in the auxiliary trace buffers.
139 */
140
141#include <endian.h>
142#include <errno.h>
143#include <byteswap.h>
144#include <inttypes.h>
145#include <linux/kernel.h>
146#include <linux/types.h>
147#include <linux/bitops.h>
148#include <linux/log2.h>
149
150#include "cpumap.h"
151#include "color.h"
152#include "evsel.h"
153#include "evlist.h"
154#include "machine.h"
155#include "session.h"
156#include "util.h"
157#include "thread.h"
158#include "debug.h"
159#include "auxtrace.h"
160#include "s390-cpumsf.h"
161#include "s390-cpumsf-kernel.h"
162
163struct s390_cpumsf {
164 struct auxtrace auxtrace;
165 struct auxtrace_queues queues;
166 struct auxtrace_heap heap;
167 struct perf_session *session;
168 struct machine *machine;
169 u32 auxtrace_type;
170 u32 pmu_type;
171 u16 machine_type;
172 bool data_queued;
173};
174
175struct s390_cpumsf_queue {
176 struct s390_cpumsf *sf;
177 unsigned int queue_nr;
178 struct auxtrace_buffer *buffer;
179 int cpu;
180};
181
182/* Display s390 CPU measurement facility basic-sampling data entry */
183static bool s390_cpumsf_basic_show(const char *color, size_t pos,
184 struct hws_basic_entry *basic)
185{
186 if (basic->def != 1) {
187 pr_err("Invalid AUX trace basic entry [%#08zx]\n", pos);
188 return false;
189 }
190 color_fprintf(stdout, color, " [%#08zx] Basic Def:%04x Inst:%#04x"
191 " %c%c%c%c AS:%d ASN:%#04x IA:%#018llx\n"
192 "\t\tCL:%d HPP:%#018llx GPP:%#018llx\n",
193 pos, basic->def, basic->U,
194 basic->T ? 'T' : ' ',
195 basic->W ? 'W' : ' ',
196 basic->P ? 'P' : ' ',
197 basic->I ? 'I' : ' ',
198 basic->AS, basic->prim_asn, basic->ia, basic->CL,
199 basic->hpp, basic->gpp);
200 return true;
201}
202
203/* Display s390 CPU measurement facility diagnostic-sampling data entry */
204static bool s390_cpumsf_diag_show(const char *color, size_t pos,
205 struct hws_diag_entry *diag)
206{
207 if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) {
208 pr_err("Invalid AUX trace diagnostic entry [%#08zx]\n", pos);
209 return false;
210 }
211 color_fprintf(stdout, color, " [%#08zx] Diag Def:%04x %c\n",
212 pos, diag->def, diag->I ? 'I' : ' ');
213 return true;
214}
215
216/* Return TOD timestamp contained in an trailer entry */
217static unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
218{
219 /* te->t set: TOD in STCKE format, bytes 8-15
220 * to->t not set: TOD in STCK format, bytes 0-7
221 */
222 unsigned long long ts;
223
224 memcpy(&ts, &te->timestamp[te->t], sizeof(ts));
225 return ts;
226}
227
228/* Display s390 CPU measurement facility trailer entry */
229static bool s390_cpumsf_trailer_show(const char *color, size_t pos,
230 struct hws_trailer_entry *te)
231{
232 if (te->bsdes != sizeof(struct hws_basic_entry)) {
233 pr_err("Invalid AUX trace trailer entry [%#08zx]\n", pos);
234 return false;
235 }
236 color_fprintf(stdout, color, " [%#08zx] Trailer %c%c%c bsdes:%d"
237 " dsdes:%d Overflow:%lld Time:%#llx\n"
238 "\t\tC:%d TOD:%#lx 1:%#llx 2:%#llx\n",
239 pos,
240 te->f ? 'F' : ' ',
241 te->a ? 'A' : ' ',
242 te->t ? 'T' : ' ',
243 te->bsdes, te->dsdes, te->overflow,
244 trailer_timestamp(te), te->clock_base, te->progusage2,
245 te->progusage[0], te->progusage[1]);
246 return true;
247}
248
249/* Test a sample data block. It must be 4KB or a multiple thereof in size and
250 * 4KB page aligned. Each sample data page has a trailer entry at the
251 * end which contains the sample entry data sizes.
252 *
253 * Return true if the sample data block passes the checks and set the
254 * basic set entry size and diagnostic set entry size.
255 *
256 * Return false on failure.
257 *
258 * Note: Old hardware does not set the basic or diagnostic entry sizes
259 * in the trailer entry. Use the type number instead.
260 */
261static bool s390_cpumsf_validate(int machine_type,
262 unsigned char *buf, size_t len,
263 unsigned short *bsdes,
264 unsigned short *dsdes)
265{
266 struct hws_basic_entry *basic = (struct hws_basic_entry *)buf;
267 struct hws_trailer_entry *te;
268
269 *dsdes = *bsdes = 0;
270 if (len & (S390_CPUMSF_PAGESZ - 1)) /* Illegal size */
271 return false;
272 if (basic->def != 1) /* No basic set entry, must be first */
273 return false;
274 /* Check for trailer entry at end of SDB */
275 te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
276 - sizeof(*te));
277 *bsdes = te->bsdes;
278 *dsdes = te->dsdes;
279 if (!te->bsdes && !te->dsdes) {
280 /* Very old hardware, use CPUID */
281 switch (machine_type) {
282 case 2097:
283 case 2098:
284 *dsdes = 64;
285 *bsdes = 32;
286 break;
287 case 2817:
288 case 2818:
289 *dsdes = 74;
290 *bsdes = 32;
291 break;
292 case 2827:
293 case 2828:
294 *dsdes = 85;
295 *bsdes = 32;
296 break;
297 default:
298 /* Illegal trailer entry */
299 return false;
300 }
301 }
302 return true;
303}
304
305/* Return true if there is room for another entry */
306static bool s390_cpumsf_reached_trailer(size_t entry_sz, size_t pos)
307{
308 size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry);
309
310 if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz)
311 return false;
312 return true;
313}
314
315/* Dump an auxiliary buffer. These buffers are multiple of
316 * 4KB SDB pages.
317 */
318static void s390_cpumsf_dump(struct s390_cpumsf *sf,
319 unsigned char *buf, size_t len)
320{
321 const char *color = PERF_COLOR_BLUE;
322 struct hws_basic_entry *basic;
323 struct hws_diag_entry *diag;
324 unsigned short bsdes, dsdes;
325 size_t pos = 0;
326
327 color_fprintf(stdout, color,
328 ". ... s390 AUX data: size %zu bytes\n",
329 len);
330
331 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
332 &dsdes)) {
333 pr_err("Invalid AUX trace data block size:%zu"
334 " (type:%d bsdes:%hd dsdes:%hd)\n",
335 len, sf->machine_type, bsdes, dsdes);
336 return;
337 }
338
339 /* s390 kernel always returns 4KB blocks fully occupied,
340 * no partially filled SDBs.
341 */
342 while (pos < len) {
343 /* Handle Basic entry */
344 basic = (struct hws_basic_entry *)(buf + pos);
345 if (s390_cpumsf_basic_show(color, pos, basic))
346 pos += bsdes;
347 else
348 return;
349
350 /* Handle Diagnostic entry */
351 diag = (struct hws_diag_entry *)(buf + pos);
352 if (s390_cpumsf_diag_show(color, pos, diag))
353 pos += dsdes;
354 else
355 return;
356
357 /* Check for trailer entry */
358 if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
359 /* Show trailer entry */
360 struct hws_trailer_entry te;
361
362 pos = (pos + S390_CPUMSF_PAGESZ)
363 & ~(S390_CPUMSF_PAGESZ - 1);
364 pos -= sizeof(te);
365 memcpy(&te, buf + pos, sizeof(te));
366 /* Set descriptor sizes in case of old hardware
367 * where these values are not set.
368 */
369 te.bsdes = bsdes;
370 te.dsdes = dsdes;
371 if (s390_cpumsf_trailer_show(color, pos, &te))
372 pos += sizeof(te);
373 else
374 return;
375 }
376 }
377}
378
379static void s390_cpumsf_dump_event(struct s390_cpumsf *sf, unsigned char *buf,
380 size_t len)
381{
382 printf(".\n");
383 s390_cpumsf_dump(sf, buf, len);
384}
385
386#define S390_LPP_PID_MASK 0xffffffff
387
388static bool s390_cpumsf_make_event(size_t pos,
389 struct hws_basic_entry *basic,
390 struct s390_cpumsf_queue *sfq)
391{
392 struct perf_sample sample = {
393 .ip = basic->ia,
394 .pid = basic->hpp & S390_LPP_PID_MASK,
395 .tid = basic->hpp & S390_LPP_PID_MASK,
396 .cpumode = PERF_RECORD_MISC_CPUMODE_UNKNOWN,
397 .cpu = sfq->cpu,
398 .period = 1
399 };
400 union perf_event event;
401
402 memset(&event, 0, sizeof(event));
403 if (basic->CL == 1) /* Native LPAR mode */
404 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
405 : PERF_RECORD_MISC_KERNEL;
406 else if (basic->CL == 2) /* Guest kernel/user space */
407 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
408 : PERF_RECORD_MISC_GUEST_KERNEL;
409 else if (basic->gpp || basic->prim_asn != 0xffff)
410 /* Use heuristics on old hardware */
411 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
412 : PERF_RECORD_MISC_GUEST_KERNEL;
413 else
414 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
415 : PERF_RECORD_MISC_KERNEL;
416
417 event.sample.header.type = PERF_RECORD_SAMPLE;
418 event.sample.header.misc = sample.cpumode;
419 event.sample.header.size = sizeof(struct perf_event_header);
420
421 pr_debug4("%s pos:%#zx ip:%#" PRIx64 " P:%d CL:%d pid:%d.%d cpumode:%d cpu:%d\n",
422 __func__, pos, sample.ip, basic->P, basic->CL, sample.pid,
423 sample.tid, sample.cpumode, sample.cpu);
424 if (perf_session__deliver_synth_event(sfq->sf->session, &event,
425 &sample)) {
426 pr_err("s390 Auxiliary Trace: failed to deliver event\n");
427 return false;
428 }
429 return true;
430}
431
432static unsigned long long get_trailer_time(const unsigned char *buf)
433{
434 struct hws_trailer_entry *te;
435 unsigned long long aux_time;
436
437 te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
438 - sizeof(*te));
439
440 if (!te->clock_base) /* TOD_CLOCK_BASE value missing */
441 return 0;
442
443 /* Correct calculation to convert time stamp in trailer entry to
444 * nano seconds (taken from arch/s390 function tod_to_ns()).
445 * TOD_CLOCK_BASE is stored in trailer entry member progusage2.
446 */
447 aux_time = trailer_timestamp(te) - te->progusage2;
448 aux_time = (aux_time >> 9) * 125 + (((aux_time & 0x1ff) * 125) >> 9);
449 return aux_time;
450}
451
452/* Process the data samples of a single queue. The first parameter is a
453 * pointer to the queue, the second parameter is the time stamp. This
454 * is the time stamp:
455 * - of the event that triggered this processing.
456 * - or the time stamp when the last proccesing of this queue stopped.
457 * In this case it stopped at a 4KB page boundary and record the
458 * position on where to continue processing on the next invocation
459 * (see buffer->use_data and buffer->use_size).
460 *
461 * When this function returns the second parameter is updated to
462 * reflect the time stamp of the last processed auxiliary data entry
463 * (taken from the trailer entry of that page). The caller uses this
464 * returned time stamp to record the last processed entry in this
465 * queue.
466 *
467 * The function returns:
468 * 0: Processing successful. The second parameter returns the
469 * time stamp from the trailer entry until which position
470 * processing took place. Subsequent calls resume from this
471 * position.
472 * <0: An error occurred during processing. The second parameter
473 * returns the maximum time stamp.
474 * >0: Done on this queue. The second parameter returns the
475 * maximum time stamp.
476 */
477static int s390_cpumsf_samples(struct s390_cpumsf_queue *sfq, u64 *ts)
478{
479 struct s390_cpumsf *sf = sfq->sf;
480 unsigned char *buf = sfq->buffer->use_data;
481 size_t len = sfq->buffer->use_size;
482 struct hws_basic_entry *basic;
483 unsigned short bsdes, dsdes;
484 size_t pos = 0;
485 int err = 1;
486 u64 aux_ts;
487
488 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
489 &dsdes)) {
490 *ts = ~0ULL;
491 return -1;
492 }
493
494 /* Get trailer entry time stamp and check if entries in
495 * this auxiliary page are ready for processing. If the
496 * time stamp of the first entry is too high, whole buffer
497 * can be skipped. In this case return time stamp.
498 */
499 aux_ts = get_trailer_time(buf);
500 if (!aux_ts) {
501 pr_err("[%#08" PRIx64 "] Invalid AUX trailer entry TOD clock base\n",
502 sfq->buffer->data_offset);
503 aux_ts = ~0ULL;
504 goto out;
505 }
506 if (aux_ts > *ts) {
507 *ts = aux_ts;
508 return 0;
509 }
510
511 while (pos < len) {
512 /* Handle Basic entry */
513 basic = (struct hws_basic_entry *)(buf + pos);
514 if (s390_cpumsf_make_event(pos, basic, sfq))
515 pos += bsdes;
516 else {
517 err = -EBADF;
518 goto out;
519 }
520
521 pos += dsdes; /* Skip diagnositic entry */
522
523 /* Check for trailer entry */
524 if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
525 pos = (pos + S390_CPUMSF_PAGESZ)
526 & ~(S390_CPUMSF_PAGESZ - 1);
527 /* Check existence of next page */
528 if (pos >= len)
529 break;
530 aux_ts = get_trailer_time(buf + pos);
531 if (!aux_ts) {
532 aux_ts = ~0ULL;
533 goto out;
534 }
535 if (aux_ts > *ts) {
536 *ts = aux_ts;
537 sfq->buffer->use_data += pos;
538 sfq->buffer->use_size -= pos;
539 return 0;
540 }
541 }
542 }
543out:
544 *ts = aux_ts;
545 sfq->buffer->use_size = 0;
546 sfq->buffer->use_data = NULL;
547 return err; /* Buffer completely scanned or error */
548}
549
550/* Run the s390 auxiliary trace decoder.
551 * Select the queue buffer to operate on, the caller already selected
552 * the proper queue, depending on second parameter 'ts'.
553 * This is the time stamp until which the auxiliary entries should
554 * be processed. This value is updated by called functions and
555 * returned to the caller.
556 *
557 * Resume processing in the current buffer. If there is no buffer
558 * get a new buffer from the queue and setup start position for
559 * processing.
560 * When a buffer is completely processed remove it from the queue
561 * before returning.
562 *
563 * This function returns
564 * 1: When the queue is empty. Second parameter will be set to
565 * maximum time stamp.
566 * 0: Normal processing done.
567 * <0: Error during queue buffer setup. This causes the caller
568 * to stop processing completely.
569 */
570static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
571 u64 *ts)
572{
573
574 struct auxtrace_buffer *buffer;
575 struct auxtrace_queue *queue;
576 int err;
577
578 queue = &sfq->sf->queues.queue_array[sfq->queue_nr];
579
580 /* Get buffer and last position in buffer to resume
581 * decoding the auxiliary entries. One buffer might be large
582 * and decoding might stop in between. This depends on the time
583 * stamp of the trailer entry in each page of the auxiliary
584 * data and the time stamp of the event triggering the decoding.
585 */
586 if (sfq->buffer == NULL) {
587 sfq->buffer = buffer = auxtrace_buffer__next(queue,
588 sfq->buffer);
589 if (!buffer) {
590 *ts = ~0ULL;
591 return 1; /* Processing done on this queue */
592 }
593 /* Start with a new buffer on this queue */
594 if (buffer->data) {
595 buffer->use_size = buffer->size;
596 buffer->use_data = buffer->data;
597 }
598 } else
599 buffer = sfq->buffer;
600
601 if (!buffer->data) {
602 int fd = perf_data__fd(sfq->sf->session->data);
603
604 buffer->data = auxtrace_buffer__get_data(buffer, fd);
605 if (!buffer->data)
606 return -ENOMEM;
607 buffer->use_size = buffer->size;
608 buffer->use_data = buffer->data;
609 }
610 pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n",
611 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset,
612 buffer->size, buffer->use_size);
613 err = s390_cpumsf_samples(sfq, ts);
614
615 /* If non-zero, there is either an error (err < 0) or the buffer is
616 * completely done (err > 0). The error is unrecoverable, usually
617 * some descriptors could not be read successfully, so continue with
618 * the next buffer.
619 * In both cases the parameter 'ts' has been updated.
620 */
621 if (err) {
622 sfq->buffer = NULL;
623 list_del(&buffer->list);
624 auxtrace_buffer__free(buffer);
625 if (err > 0) /* Buffer done, no error */
626 err = 0;
627 }
628 return err;
629}
630
631static struct s390_cpumsf_queue *
632s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr)
633{
634 struct s390_cpumsf_queue *sfq;
635
636 sfq = zalloc(sizeof(struct s390_cpumsf_queue));
637 if (sfq == NULL)
638 return NULL;
639
640 sfq->sf = sf;
641 sfq->queue_nr = queue_nr;
642 sfq->cpu = -1;
643 return sfq;
644}
645
646static int s390_cpumsf_setup_queue(struct s390_cpumsf *sf,
647 struct auxtrace_queue *queue,
648 unsigned int queue_nr, u64 ts)
649{
650 struct s390_cpumsf_queue *sfq = queue->priv;
651
652 if (list_empty(&queue->head))
653 return 0;
654
655 if (sfq == NULL) {
656 sfq = s390_cpumsf_alloc_queue(sf, queue_nr);
657 if (!sfq)
658 return -ENOMEM;
659 queue->priv = sfq;
660
661 if (queue->cpu != -1)
662 sfq->cpu = queue->cpu;
663 }
664 return auxtrace_heap__add(&sf->heap, queue_nr, ts);
665}
666
667static int s390_cpumsf_setup_queues(struct s390_cpumsf *sf, u64 ts)
668{
669 unsigned int i;
670 int ret = 0;
671
672 for (i = 0; i < sf->queues.nr_queues; i++) {
673 ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i],
674 i, ts);
675 if (ret)
676 break;
677 }
678 return ret;
679}
680
681static int s390_cpumsf_update_queues(struct s390_cpumsf *sf, u64 ts)
682{
683 if (!sf->queues.new_data)
684 return 0;
685
686 sf->queues.new_data = false;
687 return s390_cpumsf_setup_queues(sf, ts);
688}
689
690static int s390_cpumsf_process_queues(struct s390_cpumsf *sf, u64 timestamp)
691{
692 unsigned int queue_nr;
693 u64 ts;
694 int ret;
695
696 while (1) {
697 struct auxtrace_queue *queue;
698 struct s390_cpumsf_queue *sfq;
699
700 if (!sf->heap.heap_cnt)
701 return 0;
702
703 if (sf->heap.heap_array[0].ordinal >= timestamp)
704 return 0;
705
706 queue_nr = sf->heap.heap_array[0].queue_nr;
707 queue = &sf->queues.queue_array[queue_nr];
708 sfq = queue->priv;
709
710 auxtrace_heap__pop(&sf->heap);
711 if (sf->heap.heap_cnt) {
712 ts = sf->heap.heap_array[0].ordinal + 1;
713 if (ts > timestamp)
714 ts = timestamp;
715 } else {
716 ts = timestamp;
717 }
718
719 ret = s390_cpumsf_run_decoder(sfq, &ts);
720 if (ret < 0) {
721 auxtrace_heap__add(&sf->heap, queue_nr, ts);
722 return ret;
723 }
724 if (!ret) {
725 ret = auxtrace_heap__add(&sf->heap, queue_nr, ts);
726 if (ret < 0)
727 return ret;
728 }
729 }
730 return 0;
731}
732
733static int s390_cpumsf_synth_error(struct s390_cpumsf *sf, int code, int cpu,
734 pid_t pid, pid_t tid, u64 ip)
735{
736 char msg[MAX_AUXTRACE_ERROR_MSG];
737 union perf_event event;
738 int err;
739
740 strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1);
741 auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE,
742 code, cpu, pid, tid, ip, msg);
743
744 err = perf_session__deliver_synth_event(sf->session, &event, NULL);
745 if (err)
746 pr_err("s390 Auxiliary Trace: failed to deliver error event,"
747 "error %d\n", err);
748 return err;
749}
750
751static int s390_cpumsf_lost(struct s390_cpumsf *sf, struct perf_sample *sample)
752{
753 return s390_cpumsf_synth_error(sf, 1, sample->cpu,
754 sample->pid, sample->tid, 0);
755}
756
757static int
758s390_cpumsf_process_event(struct perf_session *session __maybe_unused,
759 union perf_event *event,
760 struct perf_sample *sample,
761 struct perf_tool *tool)
762{
763 struct s390_cpumsf *sf = container_of(session->auxtrace,
764 struct s390_cpumsf,
765 auxtrace);
766 u64 timestamp = sample->time;
767 int err = 0;
768
769 if (dump_trace)
770 return 0;
771
772 if (!tool->ordered_events) {
773 pr_err("s390 Auxiliary Trace requires ordered events\n");
774 return -EINVAL;
775 }
776
777 if (event->header.type == PERF_RECORD_AUX &&
778 event->aux.flags & PERF_AUX_FLAG_TRUNCATED)
779 return s390_cpumsf_lost(sf, sample);
780
781 if (timestamp) {
782 err = s390_cpumsf_update_queues(sf, timestamp);
783 if (!err)
784 err = s390_cpumsf_process_queues(sf, timestamp);
785 }
786 return err;
787}
788
789struct s390_cpumsf_synth {
790 struct perf_tool cpumsf_tool;
791 struct perf_session *session;
792};
793
794static int
795s390_cpumsf_process_auxtrace_event(struct perf_session *session,
796 union perf_event *event __maybe_unused,
797 struct perf_tool *tool __maybe_unused)
798{
799 struct s390_cpumsf *sf = container_of(session->auxtrace,
800 struct s390_cpumsf,
801 auxtrace);
802
803 int fd = perf_data__fd(session->data);
804 struct auxtrace_buffer *buffer;
805 off_t data_offset;
806 int err;
807
808 if (sf->data_queued)
809 return 0;
810
811 if (perf_data__is_pipe(session->data)) {
812 data_offset = 0;
813 } else {
814 data_offset = lseek(fd, 0, SEEK_CUR);
815 if (data_offset == -1)
816 return -errno;
817 }
818
819 err = auxtrace_queues__add_event(&sf->queues, session, event,
820 data_offset, &buffer);
821 if (err)
822 return err;
823
824 /* Dump here after copying piped trace out of the pipe */
825 if (dump_trace) {
826 if (auxtrace_buffer__get_data(buffer, fd)) {
827 s390_cpumsf_dump_event(sf, buffer->data,
828 buffer->size);
829 auxtrace_buffer__put_data(buffer);
830 }
831 }
832 return 0;
833}
834
835static void s390_cpumsf_free_events(struct perf_session *session __maybe_unused)
836{
837}
838
839static int s390_cpumsf_flush(struct perf_session *session __maybe_unused,
840 struct perf_tool *tool __maybe_unused)
841{
842 return 0;
843}
844
845static void s390_cpumsf_free_queues(struct perf_session *session)
846{
847 struct s390_cpumsf *sf = container_of(session->auxtrace,
848 struct s390_cpumsf,
849 auxtrace);
850 struct auxtrace_queues *queues = &sf->queues;
851 unsigned int i;
852
853 for (i = 0; i < queues->nr_queues; i++)
854 zfree(&queues->queue_array[i].priv);
855 auxtrace_queues__free(queues);
856}
857
858static void s390_cpumsf_free(struct perf_session *session)
859{
860 struct s390_cpumsf *sf = container_of(session->auxtrace,
861 struct s390_cpumsf,
862 auxtrace);
863
864 auxtrace_heap__free(&sf->heap);
865 s390_cpumsf_free_queues(session);
866 session->auxtrace = NULL;
867 free(sf);
868}
869
870static int s390_cpumsf_get_type(const char *cpuid)
871{
872 int ret, family = 0;
873
874 ret = sscanf(cpuid, "%*[^,],%u", &family);
875 return (ret == 1) ? family : 0;
876}
877
878/* Check itrace options set on perf report command.
879 * Return true, if none are set or all options specified can be
880 * handled on s390.
881 * Return false otherwise.
882 */
883static bool check_auxtrace_itrace(struct itrace_synth_opts *itops)
884{
885 if (!itops || !itops->set)
886 return true;
887 pr_err("No --itrace options supported\n");
888 return false;
889}
890
891int s390_cpumsf_process_auxtrace_info(union perf_event *event,
892 struct perf_session *session)
893{
894 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
895 struct s390_cpumsf *sf;
896 int err;
897
898 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event))
899 return -EINVAL;
900
901 sf = zalloc(sizeof(struct s390_cpumsf));
902 if (sf == NULL)
903 return -ENOMEM;
904
905 if (!check_auxtrace_itrace(session->itrace_synth_opts)) {
906 err = -EINVAL;
907 goto err_free;
908 }
909
910 err = auxtrace_queues__init(&sf->queues);
911 if (err)
912 goto err_free;
913
914 sf->session = session;
915 sf->machine = &session->machines.host; /* No kvm support */
916 sf->auxtrace_type = auxtrace_info->type;
917 sf->pmu_type = PERF_TYPE_RAW;
918 sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid);
919
920 sf->auxtrace.process_event = s390_cpumsf_process_event;
921 sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event;
922 sf->auxtrace.flush_events = s390_cpumsf_flush;
923 sf->auxtrace.free_events = s390_cpumsf_free_events;
924 sf->auxtrace.free = s390_cpumsf_free;
925 session->auxtrace = &sf->auxtrace;
926
927 if (dump_trace)
928 return 0;
929
930 err = auxtrace_queues__process_index(&sf->queues, session);
931 if (err)
932 goto err_free_queues;
933
934 if (sf->queues.populated)
935 sf->data_queued = true;
936
937 return 0;
938
939err_free_queues:
940 auxtrace_queues__free(&sf->queues);
941 session->auxtrace = NULL;
942err_free:
943 free(sf);
944 return err;
945}
diff --git a/tools/perf/util/s390-cpumsf.h b/tools/perf/util/s390-cpumsf.h
new file mode 100644
index 000000000000..fb64d100555c
--- /dev/null
+++ b/tools/perf/util/s390-cpumsf.h
@@ -0,0 +1,21 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright IBM Corp. 2018
4 * Auxtrace support for s390 CPU-Measurement Sampling Facility
5 *
6 * Author(s): Thomas Richter <tmricht@linux.ibm.com>
7 */
8
9#ifndef INCLUDE__PERF_S390_CPUMSF_H
10#define INCLUDE__PERF_S390_CPUMSF_H
11
12union perf_event;
13struct perf_session;
14struct perf_pmu;
15
16struct auxtrace_record *
17s390_cpumsf_recording_init(int *err, struct perf_pmu *s390_cpumsf_pmu);
18
19int s390_cpumsf_process_auxtrace_info(union perf_event *event,
20 struct perf_session *session);
21#endif
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 7b79c413486b..45484f0f7292 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -535,7 +535,7 @@ static int perl_stop_script(void)
535 return 0; 535 return 0;
536} 536}
537 537
538static int perl_generate_script(struct pevent *pevent, const char *outfile) 538static int perl_generate_script(struct tep_handle *pevent, const char *outfile)
539{ 539{
540 struct event_format *event = NULL; 540 struct event_format *event = NULL;
541 struct format_field *f; 541 struct format_field *f;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index bc32e57d17be..dfc6093f118c 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -871,8 +871,8 @@ static void python_process_tracepoint(struct perf_sample *sample,
871 offset = field->offset; 871 offset = field->offset;
872 len = field->size; 872 len = field->size;
873 if (field->flags & FIELD_IS_DYNAMIC) { 873 if (field->flags & FIELD_IS_DYNAMIC) {
874 val = pevent_read_number(scripting_context->pevent, 874 val = tep_read_number(scripting_context->pevent,
875 data + offset, len); 875 data + offset, len);
876 offset = val; 876 offset = val;
877 len = offset >> 16; 877 len = offset >> 16;
878 offset &= 0xffff; 878 offset &= 0xffff;
@@ -1588,7 +1588,7 @@ static int python_stop_script(void)
1588 return 0; 1588 return 0;
1589} 1589}
1590 1590
1591static int python_generate_script(struct pevent *pevent, const char *outfile) 1591static int python_generate_script(struct tep_handle *pevent, const char *outfile)
1592{ 1592{
1593 struct event_format *event = NULL; 1593 struct event_format *event = NULL;
1594 struct format_field *f; 1594 struct format_field *f;
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index 001be4f9d3b9..97efbcad076e 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -1,12 +1,20 @@
1#!/usr/bin/python 1#!/usr/bin/python
2 2
3from os import getenv 3from os import getenv
4from subprocess import Popen, PIPE
5from re import sub
6
7def clang_has_option(option):
8 return [o for o in Popen(['clang', option], stderr=PIPE).stderr.readlines() if "unknown argument" in o] == [ ]
4 9
5cc = getenv("CC") 10cc = getenv("CC")
6if cc == "clang": 11if cc == "clang":
7 from _sysconfigdata import build_time_vars 12 from _sysconfigdata import build_time_vars
8 from re import sub
9 build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"]) 13 build_time_vars["CFLAGS"] = sub("-specs=[^ ]+", "", build_time_vars["CFLAGS"])
14 if not clang_has_option("-mcet"):
15 build_time_vars["CFLAGS"] = sub("-mcet", "", build_time_vars["CFLAGS"])
16 if not clang_has_option("-fcf-protection"):
17 build_time_vars["CFLAGS"] = sub("-fcf-protection", "", build_time_vars["CFLAGS"])
10 18
11from distutils.core import setup, Extension 19from distutils.core import setup, Extension
12 20
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index fed2952ab45a..b284276ec963 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -601,7 +601,7 @@ static char *get_trace_output(struct hist_entry *he)
601{ 601{
602 struct trace_seq seq; 602 struct trace_seq seq;
603 struct perf_evsel *evsel; 603 struct perf_evsel *evsel;
604 struct pevent_record rec = { 604 struct tep_record rec = {
605 .data = he->raw_data, 605 .data = he->raw_data,
606 .size = he->raw_size, 606 .size = he->raw_size,
607 }; 607 };
@@ -610,10 +610,10 @@ static char *get_trace_output(struct hist_entry *he)
610 610
611 trace_seq_init(&seq); 611 trace_seq_init(&seq);
612 if (symbol_conf.raw_trace) { 612 if (symbol_conf.raw_trace) {
613 pevent_print_fields(&seq, he->raw_data, he->raw_size, 613 tep_print_fields(&seq, he->raw_data, he->raw_size,
614 evsel->tp_format); 614 evsel->tp_format);
615 } else { 615 } else {
616 pevent_event_info(&seq, evsel->tp_format, &rec); 616 tep_event_info(&seq, evsel->tp_format, &rec);
617 } 617 }
618 /* 618 /*
619 * Trim the buffer, it starts at 4KB and we're not going to 619 * Trim the buffer, it starts at 4KB and we're not going to
@@ -2047,7 +2047,7 @@ static int __sort__hde_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
2047 struct trace_seq seq; 2047 struct trace_seq seq;
2048raw_field: 2048raw_field:
2049 trace_seq_init(&seq); 2049 trace_seq_init(&seq);
2050 pevent_print_field(&seq, he->raw_data, hde->field); 2050 tep_print_field(&seq, he->raw_data, hde->field);
2051 str = seq.buffer; 2051 str = seq.buffer;
2052 } 2052 }
2053 2053
@@ -2074,7 +2074,7 @@ static int64_t __sort__hde_cmp(struct perf_hpp_fmt *fmt,
2074 if (field->flags & FIELD_IS_DYNAMIC) { 2074 if (field->flags & FIELD_IS_DYNAMIC) {
2075 unsigned long long dyn; 2075 unsigned long long dyn;
2076 2076
2077 pevent_read_number_field(field, a->raw_data, &dyn); 2077 tep_read_number_field(field, a->raw_data, &dyn);
2078 offset = dyn & 0xffff; 2078 offset = dyn & 0xffff;
2079 size = (dyn >> 16) & 0xffff; 2079 size = (dyn >> 16) & 0xffff;
2080 2080
@@ -2311,7 +2311,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2311 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
2312 continue; 2312 continue;
2313 2313
2314 field = pevent_find_any_field(evsel->tp_format, field_name); 2314 field = tep_find_any_field(evsel->tp_format, field_name);
2315 if (field == NULL) 2315 if (field == NULL)
2316 continue; 2316 continue;
2317 2317
@@ -2378,7 +2378,7 @@ static int add_dynamic_entry(struct perf_evlist *evlist, const char *tok,
2378 if (!strcmp(field_name, "*")) { 2378 if (!strcmp(field_name, "*")) {
2379 ret = add_evsel_fields(evsel, raw_trace, level); 2379 ret = add_evsel_fields(evsel, raw_trace, level);
2380 } else { 2380 } else {
2381 field = pevent_find_any_field(evsel->tp_format, field_name); 2381 field = tep_find_any_field(evsel->tp_format, field_name);
2382 if (field == NULL) { 2382 if (field == NULL) {
2383 pr_debug("Cannot find event field for %s.%s\n", 2383 pr_debug("Cannot find event field for %s.%s\n",
2384 event_name, field_name); 2384 event_name, field_name);
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 8bf302cafcec..a97cf8e6be86 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -276,7 +276,7 @@ extern struct sort_entry sort_thread;
276extern struct list_head hist_entry__sort_list; 276extern struct list_head hist_entry__sort_list;
277 277
278struct perf_evlist; 278struct perf_evlist;
279struct pevent; 279struct tep_handle;
280int setup_sorting(struct perf_evlist *evlist); 280int setup_sorting(struct perf_evlist *evlist);
281int setup_output_field(void); 281int setup_output_field(void);
282void reset_output_field(void); 282void reset_output_field(void);
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index e0a6e9a6a053..920b1d58a068 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -32,7 +32,7 @@
32static int get_common_field(struct scripting_context *context, 32static int get_common_field(struct scripting_context *context,
33 int *offset, int *size, const char *type) 33 int *offset, int *size, const char *type)
34{ 34{
35 struct pevent *pevent = context->pevent; 35 struct tep_handle *pevent = context->pevent;
36 struct event_format *event; 36 struct event_format *event;
37 struct format_field *field; 37 struct format_field *field;
38 38
@@ -41,14 +41,14 @@ static int get_common_field(struct scripting_context *context,
41 return 0; 41 return 0;
42 42
43 event = pevent->events[0]; 43 event = pevent->events[0];
44 field = pevent_find_common_field(event, type); 44 field = tep_find_common_field(event, type);
45 if (!field) 45 if (!field)
46 return 0; 46 return 0;
47 *offset = field->offset; 47 *offset = field->offset;
48 *size = field->size; 48 *size = field->size;
49 } 49 }
50 50
51 return pevent_read_number(pevent, context->event_data + *offset, *size); 51 return tep_read_number(pevent, context->event_data + *offset, *size);
52} 52}
53 53
54int common_lock_depth(struct scripting_context *context) 54int common_lock_depth(struct scripting_context *context)
@@ -99,24 +99,24 @@ raw_field_value(struct event_format *event, const char *name, void *data)
99 struct format_field *field; 99 struct format_field *field;
100 unsigned long long val; 100 unsigned long long val;
101 101
102 field = pevent_find_any_field(event, name); 102 field = tep_find_any_field(event, name);
103 if (!field) 103 if (!field)
104 return 0ULL; 104 return 0ULL;
105 105
106 pevent_read_number_field(field, data, &val); 106 tep_read_number_field(field, data, &val);
107 107
108 return val; 108 return val;
109} 109}
110 110
111unsigned long long read_size(struct event_format *event, void *ptr, int size) 111unsigned long long read_size(struct event_format *event, void *ptr, int size)
112{ 112{
113 return pevent_read_number(event->pevent, ptr, size); 113 return tep_read_number(event->pevent, ptr, size);
114} 114}
115 115
116void event_format__fprintf(struct event_format *event, 116void event_format__fprintf(struct event_format *event,
117 int cpu, void *data, int size, FILE *fp) 117 int cpu, void *data, int size, FILE *fp)
118{ 118{
119 struct pevent_record record; 119 struct tep_record record;
120 struct trace_seq s; 120 struct trace_seq s;
121 121
122 memset(&record, 0, sizeof(record)); 122 memset(&record, 0, sizeof(record));
@@ -125,7 +125,7 @@ void event_format__fprintf(struct event_format *event,
125 record.data = data; 125 record.data = data;
126 126
127 trace_seq_init(&s); 127 trace_seq_init(&s);
128 pevent_event_info(&s, event, &record); 128 tep_event_info(&s, event, &record);
129 trace_seq_do_fprintf(&s, fp); 129 trace_seq_do_fprintf(&s, fp);
130 trace_seq_destroy(&s); 130 trace_seq_destroy(&s);
131} 131}
@@ -136,7 +136,7 @@ void event_format__print(struct event_format *event,
136 return event_format__fprintf(event, cpu, data, size, stdout); 136 return event_format__fprintf(event, cpu, data, size, stdout);
137} 137}
138 138
139void parse_ftrace_printk(struct pevent *pevent, 139void parse_ftrace_printk(struct tep_handle *pevent,
140 char *file, unsigned int size __maybe_unused) 140 char *file, unsigned int size __maybe_unused)
141{ 141{
142 unsigned long long addr; 142 unsigned long long addr;
@@ -157,11 +157,11 @@ void parse_ftrace_printk(struct pevent *pevent,
157 /* fmt still has a space, skip it */ 157 /* fmt still has a space, skip it */
158 printk = strdup(fmt+1); 158 printk = strdup(fmt+1);
159 line = strtok_r(NULL, "\n", &next); 159 line = strtok_r(NULL, "\n", &next);
160 pevent_register_print_string(pevent, printk, addr); 160 tep_register_print_string(pevent, printk, addr);
161 } 161 }
162} 162}
163 163
164void parse_saved_cmdline(struct pevent *pevent, 164void parse_saved_cmdline(struct tep_handle *pevent,
165 char *file, unsigned int size __maybe_unused) 165 char *file, unsigned int size __maybe_unused)
166{ 166{
167 char *comm; 167 char *comm;
@@ -172,24 +172,24 @@ void parse_saved_cmdline(struct pevent *pevent,
172 line = strtok_r(file, "\n", &next); 172 line = strtok_r(file, "\n", &next);
173 while (line) { 173 while (line) {
174 sscanf(line, "%d %ms", &pid, &comm); 174 sscanf(line, "%d %ms", &pid, &comm);
175 pevent_register_comm(pevent, comm, pid); 175 tep_register_comm(pevent, comm, pid);
176 free(comm); 176 free(comm);
177 line = strtok_r(NULL, "\n", &next); 177 line = strtok_r(NULL, "\n", &next);
178 } 178 }
179} 179}
180 180
181int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size) 181int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size)
182{ 182{
183 return pevent_parse_event(pevent, buf, size, "ftrace"); 183 return tep_parse_event(pevent, buf, size, "ftrace");
184} 184}
185 185
186int parse_event_file(struct pevent *pevent, 186int parse_event_file(struct tep_handle *pevent,
187 char *buf, unsigned long size, char *sys) 187 char *buf, unsigned long size, char *sys)
188{ 188{
189 return pevent_parse_event(pevent, buf, size, sys); 189 return tep_parse_event(pevent, buf, size, sys);
190} 190}
191 191
192struct event_format *trace_find_next_event(struct pevent *pevent, 192struct event_format *trace_find_next_event(struct tep_handle *pevent,
193 struct event_format *event) 193 struct event_format *event)
194{ 194{
195 static int idx; 195 static int idx;
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 40b425949aa3..3dfc1db6b25b 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -96,7 +96,7 @@ static void skip(int size)
96 }; 96 };
97} 97}
98 98
99static unsigned int read4(struct pevent *pevent) 99static unsigned int read4(struct tep_handle *pevent)
100{ 100{
101 unsigned int data; 101 unsigned int data;
102 102
@@ -105,7 +105,7 @@ static unsigned int read4(struct pevent *pevent)
105 return __data2host4(pevent, data); 105 return __data2host4(pevent, data);
106} 106}
107 107
108static unsigned long long read8(struct pevent *pevent) 108static unsigned long long read8(struct tep_handle *pevent)
109{ 109{
110 unsigned long long data; 110 unsigned long long data;
111 111
@@ -158,7 +158,7 @@ out:
158 return str; 158 return str;
159} 159}
160 160
161static int read_proc_kallsyms(struct pevent *pevent) 161static int read_proc_kallsyms(struct tep_handle *pevent)
162{ 162{
163 unsigned int size; 163 unsigned int size;
164 164
@@ -181,7 +181,7 @@ static int read_proc_kallsyms(struct pevent *pevent)
181 return 0; 181 return 0;
182} 182}
183 183
184static int read_ftrace_printk(struct pevent *pevent) 184static int read_ftrace_printk(struct tep_handle *pevent)
185{ 185{
186 unsigned int size; 186 unsigned int size;
187 char *buf; 187 char *buf;
@@ -208,7 +208,7 @@ static int read_ftrace_printk(struct pevent *pevent)
208 return 0; 208 return 0;
209} 209}
210 210
211static int read_header_files(struct pevent *pevent) 211static int read_header_files(struct tep_handle *pevent)
212{ 212{
213 unsigned long long size; 213 unsigned long long size;
214 char *header_page; 214 char *header_page;
@@ -235,13 +235,13 @@ static int read_header_files(struct pevent *pevent)
235 return -1; 235 return -1;
236 } 236 }
237 237
238 if (!pevent_parse_header_page(pevent, header_page, size, 238 if (!tep_parse_header_page(pevent, header_page, size,
239 pevent_get_long_size(pevent))) { 239 tep_get_long_size(pevent))) {
240 /* 240 /*
241 * The commit field in the page is of type long, 241 * The commit field in the page is of type long,
242 * use that instead, since it represents the kernel. 242 * use that instead, since it represents the kernel.
243 */ 243 */
244 pevent_set_long_size(pevent, pevent->header_page_size_size); 244 tep_set_long_size(pevent, pevent->header_page_size_size);
245 } 245 }
246 free(header_page); 246 free(header_page);
247 247
@@ -259,7 +259,7 @@ static int read_header_files(struct pevent *pevent)
259 return ret; 259 return ret;
260} 260}
261 261
262static int read_ftrace_file(struct pevent *pevent, unsigned long long size) 262static int read_ftrace_file(struct tep_handle *pevent, unsigned long long size)
263{ 263{
264 int ret; 264 int ret;
265 char *buf; 265 char *buf;
@@ -284,8 +284,8 @@ out:
284 return ret; 284 return ret;
285} 285}
286 286
287static int read_event_file(struct pevent *pevent, char *sys, 287static int read_event_file(struct tep_handle *pevent, char *sys,
288 unsigned long long size) 288 unsigned long long size)
289{ 289{
290 int ret; 290 int ret;
291 char *buf; 291 char *buf;
@@ -310,7 +310,7 @@ out:
310 return ret; 310 return ret;
311} 311}
312 312
313static int read_ftrace_files(struct pevent *pevent) 313static int read_ftrace_files(struct tep_handle *pevent)
314{ 314{
315 unsigned long long size; 315 unsigned long long size;
316 int count; 316 int count;
@@ -328,7 +328,7 @@ static int read_ftrace_files(struct pevent *pevent)
328 return 0; 328 return 0;
329} 329}
330 330
331static int read_event_files(struct pevent *pevent) 331static int read_event_files(struct tep_handle *pevent)
332{ 332{
333 unsigned long long size; 333 unsigned long long size;
334 char *sys; 334 char *sys;
@@ -356,7 +356,7 @@ static int read_event_files(struct pevent *pevent)
356 return 0; 356 return 0;
357} 357}
358 358
359static int read_saved_cmdline(struct pevent *pevent) 359static int read_saved_cmdline(struct tep_handle *pevent)
360{ 360{
361 unsigned long long size; 361 unsigned long long size;
362 char *buf; 362 char *buf;
@@ -399,7 +399,7 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
399 int host_bigendian; 399 int host_bigendian;
400 int file_long_size; 400 int file_long_size;
401 int file_page_size; 401 int file_page_size;
402 struct pevent *pevent = NULL; 402 struct tep_handle *pevent = NULL;
403 int err; 403 int err;
404 404
405 repipe = __repipe; 405 repipe = __repipe;
@@ -439,9 +439,9 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
439 439
440 pevent = tevent->pevent; 440 pevent = tevent->pevent;
441 441
442 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 442 tep_set_flag(pevent, TEP_NSEC_OUTPUT);
443 pevent_set_file_bigendian(pevent, file_bigendian); 443 tep_set_file_bigendian(pevent, file_bigendian);
444 pevent_set_host_bigendian(pevent, host_bigendian); 444 tep_set_host_bigendian(pevent, host_bigendian);
445 445
446 if (do_read(buf, 1) < 0) 446 if (do_read(buf, 1) < 0)
447 goto out; 447 goto out;
@@ -451,8 +451,8 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
451 if (!file_page_size) 451 if (!file_page_size)
452 goto out; 452 goto out;
453 453
454 pevent_set_long_size(pevent, file_long_size); 454 tep_set_long_size(pevent, file_long_size);
455 pevent_set_page_size(pevent, file_page_size); 455 tep_set_page_size(pevent, file_page_size);
456 456
457 err = read_header_files(pevent); 457 err = read_header_files(pevent);
458 if (err) 458 if (err)
@@ -479,9 +479,9 @@ ssize_t trace_report(int fd, struct trace_event *tevent, bool __repipe)
479 repipe = false; 479 repipe = false;
480 480
481 if (show_funcs) { 481 if (show_funcs) {
482 pevent_print_funcs(pevent); 482 tep_print_funcs(pevent);
483 } else if (show_printk) { 483 } else if (show_printk) {
484 pevent_print_printk(pevent); 484 tep_print_printk(pevent);
485 } 485 }
486 486
487 pevent = NULL; 487 pevent = NULL;
diff --git a/tools/perf/util/trace-event-scripting.c b/tools/perf/util/trace-event-scripting.c
index b1e5c3a2b8e3..b749f812ac70 100644
--- a/tools/perf/util/trace-event-scripting.c
+++ b/tools/perf/util/trace-event-scripting.c
@@ -66,7 +66,7 @@ static int python_start_script_unsupported(const char *script __maybe_unused,
66 return -1; 66 return -1;
67} 67}
68 68
69static int python_generate_script_unsupported(struct pevent *pevent 69static int python_generate_script_unsupported(struct tep_handle *pevent
70 __maybe_unused, 70 __maybe_unused,
71 const char *outfile 71 const char *outfile
72 __maybe_unused) 72 __maybe_unused)
@@ -130,7 +130,7 @@ static int perl_start_script_unsupported(const char *script __maybe_unused,
130 return -1; 130 return -1;
131} 131}
132 132
133static int perl_generate_script_unsupported(struct pevent *pevent 133static int perl_generate_script_unsupported(struct tep_handle *pevent
134 __maybe_unused, 134 __maybe_unused,
135 const char *outfile __maybe_unused) 135 const char *outfile __maybe_unused)
136{ 136{
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 1aa368603268..58bb72f266f3 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -28,10 +28,10 @@ static bool tevent_initialized;
28 28
29int trace_event__init(struct trace_event *t) 29int trace_event__init(struct trace_event *t)
30{ 30{
31 struct pevent *pevent = pevent_alloc(); 31 struct tep_handle *pevent = tep_alloc();
32 32
33 if (pevent) { 33 if (pevent) {
34 t->plugin_list = traceevent_load_plugins(pevent); 34 t->plugin_list = tep_load_plugins(pevent);
35 t->pevent = pevent; 35 t->pevent = pevent;
36 } 36 }
37 37
@@ -40,33 +40,33 @@ int trace_event__init(struct trace_event *t)
40 40
41static int trace_event__init2(void) 41static int trace_event__init2(void)
42{ 42{
43 int be = traceevent_host_bigendian(); 43 int be = tep_host_bigendian();
44 struct pevent *pevent; 44 struct tep_handle *pevent;
45 45
46 if (trace_event__init(&tevent)) 46 if (trace_event__init(&tevent))
47 return -1; 47 return -1;
48 48
49 pevent = tevent.pevent; 49 pevent = tevent.pevent;
50 pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT); 50 tep_set_flag(pevent, TEP_NSEC_OUTPUT);
51 pevent_set_file_bigendian(pevent, be); 51 tep_set_file_bigendian(pevent, be);
52 pevent_set_host_bigendian(pevent, be); 52 tep_set_host_bigendian(pevent, be);
53 tevent_initialized = true; 53 tevent_initialized = true;
54 return 0; 54 return 0;
55} 55}
56 56
57int trace_event__register_resolver(struct machine *machine, 57int trace_event__register_resolver(struct machine *machine,
58 pevent_func_resolver_t *func) 58 tep_func_resolver_t *func)
59{ 59{
60 if (!tevent_initialized && trace_event__init2()) 60 if (!tevent_initialized && trace_event__init2())
61 return -1; 61 return -1;
62 62
63 return pevent_set_function_resolver(tevent.pevent, func, machine); 63 return tep_set_function_resolver(tevent.pevent, func, machine);
64} 64}
65 65
66void trace_event__cleanup(struct trace_event *t) 66void trace_event__cleanup(struct trace_event *t)
67{ 67{
68 traceevent_unload_plugins(t->plugin_list, t->pevent); 68 tep_unload_plugins(t->plugin_list, t->pevent);
69 pevent_free(t->pevent); 69 tep_free(t->pevent);
70} 70}
71 71
72/* 72/*
@@ -76,7 +76,7 @@ static struct event_format*
76tp_format(const char *sys, const char *name) 76tp_format(const char *sys, const char *name)
77{ 77{
78 char *tp_dir = get_events_file(sys); 78 char *tp_dir = get_events_file(sys);
79 struct pevent *pevent = tevent.pevent; 79 struct tep_handle *pevent = tevent.pevent;
80 struct event_format *event = NULL; 80 struct event_format *event = NULL;
81 char path[PATH_MAX]; 81 char path[PATH_MAX];
82 size_t size; 82 size_t size;
@@ -93,7 +93,7 @@ tp_format(const char *sys, const char *name)
93 if (err) 93 if (err)
94 return ERR_PTR(err); 94 return ERR_PTR(err);
95 95
96 pevent_parse_format(pevent, &event, data, size, sys); 96 tep_parse_format(pevent, &event, data, size, sys);
97 97
98 free(data); 98 free(data);
99 return event; 99 return event;
@@ -116,5 +116,5 @@ struct event_format *trace_event__tp_format_id(int id)
116 if (!tevent_initialized && trace_event__init2()) 116 if (!tevent_initialized && trace_event__init2())
117 return ERR_PTR(-ENOMEM); 117 return ERR_PTR(-ENOMEM);
118 118
119 return pevent_find_event(tevent.pevent, id); 119 return tep_find_event(tevent.pevent, id);
120} 120}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index dcbdb53dc702..40204ec3a7a2 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -13,14 +13,14 @@ struct thread;
13struct plugin_list; 13struct plugin_list;
14 14
15struct trace_event { 15struct trace_event {
16 struct pevent *pevent; 16 struct tep_handle *pevent;
17 struct plugin_list *plugin_list; 17 struct plugin_list *plugin_list;
18}; 18};
19 19
20int trace_event__init(struct trace_event *t); 20int trace_event__init(struct trace_event *t);
21void trace_event__cleanup(struct trace_event *t); 21void trace_event__cleanup(struct trace_event *t);
22int trace_event__register_resolver(struct machine *machine, 22int trace_event__register_resolver(struct machine *machine,
23 pevent_func_resolver_t *func); 23 tep_func_resolver_t *func);
24struct event_format* 24struct event_format*
25trace_event__tp_format(const char *sys, const char *name); 25trace_event__tp_format(const char *sys, const char *name);
26 26
@@ -34,20 +34,20 @@ void event_format__fprintf(struct event_format *event,
34void event_format__print(struct event_format *event, 34void event_format__print(struct event_format *event,
35 int cpu, void *data, int size); 35 int cpu, void *data, int size);
36 36
37int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size); 37int parse_ftrace_file(struct tep_handle *pevent, char *buf, unsigned long size);
38int parse_event_file(struct pevent *pevent, 38int parse_event_file(struct tep_handle *pevent,
39 char *buf, unsigned long size, char *sys); 39 char *buf, unsigned long size, char *sys);
40 40
41unsigned long long 41unsigned long long
42raw_field_value(struct event_format *event, const char *name, void *data); 42raw_field_value(struct event_format *event, const char *name, void *data);
43 43
44void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size); 44void parse_proc_kallsyms(struct tep_handle *pevent, char *file, unsigned int size);
45void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size); 45void parse_ftrace_printk(struct tep_handle *pevent, char *file, unsigned int size);
46void parse_saved_cmdline(struct pevent *pevent, char *file, unsigned int size); 46void parse_saved_cmdline(struct tep_handle *pevent, char *file, unsigned int size);
47 47
48ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe); 48ssize_t trace_report(int fd, struct trace_event *tevent, bool repipe);
49 49
50struct event_format *trace_find_next_event(struct pevent *pevent, 50struct event_format *trace_find_next_event(struct tep_handle *pevent,
51 struct event_format *event); 51 struct event_format *event);
52unsigned long long read_size(struct event_format *event, void *ptr, int size); 52unsigned long long read_size(struct event_format *event, void *ptr, int size);
53unsigned long long eval_flag(const char *flag); 53unsigned long long eval_flag(const char *flag);
@@ -83,7 +83,7 @@ struct scripting_ops {
83 void (*process_stat)(struct perf_stat_config *config, 83 void (*process_stat)(struct perf_stat_config *config,
84 struct perf_evsel *evsel, u64 tstamp); 84 struct perf_evsel *evsel, u64 tstamp);
85 void (*process_stat_interval)(u64 tstamp); 85 void (*process_stat_interval)(u64 tstamp);
86 int (*generate_script) (struct pevent *pevent, const char *outfile); 86 int (*generate_script) (struct tep_handle *pevent, const char *outfile);
87}; 87};
88 88
89extern unsigned int scripting_max_stack; 89extern unsigned int scripting_max_stack;
@@ -94,7 +94,7 @@ void setup_perl_scripting(void);
94void setup_python_scripting(void); 94void setup_python_scripting(void);
95 95
96struct scripting_context { 96struct scripting_context {
97 struct pevent *pevent; 97 struct tep_handle *pevent;
98 void *event_data; 98 void *event_data;
99}; 99};
100 100