1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2465f27a3SJiri Olsa /*
3465f27a3SJiri Olsa * This is rewrite of original c2c tool introduced in here:
4465f27a3SJiri Olsa * http://lwn.net/Articles/588866/
5465f27a3SJiri Olsa *
6465f27a3SJiri Olsa * The original tool was changed to fit in current perf state.
7465f27a3SJiri Olsa *
8465f27a3SJiri Olsa * Original authors:
9465f27a3SJiri Olsa * Don Zickus <dzickus@redhat.com>
10465f27a3SJiri Olsa * Dick Fowles <fowles@inreach.com>
11465f27a3SJiri Olsa * Joe Mario <jmario@redhat.com>
12465f27a3SJiri Olsa */
13a43783aeSArnaldo Carvalho de Melo #include <errno.h>
14fd20e811SArnaldo Carvalho de Melo #include <inttypes.h>
157aef3bf3SJiri Olsa #include <linux/compiler.h>
166ef81c55SMamatha Inamdar #include <linux/err.h>
177aef3bf3SJiri Olsa #include <linux/kernel.h>
18cbb88500SJiri Olsa #include <linux/stringify.h>
197f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h>
201e181b92SJiri Olsa #include <asm/bug.h>
21391e4206SArnaldo Carvalho de Melo #include <sys/param.h>
227aef3bf3SJiri Olsa #include "debug.h"
237aef3bf3SJiri Olsa #include "builtin.h"
2487ffb6c6SArnaldo Carvalho de Melo #include <perf/cpumap.h>
258520a98dSArnaldo Carvalho de Melo #include <subcmd/pager.h>
267aef3bf3SJiri Olsa #include <subcmd/parse-options.h>
27d3300a3cSArnaldo Carvalho de Melo #include "map_symbol.h"
2839bcd4a4SJiri Olsa #include "mem-events.h"
29903a6f15SJiri Olsa #include "session.h"
30903a6f15SJiri Olsa #include "hist.h"
31cbb88500SJiri Olsa #include "sort.h"
32903a6f15SJiri Olsa #include "tool.h"
3312500902SArnaldo Carvalho de Melo #include "cacheline.h"
34903a6f15SJiri Olsa #include "data.h"
355ab8c689SArnaldo Carvalho de Melo #include "event.h"
362709b97dSJiri Olsa #include "evlist.h"
372709b97dSJiri Olsa #include "evsel.h"
385a1a99cdSJiri Olsa #include "ui/browsers/hists.h"
39e7ff8920SArnaldo Carvalho de Melo #include "thread.h"
407f834c2eSJiri Olsa #include "mem2node.h"
41daecf9e0SArnaldo Carvalho de Melo #include "symbol.h"
428520a98dSArnaldo Carvalho de Melo #include "ui/ui.h"
43171f7474SArnaldo Carvalho de Melo #include "ui/progress.h"
4479e157b0SJin Yao #include "pmus.h"
4579e157b0SJin Yao #include "string2.h"
46ae0f4eb3SWei Li #include "util/util.h"
47f12ad272SIan Rogers
48903a6f15SJiri Olsa struct c2c_hists {
49c75540e3SJiri Olsa struct hists hists;
50c75540e3SJiri Olsa struct perf_hpp_list list;
51c75540e3SJiri Olsa struct c2c_stats stats;
52b2252ae6SJiri Olsa };
53c75540e3SJiri Olsa
54c75540e3SJiri Olsa struct compute_stats {
5592062d54SJiri Olsa struct stats lcl_hitm;
5692062d54SJiri Olsa struct stats rmt_hitm;
5792062d54SJiri Olsa struct stats lcl_peer;
58682352e5SLeo Yan struct stats rmt_peer;
59682352e5SLeo Yan struct stats load;
6092062d54SJiri Olsa };
6192062d54SJiri Olsa
6292062d54SJiri Olsa struct c2c_hist_entry {
6378b27543SJiri Olsa struct c2c_hists *hists;
6478b27543SJiri Olsa struct c2c_stats stats;
65b2252ae6SJiri Olsa unsigned long *cpuset;
661e181b92SJiri Olsa unsigned long *nodeset;
677f834c2eSJiri Olsa struct c2c_stats *node_stats;
681e181b92SJiri Olsa unsigned int cacheline_idx;
69bb342daeSJiri Olsa
7092062d54SJiri Olsa struct compute_stats cstats;
7192062d54SJiri Olsa
7292062d54SJiri Olsa unsigned long paddr;
734c820527SJiri Olsa unsigned long paddr_cnt;
744c820527SJiri Olsa bool paddr_zero;
754c820527SJiri Olsa char *nodestr;
764c820527SJiri Olsa
774c820527SJiri Olsa /*
7878b27543SJiri Olsa * must be at the end,
7978b27543SJiri Olsa * because of its callchain dynamic entry
8078b27543SJiri Olsa */
8178b27543SJiri Olsa struct hist_entry he;
8278b27543SJiri Olsa };
8378b27543SJiri Olsa
8478b27543SJiri Olsa static char const *coalesce_default = "iaddr";
85423701a0SJiri Olsa
86fc9c630eSJiri Olsa struct perf_c2c {
87903a6f15SJiri Olsa struct perf_tool tool;
88903a6f15SJiri Olsa struct c2c_hists hists;
89c75540e3SJiri Olsa struct mem2node mem2node;
907f834c2eSJiri Olsa
911e181b92SJiri Olsa unsigned long **nodes;
921e181b92SJiri Olsa int nodes_cnt;
931e181b92SJiri Olsa int cpus_cnt;
941e181b92SJiri Olsa int *cpu2node;
951e181b92SJiri Olsa int node_info;
961e181b92SJiri Olsa
9789d9ba8fSJiri Olsa bool show_src;
9889d9ba8fSJiri Olsa bool show_all;
99af09b2d3SJiri Olsa bool use_stdio;
1005a1a99cdSJiri Olsa bool stats_only;
10174c63a25SJiri Olsa bool symbol_full;
102590b6a3aSJiri Olsa bool stitch_lbr;
103d80da766SKan Liang
1047ef2efaaSJiri Olsa /* Shared cache line stats */
1051834436eSLeo Yan struct c2c_stats shared_clines_stats;
1061834436eSLeo Yan int shared_clines;
1077ef2efaaSJiri Olsa
10855b95776SJiri Olsa int display;
10955b95776SJiri Olsa
110fc9c630eSJiri Olsa const char *coalesce;
111fc9c630eSJiri Olsa char *cl_sort;
112fc9c630eSJiri Olsa char *cl_resort;
113fc9c630eSJiri Olsa char *cl_output;
114fc9c630eSJiri Olsa };
11555b95776SJiri Olsa
11655b95776SJiri Olsa enum {
11755b95776SJiri Olsa DISPLAY_LCL_HITM,
118c82ccc3aSLeo Yan DISPLAY_RMT_HITM,
119c82ccc3aSLeo Yan DISPLAY_TOT_HITM,
120c82ccc3aSLeo Yan DISPLAY_SNP_PEER,
121f37c5d91SLeo Yan DISPLAY_MAX,
122d940baccSJiri Olsa };
123d940baccSJiri Olsa
124d940baccSJiri Olsa static const char *display_str[DISPLAY_MAX] = {
125d940baccSJiri Olsa [DISPLAY_LCL_HITM] = "Local HITMs",
126faa30dfaSLeo Yan [DISPLAY_RMT_HITM] = "Remote HITMs",
127faa30dfaSLeo Yan [DISPLAY_TOT_HITM] = "Total HITMs",
128faa30dfaSLeo Yan [DISPLAY_SNP_PEER] = "Peer Snoop",
129f37c5d91SLeo Yan };
130903a6f15SJiri Olsa
131903a6f15SJiri Olsa static const struct option c2c_options[] = {
1323a5bfab6SJiri Olsa OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
1333a5bfab6SJiri Olsa OPT_END()
1343a5bfab6SJiri Olsa };
1353a5bfab6SJiri Olsa
1363a5bfab6SJiri Olsa static struct perf_c2c c2c;
137903a6f15SJiri Olsa
c2c_he_zalloc(size_t size)1387aef3bf3SJiri Olsa static void *c2c_he_zalloc(size_t size)
13978b27543SJiri Olsa {
14078b27543SJiri Olsa struct c2c_hist_entry *c2c_he;
14178b27543SJiri Olsa
14278b27543SJiri Olsa c2c_he = zalloc(size + sizeof(*c2c_he));
14378b27543SJiri Olsa if (!c2c_he)
14478b27543SJiri Olsa return NULL;
14578b27543SJiri Olsa
14678b27543SJiri Olsa c2c_he->cpuset = bitmap_zalloc(c2c.cpus_cnt);
1477fc5b571SAndy Shevchenko if (!c2c_he->cpuset)
1481e181b92SJiri Olsa goto out_free;
1494efa8e31SShang XiaoJing
1501e181b92SJiri Olsa c2c_he->nodeset = bitmap_zalloc(c2c.nodes_cnt);
1517fc5b571SAndy Shevchenko if (!c2c_he->nodeset)
1527f834c2eSJiri Olsa goto out_free;
1534efa8e31SShang XiaoJing
1547f834c2eSJiri Olsa c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
1551e181b92SJiri Olsa if (!c2c_he->node_stats)
1561e181b92SJiri Olsa goto out_free;
1574efa8e31SShang XiaoJing
1581e181b92SJiri Olsa init_stats(&c2c_he->cstats.lcl_hitm);
15992062d54SJiri Olsa init_stats(&c2c_he->cstats.rmt_hitm);
16092062d54SJiri Olsa init_stats(&c2c_he->cstats.lcl_peer);
161682352e5SLeo Yan init_stats(&c2c_he->cstats.rmt_peer);
162682352e5SLeo Yan init_stats(&c2c_he->cstats.load);
16392062d54SJiri Olsa
16492062d54SJiri Olsa return &c2c_he->he;
16578b27543SJiri Olsa
1664efa8e31SShang XiaoJing out_free:
1674efa8e31SShang XiaoJing zfree(&c2c_he->nodeset);
168*190de754SArnaldo Carvalho de Melo zfree(&c2c_he->cpuset);
169*190de754SArnaldo Carvalho de Melo free(c2c_he);
1704efa8e31SShang XiaoJing return NULL;
1714efa8e31SShang XiaoJing }
17278b27543SJiri Olsa
c2c_he_free(void * he)17378b27543SJiri Olsa static void c2c_he_free(void *he)
17478b27543SJiri Olsa {
17578b27543SJiri Olsa struct c2c_hist_entry *c2c_he;
17678b27543SJiri Olsa
17778b27543SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
17878b27543SJiri Olsa if (c2c_he->hists) {
17978b27543SJiri Olsa hists__delete_entries(&c2c_he->hists->hists);
18078b27543SJiri Olsa zfree(&c2c_he->hists);
181*190de754SArnaldo Carvalho de Melo }
18278b27543SJiri Olsa
18378b27543SJiri Olsa zfree(&c2c_he->cpuset);
184*190de754SArnaldo Carvalho de Melo zfree(&c2c_he->nodeset);
185*190de754SArnaldo Carvalho de Melo zfree(&c2c_he->nodestr);
186*190de754SArnaldo Carvalho de Melo zfree(&c2c_he->node_stats);
187*190de754SArnaldo Carvalho de Melo free(c2c_he);
18878b27543SJiri Olsa }
18978b27543SJiri Olsa
19078b27543SJiri Olsa static struct hist_entry_ops c2c_entry_ops = {
19178b27543SJiri Olsa .new = c2c_he_zalloc,
19278b27543SJiri Olsa .free = c2c_he_free,
19378b27543SJiri Olsa };
19478b27543SJiri Olsa
19578b27543SJiri Olsa static int c2c_hists__init(struct c2c_hists *hists,
196ec06f9b9SJiri Olsa const char *sort,
1971d62fcd6SJiri Olsa int nr_header_lines);
1981d62fcd6SJiri Olsa
199ec06f9b9SJiri Olsa static struct c2c_hists*
he__get_c2c_hists(struct hist_entry * he,const char * sort,int nr_header_lines)200b2252ae6SJiri Olsa he__get_c2c_hists(struct hist_entry *he,
201b2252ae6SJiri Olsa const char *sort,
2021d62fcd6SJiri Olsa int nr_header_lines)
2031d62fcd6SJiri Olsa {
204ec06f9b9SJiri Olsa struct c2c_hist_entry *c2c_he;
205ec06f9b9SJiri Olsa struct c2c_hists *hists;
206ec06f9b9SJiri Olsa int ret;
207ec06f9b9SJiri Olsa
208ec06f9b9SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
209ec06f9b9SJiri Olsa if (c2c_he->hists)
210ec06f9b9SJiri Olsa return c2c_he->hists;
211b2252ae6SJiri Olsa
212ec06f9b9SJiri Olsa hists = c2c_he->hists = zalloc(sizeof(*hists));
213ec06f9b9SJiri Olsa if (!hists)
214ec06f9b9SJiri Olsa return NULL;
215ec06f9b9SJiri Olsa
216ec06f9b9SJiri Olsa ret = c2c_hists__init(hists, sort, nr_header_lines);
2171d62fcd6SJiri Olsa if (ret) {
218ec06f9b9SJiri Olsa free(hists);
219ec06f9b9SJiri Olsa return NULL;
220ec06f9b9SJiri Olsa }
221ec06f9b9SJiri Olsa
222ec06f9b9SJiri Olsa return hists;
223b2252ae6SJiri Olsa }
224ec06f9b9SJiri Olsa
c2c_he__set_cpu(struct c2c_hist_entry * c2c_he,struct perf_sample * sample)225ec06f9b9SJiri Olsa static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
2261e181b92SJiri Olsa struct perf_sample *sample)
2271e181b92SJiri Olsa {
2281e181b92SJiri Olsa if (WARN_ONCE(sample->cpu == (unsigned int) -1,
2291e181b92SJiri Olsa "WARNING: no sample cpu value"))
2301e181b92SJiri Olsa return;
2311e181b92SJiri Olsa
2321e181b92SJiri Olsa __set_bit(sample->cpu, c2c_he->cpuset);
23375d7ba32SSean Christopherson }
2341e181b92SJiri Olsa
c2c_he__set_node(struct c2c_hist_entry * c2c_he,struct perf_sample * sample)2351e181b92SJiri Olsa static void c2c_he__set_node(struct c2c_hist_entry *c2c_he,
2367f834c2eSJiri Olsa struct perf_sample *sample)
2377f834c2eSJiri Olsa {
2387f834c2eSJiri Olsa int node;
2397f834c2eSJiri Olsa
2407f834c2eSJiri Olsa if (!sample->phys_addr) {
2417f834c2eSJiri Olsa c2c_he->paddr_zero = true;
2427f834c2eSJiri Olsa return;
2437f834c2eSJiri Olsa }
2447f834c2eSJiri Olsa
2457f834c2eSJiri Olsa node = mem2node__node(&c2c.mem2node, sample->phys_addr);
2467f834c2eSJiri Olsa if (WARN_ONCE(node < 0, "WARNING: failed to find node\n"))
2477f834c2eSJiri Olsa return;
2487f834c2eSJiri Olsa
2497f834c2eSJiri Olsa __set_bit(node, c2c_he->nodeset);
25075d7ba32SSean Christopherson
2517f834c2eSJiri Olsa if (c2c_he->paddr != sample->phys_addr) {
2527f834c2eSJiri Olsa c2c_he->paddr_cnt++;
2537f834c2eSJiri Olsa c2c_he->paddr = sample->phys_addr;
2547f834c2eSJiri Olsa }
2557f834c2eSJiri Olsa }
2567f834c2eSJiri Olsa
compute_stats(struct c2c_hist_entry * c2c_he,struct c2c_stats * stats,u64 weight)2577f834c2eSJiri Olsa static void compute_stats(struct c2c_hist_entry *c2c_he,
25892062d54SJiri Olsa struct c2c_stats *stats,
25992062d54SJiri Olsa u64 weight)
26092062d54SJiri Olsa {
26192062d54SJiri Olsa struct compute_stats *cstats = &c2c_he->cstats;
26292062d54SJiri Olsa
26392062d54SJiri Olsa if (stats->rmt_hitm)
26492062d54SJiri Olsa update_stats(&cstats->rmt_hitm, weight);
26592062d54SJiri Olsa else if (stats->lcl_hitm)
26692062d54SJiri Olsa update_stats(&cstats->lcl_hitm, weight);
26792062d54SJiri Olsa else if (stats->rmt_peer)
268682352e5SLeo Yan update_stats(&cstats->rmt_peer, weight);
269682352e5SLeo Yan else if (stats->lcl_peer)
270682352e5SLeo Yan update_stats(&cstats->lcl_peer, weight);
271682352e5SLeo Yan else if (stats->load)
27292062d54SJiri Olsa update_stats(&cstats->load, weight);
27392062d54SJiri Olsa }
27492062d54SJiri Olsa
process_sample_event(struct perf_tool * tool __maybe_unused,union perf_event * event,struct perf_sample * sample,struct evsel * evsel,struct machine * machine)27592062d54SJiri Olsa static int process_sample_event(struct perf_tool *tool __maybe_unused,
27678b27543SJiri Olsa union perf_event *event,
27778b27543SJiri Olsa struct perf_sample *sample,
27878b27543SJiri Olsa struct evsel *evsel,
27932dcd021SJiri Olsa struct machine *machine)
28078b27543SJiri Olsa {
28178b27543SJiri Olsa struct c2c_hists *c2c_hists = &c2c.hists;
282b2252ae6SJiri Olsa struct c2c_hist_entry *c2c_he;
283b2252ae6SJiri Olsa struct c2c_stats stats = { .nr_entries = 0, };
284b2252ae6SJiri Olsa struct hist_entry *he;
28578b27543SJiri Olsa struct addr_location al;
28678b27543SJiri Olsa struct mem_info *mi, *mi_dup;
287ec06f9b9SJiri Olsa struct callchain_cursor *cursor;
28878b27543SJiri Olsa int ret;
28978b27543SJiri Olsa
29078b27543SJiri Olsa addr_location__init(&al);
29178b27543SJiri Olsa if (machine__resolve(machine, &al, sample) < 0) {
29278b27543SJiri Olsa pr_debug("problem processing %d event, skipping it.\n",
29378b27543SJiri Olsa event->header.type);
29478b27543SJiri Olsa ret = -1;
29578b27543SJiri Olsa goto out;
296d80da766SKan Liang }
297d80da766SKan Liang
298d80da766SKan Liang if (c2c.stitch_lbr)
299dd805768SJiri Olsa thread__set_lbr_stitch_enable(al.thread, true);
300dd805768SJiri Olsa
301dd805768SJiri Olsa cursor = get_tls_callchain_cursor();
302dd805768SJiri Olsa ret = sample__resolve_callchain(sample, cursor, NULL,
303dd805768SJiri Olsa evsel, &al, sysctl_perf_event_max_stack);
30478b27543SJiri Olsa if (ret)
30578b27543SJiri Olsa goto out;
30678b27543SJiri Olsa
30778b27543SJiri Olsa mi = sample__resolve_mem(sample, &al);
3085cedb413SJiri Olsa if (mi == NULL) {
3095cedb413SJiri Olsa ret = -ENOMEM;
3105cedb413SJiri Olsa goto out;
3115cedb413SJiri Olsa }
3125cedb413SJiri Olsa
3135cedb413SJiri Olsa /*
314ec06f9b9SJiri Olsa * The mi object is released in hists__add_entry_ops,
315b2252ae6SJiri Olsa * if it gets sorted out into existing data, so we need
316b2252ae6SJiri Olsa * to take the copy now.
317b2252ae6SJiri Olsa */
318ebf39d29SLeo Yan mi_dup = mem_info__get(mi);
31978b27543SJiri Olsa
320ec06f9b9SJiri Olsa c2c_decode_stats(&stats, mi);
3215cedb413SJiri Olsa
32278b27543SJiri Olsa he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
323b2252ae6SJiri Olsa &al, NULL, NULL, mi, NULL,
324b2252ae6SJiri Olsa sample, true);
325b2252ae6SJiri Olsa if (he == NULL)
326b2252ae6SJiri Olsa goto free_mi;
3271e181b92SJiri Olsa
3287f834c2eSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
3291e181b92SJiri Olsa c2c_add_stats(&c2c_he->stats, &stats);
330b2252ae6SJiri Olsa c2c_add_stats(&c2c_hists->stats, &stats);
33178b27543SJiri Olsa
33278b27543SJiri Olsa c2c_he__set_cpu(c2c_he, sample);
333ec06f9b9SJiri Olsa c2c_he__set_node(c2c_he, sample);
3341e181b92SJiri Olsa
3351e181b92SJiri Olsa hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
3361e181b92SJiri Olsa ret = hist_entry__append_callchain(he, sample);
3371e181b92SJiri Olsa
3381e181b92SJiri Olsa if (!ret) {
3391e181b92SJiri Olsa /*
3401e181b92SJiri Olsa * There's already been warning about missing
3411e181b92SJiri Olsa * sample's cpu value. Let's account all to
3421e181b92SJiri Olsa * node 0 in this case, without any further
3431e181b92SJiri Olsa * warning.
3441e181b92SJiri Olsa *
345ec06f9b9SJiri Olsa * Doing node stats only for single callchain data.
346ec06f9b9SJiri Olsa */
347fc9c630eSJiri Olsa int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu;
348b2252ae6SJiri Olsa int node = c2c.cpu2node[cpu];
3495cedb413SJiri Olsa
350ec06f9b9SJiri Olsa mi = mi_dup;
351b2252ae6SJiri Olsa
352ebf39d29SLeo Yan c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
353ec06f9b9SJiri Olsa if (!c2c_hists)
354ec06f9b9SJiri Olsa goto free_mi;
3555cedb413SJiri Olsa
356ec06f9b9SJiri Olsa he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
357b2252ae6SJiri Olsa &al, NULL, NULL, mi, NULL,
358b2252ae6SJiri Olsa sample, true);
359b2252ae6SJiri Olsa if (he == NULL)
3601e181b92SJiri Olsa goto free_mi;
3611e181b92SJiri Olsa
36292062d54SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
36392062d54SJiri Olsa c2c_add_stats(&c2c_he->stats, &stats);
3641e181b92SJiri Olsa c2c_add_stats(&c2c_hists->stats, &stats);
3657f834c2eSJiri Olsa c2c_add_stats(&c2c_he->node_stats[node], &stats);
366b2252ae6SJiri Olsa
367b2252ae6SJiri Olsa compute_stats(c2c_he, &stats, sample->weight);
368ec06f9b9SJiri Olsa
369ec06f9b9SJiri Olsa c2c_he__set_cpu(c2c_he, sample);
370ec06f9b9SJiri Olsa c2c_he__set_node(c2c_he, sample);
371ec06f9b9SJiri Olsa
37278b27543SJiri Olsa hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
37378b27543SJiri Olsa ret = hist_entry__append_callchain(he, sample);
374ec06f9b9SJiri Olsa }
375ec06f9b9SJiri Olsa
3765cedb413SJiri Olsa out:
3775cedb413SJiri Olsa addr_location__exit(&al);
378ec06f9b9SJiri Olsa return ret;
379ec06f9b9SJiri Olsa
38078b27543SJiri Olsa free_mi:
38178b27543SJiri Olsa mem_info__put(mi_dup);
38278b27543SJiri Olsa mem_info__put(mi);
38378b27543SJiri Olsa ret = -ENOMEM;
38478b27543SJiri Olsa goto out;
38578b27543SJiri Olsa }
38678b27543SJiri Olsa
38778b27543SJiri Olsa static struct perf_c2c c2c = {
38878b27543SJiri Olsa .tool = {
38978b27543SJiri Olsa .sample = process_sample_event,
39078b27543SJiri Olsa .mmap = perf_event__process_mmap,
391c825f788SLeo Yan .mmap2 = perf_event__process_mmap2,
392c825f788SLeo Yan .comm = perf_event__process_comm,
393c825f788SLeo Yan .exit = perf_event__process_exit,
394c825f788SLeo Yan .fork = perf_event__process_fork,
39578b27543SJiri Olsa .lost = perf_event__process_lost,
39678b27543SJiri Olsa .attr = perf_event__process_attr,
39778b27543SJiri Olsa .auxtrace_info = perf_event__process_auxtrace_info,
39878b27543SJiri Olsa .auxtrace = perf_event__process_auxtrace,
39978b27543SJiri Olsa .auxtrace_error = perf_event__process_auxtrace_error,
4007aef3bf3SJiri Olsa .ordered_events = true,
401903a6f15SJiri Olsa .ordering_requires_timestamps = true,
4027aef3bf3SJiri Olsa },
4037aef3bf3SJiri Olsa };
4047aef3bf3SJiri Olsa
405903a6f15SJiri Olsa static const char * const c2c_usage[] = {
406903a6f15SJiri Olsa "perf c2c {record|report}",
407903a6f15SJiri Olsa NULL
408903a6f15SJiri Olsa };
409903a6f15SJiri Olsa
410903a6f15SJiri Olsa static const char * const __usage_report[] = {
411903a6f15SJiri Olsa "perf c2c report",
412c75540e3SJiri Olsa NULL
413c75540e3SJiri Olsa };
414c75540e3SJiri Olsa
415c75540e3SJiri Olsa static const char * const *report_c2c_usage = __usage_report;
416c75540e3SJiri Olsa
417c75540e3SJiri Olsa #define C2C_HEADER_MAX 2
418c75540e3SJiri Olsa
419c75540e3SJiri Olsa struct c2c_header {
420c75540e3SJiri Olsa struct {
421c75540e3SJiri Olsa const char *text;
422c75540e3SJiri Olsa int span;
423c75540e3SJiri Olsa } line[C2C_HEADER_MAX];
424c75540e3SJiri Olsa };
4258d3f938dSJiri Olsa
426c75540e3SJiri Olsa struct c2c_dimension {
427c75540e3SJiri Olsa struct c2c_header header;
428c75540e3SJiri Olsa const char *name;
429c75540e3SJiri Olsa int width;
430c75540e3SJiri Olsa struct sort_entry *se;
431c75540e3SJiri Olsa
432c75540e3SJiri Olsa int64_t (*cmp)(struct perf_hpp_fmt *fmt,
433c75540e3SJiri Olsa struct hist_entry *, struct hist_entry *);
434c75540e3SJiri Olsa int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
435c75540e3SJiri Olsa struct hist_entry *he);
436c75540e3SJiri Olsa int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
437c75540e3SJiri Olsa struct hist_entry *he);
438c75540e3SJiri Olsa };
439c75540e3SJiri Olsa
440590b6a3aSJiri Olsa struct c2c_fmt {
441590b6a3aSJiri Olsa struct perf_hpp_fmt fmt;
442590b6a3aSJiri Olsa struct c2c_dimension *dim;
443590b6a3aSJiri Olsa };
444590b6a3aSJiri Olsa
445590b6a3aSJiri Olsa #define SYMBOL_WIDTH 30
446590b6a3aSJiri Olsa
447590b6a3aSJiri Olsa static struct c2c_dimension dim_symbol;
448590b6a3aSJiri Olsa static struct c2c_dimension dim_srcline;
449590b6a3aSJiri Olsa
symbol_width(struct hists * hists,struct sort_entry * se)450590b6a3aSJiri Olsa static int symbol_width(struct hists *hists, struct sort_entry *se)
451590b6a3aSJiri Olsa {
452590b6a3aSJiri Olsa int width = hists__col_len(hists, se->se_width_idx);
453590b6a3aSJiri Olsa
454590b6a3aSJiri Olsa if (!c2c.symbol_full)
455c75540e3SJiri Olsa width = MIN(width, SYMBOL_WIDTH);
456c75540e3SJiri Olsa
4577e6a7998SArnaldo Carvalho de Melo return width;
458c75540e3SJiri Olsa }
459c75540e3SJiri Olsa
c2c_width(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp __maybe_unused,struct hists * hists)460c75540e3SJiri Olsa static int c2c_width(struct perf_hpp_fmt *fmt,
461c75540e3SJiri Olsa struct perf_hpp *hpp __maybe_unused,
462c75540e3SJiri Olsa struct hists *hists)
463c75540e3SJiri Olsa {
464c75540e3SJiri Olsa struct c2c_fmt *c2c_fmt;
465590b6a3aSJiri Olsa struct c2c_dimension *dim;
466590b6a3aSJiri Olsa
467590b6a3aSJiri Olsa c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
4688d3f938dSJiri Olsa dim = c2c_fmt->dim;
4698d3f938dSJiri Olsa
4708d3f938dSJiri Olsa if (dim == &dim_symbol || dim == &dim_srcline)
4718d3f938dSJiri Olsa return symbol_width(hists, dim->se);
4728d3f938dSJiri Olsa
4738d3f938dSJiri Olsa return dim->se ? hists__col_len(hists, dim->se->se_width_idx) :
4748d3f938dSJiri Olsa c2c_fmt->dim->width;
4758d3f938dSJiri Olsa }
4768d3f938dSJiri Olsa
c2c_header(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hists * hists,int line,int * span)4778d3f938dSJiri Olsa static int c2c_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
4788d3f938dSJiri Olsa struct hists *hists, int line, int *span)
4798d3f938dSJiri Olsa {
4808d3f938dSJiri Olsa struct perf_hpp_list *hpp_list = hists->hpp_list;
4818d3f938dSJiri Olsa struct c2c_fmt *c2c_fmt;
4828d3f938dSJiri Olsa struct c2c_dimension *dim;
4838d3f938dSJiri Olsa const char *text = NULL;
4848d3f938dSJiri Olsa int width = c2c_width(fmt, hpp, hists);
485c75540e3SJiri Olsa
4868d3f938dSJiri Olsa c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
4878d3f938dSJiri Olsa dim = c2c_fmt->dim;
4888d3f938dSJiri Olsa
4898d3f938dSJiri Olsa if (dim->se) {
4908d3f938dSJiri Olsa text = dim->header.line[line].text;
491c75540e3SJiri Olsa /* Use the last line from sort_entry if not defined. */
492c75540e3SJiri Olsa if (!text && (line == hpp_list->nr_header_lines - 1))
493c75540e3SJiri Olsa text = dim->se->se_header;
494c75540e3SJiri Olsa } else {
495c75540e3SJiri Olsa text = dim->header.line[line].text;
496c75540e3SJiri Olsa
497c75540e3SJiri Olsa if (*span) {
4988d3f938dSJiri Olsa (*span)--;
499c75540e3SJiri Olsa return 0;
5008d3f938dSJiri Olsa } else {
5018d3f938dSJiri Olsa *span = dim->header.line[line].span;
5028d3f938dSJiri Olsa }
5038d3f938dSJiri Olsa }
504c75540e3SJiri Olsa
505c75540e3SJiri Olsa if (text == NULL)
506cbb88500SJiri Olsa text = "";
507cbb88500SJiri Olsa
508cbb88500SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, text);
509cbb88500SJiri Olsa }
510cbb88500SJiri Olsa
511cbb88500SJiri Olsa #define HEX_STR(__s, __v) \
512cbb88500SJiri Olsa ({ \
513cbb88500SJiri Olsa scnprintf(__s, sizeof(__s), "0x%" PRIx64, __v); \
514cbb88500SJiri Olsa __s; \
515cbb88500SJiri Olsa })
516cbb88500SJiri Olsa
517cbb88500SJiri Olsa static int64_t
dcacheline_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)518cbb88500SJiri Olsa dcacheline_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
519cbb88500SJiri Olsa struct hist_entry *left, struct hist_entry *right)
520cbb88500SJiri Olsa {
521cbb88500SJiri Olsa return sort__dcacheline_cmp(left, right);
522cbb88500SJiri Olsa }
523cbb88500SJiri Olsa
dcacheline_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)524cbb88500SJiri Olsa static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
525cbb88500SJiri Olsa struct hist_entry *he)
526cbb88500SJiri Olsa {
5271470a108SFeng Tang uint64_t addr = 0;
528cbb88500SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
529cbb88500SJiri Olsa char buf[20];
530cbb88500SJiri Olsa
531cbb88500SJiri Olsa if (he->mem_info)
5327f834c2eSJiri Olsa addr = cl_address(he->mem_info->daddr.addr, chk_double_cl);
5337f834c2eSJiri Olsa
5347f834c2eSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
5357f834c2eSJiri Olsa }
5367f834c2eSJiri Olsa
5377f834c2eSJiri Olsa static int
dcacheline_node_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)5387f834c2eSJiri Olsa dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
5397f834c2eSJiri Olsa struct hist_entry *he)
5407f834c2eSJiri Olsa {
5417f834c2eSJiri Olsa struct c2c_hist_entry *c2c_he;
5427f834c2eSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
5437f834c2eSJiri Olsa
5447f834c2eSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
5457f834c2eSJiri Olsa if (WARN_ON_ONCE(!c2c_he->nodestr))
54603d9fcb7SJiri Olsa return 0;
54703d9fcb7SJiri Olsa
54803d9fcb7SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, c2c_he->nodestr);
54903d9fcb7SJiri Olsa }
55003d9fcb7SJiri Olsa
55103d9fcb7SJiri Olsa static int
dcacheline_node_count(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)55203d9fcb7SJiri Olsa dcacheline_node_count(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
55303d9fcb7SJiri Olsa struct hist_entry *he)
55403d9fcb7SJiri Olsa {
55503d9fcb7SJiri Olsa struct c2c_hist_entry *c2c_he;
55603d9fcb7SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
55748acdebdSJiri Olsa
55848acdebdSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
55948acdebdSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*lu", width, c2c_he->paddr_cnt);
56048acdebdSJiri Olsa }
56148acdebdSJiri Olsa
offset_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)56248acdebdSJiri Olsa static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
56348acdebdSJiri Olsa struct hist_entry *he)
56448acdebdSJiri Olsa {
5651470a108SFeng Tang uint64_t addr = 0;
56648acdebdSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
56748acdebdSJiri Olsa char buf[20];
56848acdebdSJiri Olsa
56948acdebdSJiri Olsa if (he->mem_info)
57048acdebdSJiri Olsa addr = cl_offset(he->mem_info->daddr.al_addr, chk_double_cl);
57148acdebdSJiri Olsa
57248acdebdSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
57348acdebdSJiri Olsa }
57448acdebdSJiri Olsa
57548acdebdSJiri Olsa static int64_t
offset_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)57648acdebdSJiri Olsa offset_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
5771470a108SFeng Tang struct hist_entry *left, struct hist_entry *right)
5781470a108SFeng Tang {
57948acdebdSJiri Olsa uint64_t l = 0, r = 0;
5801470a108SFeng Tang
58148acdebdSJiri Olsa if (left->mem_info)
58248acdebdSJiri Olsa l = cl_offset(left->mem_info->daddr.addr, chk_double_cl);
58348acdebdSJiri Olsa
58448acdebdSJiri Olsa if (right->mem_info)
58543575a95SJiri Olsa r = cl_offset(right->mem_info->daddr.addr, chk_double_cl);
58643575a95SJiri Olsa
58743575a95SJiri Olsa return (int64_t)(r - l);
58843575a95SJiri Olsa }
58943575a95SJiri Olsa
59043575a95SJiri Olsa static int
iaddr_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)59143575a95SJiri Olsa iaddr_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
59243575a95SJiri Olsa struct hist_entry *he)
59343575a95SJiri Olsa {
59443575a95SJiri Olsa uint64_t addr = 0;
59543575a95SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
59643575a95SJiri Olsa char buf[20];
59743575a95SJiri Olsa
59843575a95SJiri Olsa if (he->mem_info)
59943575a95SJiri Olsa addr = he->mem_info->iaddr.addr;
60043575a95SJiri Olsa
60143575a95SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
60243575a95SJiri Olsa }
60343575a95SJiri Olsa
60443575a95SJiri Olsa static int64_t
iaddr_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)60543575a95SJiri Olsa iaddr_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
60697cb486eSJiri Olsa struct hist_entry *left, struct hist_entry *right)
60797cb486eSJiri Olsa {
60897cb486eSJiri Olsa return sort__iaddr_cmp(left, right);
60997cb486eSJiri Olsa }
61097cb486eSJiri Olsa
61197cb486eSJiri Olsa static int
tot_hitm_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)61297cb486eSJiri Olsa tot_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
61397cb486eSJiri Olsa struct hist_entry *he)
61497cb486eSJiri Olsa {
61597cb486eSJiri Olsa struct c2c_hist_entry *c2c_he;
61697cb486eSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
61797cb486eSJiri Olsa unsigned int tot_hitm;
61897cb486eSJiri Olsa
61997cb486eSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
62097cb486eSJiri Olsa tot_hitm = c2c_he->stats.lcl_hitm + c2c_he->stats.rmt_hitm;
62197cb486eSJiri Olsa
62297cb486eSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*u", width, tot_hitm);
62397cb486eSJiri Olsa }
62497cb486eSJiri Olsa
62597cb486eSJiri Olsa static int64_t
tot_hitm_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)626c1c8013eSAndres Freund tot_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
627c1c8013eSAndres Freund struct hist_entry *left, struct hist_entry *right)
62897cb486eSJiri Olsa {
62997cb486eSJiri Olsa struct c2c_hist_entry *c2c_left;
63097cb486eSJiri Olsa struct c2c_hist_entry *c2c_right;
63197cb486eSJiri Olsa uint64_t tot_hitm_left;
63297cb486eSJiri Olsa uint64_t tot_hitm_right;
63397cb486eSJiri Olsa
63497cb486eSJiri Olsa c2c_left = container_of(left, struct c2c_hist_entry, he);
63597cb486eSJiri Olsa c2c_right = container_of(right, struct c2c_hist_entry, he);
63697cb486eSJiri Olsa
63797cb486eSJiri Olsa tot_hitm_left = c2c_left->stats.lcl_hitm + c2c_left->stats.rmt_hitm;
63897cb486eSJiri Olsa tot_hitm_right = c2c_right->stats.lcl_hitm + c2c_right->stats.rmt_hitm;
63997cb486eSJiri Olsa
64097cb486eSJiri Olsa return tot_hitm_left - tot_hitm_right;
64197cb486eSJiri Olsa }
64297cb486eSJiri Olsa
64397cb486eSJiri Olsa #define STAT_FN_ENTRY(__f) \
64497cb486eSJiri Olsa static int \
64597cb486eSJiri Olsa __f ## _entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, \
64697cb486eSJiri Olsa struct hist_entry *he) \
64797cb486eSJiri Olsa { \
64897cb486eSJiri Olsa struct c2c_hist_entry *c2c_he; \
64997cb486eSJiri Olsa int width = c2c_width(fmt, hpp, he->hists); \
65097cb486eSJiri Olsa \
65197cb486eSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he); \
65297cb486eSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*u", width, \
65397cb486eSJiri Olsa c2c_he->stats.__f); \
65497cb486eSJiri Olsa }
65597cb486eSJiri Olsa
65697cb486eSJiri Olsa #define STAT_FN_CMP(__f) \
65797cb486eSJiri Olsa static int64_t \
65897cb486eSJiri Olsa __f ## _cmp(struct perf_hpp_fmt *fmt __maybe_unused, \
65997cb486eSJiri Olsa struct hist_entry *left, struct hist_entry *right) \
660c1c8013eSAndres Freund { \
661c1c8013eSAndres Freund struct c2c_hist_entry *c2c_left, *c2c_right; \
66297cb486eSJiri Olsa \
66397cb486eSJiri Olsa c2c_left = container_of(left, struct c2c_hist_entry, he); \
66497cb486eSJiri Olsa c2c_right = container_of(right, struct c2c_hist_entry, he); \
66597cb486eSJiri Olsa return (uint64_t) c2c_left->stats.__f - \
66697cb486eSJiri Olsa (uint64_t) c2c_right->stats.__f; \
66797cb486eSJiri Olsa }
66897cb486eSJiri Olsa
66997cb486eSJiri Olsa #define STAT_FN(__f) \
67063e74ab5SLeo Yan STAT_FN_ENTRY(__f) \
67163e74ab5SLeo Yan STAT_FN_CMP(__f)
67263e74ab5SLeo Yan
6730f18896dSJiri Olsa STAT_FN(rmt_hitm)
STAT_FN(lcl_hitm)6740f18896dSJiri Olsa STAT_FN(lcl_hitm)
6750f18896dSJiri Olsa STAT_FN(rmt_peer)
676550b4d6fSLeo Yan STAT_FN(lcl_peer)
6771295f685SJiri Olsa STAT_FN(tot_peer)
6781295f685SJiri Olsa STAT_FN(store)
6791295f685SJiri Olsa STAT_FN(st_l1hit)
6804d08910cSJiri Olsa STAT_FN(st_l1miss)
6814d08910cSJiri Olsa STAT_FN(st_na)
68297cb486eSJiri Olsa STAT_FN(ld_fbhit)
683cf874a01SShang XiaoJing STAT_FN(ld_l1hit)
68401b84d76SJiri Olsa STAT_FN(ld_l2hit)
685cf874a01SShang XiaoJing STAT_FN(ld_llchit)
68601b84d76SJiri Olsa STAT_FN(rmt_hit)
68701b84d76SJiri Olsa
68801b84d76SJiri Olsa static uint64_t get_load_llc_misses(struct c2c_stats *stats)
689cf874a01SShang XiaoJing {
69001b84d76SJiri Olsa return stats->lcl_dram +
691cf874a01SShang XiaoJing stats->rmt_dram +
692cf874a01SShang XiaoJing stats->rmt_hitm +
693cf874a01SShang XiaoJing stats->rmt_hit;
69401b84d76SJiri Olsa }
69501b84d76SJiri Olsa
get_load_cache_hits(struct c2c_stats * stats)69601b84d76SJiri Olsa static uint64_t get_load_cache_hits(struct c2c_stats *stats)
69701b84d76SJiri Olsa {
698cf874a01SShang XiaoJing return stats->ld_fbhit +
69901b84d76SJiri Olsa stats->ld_l1hit +
700cf874a01SShang XiaoJing stats->ld_l2hit +
701cf874a01SShang XiaoJing stats->ld_llchit +
702cf874a01SShang XiaoJing stats->lcl_hitm;
703550b4d6fSLeo Yan }
704550b4d6fSLeo Yan
get_stores(struct c2c_stats * stats)705cf874a01SShang XiaoJing static uint64_t get_stores(struct c2c_stats *stats)
70601b84d76SJiri Olsa {
707cf874a01SShang XiaoJing return stats->st_l1hit +
708cf874a01SShang XiaoJing stats->st_l1miss +
709cf874a01SShang XiaoJing stats->st_na;
710cf874a01SShang XiaoJing }
711cf874a01SShang XiaoJing
total_records(struct c2c_stats * stats)71201b84d76SJiri Olsa static uint64_t total_records(struct c2c_stats *stats)
71301b84d76SJiri Olsa {
71401b84d76SJiri Olsa return get_load_llc_misses(stats) +
71501b84d76SJiri Olsa get_load_cache_hits(stats) +
71601b84d76SJiri Olsa get_stores(stats);
71701b84d76SJiri Olsa }
71801b84d76SJiri Olsa
71901b84d76SJiri Olsa static int
tot_recs_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)72001b84d76SJiri Olsa tot_recs_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
72101b84d76SJiri Olsa struct hist_entry *he)
72201b84d76SJiri Olsa {
72301b84d76SJiri Olsa struct c2c_hist_entry *c2c_he;
72401b84d76SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
72501b84d76SJiri Olsa uint64_t tot_recs;
72601b84d76SJiri Olsa
72701b84d76SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
72801b84d76SJiri Olsa tot_recs = total_records(&c2c_he->stats);
72901b84d76SJiri Olsa
73001b84d76SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs);
73101b84d76SJiri Olsa }
73201b84d76SJiri Olsa
73301b84d76SJiri Olsa static int64_t
tot_recs_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)73401b84d76SJiri Olsa tot_recs_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
73501b84d76SJiri Olsa struct hist_entry *left, struct hist_entry *right)
73601b84d76SJiri Olsa {
73701b84d76SJiri Olsa struct c2c_hist_entry *c2c_left;
73801b84d76SJiri Olsa struct c2c_hist_entry *c2c_right;
73901b84d76SJiri Olsa uint64_t tot_recs_left;
74001b84d76SJiri Olsa uint64_t tot_recs_right;
74101b84d76SJiri Olsa
74201b84d76SJiri Olsa c2c_left = container_of(left, struct c2c_hist_entry, he);
74301b84d76SJiri Olsa c2c_right = container_of(right, struct c2c_hist_entry, he);
74401b84d76SJiri Olsa
74501b84d76SJiri Olsa tot_recs_left = total_records(&c2c_left->stats);
74655177c4eSJiri Olsa tot_recs_right = total_records(&c2c_right->stats);
74755177c4eSJiri Olsa
748cf874a01SShang XiaoJing return tot_recs_left - tot_recs_right;
749cf874a01SShang XiaoJing }
75055177c4eSJiri Olsa
total_loads(struct c2c_stats * stats)75155177c4eSJiri Olsa static uint64_t total_loads(struct c2c_stats *stats)
75255177c4eSJiri Olsa {
75355177c4eSJiri Olsa return get_load_llc_misses(stats) +
75455177c4eSJiri Olsa get_load_cache_hits(stats);
75555177c4eSJiri Olsa }
75655177c4eSJiri Olsa
75755177c4eSJiri Olsa static int
tot_loads_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)75855177c4eSJiri Olsa tot_loads_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
75955177c4eSJiri Olsa struct hist_entry *he)
76055177c4eSJiri Olsa {
76155177c4eSJiri Olsa struct c2c_hist_entry *c2c_he;
76255177c4eSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
76355177c4eSJiri Olsa uint64_t tot_recs;
76455177c4eSJiri Olsa
76555177c4eSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
76655177c4eSJiri Olsa tot_recs = total_loads(&c2c_he->stats);
76755177c4eSJiri Olsa
76855177c4eSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs);
76955177c4eSJiri Olsa }
77055177c4eSJiri Olsa
77155177c4eSJiri Olsa static int64_t
tot_loads_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)77255177c4eSJiri Olsa tot_loads_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
77355177c4eSJiri Olsa struct hist_entry *left, struct hist_entry *right)
77455177c4eSJiri Olsa {
77555177c4eSJiri Olsa struct c2c_hist_entry *c2c_left;
77655177c4eSJiri Olsa struct c2c_hist_entry *c2c_right;
77755177c4eSJiri Olsa uint64_t tot_recs_left;
77855177c4eSJiri Olsa uint64_t tot_recs_right;
77955177c4eSJiri Olsa
78055177c4eSJiri Olsa c2c_left = container_of(left, struct c2c_hist_entry, he);
78155177c4eSJiri Olsa c2c_right = container_of(right, struct c2c_hist_entry, he);
78255177c4eSJiri Olsa
78355177c4eSJiri Olsa tot_recs_left = total_loads(&c2c_left->stats);
784f0c50c15SJiri Olsa tot_recs_right = total_loads(&c2c_right->stats);
785f0c50c15SJiri Olsa
786f0c50c15SJiri Olsa return tot_recs_left - tot_recs_right;
787f0c50c15SJiri Olsa }
788f0c50c15SJiri Olsa
789f0c50c15SJiri Olsa typedef double (get_percent_cb)(struct c2c_hist_entry *);
790f0c50c15SJiri Olsa
791f0c50c15SJiri Olsa static int
percent_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he,get_percent_cb get_percent)792f0c50c15SJiri Olsa percent_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
793f0c50c15SJiri Olsa struct hist_entry *he, get_percent_cb get_percent)
794f0c50c15SJiri Olsa {
795f0c50c15SJiri Olsa struct c2c_hist_entry *c2c_he;
796f0c50c15SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
7975a1a99cdSJiri Olsa double per;
7985a1a99cdSJiri Olsa
7995a1a99cdSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
8005a1a99cdSJiri Olsa per = get_percent(c2c_he);
801f0c50c15SJiri Olsa
802f0c50c15SJiri Olsa #ifdef HAVE_SLANG_SUPPORT
803f0c50c15SJiri Olsa if (use_browser)
8042be0bc75SLeo Yan return __hpp__slsmg_color_printf(hpp, "%*.2f%%", width - 1, per);
805f0c50c15SJiri Olsa #endif
806f0c50c15SJiri Olsa return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, per);
807f0c50c15SJiri Olsa }
808f0c50c15SJiri Olsa
percent_costly_snoop(struct c2c_hist_entry * c2c_he)80955b95776SJiri Olsa static double percent_costly_snoop(struct c2c_hist_entry *c2c_he)
810f0c50c15SJiri Olsa {
811f0c50c15SJiri Olsa struct c2c_hists *hists;
812f0c50c15SJiri Olsa struct c2c_stats *stats;
813f0c50c15SJiri Olsa struct c2c_stats *total;
814f0c50c15SJiri Olsa int tot = 0, st = 0;
815f0c50c15SJiri Olsa double p;
81655b95776SJiri Olsa
817c82ccc3aSLeo Yan hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
818f0c50c15SJiri Olsa stats = &c2c_he->stats;
819f0c50c15SJiri Olsa total = &hists->stats;
82055b95776SJiri Olsa
821c82ccc3aSLeo Yan switch (c2c.display) {
82255b95776SJiri Olsa case DISPLAY_RMT_HITM:
82355b95776SJiri Olsa st = stats->rmt_hitm;
824d940baccSJiri Olsa tot = total->rmt_hitm;
825c82ccc3aSLeo Yan break;
826d940baccSJiri Olsa case DISPLAY_LCL_HITM:
827d940baccSJiri Olsa st = stats->lcl_hitm;
828f37c5d91SLeo Yan tot = total->lcl_hitm;
829f37c5d91SLeo Yan break;
830f37c5d91SLeo Yan case DISPLAY_TOT_HITM:
831f37c5d91SLeo Yan st = stats->tot_hitm;
832f37c5d91SLeo Yan tot = total->tot_hitm;
83355b95776SJiri Olsa break;
83455b95776SJiri Olsa case DISPLAY_SNP_PEER:
83555b95776SJiri Olsa st = stats->tot_peer;
836f0c50c15SJiri Olsa tot = total->tot_peer;
837f0c50c15SJiri Olsa break;
838f0c50c15SJiri Olsa default:
839f0c50c15SJiri Olsa break;
840f0c50c15SJiri Olsa }
841f0c50c15SJiri Olsa
842f0c50c15SJiri Olsa p = tot ? (double) st / tot : 0;
843f0c50c15SJiri Olsa
844f0c50c15SJiri Olsa return 100 * p;
845f0c50c15SJiri Olsa }
846f0c50c15SJiri Olsa
847f0c50c15SJiri Olsa #define PERC_STR(__s, __v) \
848f0c50c15SJiri Olsa ({ \
8492be0bc75SLeo Yan scnprintf(__s, sizeof(__s), "%.2F%%", __v); \
850f0c50c15SJiri Olsa __s; \
851f0c50c15SJiri Olsa })
852f0c50c15SJiri Olsa
853f0c50c15SJiri Olsa static int
percent_costly_snoop_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)854f0c50c15SJiri Olsa percent_costly_snoop_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
855f0c50c15SJiri Olsa struct hist_entry *he)
856f0c50c15SJiri Olsa {
857f0c50c15SJiri Olsa struct c2c_hist_entry *c2c_he;
8582be0bc75SLeo Yan int width = c2c_width(fmt, hpp, he->hists);
859f0c50c15SJiri Olsa char buf[10];
860f0c50c15SJiri Olsa double per;
861f0c50c15SJiri Olsa
862f0c50c15SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
8632be0bc75SLeo Yan per = percent_costly_snoop(c2c_he);
864f0c50c15SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
865f0c50c15SJiri Olsa }
8662be0bc75SLeo Yan
867f0c50c15SJiri Olsa static int
percent_costly_snoop_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)868f0c50c15SJiri Olsa percent_costly_snoop_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
869f0c50c15SJiri Olsa struct hist_entry *he)
8702be0bc75SLeo Yan {
871f0c50c15SJiri Olsa return percent_color(fmt, hpp, he, percent_costly_snoop);
872f0c50c15SJiri Olsa }
873f0c50c15SJiri Olsa
874f0c50c15SJiri Olsa static int64_t
percent_costly_snoop_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)875f0c50c15SJiri Olsa percent_costly_snoop_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
876f0c50c15SJiri Olsa struct hist_entry *left, struct hist_entry *right)
877f0c50c15SJiri Olsa {
878f0c50c15SJiri Olsa struct c2c_hist_entry *c2c_left;
879f0c50c15SJiri Olsa struct c2c_hist_entry *c2c_right;
880f0c50c15SJiri Olsa double per_left;
8812be0bc75SLeo Yan double per_right;
8822be0bc75SLeo Yan
883f0c50c15SJiri Olsa c2c_left = container_of(left, struct c2c_hist_entry, he);
884f0c50c15SJiri Olsa c2c_right = container_of(right, struct c2c_hist_entry, he);
885f0c50c15SJiri Olsa
886f0c50c15SJiri Olsa per_left = percent_costly_snoop(c2c_left);
8879cb3500aSJiri Olsa per_right = percent_costly_snoop(c2c_right);
8889cb3500aSJiri Olsa
8899cb3500aSJiri Olsa return per_left - per_right;
8909cb3500aSJiri Olsa }
8919cb3500aSJiri Olsa
he_stats(struct hist_entry * he)8929cb3500aSJiri Olsa static struct c2c_stats *he_stats(struct hist_entry *he)
8939cb3500aSJiri Olsa {
8949cb3500aSJiri Olsa struct c2c_hist_entry *c2c_he;
8959cb3500aSJiri Olsa
8969cb3500aSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
8979cb3500aSJiri Olsa return &c2c_he->stats;
8989cb3500aSJiri Olsa }
8999cb3500aSJiri Olsa
total_stats(struct hist_entry * he)9009cb3500aSJiri Olsa static struct c2c_stats *total_stats(struct hist_entry *he)
9019cb3500aSJiri Olsa {
9029cb3500aSJiri Olsa struct c2c_hists *hists;
903111c1415SLeo Yan
9049cb3500aSJiri Olsa hists = container_of(he->hists, struct c2c_hists, hists);
9059cb3500aSJiri Olsa return &hists->stats;
9069cb3500aSJiri Olsa }
9079cb3500aSJiri Olsa
percent(u32 st,u32 tot)9089cb3500aSJiri Olsa static double percent(u32 st, u32 tot)
9099cb3500aSJiri Olsa {
9109cb3500aSJiri Olsa return tot ? 100. * (double) st / (double) tot : 0;
9119cb3500aSJiri Olsa }
9129cb3500aSJiri Olsa
9139cb3500aSJiri Olsa #define PERCENT(__h, __f) percent(he_stats(__h)->__f, total_stats(__h)->__f)
9149cb3500aSJiri Olsa
9159cb3500aSJiri Olsa #define PERCENT_FN(__f) \
9169cb3500aSJiri Olsa static double percent_ ## __f(struct c2c_hist_entry *c2c_he) \
9179cb3500aSJiri Olsa { \
9189cb3500aSJiri Olsa struct c2c_hists *hists; \
9199cb3500aSJiri Olsa \
9209cb3500aSJiri Olsa hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); \
9219082282fSLeo Yan return percent(c2c_he->stats.__f, hists->stats.__f); \
9229082282fSLeo Yan }
9239cb3500aSJiri Olsa
9249cb3500aSJiri Olsa PERCENT_FN(rmt_hitm)
PERCENT_FN(lcl_hitm)925550b4d6fSLeo Yan PERCENT_FN(lcl_hitm)
9269cb3500aSJiri Olsa PERCENT_FN(rmt_peer)
9279cb3500aSJiri Olsa PERCENT_FN(lcl_peer)
9289cb3500aSJiri Olsa PERCENT_FN(st_l1hit)
9299cb3500aSJiri Olsa PERCENT_FN(st_l1miss)
9309cb3500aSJiri Olsa PERCENT_FN(st_na)
9319cb3500aSJiri Olsa
9329cb3500aSJiri Olsa static int
9339cb3500aSJiri Olsa percent_rmt_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
9349cb3500aSJiri Olsa struct hist_entry *he)
9359cb3500aSJiri Olsa {
9369cb3500aSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
9379cb3500aSJiri Olsa double per = PERCENT(he, rmt_hitm);
9389cb3500aSJiri Olsa char buf[10];
9399cb3500aSJiri Olsa
9409cb3500aSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
9419cb3500aSJiri Olsa }
9429cb3500aSJiri Olsa
9439cb3500aSJiri Olsa static int
percent_rmt_hitm_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)9449cb3500aSJiri Olsa percent_rmt_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
9459cb3500aSJiri Olsa struct hist_entry *he)
9469cb3500aSJiri Olsa {
9479cb3500aSJiri Olsa return percent_color(fmt, hpp, he, percent_rmt_hitm);
9489cb3500aSJiri Olsa }
9499cb3500aSJiri Olsa
9509cb3500aSJiri Olsa static int64_t
percent_rmt_hitm_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)9519cb3500aSJiri Olsa percent_rmt_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
952b24192a1SLeo Yan struct hist_entry *left, struct hist_entry *right)
953b24192a1SLeo Yan {
9549cb3500aSJiri Olsa double per_left;
9559cb3500aSJiri Olsa double per_right;
9569cb3500aSJiri Olsa
9579cb3500aSJiri Olsa per_left = PERCENT(left, rmt_hitm);
9589cb3500aSJiri Olsa per_right = PERCENT(right, rmt_hitm);
9599cb3500aSJiri Olsa
9609cb3500aSJiri Olsa return per_left - per_right;
9619cb3500aSJiri Olsa }
9629cb3500aSJiri Olsa
9639cb3500aSJiri Olsa static int
percent_lcl_hitm_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)9649cb3500aSJiri Olsa percent_lcl_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
9659cb3500aSJiri Olsa struct hist_entry *he)
9669cb3500aSJiri Olsa {
9679cb3500aSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
9689cb3500aSJiri Olsa double per = PERCENT(he, lcl_hitm);
9699cb3500aSJiri Olsa char buf[10];
9709cb3500aSJiri Olsa
9719cb3500aSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
9729cb3500aSJiri Olsa }
9739cb3500aSJiri Olsa
9749cb3500aSJiri Olsa static int
percent_lcl_hitm_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)9759cb3500aSJiri Olsa percent_lcl_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
9769cb3500aSJiri Olsa struct hist_entry *he)
9779cb3500aSJiri Olsa {
9789cb3500aSJiri Olsa return percent_color(fmt, hpp, he, percent_lcl_hitm);
9799cb3500aSJiri Olsa }
9809cb3500aSJiri Olsa
9819cb3500aSJiri Olsa static int64_t
percent_lcl_hitm_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)9829cb3500aSJiri Olsa percent_lcl_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
9839cb3500aSJiri Olsa struct hist_entry *left, struct hist_entry *right)
9849cb3500aSJiri Olsa {
9859cb3500aSJiri Olsa double per_left;
9869cb3500aSJiri Olsa double per_right;
9879cb3500aSJiri Olsa
9889cb3500aSJiri Olsa per_left = PERCENT(left, lcl_hitm);
9899cb3500aSJiri Olsa per_right = PERCENT(right, lcl_hitm);
9909082282fSLeo Yan
9919082282fSLeo Yan return per_left - per_right;
9929082282fSLeo Yan }
9939082282fSLeo Yan
9949082282fSLeo Yan static int
percent_lcl_peer_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)9959082282fSLeo Yan percent_lcl_peer_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
9969082282fSLeo Yan struct hist_entry *he)
9979082282fSLeo Yan {
9989082282fSLeo Yan int width = c2c_width(fmt, hpp, he->hists);
9999082282fSLeo Yan double per = PERCENT(he, lcl_peer);
10009082282fSLeo Yan char buf[10];
10019082282fSLeo Yan
10029082282fSLeo Yan return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
10039082282fSLeo Yan }
10049082282fSLeo Yan
10059082282fSLeo Yan static int
percent_lcl_peer_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)10069082282fSLeo Yan percent_lcl_peer_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
10079082282fSLeo Yan struct hist_entry *he)
10089082282fSLeo Yan {
10099082282fSLeo Yan return percent_color(fmt, hpp, he, percent_lcl_peer);
10109082282fSLeo Yan }
10119082282fSLeo Yan
10129082282fSLeo Yan static int64_t
percent_lcl_peer_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)10139082282fSLeo Yan percent_lcl_peer_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
10149082282fSLeo Yan struct hist_entry *left, struct hist_entry *right)
10159082282fSLeo Yan {
10169082282fSLeo Yan double per_left;
10179082282fSLeo Yan double per_right;
10189082282fSLeo Yan
10199082282fSLeo Yan per_left = PERCENT(left, lcl_peer);
10209082282fSLeo Yan per_right = PERCENT(right, lcl_peer);
10219082282fSLeo Yan
10229082282fSLeo Yan return per_left - per_right;
10239082282fSLeo Yan }
10249082282fSLeo Yan
10259082282fSLeo Yan static int
percent_rmt_peer_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)10269082282fSLeo Yan percent_rmt_peer_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
10279082282fSLeo Yan struct hist_entry *he)
10289082282fSLeo Yan {
10299082282fSLeo Yan int width = c2c_width(fmt, hpp, he->hists);
10309082282fSLeo Yan double per = PERCENT(he, rmt_peer);
10319082282fSLeo Yan char buf[10];
10329082282fSLeo Yan
10339082282fSLeo Yan return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
10349082282fSLeo Yan }
10359082282fSLeo Yan
10369082282fSLeo Yan static int
percent_rmt_peer_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)10379082282fSLeo Yan percent_rmt_peer_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
10389082282fSLeo Yan struct hist_entry *he)
10399082282fSLeo Yan {
10409082282fSLeo Yan return percent_color(fmt, hpp, he, percent_rmt_peer);
10419082282fSLeo Yan }
10429082282fSLeo Yan
10439082282fSLeo Yan static int64_t
percent_rmt_peer_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)10449082282fSLeo Yan percent_rmt_peer_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
10459082282fSLeo Yan struct hist_entry *left, struct hist_entry *right)
10469082282fSLeo Yan {
10479082282fSLeo Yan double per_left;
10489082282fSLeo Yan double per_right;
10499082282fSLeo Yan
10509082282fSLeo Yan per_left = PERCENT(left, rmt_peer);
10519082282fSLeo Yan per_right = PERCENT(right, rmt_peer);
10529cb3500aSJiri Olsa
10539cb3500aSJiri Olsa return per_left - per_right;
10549cb3500aSJiri Olsa }
10559cb3500aSJiri Olsa
10569cb3500aSJiri Olsa static int
percent_stores_l1hit_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)10579cb3500aSJiri Olsa percent_stores_l1hit_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
10589cb3500aSJiri Olsa struct hist_entry *he)
10599cb3500aSJiri Olsa {
10609cb3500aSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
10619cb3500aSJiri Olsa double per = PERCENT(he, st_l1hit);
10629cb3500aSJiri Olsa char buf[10];
10639cb3500aSJiri Olsa
10649cb3500aSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
10659cb3500aSJiri Olsa }
10669cb3500aSJiri Olsa
10679cb3500aSJiri Olsa static int
percent_stores_l1hit_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)10689cb3500aSJiri Olsa percent_stores_l1hit_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
10699cb3500aSJiri Olsa struct hist_entry *he)
10709cb3500aSJiri Olsa {
10719cb3500aSJiri Olsa return percent_color(fmt, hpp, he, percent_st_l1hit);
10729cb3500aSJiri Olsa }
10739cb3500aSJiri Olsa
10749cb3500aSJiri Olsa static int64_t
percent_stores_l1hit_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)10759cb3500aSJiri Olsa percent_stores_l1hit_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
10769cb3500aSJiri Olsa struct hist_entry *left, struct hist_entry *right)
10779cb3500aSJiri Olsa {
10789cb3500aSJiri Olsa double per_left;
10799cb3500aSJiri Olsa double per_right;
10809cb3500aSJiri Olsa
10819cb3500aSJiri Olsa per_left = PERCENT(left, st_l1hit);
10829cb3500aSJiri Olsa per_right = PERCENT(right, st_l1hit);
10839cb3500aSJiri Olsa
10849cb3500aSJiri Olsa return per_left - per_right;
10859cb3500aSJiri Olsa }
10869cb3500aSJiri Olsa
10879cb3500aSJiri Olsa static int
percent_stores_l1miss_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)10889cb3500aSJiri Olsa percent_stores_l1miss_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
10899cb3500aSJiri Olsa struct hist_entry *he)
10909cb3500aSJiri Olsa {
10919cb3500aSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
10929cb3500aSJiri Olsa double per = PERCENT(he, st_l1miss);
10939cb3500aSJiri Olsa char buf[10];
10949cb3500aSJiri Olsa
10959cb3500aSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
10969cb3500aSJiri Olsa }
10979cb3500aSJiri Olsa
10989cb3500aSJiri Olsa static int
percent_stores_l1miss_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)10999cb3500aSJiri Olsa percent_stores_l1miss_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
11009cb3500aSJiri Olsa struct hist_entry *he)
11019cb3500aSJiri Olsa {
11029cb3500aSJiri Olsa return percent_color(fmt, hpp, he, percent_st_l1miss);
11039cb3500aSJiri Olsa }
11049cb3500aSJiri Olsa
11059cb3500aSJiri Olsa static int64_t
percent_stores_l1miss_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)11069cb3500aSJiri Olsa percent_stores_l1miss_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
11079cb3500aSJiri Olsa struct hist_entry *left, struct hist_entry *right)
11089cb3500aSJiri Olsa {
11099cb3500aSJiri Olsa double per_left;
11109cb3500aSJiri Olsa double per_right;
11119cb3500aSJiri Olsa
11129cb3500aSJiri Olsa per_left = PERCENT(left, st_l1miss);
1113550b4d6fSLeo Yan per_right = PERCENT(right, st_l1miss);
1114550b4d6fSLeo Yan
1115550b4d6fSLeo Yan return per_left - per_right;
1116550b4d6fSLeo Yan }
1117550b4d6fSLeo Yan
1118550b4d6fSLeo Yan static int
percent_stores_na_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)1119550b4d6fSLeo Yan percent_stores_na_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1120550b4d6fSLeo Yan struct hist_entry *he)
1121550b4d6fSLeo Yan {
1122550b4d6fSLeo Yan int width = c2c_width(fmt, hpp, he->hists);
1123550b4d6fSLeo Yan double per = PERCENT(he, st_na);
1124550b4d6fSLeo Yan char buf[10];
1125550b4d6fSLeo Yan
1126550b4d6fSLeo Yan return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
1127550b4d6fSLeo Yan }
1128550b4d6fSLeo Yan
1129550b4d6fSLeo Yan static int
percent_stores_na_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)1130550b4d6fSLeo Yan percent_stores_na_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1131550b4d6fSLeo Yan struct hist_entry *he)
1132550b4d6fSLeo Yan {
1133550b4d6fSLeo Yan return percent_color(fmt, hpp, he, percent_st_na);
1134550b4d6fSLeo Yan }
1135550b4d6fSLeo Yan
1136550b4d6fSLeo Yan static int64_t
percent_stores_na_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)1137550b4d6fSLeo Yan percent_stores_na_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
1138550b4d6fSLeo Yan struct hist_entry *left, struct hist_entry *right)
1139550b4d6fSLeo Yan {
1140550b4d6fSLeo Yan double per_left;
1141550b4d6fSLeo Yan double per_right;
1142550b4d6fSLeo Yan
1143550b4d6fSLeo Yan per_left = PERCENT(left, st_na);
11446c70f54cSJiri Olsa per_right = PERCENT(right, st_na);
11456c70f54cSJiri Olsa
11466c70f54cSJiri Olsa return per_left - per_right;
114736d3deb9SJiri Olsa }
114836d3deb9SJiri Olsa
114936d3deb9SJiri Olsa STAT_FN(lcl_dram)
STAT_FN(rmt_dram)115036d3deb9SJiri Olsa STAT_FN(rmt_dram)
115136d3deb9SJiri Olsa
115236d3deb9SJiri Olsa static int
115336d3deb9SJiri Olsa pid_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
115436d3deb9SJiri Olsa struct hist_entry *he)
115536d3deb9SJiri Olsa {
115636d3deb9SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
115736d3deb9SJiri Olsa
115836d3deb9SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*d", width, thread__pid(he->thread));
115936d3deb9SJiri Olsa }
116036d3deb9SJiri Olsa
116136d3deb9SJiri Olsa static int64_t
pid_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left,struct hist_entry * right)116236d3deb9SJiri Olsa pid_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
11631e181b92SJiri Olsa struct hist_entry *left, struct hist_entry *right)
11641e181b92SJiri Olsa {
11651e181b92SJiri Olsa return thread__pid(left->thread) - thread__pid(right->thread);
11661e181b92SJiri Olsa }
11671e181b92SJiri Olsa
11681e181b92SJiri Olsa static int64_t
empty_cmp(struct perf_hpp_fmt * fmt __maybe_unused,struct hist_entry * left __maybe_unused,struct hist_entry * right __maybe_unused)11691e181b92SJiri Olsa empty_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
11701e181b92SJiri Olsa struct hist_entry *left __maybe_unused,
1171f3d0a551SLeo Yan struct hist_entry *right __maybe_unused)
1172f3d0a551SLeo Yan {
1173f3d0a551SLeo Yan return 0;
1174f3d0a551SLeo Yan }
1175f3d0a551SLeo Yan
display_metrics(struct perf_hpp * hpp,u32 val,u32 sum)1176f3d0a551SLeo Yan static int display_metrics(struct perf_hpp *hpp, u32 val, u32 sum)
1177f3d0a551SLeo Yan {
1178f3d0a551SLeo Yan int ret;
1179f3d0a551SLeo Yan
1180f3d0a551SLeo Yan if (sum != 0)
1181f3d0a551SLeo Yan ret = scnprintf(hpp->buf, hpp->size, "%5.1f%% ",
1182f3d0a551SLeo Yan percent(val, sum));
1183f3d0a551SLeo Yan else
11841e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%6s ", "n/a");
11851e181b92SJiri Olsa
11861e181b92SJiri Olsa return ret;
11871e181b92SJiri Olsa }
11881e181b92SJiri Olsa
11891e181b92SJiri Olsa static int
node_entry(struct perf_hpp_fmt * fmt __maybe_unused,struct perf_hpp * hpp,struct hist_entry * he)11901e181b92SJiri Olsa node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
11911e181b92SJiri Olsa struct hist_entry *he)
11921e181b92SJiri Olsa {
11931e181b92SJiri Olsa struct c2c_hist_entry *c2c_he;
11941e181b92SJiri Olsa bool first = true;
11951e181b92SJiri Olsa int node;
11961e181b92SJiri Olsa int ret = 0;
11971e181b92SJiri Olsa
11981e181b92SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
11991e181b92SJiri Olsa
12001e181b92SJiri Olsa for (node = 0; node < c2c.nodes_cnt; node++) {
12011006c5c1SYury Norov DECLARE_BITMAP(set, c2c.cpus_cnt);
12021e181b92SJiri Olsa
12031e181b92SJiri Olsa bitmap_zero(set, c2c.cpus_cnt);
12041e181b92SJiri Olsa bitmap_and(set, c2c_he->cpuset, c2c.nodes[node], c2c.cpus_cnt);
12051e181b92SJiri Olsa
12061e181b92SJiri Olsa if (bitmap_empty(set, c2c.cpus_cnt)) {
12071e181b92SJiri Olsa if (c2c.node_info == 1) {
12081e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%21s", " ");
12091e181b92SJiri Olsa advance_hpp(hpp, ret);
12101e181b92SJiri Olsa }
12111e181b92SJiri Olsa continue;
12121e181b92SJiri Olsa }
12131e181b92SJiri Olsa
12141e181b92SJiri Olsa if (!first) {
12151e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, " ");
12161e181b92SJiri Olsa advance_hpp(hpp, ret);
12171e181b92SJiri Olsa }
12181e181b92SJiri Olsa
12191e181b92SJiri Olsa switch (c2c.node_info) {
12201e181b92SJiri Olsa case 0:
122167260e8cSJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%2d", node);
12221e181b92SJiri Olsa advance_hpp(hpp, ret);
12231e181b92SJiri Olsa break;
12241e181b92SJiri Olsa case 1:
12251e181b92SJiri Olsa {
12261e181b92SJiri Olsa int num = bitmap_weight(set, c2c.cpus_cnt);
122755b95776SJiri Olsa struct c2c_stats *stats = &c2c_he->node_stats[node];
1228c82ccc3aSLeo Yan
1229f3d0a551SLeo Yan ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num);
1230f3d0a551SLeo Yan advance_hpp(hpp, ret);
123155b95776SJiri Olsa
1232c82ccc3aSLeo Yan switch (c2c.display) {
1233f3d0a551SLeo Yan case DISPLAY_RMT_HITM:
1234f3d0a551SLeo Yan ret = display_metrics(hpp, stats->rmt_hitm,
1235d940baccSJiri Olsa c2c_he->stats.rmt_hitm);
1236c82ccc3aSLeo Yan break;
1237f3d0a551SLeo Yan case DISPLAY_LCL_HITM:
1238f3d0a551SLeo Yan ret = display_metrics(hpp, stats->lcl_hitm,
1239f3d0a551SLeo Yan c2c_he->stats.lcl_hitm);
1240f37c5d91SLeo Yan break;
1241f37c5d91SLeo Yan case DISPLAY_TOT_HITM:
1242f37c5d91SLeo Yan ret = display_metrics(hpp, stats->tot_hitm,
1243f37c5d91SLeo Yan c2c_he->stats.tot_hitm);
124455b95776SJiri Olsa break;
124555b95776SJiri Olsa case DISPLAY_SNP_PEER:
124655b95776SJiri Olsa ret = display_metrics(hpp, stats->tot_peer,
124755b95776SJiri Olsa c2c_he->stats.tot_peer);
12481e181b92SJiri Olsa break;
12491e181b92SJiri Olsa default:
12501e181b92SJiri Olsa break;
12511e181b92SJiri Olsa }
12521e181b92SJiri Olsa
12531e181b92SJiri Olsa advance_hpp(hpp, ret);
12541e181b92SJiri Olsa
12551e181b92SJiri Olsa if (c2c_he->stats.store > 0) {
12561e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%5.1f%%}",
12571e181b92SJiri Olsa percent(stats->store, c2c_he->stats.store));
12581e181b92SJiri Olsa } else {
12591e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%6s}", "n/a");
12601e181b92SJiri Olsa }
12611e181b92SJiri Olsa
12621e181b92SJiri Olsa advance_hpp(hpp, ret);
12631e181b92SJiri Olsa break;
12641e181b92SJiri Olsa }
12651e181b92SJiri Olsa case 2:
12661e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%2d{", node);
12671e181b92SJiri Olsa advance_hpp(hpp, ret);
12681e181b92SJiri Olsa
12691e181b92SJiri Olsa ret = bitmap_scnprintf(set, c2c.cpus_cnt, hpp->buf, hpp->size);
12701e181b92SJiri Olsa advance_hpp(hpp, ret);
12711e181b92SJiri Olsa
12721e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "}");
12731e181b92SJiri Olsa advance_hpp(hpp, ret);
12741e181b92SJiri Olsa break;
12751e181b92SJiri Olsa default:
12761e181b92SJiri Olsa break;
12771e181b92SJiri Olsa }
12781e181b92SJiri Olsa
12791e181b92SJiri Olsa first = false;
128092062d54SJiri Olsa }
128192062d54SJiri Olsa
128292062d54SJiri Olsa return 0;
128392062d54SJiri Olsa }
128492062d54SJiri Olsa
128592062d54SJiri Olsa static int
mean_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he,double mean)128692062d54SJiri Olsa mean_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
128792062d54SJiri Olsa struct hist_entry *he, double mean)
128892062d54SJiri Olsa {
128992062d54SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
129092062d54SJiri Olsa char buf[10];
129192062d54SJiri Olsa
129292062d54SJiri Olsa scnprintf(buf, 10, "%6.0f", mean);
129392062d54SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
129492062d54SJiri Olsa }
129592062d54SJiri Olsa
129692062d54SJiri Olsa #define MEAN_ENTRY(__func, __val) \
129792062d54SJiri Olsa static int \
129892062d54SJiri Olsa __func(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he) \
129992062d54SJiri Olsa { \
130092062d54SJiri Olsa struct c2c_hist_entry *c2c_he; \
130192062d54SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he); \
130292062d54SJiri Olsa return mean_entry(fmt, hpp, he, avg_stats(&c2c_he->cstats.__val)); \
1303682352e5SLeo Yan }
1304682352e5SLeo Yan
130592062d54SJiri Olsa MEAN_ENTRY(mean_rmt_entry, rmt_hitm);
1306b6fe2bbcSJiri Olsa MEAN_ENTRY(mean_lcl_entry, lcl_hitm);
13077e6a7998SArnaldo Carvalho de Melo MEAN_ENTRY(mean_load_entry, load);
1308b6fe2bbcSJiri Olsa MEAN_ENTRY(mean_rmt_peer_entry, rmt_peer);
1309b6fe2bbcSJiri Olsa MEAN_ENTRY(mean_lcl_peer_entry, lcl_peer);
1310b6fe2bbcSJiri Olsa
1311b6fe2bbcSJiri Olsa static int
cpucnt_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)1312b6fe2bbcSJiri Olsa cpucnt_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1313b6fe2bbcSJiri Olsa struct hist_entry *he)
1314b6fe2bbcSJiri Olsa {
1315b6fe2bbcSJiri Olsa struct c2c_hist_entry *c2c_he;
1316b6fe2bbcSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
1317b6fe2bbcSJiri Olsa char buf[10];
1318b6fe2bbcSJiri Olsa
1319b6fe2bbcSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
1320bb342daeSJiri Olsa
13217e6a7998SArnaldo Carvalho de Melo scnprintf(buf, 10, "%d", bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt));
1322bb342daeSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
1323bb342daeSJiri Olsa }
1324bb342daeSJiri Olsa
1325bb342daeSJiri Olsa static int
cl_idx_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)1326bb342daeSJiri Olsa cl_idx_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1327bb342daeSJiri Olsa struct hist_entry *he)
1328bb342daeSJiri Olsa {
1329bb342daeSJiri Olsa struct c2c_hist_entry *c2c_he;
1330bb342daeSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
1331bb342daeSJiri Olsa char buf[10];
1332bb342daeSJiri Olsa
1333bb342daeSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
1334bb342daeSJiri Olsa
13357e6a7998SArnaldo Carvalho de Melo scnprintf(buf, 10, "%u", c2c_he->cacheline_idx);
1336bb342daeSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
1337bb342daeSJiri Olsa }
1338bb342daeSJiri Olsa
1339bb342daeSJiri Olsa static int
cl_idx_empty_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)1340bb342daeSJiri Olsa cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1341bb342daeSJiri Olsa struct hist_entry *he)
1342bb342daeSJiri Olsa {
1343600a8cf4SJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
1344600a8cf4SJiri Olsa
1345600a8cf4SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, "");
1346600a8cf4SJiri Olsa }
1347600a8cf4SJiri Olsa
1348600a8cf4SJiri Olsa #define HEADER_LOW(__h) \
1349600a8cf4SJiri Olsa { \
1350600a8cf4SJiri Olsa .line[1] = { \
1351600a8cf4SJiri Olsa .text = __h, \
1352600a8cf4SJiri Olsa }, \
1353600a8cf4SJiri Olsa }
1354600a8cf4SJiri Olsa
1355600a8cf4SJiri Olsa #define HEADER_BOTH(__h0, __h1) \
1356600a8cf4SJiri Olsa { \
1357600a8cf4SJiri Olsa .line[0] = { \
1358600a8cf4SJiri Olsa .text = __h0, \
1359600a8cf4SJiri Olsa }, \
1360600a8cf4SJiri Olsa .line[1] = { \
1361600a8cf4SJiri Olsa .text = __h1, \
1362600a8cf4SJiri Olsa }, \
1363600a8cf4SJiri Olsa }
1364600a8cf4SJiri Olsa
1365600a8cf4SJiri Olsa #define HEADER_SPAN(__h0, __h1, __s) \
1366600a8cf4SJiri Olsa { \
1367600a8cf4SJiri Olsa .line[0] = { \
1368600a8cf4SJiri Olsa .text = __h0, \
1369600a8cf4SJiri Olsa .span = __s, \
1370600a8cf4SJiri Olsa }, \
1371600a8cf4SJiri Olsa .line[1] = { \
1372600a8cf4SJiri Olsa .text = __h1, \
1373600a8cf4SJiri Olsa }, \
1374600a8cf4SJiri Olsa }
1375600a8cf4SJiri Olsa
1376600a8cf4SJiri Olsa #define HEADER_SPAN_LOW(__h) \
1377600a8cf4SJiri Olsa { \
1378cbb88500SJiri Olsa .line[1] = { \
137903d9fcb7SJiri Olsa .text = __h, \
1380cbb88500SJiri Olsa }, \
1381cbb88500SJiri Olsa }
1382cbb88500SJiri Olsa
1383cbb88500SJiri Olsa static struct c2c_dimension dim_dcacheline = {
1384cbb88500SJiri Olsa .header = HEADER_SPAN("--- Cacheline ----", "Address", 2),
1385cbb88500SJiri Olsa .name = "dcacheline",
13867f834c2eSJiri Olsa .cmp = dcacheline_cmp,
13877f834c2eSJiri Olsa .entry = dcacheline_entry,
13887f834c2eSJiri Olsa .width = 18,
13897f834c2eSJiri Olsa };
13907f834c2eSJiri Olsa
13917f834c2eSJiri Olsa static struct c2c_dimension dim_dcacheline_node = {
13927f834c2eSJiri Olsa .header = HEADER_LOW("Node"),
13937f834c2eSJiri Olsa .name = "dcacheline_node",
139403d9fcb7SJiri Olsa .cmp = empty_cmp,
139503d9fcb7SJiri Olsa .entry = dcacheline_node_entry,
139603d9fcb7SJiri Olsa .width = 4,
139703d9fcb7SJiri Olsa };
139803d9fcb7SJiri Olsa
139903d9fcb7SJiri Olsa static struct c2c_dimension dim_dcacheline_count = {
140003d9fcb7SJiri Olsa .header = HEADER_LOW("PA cnt"),
140103d9fcb7SJiri Olsa .name = "dcacheline_count",
140203d9fcb7SJiri Olsa .cmp = empty_cmp,
14035a1a99cdSJiri Olsa .entry = dcacheline_node_count,
140448acdebdSJiri Olsa .width = 6,
140503d9fcb7SJiri Olsa };
140648acdebdSJiri Olsa
140748acdebdSJiri Olsa static struct c2c_header header_offset_tui = HEADER_SPAN("-----", "Off", 2);
140848acdebdSJiri Olsa
140948acdebdSJiri Olsa static struct c2c_dimension dim_offset = {
141048acdebdSJiri Olsa .header = HEADER_SPAN("--- Data address -", "Offset", 2),
141148acdebdSJiri Olsa .name = "offset",
14127f834c2eSJiri Olsa .cmp = offset_cmp,
14137f834c2eSJiri Olsa .entry = offset_entry,
14147f834c2eSJiri Olsa .width = 18,
14157f834c2eSJiri Olsa };
14167f834c2eSJiri Olsa
14177f834c2eSJiri Olsa static struct c2c_dimension dim_offset_node = {
14187f834c2eSJiri Olsa .header = HEADER_LOW("Node"),
14197f834c2eSJiri Olsa .name = "offset_node",
142043575a95SJiri Olsa .cmp = empty_cmp,
142143575a95SJiri Olsa .entry = dcacheline_node_entry,
142243575a95SJiri Olsa .width = 4,
142343575a95SJiri Olsa };
142443575a95SJiri Olsa
142543575a95SJiri Olsa static struct c2c_dimension dim_iaddr = {
142643575a95SJiri Olsa .header = HEADER_LOW("Code address"),
142743575a95SJiri Olsa .name = "iaddr",
142897cb486eSJiri Olsa .cmp = iaddr_cmp,
1429fdd32d7eSLeo Yan .entry = iaddr_entry,
143097cb486eSJiri Olsa .width = 18,
143197cb486eSJiri Olsa };
143297cb486eSJiri Olsa
143397cb486eSJiri Olsa static struct c2c_dimension dim_tot_hitm = {
143497cb486eSJiri Olsa .header = HEADER_SPAN("------- Load Hitm -------", "Total", 2),
143597cb486eSJiri Olsa .name = "tot_hitm",
143697cb486eSJiri Olsa .cmp = tot_hitm_cmp,
14370fbe2fe9SLeo Yan .entry = tot_hitm_entry,
143897cb486eSJiri Olsa .width = 7,
143997cb486eSJiri Olsa };
144097cb486eSJiri Olsa
144197cb486eSJiri Olsa static struct c2c_dimension dim_lcl_hitm = {
144297cb486eSJiri Olsa .header = HEADER_SPAN_LOW("LclHitm"),
144397cb486eSJiri Olsa .name = "lcl_hitm",
144497cb486eSJiri Olsa .cmp = lcl_hitm_cmp,
14450fbe2fe9SLeo Yan .entry = lcl_hitm_entry,
144697cb486eSJiri Olsa .width = 7,
144797cb486eSJiri Olsa };
144897cb486eSJiri Olsa
144997cb486eSJiri Olsa static struct c2c_dimension dim_rmt_hitm = {
145097cb486eSJiri Olsa .header = HEADER_SPAN_LOW("RmtHitm"),
145197cb486eSJiri Olsa .name = "rmt_hitm",
145263e74ab5SLeo Yan .cmp = rmt_hitm_cmp,
145363e74ab5SLeo Yan .entry = rmt_hitm_entry,
145463e74ab5SLeo Yan .width = 7,
145563e74ab5SLeo Yan };
145663e74ab5SLeo Yan
145763e74ab5SLeo Yan static struct c2c_dimension dim_tot_peer = {
145863e74ab5SLeo Yan .header = HEADER_SPAN("------- Load Peer -------", "Total", 2),
145963e74ab5SLeo Yan .name = "tot_peer",
146063e74ab5SLeo Yan .cmp = tot_peer_cmp,
146163e74ab5SLeo Yan .entry = tot_peer_entry,
146263e74ab5SLeo Yan .width = 7,
146363e74ab5SLeo Yan };
146463e74ab5SLeo Yan
146563e74ab5SLeo Yan static struct c2c_dimension dim_lcl_peer = {
146663e74ab5SLeo Yan .header = HEADER_SPAN_LOW("Local"),
146763e74ab5SLeo Yan .name = "lcl_peer",
146863e74ab5SLeo Yan .cmp = lcl_peer_cmp,
146963e74ab5SLeo Yan .entry = lcl_peer_entry,
147063e74ab5SLeo Yan .width = 7,
147163e74ab5SLeo Yan };
147263e74ab5SLeo Yan
147363e74ab5SLeo Yan static struct c2c_dimension dim_rmt_peer = {
147463e74ab5SLeo Yan .header = HEADER_SPAN_LOW("Remote"),
147563e74ab5SLeo Yan .name = "rmt_peer",
147697cb486eSJiri Olsa .cmp = rmt_peer_cmp,
147797cb486eSJiri Olsa .entry = rmt_peer_entry,
147897cb486eSJiri Olsa .width = 7,
147997cb486eSJiri Olsa };
148097cb486eSJiri Olsa
148197cb486eSJiri Olsa static struct c2c_dimension dim_cl_rmt_hitm = {
148297cb486eSJiri Olsa .header = HEADER_SPAN("----- HITM -----", "Rmt", 1),
148397cb486eSJiri Olsa .name = "cl_rmt_hitm",
148497cb486eSJiri Olsa .cmp = rmt_hitm_cmp,
148597cb486eSJiri Olsa .entry = rmt_hitm_entry,
148697cb486eSJiri Olsa .width = 7,
148797cb486eSJiri Olsa };
148897cb486eSJiri Olsa
148997cb486eSJiri Olsa static struct c2c_dimension dim_cl_lcl_hitm = {
149097cb486eSJiri Olsa .header = HEADER_SPAN_LOW("Lcl"),
149197cb486eSJiri Olsa .name = "cl_lcl_hitm",
14929082282fSLeo Yan .cmp = lcl_hitm_cmp,
14939082282fSLeo Yan .entry = lcl_hitm_entry,
14949082282fSLeo Yan .width = 7,
14959082282fSLeo Yan };
14969082282fSLeo Yan
14979082282fSLeo Yan static struct c2c_dimension dim_cl_rmt_peer = {
14989082282fSLeo Yan .header = HEADER_SPAN("----- Peer -----", "Rmt", 1),
14999082282fSLeo Yan .name = "cl_rmt_peer",
15009082282fSLeo Yan .cmp = rmt_peer_cmp,
15019082282fSLeo Yan .entry = rmt_peer_entry,
15029082282fSLeo Yan .width = 7,
15039082282fSLeo Yan };
15049082282fSLeo Yan
15059082282fSLeo Yan static struct c2c_dimension dim_cl_lcl_peer = {
15069082282fSLeo Yan .header = HEADER_SPAN_LOW("Lcl"),
15079082282fSLeo Yan .name = "cl_lcl_peer",
15084f28641bSLeo Yan .cmp = lcl_peer_cmp,
15094f28641bSLeo Yan .entry = lcl_peer_entry,
15104f28641bSLeo Yan .width = 7,
15110f18896dSJiri Olsa };
15120f18896dSJiri Olsa
15130f18896dSJiri Olsa static struct c2c_dimension dim_tot_stores = {
15140f18896dSJiri Olsa .header = HEADER_BOTH("Total", "Stores"),
15150f18896dSJiri Olsa .name = "tot_stores",
15160f18896dSJiri Olsa .cmp = store_cmp,
1517550b4d6fSLeo Yan .entry = store_entry,
15180f18896dSJiri Olsa .width = 7,
15190f18896dSJiri Olsa };
15200f18896dSJiri Olsa
15210f18896dSJiri Olsa static struct c2c_dimension dim_stores_l1hit = {
15220f18896dSJiri Olsa .header = HEADER_SPAN("--------- Stores --------", "L1Hit", 2),
15230f18896dSJiri Olsa .name = "stores_l1hit",
15240f18896dSJiri Olsa .cmp = st_l1hit_cmp,
15250f18896dSJiri Olsa .entry = st_l1hit_entry,
15260f18896dSJiri Olsa .width = 7,
15270f18896dSJiri Olsa };
15280f18896dSJiri Olsa
15290f18896dSJiri Olsa static struct c2c_dimension dim_stores_l1miss = {
15300f18896dSJiri Olsa .header = HEADER_SPAN_LOW("L1Miss"),
15310f18896dSJiri Olsa .name = "stores_l1miss",
1532550b4d6fSLeo Yan .cmp = st_l1miss_cmp,
1533550b4d6fSLeo Yan .entry = st_l1miss_entry,
1534550b4d6fSLeo Yan .width = 7,
1535550b4d6fSLeo Yan };
1536550b4d6fSLeo Yan
1537550b4d6fSLeo Yan static struct c2c_dimension dim_stores_na = {
1538550b4d6fSLeo Yan .header = HEADER_SPAN_LOW("N/A"),
1539550b4d6fSLeo Yan .name = "stores_na",
15400f18896dSJiri Olsa .cmp = st_na_cmp,
1541550b4d6fSLeo Yan .entry = st_na_entry,
15420f18896dSJiri Olsa .width = 7,
15430f18896dSJiri Olsa };
15440f18896dSJiri Olsa
15450f18896dSJiri Olsa static struct c2c_dimension dim_cl_stores_l1hit = {
15460f18896dSJiri Olsa .header = HEADER_SPAN("------- Store Refs ------", "L1 Hit", 2),
15470f18896dSJiri Olsa .name = "cl_stores_l1hit",
15480f18896dSJiri Olsa .cmp = st_l1hit_cmp,
15490f18896dSJiri Olsa .entry = st_l1hit_entry,
15500f18896dSJiri Olsa .width = 7,
15510f18896dSJiri Olsa };
15520f18896dSJiri Olsa
15530f18896dSJiri Olsa static struct c2c_dimension dim_cl_stores_l1miss = {
15540f18896dSJiri Olsa .header = HEADER_SPAN_LOW("L1 Miss"),
15550f18896dSJiri Olsa .name = "cl_stores_l1miss",
1556550b4d6fSLeo Yan .cmp = st_l1miss_cmp,
1557550b4d6fSLeo Yan .entry = st_l1miss_entry,
1558550b4d6fSLeo Yan .width = 7,
1559550b4d6fSLeo Yan };
1560550b4d6fSLeo Yan
1561550b4d6fSLeo Yan static struct c2c_dimension dim_cl_stores_na = {
1562550b4d6fSLeo Yan .header = HEADER_SPAN_LOW("N/A"),
1563550b4d6fSLeo Yan .name = "cl_stores_na",
15641295f685SJiri Olsa .cmp = st_na_cmp,
15651295f685SJiri Olsa .entry = st_na_entry,
15661295f685SJiri Olsa .width = 7,
15671295f685SJiri Olsa };
15681295f685SJiri Olsa
15691295f685SJiri Olsa static struct c2c_dimension dim_ld_fbhit = {
15701295f685SJiri Olsa .header = HEADER_SPAN("----- Core Load Hit -----", "FB", 2),
15711295f685SJiri Olsa .name = "ld_fbhit",
15721295f685SJiri Olsa .cmp = ld_fbhit_cmp,
15731295f685SJiri Olsa .entry = ld_fbhit_entry,
15741295f685SJiri Olsa .width = 7,
15751295f685SJiri Olsa };
15761295f685SJiri Olsa
15771295f685SJiri Olsa static struct c2c_dimension dim_ld_l1hit = {
15781295f685SJiri Olsa .header = HEADER_SPAN_LOW("L1"),
15791295f685SJiri Olsa .name = "ld_l1hit",
15801295f685SJiri Olsa .cmp = ld_l1hit_cmp,
15811295f685SJiri Olsa .entry = ld_l1hit_entry,
15821295f685SJiri Olsa .width = 7,
15831295f685SJiri Olsa };
15841295f685SJiri Olsa
15851295f685SJiri Olsa static struct c2c_dimension dim_ld_l2hit = {
15861295f685SJiri Olsa .header = HEADER_SPAN_LOW("L2"),
15871295f685SJiri Olsa .name = "ld_l2hit",
15884d08910cSJiri Olsa .cmp = ld_l2hit_cmp,
158977c15869SLeo Yan .entry = ld_l2hit_entry,
15904d08910cSJiri Olsa .width = 7,
15914d08910cSJiri Olsa };
15924d08910cSJiri Olsa
15934d08910cSJiri Olsa static struct c2c_dimension dim_ld_llchit = {
15944d08910cSJiri Olsa .header = HEADER_SPAN("- LLC Load Hit --", "LclHit", 1),
15954d08910cSJiri Olsa .name = "ld_lclhit",
15964d08910cSJiri Olsa .cmp = ld_llchit_cmp,
159791d933c2SLeo Yan .entry = ld_llchit_entry,
15984d08910cSJiri Olsa .width = 8,
15994d08910cSJiri Olsa };
16004d08910cSJiri Olsa
16014d08910cSJiri Olsa static struct c2c_dimension dim_ld_rmthit = {
16024d08910cSJiri Olsa .header = HEADER_SPAN("- RMT Load Hit --", "RmtHit", 1),
16034d08910cSJiri Olsa .name = "ld_rmthit",
160401b84d76SJiri Olsa .cmp = rmt_hit_cmp,
160501b84d76SJiri Olsa .entry = rmt_hit_entry,
160601b84d76SJiri Olsa .width = 8,
160701b84d76SJiri Olsa };
160801b84d76SJiri Olsa
160901b84d76SJiri Olsa static struct c2c_dimension dim_tot_recs = {
161001b84d76SJiri Olsa .header = HEADER_BOTH("Total", "records"),
161101b84d76SJiri Olsa .name = "tot_recs",
161255177c4eSJiri Olsa .cmp = tot_recs_cmp,
161355177c4eSJiri Olsa .entry = tot_recs_entry,
161455177c4eSJiri Olsa .width = 7,
161555177c4eSJiri Olsa };
161655177c4eSJiri Olsa
161755177c4eSJiri Olsa static struct c2c_dimension dim_tot_loads = {
161855177c4eSJiri Olsa .header = HEADER_BOTH("Total", "Loads"),
161955177c4eSJiri Olsa .name = "tot_loads",
16202be0bc75SLeo Yan .cmp = tot_loads_cmp,
1621c82ccc3aSLeo Yan .entry = tot_loads_entry,
1622c82ccc3aSLeo Yan .width = 7,
1623c82ccc3aSLeo Yan };
1624f37c5d91SLeo Yan
162555b95776SJiri Olsa static struct c2c_header percent_costly_snoop_header[] = {
162655b95776SJiri Olsa [DISPLAY_LCL_HITM] = HEADER_BOTH("Lcl", "Hitm"),
16272be0bc75SLeo Yan [DISPLAY_RMT_HITM] = HEADER_BOTH("Rmt", "Hitm"),
16282be0bc75SLeo Yan [DISPLAY_TOT_HITM] = HEADER_BOTH("Tot", "Hitm"),
16292be0bc75SLeo Yan [DISPLAY_SNP_PEER] = HEADER_BOTH("Peer", "Snoop"),
16302be0bc75SLeo Yan };
16312be0bc75SLeo Yan
1632f0c50c15SJiri Olsa static struct c2c_dimension dim_percent_costly_snoop = {
1633f0c50c15SJiri Olsa .name = "percent_costly_snoop",
1634f0c50c15SJiri Olsa .cmp = percent_costly_snoop_cmp,
16359cb3500aSJiri Olsa .entry = percent_costly_snoop_entry,
16360fbe2fe9SLeo Yan .color = percent_costly_snoop_color,
16379cb3500aSJiri Olsa .width = 7,
16389cb3500aSJiri Olsa };
16399cb3500aSJiri Olsa
16409cb3500aSJiri Olsa static struct c2c_dimension dim_percent_rmt_hitm = {
16419cb3500aSJiri Olsa .header = HEADER_SPAN("----- HITM -----", "RmtHitm", 1),
16429cb3500aSJiri Olsa .name = "percent_rmt_hitm",
16439cb3500aSJiri Olsa .cmp = percent_rmt_hitm_cmp,
16449cb3500aSJiri Olsa .entry = percent_rmt_hitm_entry,
16450fbe2fe9SLeo Yan .color = percent_rmt_hitm_color,
16469cb3500aSJiri Olsa .width = 7,
16479cb3500aSJiri Olsa };
16489cb3500aSJiri Olsa
16499cb3500aSJiri Olsa static struct c2c_dimension dim_percent_lcl_hitm = {
16509cb3500aSJiri Olsa .header = HEADER_SPAN_LOW("LclHitm"),
16519cb3500aSJiri Olsa .name = "percent_lcl_hitm",
16529cb3500aSJiri Olsa .cmp = percent_lcl_hitm_cmp,
16539082282fSLeo Yan .entry = percent_lcl_hitm_entry,
16549082282fSLeo Yan .color = percent_lcl_hitm_color,
16559082282fSLeo Yan .width = 7,
16569082282fSLeo Yan };
16579082282fSLeo Yan
16589082282fSLeo Yan static struct c2c_dimension dim_percent_rmt_peer = {
16599082282fSLeo Yan .header = HEADER_SPAN("-- Peer Snoop --", "Rmt", 1),
16609082282fSLeo Yan .name = "percent_rmt_peer",
16619082282fSLeo Yan .cmp = percent_rmt_peer_cmp,
16629082282fSLeo Yan .entry = percent_rmt_peer_entry,
16639082282fSLeo Yan .color = percent_rmt_peer_color,
16649082282fSLeo Yan .width = 7,
16659082282fSLeo Yan };
16669082282fSLeo Yan
16679082282fSLeo Yan static struct c2c_dimension dim_percent_lcl_peer = {
16689082282fSLeo Yan .header = HEADER_SPAN_LOW("Lcl"),
16699082282fSLeo Yan .name = "percent_lcl_peer",
16709082282fSLeo Yan .cmp = percent_lcl_peer_cmp,
16719cb3500aSJiri Olsa .entry = percent_lcl_peer_entry,
1672550b4d6fSLeo Yan .color = percent_lcl_peer_color,
16739cb3500aSJiri Olsa .width = 7,
16749cb3500aSJiri Olsa };
16759cb3500aSJiri Olsa
16769cb3500aSJiri Olsa static struct c2c_dimension dim_percent_stores_l1hit = {
16779cb3500aSJiri Olsa .header = HEADER_SPAN("------- Store Refs ------", "L1 Hit", 2),
16789cb3500aSJiri Olsa .name = "percent_stores_l1hit",
16799cb3500aSJiri Olsa .cmp = percent_stores_l1hit_cmp,
16809cb3500aSJiri Olsa .entry = percent_stores_l1hit_entry,
16819cb3500aSJiri Olsa .color = percent_stores_l1hit_color,
16829cb3500aSJiri Olsa .width = 7,
16839cb3500aSJiri Olsa };
16849cb3500aSJiri Olsa
16859cb3500aSJiri Olsa static struct c2c_dimension dim_percent_stores_l1miss = {
16869cb3500aSJiri Olsa .header = HEADER_SPAN_LOW("L1 Miss"),
16879cb3500aSJiri Olsa .name = "percent_stores_l1miss",
16889cb3500aSJiri Olsa .cmp = percent_stores_l1miss_cmp,
1689550b4d6fSLeo Yan .entry = percent_stores_l1miss_entry,
1690550b4d6fSLeo Yan .color = percent_stores_l1miss_color,
1691550b4d6fSLeo Yan .width = 7,
1692550b4d6fSLeo Yan };
1693550b4d6fSLeo Yan
1694550b4d6fSLeo Yan static struct c2c_dimension dim_percent_stores_na = {
1695550b4d6fSLeo Yan .header = HEADER_SPAN_LOW("N/A"),
1696550b4d6fSLeo Yan .name = "percent_stores_na",
1697550b4d6fSLeo Yan .cmp = percent_stores_na_cmp,
16986c70f54cSJiri Olsa .entry = percent_stores_na_entry,
16996c70f54cSJiri Olsa .color = percent_stores_na_color,
17006c70f54cSJiri Olsa .width = 7,
17016c70f54cSJiri Olsa };
17026c70f54cSJiri Olsa
17036c70f54cSJiri Olsa static struct c2c_dimension dim_dram_lcl = {
17046c70f54cSJiri Olsa .header = HEADER_SPAN("--- Load Dram ----", "Lcl", 1),
17056c70f54cSJiri Olsa .name = "dram_lcl",
17066c70f54cSJiri Olsa .cmp = lcl_dram_cmp,
17076c70f54cSJiri Olsa .entry = lcl_dram_entry,
17086c70f54cSJiri Olsa .width = 8,
17096c70f54cSJiri Olsa };
17106c70f54cSJiri Olsa
17116c70f54cSJiri Olsa static struct c2c_dimension dim_dram_rmt = {
17126c70f54cSJiri Olsa .header = HEADER_SPAN_LOW("Rmt"),
17136c70f54cSJiri Olsa .name = "dram_rmt",
171436d3deb9SJiri Olsa .cmp = rmt_dram_cmp,
171536d3deb9SJiri Olsa .entry = rmt_dram_entry,
171636d3deb9SJiri Olsa .width = 8,
171736d3deb9SJiri Olsa };
171836d3deb9SJiri Olsa
171936d3deb9SJiri Olsa static struct c2c_dimension dim_pid = {
172036d3deb9SJiri Olsa .header = HEADER_LOW("Pid"),
172136d3deb9SJiri Olsa .name = "pid",
1722e87019c5SJiri Olsa .cmp = pid_cmp,
1723e87019c5SJiri Olsa .entry = pid_entry,
1724e87019c5SJiri Olsa .width = 7,
1725e87019c5SJiri Olsa };
1726e87019c5SJiri Olsa
1727e87019c5SJiri Olsa static struct c2c_dimension dim_tid = {
172851dedaa4SJiri Olsa .header = HEADER_LOW("Tid"),
172951dedaa4SJiri Olsa .name = "tid",
173051dedaa4SJiri Olsa .se = &sort_thread,
173151dedaa4SJiri Olsa };
173251dedaa4SJiri Olsa
173351dedaa4SJiri Olsa static struct c2c_dimension dim_symbol = {
173451dedaa4SJiri Olsa .name = "symbol",
173551dedaa4SJiri Olsa .se = &sort_sym,
173651dedaa4SJiri Olsa };
173751dedaa4SJiri Olsa
173851dedaa4SJiri Olsa static struct c2c_dimension dim_dso = {
17391e181b92SJiri Olsa .header = HEADER_BOTH("Shared", "Object"),
17401e181b92SJiri Olsa .name = "dso",
17411e181b92SJiri Olsa .se = &sort_dso,
17421e181b92SJiri Olsa };
17431e181b92SJiri Olsa
17441e181b92SJiri Olsa static struct c2c_dimension dim_node = {
17451e181b92SJiri Olsa .name = "node",
174692062d54SJiri Olsa .cmp = empty_cmp,
174792062d54SJiri Olsa .entry = node_entry,
174892062d54SJiri Olsa .width = 4,
174992062d54SJiri Olsa };
175092062d54SJiri Olsa
175192062d54SJiri Olsa static struct c2c_dimension dim_mean_rmt = {
175292062d54SJiri Olsa .header = HEADER_SPAN("---------- cycles ----------", "rmt hitm", 2),
175392062d54SJiri Olsa .name = "mean_rmt",
175492062d54SJiri Olsa .cmp = empty_cmp,
175592062d54SJiri Olsa .entry = mean_rmt_entry,
175692062d54SJiri Olsa .width = 8,
175792062d54SJiri Olsa };
175892062d54SJiri Olsa
175992062d54SJiri Olsa static struct c2c_dimension dim_mean_lcl = {
176092062d54SJiri Olsa .header = HEADER_SPAN_LOW("lcl hitm"),
176192062d54SJiri Olsa .name = "mean_lcl",
176292062d54SJiri Olsa .cmp = empty_cmp,
176392062d54SJiri Olsa .entry = mean_lcl_entry,
176492062d54SJiri Olsa .width = 8,
176592062d54SJiri Olsa };
176692062d54SJiri Olsa
176792062d54SJiri Olsa static struct c2c_dimension dim_mean_load = {
176892062d54SJiri Olsa .header = HEADER_SPAN_LOW("load"),
176992062d54SJiri Olsa .name = "mean_load",
1770682352e5SLeo Yan .cmp = empty_cmp,
1771682352e5SLeo Yan .entry = mean_load_entry,
1772682352e5SLeo Yan .width = 8,
1773682352e5SLeo Yan };
1774682352e5SLeo Yan
1775682352e5SLeo Yan static struct c2c_dimension dim_mean_rmt_peer = {
1776682352e5SLeo Yan .header = HEADER_SPAN("---------- cycles ----------", "rmt peer", 2),
1777682352e5SLeo Yan .name = "mean_rmt_peer",
1778682352e5SLeo Yan .cmp = empty_cmp,
1779682352e5SLeo Yan .entry = mean_rmt_peer_entry,
1780682352e5SLeo Yan .width = 8,
1781682352e5SLeo Yan };
1782682352e5SLeo Yan
1783682352e5SLeo Yan static struct c2c_dimension dim_mean_lcl_peer = {
1784682352e5SLeo Yan .header = HEADER_SPAN_LOW("lcl peer"),
1785682352e5SLeo Yan .name = "mean_lcl_peer",
1786b6fe2bbcSJiri Olsa .cmp = empty_cmp,
1787b6fe2bbcSJiri Olsa .entry = mean_lcl_peer_entry,
1788b6fe2bbcSJiri Olsa .width = 8,
1789b6fe2bbcSJiri Olsa };
1790b6fe2bbcSJiri Olsa
1791b6fe2bbcSJiri Olsa static struct c2c_dimension dim_cpucnt = {
1792b6fe2bbcSJiri Olsa .header = HEADER_BOTH("cpu", "cnt"),
1793b6fe2bbcSJiri Olsa .name = "cpucnt",
179489d9ba8fSJiri Olsa .cmp = empty_cmp,
179589d9ba8fSJiri Olsa .entry = cpucnt_entry,
179689d9ba8fSJiri Olsa .width = 8,
179789d9ba8fSJiri Olsa };
179889d9ba8fSJiri Olsa
1799bb342daeSJiri Olsa static struct c2c_dimension dim_srcline = {
1800bb342daeSJiri Olsa .name = "cl_srcline",
1801bb342daeSJiri Olsa .se = &sort_srcline,
1802bb342daeSJiri Olsa };
1803bb342daeSJiri Olsa
1804bb342daeSJiri Olsa static struct c2c_dimension dim_dcacheline_idx = {
1805bb342daeSJiri Olsa .header = HEADER_LOW("Index"),
1806bb342daeSJiri Olsa .name = "cl_idx",
1807bb342daeSJiri Olsa .cmp = empty_cmp,
1808bb342daeSJiri Olsa .entry = cl_idx_entry,
1809bb342daeSJiri Olsa .width = 5,
1810bb342daeSJiri Olsa };
1811bb342daeSJiri Olsa
1812bb342daeSJiri Olsa static struct c2c_dimension dim_dcacheline_num = {
1813bb342daeSJiri Olsa .header = HEADER_LOW("Num"),
1814bb342daeSJiri Olsa .name = "cl_num",
1815bb342daeSJiri Olsa .cmp = empty_cmp,
1816bb342daeSJiri Olsa .entry = cl_idx_entry,
1817bb342daeSJiri Olsa .width = 5,
1818bb342daeSJiri Olsa };
1819bb342daeSJiri Olsa
1820bb342daeSJiri Olsa static struct c2c_dimension dim_dcacheline_num_empty = {
1821bb342daeSJiri Olsa .header = HEADER_LOW("Num"),
1822bb342daeSJiri Olsa .name = "cl_num_empty",
1823c75540e3SJiri Olsa .cmp = empty_cmp,
1824cbb88500SJiri Olsa .entry = cl_idx_empty_entry,
18257f834c2eSJiri Olsa .width = 5,
182603d9fcb7SJiri Olsa };
182748acdebdSJiri Olsa
18287f834c2eSJiri Olsa static struct c2c_dimension *dimensions[] = {
182943575a95SJiri Olsa &dim_dcacheline,
183097cb486eSJiri Olsa &dim_dcacheline_node,
183197cb486eSJiri Olsa &dim_dcacheline_count,
183297cb486eSJiri Olsa &dim_offset,
183363e74ab5SLeo Yan &dim_offset_node,
183463e74ab5SLeo Yan &dim_iaddr,
183563e74ab5SLeo Yan &dim_tot_hitm,
183697cb486eSJiri Olsa &dim_lcl_hitm,
183797cb486eSJiri Olsa &dim_rmt_hitm,
18389082282fSLeo Yan &dim_tot_peer,
18399082282fSLeo Yan &dim_lcl_peer,
18404f28641bSLeo Yan &dim_rmt_peer,
18410f18896dSJiri Olsa &dim_cl_lcl_hitm,
18420f18896dSJiri Olsa &dim_cl_rmt_hitm,
1843550b4d6fSLeo Yan &dim_cl_lcl_peer,
18440f18896dSJiri Olsa &dim_cl_rmt_peer,
18450f18896dSJiri Olsa &dim_tot_stores,
1846550b4d6fSLeo Yan &dim_stores_l1hit,
18471295f685SJiri Olsa &dim_stores_l1miss,
18481295f685SJiri Olsa &dim_stores_na,
18491295f685SJiri Olsa &dim_cl_stores_l1hit,
18504d08910cSJiri Olsa &dim_cl_stores_l1miss,
18514d08910cSJiri Olsa &dim_cl_stores_na,
185201b84d76SJiri Olsa &dim_ld_fbhit,
185355177c4eSJiri Olsa &dim_ld_l1hit,
18542be0bc75SLeo Yan &dim_ld_l2hit,
18559cb3500aSJiri Olsa &dim_ld_llchit,
18569cb3500aSJiri Olsa &dim_ld_rmthit,
18579082282fSLeo Yan &dim_tot_recs,
18589082282fSLeo Yan &dim_tot_loads,
18599cb3500aSJiri Olsa &dim_percent_costly_snoop,
18609cb3500aSJiri Olsa &dim_percent_rmt_hitm,
1861550b4d6fSLeo Yan &dim_percent_lcl_hitm,
18626c70f54cSJiri Olsa &dim_percent_rmt_peer,
18636c70f54cSJiri Olsa &dim_percent_lcl_peer,
186436d3deb9SJiri Olsa &dim_percent_stores_l1hit,
1865e87019c5SJiri Olsa &dim_percent_stores_l1miss,
186651dedaa4SJiri Olsa &dim_percent_stores_na,
186751dedaa4SJiri Olsa &dim_dram_lcl,
18681e181b92SJiri Olsa &dim_dram_rmt,
186992062d54SJiri Olsa &dim_pid,
187092062d54SJiri Olsa &dim_tid,
1871682352e5SLeo Yan &dim_symbol,
1872682352e5SLeo Yan &dim_dso,
187392062d54SJiri Olsa &dim_node,
1874b6fe2bbcSJiri Olsa &dim_mean_rmt,
187589d9ba8fSJiri Olsa &dim_mean_lcl,
1876bb342daeSJiri Olsa &dim_mean_rmt_peer,
1877bb342daeSJiri Olsa &dim_mean_lcl_peer,
1878bb342daeSJiri Olsa &dim_mean_load,
1879c75540e3SJiri Olsa &dim_cpucnt,
1880c75540e3SJiri Olsa &dim_srcline,
1881c75540e3SJiri Olsa &dim_dcacheline_idx,
1882c75540e3SJiri Olsa &dim_dcacheline_num,
1883c75540e3SJiri Olsa &dim_dcacheline_num_empty,
1884c75540e3SJiri Olsa NULL,
1885c75540e3SJiri Olsa };
1886c75540e3SJiri Olsa
fmt_free(struct perf_hpp_fmt * fmt)1887c75540e3SJiri Olsa static void fmt_free(struct perf_hpp_fmt *fmt)
1888c75540e3SJiri Olsa {
1889c75540e3SJiri Olsa struct c2c_fmt *c2c_fmt;
1890c75540e3SJiri Olsa
1891c75540e3SJiri Olsa c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
1892c75540e3SJiri Olsa free(c2c_fmt);
1893c75540e3SJiri Olsa }
1894c75540e3SJiri Olsa
fmt_equal(struct perf_hpp_fmt * a,struct perf_hpp_fmt * b)1895c75540e3SJiri Olsa static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
1896c75540e3SJiri Olsa {
1897c75540e3SJiri Olsa struct c2c_fmt *c2c_a = container_of(a, struct c2c_fmt, fmt);
1898c75540e3SJiri Olsa struct c2c_fmt *c2c_b = container_of(b, struct c2c_fmt, fmt);
1899c75540e3SJiri Olsa
1900c75540e3SJiri Olsa return c2c_a->dim == c2c_b->dim;
1901c75540e3SJiri Olsa }
1902c75540e3SJiri Olsa
get_dimension(const char * name)1903c75540e3SJiri Olsa static struct c2c_dimension *get_dimension(const char *name)
1904c75540e3SJiri Olsa {
1905c75540e3SJiri Olsa unsigned int i;
1906c75540e3SJiri Olsa
19072cca512aSZou Wei for (i = 0; dimensions[i]; i++) {
1908c75540e3SJiri Olsa struct c2c_dimension *dim = dimensions[i];
1909c75540e3SJiri Olsa
1910c75540e3SJiri Olsa if (!strcmp(dim->name, name))
1911c75540e3SJiri Olsa return dim;
19128d3f938dSJiri Olsa }
19138d3f938dSJiri Olsa
19148d3f938dSJiri Olsa return NULL;
19158d3f938dSJiri Olsa }
19168d3f938dSJiri Olsa
c2c_se_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)19178d3f938dSJiri Olsa static int c2c_se_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
19188d3f938dSJiri Olsa struct hist_entry *he)
1919590b6a3aSJiri Olsa {
19208d3f938dSJiri Olsa struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
19218d3f938dSJiri Olsa struct c2c_dimension *dim = c2c_fmt->dim;
1922590b6a3aSJiri Olsa size_t len = fmt->user_len;
1923590b6a3aSJiri Olsa
1924590b6a3aSJiri Olsa if (!len) {
1925590b6a3aSJiri Olsa len = hists__col_len(he->hists, dim->se->se_width_idx);
19268d3f938dSJiri Olsa
19278d3f938dSJiri Olsa if (dim == &dim_symbol || dim == &dim_srcline)
19288d3f938dSJiri Olsa len = symbol_width(he->hists, dim->se);
19298d3f938dSJiri Olsa }
19308d3f938dSJiri Olsa
19318d3f938dSJiri Olsa return dim->se->se_snprintf(he, hpp->buf, hpp->size, len);
19328d3f938dSJiri Olsa }
19338d3f938dSJiri Olsa
c2c_se_cmp(struct perf_hpp_fmt * fmt,struct hist_entry * a,struct hist_entry * b)19348d3f938dSJiri Olsa static int64_t c2c_se_cmp(struct perf_hpp_fmt *fmt,
19358d3f938dSJiri Olsa struct hist_entry *a, struct hist_entry *b)
19368d3f938dSJiri Olsa {
19378d3f938dSJiri Olsa struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
19388d3f938dSJiri Olsa struct c2c_dimension *dim = c2c_fmt->dim;
19398d3f938dSJiri Olsa
19408d3f938dSJiri Olsa return dim->se->se_cmp(a, b);
19418d3f938dSJiri Olsa }
19428d3f938dSJiri Olsa
c2c_se_collapse(struct perf_hpp_fmt * fmt,struct hist_entry * a,struct hist_entry * b)19438d3f938dSJiri Olsa static int64_t c2c_se_collapse(struct perf_hpp_fmt *fmt,
19448d3f938dSJiri Olsa struct hist_entry *a, struct hist_entry *b)
19458d3f938dSJiri Olsa {
19468d3f938dSJiri Olsa struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
19478d3f938dSJiri Olsa struct c2c_dimension *dim = c2c_fmt->dim;
19488d3f938dSJiri Olsa int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
1949c75540e3SJiri Olsa
1950c75540e3SJiri Olsa collapse_fn = dim->se->se_collapse ?: dim->se->se_cmp;
1951c75540e3SJiri Olsa return collapse_fn(a, b);
1952c75540e3SJiri Olsa }
1953c75540e3SJiri Olsa
get_format(const char * name)1954c75540e3SJiri Olsa static struct c2c_fmt *get_format(const char *name)
1955c75540e3SJiri Olsa {
1956c75540e3SJiri Olsa struct c2c_dimension *dim = get_dimension(name);
1957c75540e3SJiri Olsa struct c2c_fmt *c2c_fmt;
1958c75540e3SJiri Olsa struct perf_hpp_fmt *fmt;
1959c75540e3SJiri Olsa
1960c75540e3SJiri Olsa if (!dim)
1961c75540e3SJiri Olsa return NULL;
1962c75540e3SJiri Olsa
1963c75540e3SJiri Olsa c2c_fmt = zalloc(sizeof(*c2c_fmt));
1964c75540e3SJiri Olsa if (!c2c_fmt)
1965c75540e3SJiri Olsa return NULL;
1966c75540e3SJiri Olsa
1967c75540e3SJiri Olsa c2c_fmt->dim = dim;
19688d3f938dSJiri Olsa
19698d3f938dSJiri Olsa fmt = &c2c_fmt->fmt;
19709cb3500aSJiri Olsa INIT_LIST_HEAD(&fmt->list);
19718d3f938dSJiri Olsa INIT_LIST_HEAD(&fmt->sort_list);
1972c75540e3SJiri Olsa
1973c75540e3SJiri Olsa fmt->cmp = dim->se ? c2c_se_cmp : dim->cmp;
19748d3f938dSJiri Olsa fmt->sort = dim->se ? c2c_se_cmp : dim->cmp;
1975c75540e3SJiri Olsa fmt->color = dim->se ? NULL : dim->color;
1976c75540e3SJiri Olsa fmt->entry = dim->se ? c2c_se_entry : dim->entry;
1977c75540e3SJiri Olsa fmt->header = c2c_header;
1978c75540e3SJiri Olsa fmt->width = c2c_width;
1979c75540e3SJiri Olsa fmt->collapse = dim->se ? c2c_se_collapse : dim->cmp;
1980c75540e3SJiri Olsa fmt->equal = fmt_equal;
1981c75540e3SJiri Olsa fmt->free = fmt_free;
1982c75540e3SJiri Olsa
1983c75540e3SJiri Olsa return c2c_fmt;
1984c75540e3SJiri Olsa }
19855f2eca83SJiri Olsa
c2c_hists__init_output(struct perf_hpp_list * hpp_list,char * name)19865f2eca83SJiri Olsa static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
19875f2eca83SJiri Olsa {
19885f2eca83SJiri Olsa struct c2c_fmt *c2c_fmt = get_format(name);
1989c75540e3SJiri Olsa
1990c75540e3SJiri Olsa if (!c2c_fmt) {
1991c75540e3SJiri Olsa reset_dimensions();
1992c75540e3SJiri Olsa return output_field_add(hpp_list, name);
1993c75540e3SJiri Olsa }
1994c75540e3SJiri Olsa
1995c75540e3SJiri Olsa perf_hpp_list__column_register(hpp_list, &c2c_fmt->fmt);
1996c75540e3SJiri Olsa return 0;
199751dedaa4SJiri Olsa }
1998c75540e3SJiri Olsa
c2c_hists__init_sort(struct perf_hpp_list * hpp_list,char * name)19995f2eca83SJiri Olsa static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
20005f2eca83SJiri Olsa {
20015f2eca83SJiri Olsa struct c2c_fmt *c2c_fmt = get_format(name);
20025f2eca83SJiri Olsa struct c2c_dimension *dim;
2003c75540e3SJiri Olsa
200451dedaa4SJiri Olsa if (!c2c_fmt) {
200551dedaa4SJiri Olsa reset_dimensions();
200651dedaa4SJiri Olsa return sort_dimension__add(hpp_list, name, NULL, 0);
200751dedaa4SJiri Olsa }
2008c75540e3SJiri Olsa
2009c75540e3SJiri Olsa dim = c2c_fmt->dim;
2010c75540e3SJiri Olsa if (dim == &dim_dso)
2011c75540e3SJiri Olsa hpp_list->dso = 1;
2012c75540e3SJiri Olsa
2013c75540e3SJiri Olsa perf_hpp_list__register_sort_field(hpp_list, &c2c_fmt->fmt);
2014c75540e3SJiri Olsa return 0;
2015c75540e3SJiri Olsa }
2016c75540e3SJiri Olsa
2017c75540e3SJiri Olsa #define PARSE_LIST(_list, _fn) \
2018c75540e3SJiri Olsa do { \
2019c75540e3SJiri Olsa char *tmp, *tok; \
2020c75540e3SJiri Olsa ret = 0; \
2021c75540e3SJiri Olsa \
2022c75540e3SJiri Olsa if (!_list) \
2023c75540e3SJiri Olsa break; \
202462d94b00SArnaldo Carvalho de Melo \
2025c75540e3SJiri Olsa for (tok = strtok_r((char *)_list, ", ", &tmp); \
2026c75540e3SJiri Olsa tok; tok = strtok_r(NULL, ", ", &tmp)) { \
202762d94b00SArnaldo Carvalho de Melo ret = _fn(hpp_list, tok); \
2028c75540e3SJiri Olsa if (ret == -EINVAL) { \
2029c75540e3SJiri Olsa pr_err("Invalid --fields key: `%s'", tok); \
2030c75540e3SJiri Olsa break; \
2031c75540e3SJiri Olsa } else if (ret == -ESRCH) { \
2032c75540e3SJiri Olsa pr_err("Unknown --fields key: `%s'", tok); \
2033c75540e3SJiri Olsa break; \
2034c75540e3SJiri Olsa } \
2035c75540e3SJiri Olsa } \
2036c75540e3SJiri Olsa } while (0)
2037c75540e3SJiri Olsa
hpp_list__parse(struct perf_hpp_list * hpp_list,const char * output_,const char * sort_)2038c75540e3SJiri Olsa static int hpp_list__parse(struct perf_hpp_list *hpp_list,
2039c75540e3SJiri Olsa const char *output_,
2040c75540e3SJiri Olsa const char *sort_)
2041c75540e3SJiri Olsa {
2042c75540e3SJiri Olsa char *output = output_ ? strdup(output_) : NULL;
2043c75540e3SJiri Olsa char *sort = sort_ ? strdup(sort_) : NULL;
2044c75540e3SJiri Olsa int ret;
2045c75540e3SJiri Olsa
2046c75540e3SJiri Olsa PARSE_LIST(output, c2c_hists__init_output);
2047c75540e3SJiri Olsa PARSE_LIST(sort, c2c_hists__init_sort);
2048c75540e3SJiri Olsa
2049c75540e3SJiri Olsa /* copy sort keys to output fields */
2050c75540e3SJiri Olsa perf_hpp__setup_output_field(hpp_list);
2051c75540e3SJiri Olsa
2052c75540e3SJiri Olsa /*
2053c75540e3SJiri Olsa * We dont need other sorting keys other than those
2054c75540e3SJiri Olsa * we already specified. It also really slows down
2055c75540e3SJiri Olsa * the processing a lot with big number of output
2056c75540e3SJiri Olsa * fields, so switching this off for c2c.
2057c75540e3SJiri Olsa */
2058c75540e3SJiri Olsa
2059c75540e3SJiri Olsa #if 0
2060c75540e3SJiri Olsa /* and then copy output fields to sort keys */
2061c75540e3SJiri Olsa perf_hpp__append_sort_keys(&hists->list);
2062c75540e3SJiri Olsa #endif
2063c75540e3SJiri Olsa
2064c75540e3SJiri Olsa free(output);
20651d62fcd6SJiri Olsa free(sort);
20661d62fcd6SJiri Olsa return ret;
2067c75540e3SJiri Olsa }
2068c75540e3SJiri Olsa
c2c_hists__init(struct c2c_hists * hists,const char * sort,int nr_header_lines)2069c75540e3SJiri Olsa static int c2c_hists__init(struct c2c_hists *hists,
2070c75540e3SJiri Olsa const char *sort,
2071c75540e3SJiri Olsa int nr_header_lines)
2072c75540e3SJiri Olsa {
2073c75540e3SJiri Olsa __hists__init(&hists->hists, &hists->list);
2074c75540e3SJiri Olsa
2075c75540e3SJiri Olsa /*
2076c75540e3SJiri Olsa * Initialize only with sort fields, we need to resort
20771d62fcd6SJiri Olsa * later anyway, and that's where we add output fields
20781d62fcd6SJiri Olsa * as well.
20791d62fcd6SJiri Olsa */
2080c75540e3SJiri Olsa perf_hpp_list__init(&hists->list);
2081c75540e3SJiri Olsa
2082c75540e3SJiri Olsa /* Overload number of header lines.*/
2083c75540e3SJiri Olsa hists->list.nr_header_lines = nr_header_lines;
2084c75540e3SJiri Olsa
2085c75540e3SJiri Olsa return hpp_list__parse(&hists->list, NULL, sort);
2086c75540e3SJiri Olsa }
2087c75540e3SJiri Olsa
c2c_hists__reinit(struct c2c_hists * c2c_hists,const char * output,const char * sort)2088c75540e3SJiri Olsa static int c2c_hists__reinit(struct c2c_hists *c2c_hists,
2089c75540e3SJiri Olsa const char *output,
2090c75540e3SJiri Olsa const char *sort)
2091c4a75bb9SJiri Olsa {
20929857b717SJiri Olsa perf_hpp__reset_output_field(&c2c_hists->list);
209369a95bfdSLeo Yan return hpp_list__parse(&c2c_hists->list, output, sort);
209469a95bfdSLeo Yan }
209569a95bfdSLeo Yan
209669a95bfdSLeo Yan #define DISPLAY_LINE_LIMIT 0.001
209769a95bfdSLeo Yan
filter_display(u32 val,u32 sum)209869a95bfdSLeo Yan static u8 filter_display(u32 val, u32 sum)
209969a95bfdSLeo Yan {
210069a95bfdSLeo Yan if (sum == 0 || ((double)val / sum) < DISPLAY_LINE_LIMIT)
21019857b717SJiri Olsa return HIST_FILTER__C2C;
21029857b717SJiri Olsa
21039857b717SJiri Olsa return 0;
21049857b717SJiri Olsa }
2105af09b2d3SJiri Olsa
he__display(struct hist_entry * he,struct c2c_stats * stats)21069857b717SJiri Olsa static bool he__display(struct hist_entry *he, struct c2c_stats *stats)
21079857b717SJiri Olsa {
21089857b717SJiri Olsa struct c2c_hist_entry *c2c_he;
21099857b717SJiri Olsa
211055b95776SJiri Olsa if (c2c.show_all)
2111c82ccc3aSLeo Yan return true;
211269a95bfdSLeo Yan
211369a95bfdSLeo Yan c2c_he = container_of(he, struct c2c_hist_entry, he);
211455b95776SJiri Olsa
2115c82ccc3aSLeo Yan switch (c2c.display) {
211669a95bfdSLeo Yan case DISPLAY_LCL_HITM:
211769a95bfdSLeo Yan he->filtered = filter_display(c2c_he->stats.lcl_hitm,
2118d940baccSJiri Olsa stats->lcl_hitm);
2119c82ccc3aSLeo Yan break;
212069a95bfdSLeo Yan case DISPLAY_RMT_HITM:
212169a95bfdSLeo Yan he->filtered = filter_display(c2c_he->stats.rmt_hitm,
212269a95bfdSLeo Yan stats->rmt_hitm);
2123f37c5d91SLeo Yan break;
2124f37c5d91SLeo Yan case DISPLAY_TOT_HITM:
2125f37c5d91SLeo Yan he->filtered = filter_display(c2c_he->stats.tot_hitm,
2126f37c5d91SLeo Yan stats->tot_hitm);
212755b95776SJiri Olsa break;
212855b95776SJiri Olsa case DISPLAY_SNP_PEER:
21292cca512aSZou Wei he->filtered = filter_display(c2c_he->stats.tot_peer,
213055b95776SJiri Olsa stats->tot_peer);
21319857b717SJiri Olsa break;
21329857b717SJiri Olsa default:
21339857b717SJiri Olsa break;
21342290e1d6SLeo Yan }
21359857b717SJiri Olsa
21369857b717SJiri Olsa return he->filtered == 0;
21372290e1d6SLeo Yan }
21389857b717SJiri Olsa
is_valid_hist_entry(struct hist_entry * he)21399857b717SJiri Olsa static inline bool is_valid_hist_entry(struct hist_entry *he)
21402290e1d6SLeo Yan {
21412290e1d6SLeo Yan struct c2c_hist_entry *c2c_he;
21422290e1d6SLeo Yan bool has_record = false;
21432290e1d6SLeo Yan
21442290e1d6SLeo Yan c2c_he = container_of(he, struct c2c_hist_entry, he);
21452290e1d6SLeo Yan
2146c82ccc3aSLeo Yan /* It's a valid entry if contains stores */
21472290e1d6SLeo Yan if (c2c_he->stats.store)
21482290e1d6SLeo Yan return true;
2149c82ccc3aSLeo Yan
21502290e1d6SLeo Yan switch (c2c.display) {
21512290e1d6SLeo Yan case DISPLAY_LCL_HITM:
2152c82ccc3aSLeo Yan has_record = !!c2c_he->stats.lcl_hitm;
21532290e1d6SLeo Yan break;
21542290e1d6SLeo Yan case DISPLAY_RMT_HITM:
2155f37c5d91SLeo Yan has_record = !!c2c_he->stats.rmt_hitm;
2156f37c5d91SLeo Yan break;
21572290e1d6SLeo Yan case DISPLAY_TOT_HITM:
21582290e1d6SLeo Yan has_record = !!c2c_he->stats.tot_hitm;
21592290e1d6SLeo Yan break;
21602290e1d6SLeo Yan case DISPLAY_SNP_PEER:
21612290e1d6SLeo Yan has_record = !!c2c_he->stats.tot_peer;
21629857b717SJiri Olsa default:
21639857b717SJiri Olsa break;
21647f834c2eSJiri Olsa }
21657f834c2eSJiri Olsa
21667f834c2eSJiri Olsa return has_record;
21677f834c2eSJiri Olsa }
21687f834c2eSJiri Olsa
set_node_width(struct c2c_hist_entry * c2c_he,int len)21697f834c2eSJiri Olsa static void set_node_width(struct c2c_hist_entry *c2c_he, int len)
21707f834c2eSJiri Olsa {
21717f834c2eSJiri Olsa struct c2c_dimension *dim;
21727f834c2eSJiri Olsa
21737f834c2eSJiri Olsa dim = &c2c.hists == c2c_he->hists ?
21747f834c2eSJiri Olsa &dim_dcacheline_node : &dim_offset_node;
21757f834c2eSJiri Olsa
21767f834c2eSJiri Olsa if (len > dim->width)
21777f834c2eSJiri Olsa dim->width = len;
21787f834c2eSJiri Olsa }
21797f834c2eSJiri Olsa
set_nodestr(struct c2c_hist_entry * c2c_he)21807f834c2eSJiri Olsa static int set_nodestr(struct c2c_hist_entry *c2c_he)
21817f834c2eSJiri Olsa {
21827f834c2eSJiri Olsa char buf[30];
21831006c5c1SYury Norov int len;
21847f834c2eSJiri Olsa
21857f834c2eSJiri Olsa if (c2c_he->nodestr)
21867f834c2eSJiri Olsa return 0;
21877f834c2eSJiri Olsa
21887f834c2eSJiri Olsa if (!bitmap_empty(c2c_he->nodeset, c2c.nodes_cnt)) {
21897f834c2eSJiri Olsa len = bitmap_scnprintf(c2c_he->nodeset, c2c.nodes_cnt,
21907f834c2eSJiri Olsa buf, sizeof(buf));
21917f834c2eSJiri Olsa } else {
21927f834c2eSJiri Olsa len = scnprintf(buf, sizeof(buf), "N/A");
21937f834c2eSJiri Olsa }
21947f834c2eSJiri Olsa
219537731388SJiri Olsa set_node_width(c2c_he, len);
219625aa84e3SJiri Olsa c2c_he->nodestr = strdup(buf);
219725aa84e3SJiri Olsa return c2c_he->nodestr ? 0 : -ENOMEM;
219825aa84e3SJiri Olsa }
219937731388SJiri Olsa
calc_width(struct c2c_hist_entry * c2c_he)220037731388SJiri Olsa static void calc_width(struct c2c_hist_entry *c2c_he)
22017f834c2eSJiri Olsa {
220225aa84e3SJiri Olsa struct c2c_hists *c2c_hists;
220325aa84e3SJiri Olsa
2204e4c38fd4SJiri Olsa c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
2205ec06f9b9SJiri Olsa hists__calc_col_len(&c2c_hists->hists, &c2c_he->he);
220637731388SJiri Olsa set_nodestr(c2c_he);
220737731388SJiri Olsa }
220837731388SJiri Olsa
filter_cb(struct hist_entry * he,void * arg __maybe_unused)220937731388SJiri Olsa static int filter_cb(struct hist_entry *he, void *arg __maybe_unused)
221089d9ba8fSJiri Olsa {
22116a53da05SArnaldo Carvalho de Melo struct c2c_hist_entry *c2c_he;
221289d9ba8fSJiri Olsa
221337731388SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
221425aa84e3SJiri Olsa
22152290e1d6SLeo Yan if (c2c.show_src && !he->srcline)
22169857b717SJiri Olsa he->srcline = hist_entry__srcline(he);
22179857b717SJiri Olsa
2218ec06f9b9SJiri Olsa calc_width(c2c_he);
2219ec06f9b9SJiri Olsa
2220ec06f9b9SJiri Olsa if (!is_valid_hist_entry(he))
2221e4c38fd4SJiri Olsa he->filtered = HIST_FILTER__C2C;
2222ec06f9b9SJiri Olsa
2223ec06f9b9SJiri Olsa return 0;
2224ec06f9b9SJiri Olsa }
22251834436eSLeo Yan
resort_cl_cb(struct hist_entry * he,void * arg __maybe_unused)2226ec06f9b9SJiri Olsa static int resort_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
2227ec06f9b9SJiri Olsa {
2228ec06f9b9SJiri Olsa struct c2c_hist_entry *c2c_he;
2229ec06f9b9SJiri Olsa struct c2c_hists *c2c_hists;
22309857b717SJiri Olsa bool display = he__display(he, &c2c.shared_clines_stats);
2231bb342daeSJiri Olsa
2232bb342daeSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
2233bb342daeSJiri Olsa c2c_hists = c2c_he->hists;
2234bc229c21SJiri Olsa
2235bb342daeSJiri Olsa if (display && c2c_hists) {
2236fc9c630eSJiri Olsa static unsigned int idx;
223722dd59d1SJiri Olsa
2238ec06f9b9SJiri Olsa c2c_he->cacheline_idx = idx++;
2239ec06f9b9SJiri Olsa calc_width(c2c_he);
2240ec06f9b9SJiri Olsa
2241ec06f9b9SJiri Olsa c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
2242ec06f9b9SJiri Olsa
2243ec06f9b9SJiri Olsa hists__collapse_resort(&c2c_hists->hists, NULL);
2244ec06f9b9SJiri Olsa hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb);
22457c10b65aSLeo Yan }
2246f37c5d91SLeo Yan
2247f37c5d91SLeo Yan return 0;
2248f37c5d91SLeo Yan }
2249f37c5d91SLeo Yan
22507c10b65aSLeo Yan static struct c2c_header header_node_0 = HEADER_LOW("Node");
22517c10b65aSLeo Yan static struct c2c_header header_node_1_hitms_stores =
22521e181b92SJiri Olsa HEADER_LOW("Node{cpus %hitms %stores}");
22531e181b92SJiri Olsa static struct c2c_header header_node_1_peers_stores =
22547c10b65aSLeo Yan HEADER_LOW("Node{cpus %peers %stores}");
22557c10b65aSLeo Yan static struct c2c_header header_node_2 = HEADER_LOW("Node{cpu list}");
22567c10b65aSLeo Yan
setup_nodes_header(void)22577c10b65aSLeo Yan static void setup_nodes_header(void)
22587c10b65aSLeo Yan {
2259f37c5d91SLeo Yan switch (c2c.node_info) {
2260f37c5d91SLeo Yan case 0:
2261f37c5d91SLeo Yan dim_node.header = header_node_0;
2262f37c5d91SLeo Yan break;
22637c10b65aSLeo Yan case 1:
22647c10b65aSLeo Yan if (c2c.display == DISPLAY_SNP_PEER)
22657c10b65aSLeo Yan dim_node.header = header_node_1_peers_stores;
22667c10b65aSLeo Yan else
22677c10b65aSLeo Yan dim_node.header = header_node_1_hitms_stores;
22687c10b65aSLeo Yan break;
22697c10b65aSLeo Yan case 2:
22707c10b65aSLeo Yan dim_node.header = header_node_2;
22717c10b65aSLeo Yan break;
22721e181b92SJiri Olsa default:
22731e181b92SJiri Olsa break;
22741e181b92SJiri Olsa }
22751e181b92SJiri Olsa
22761e181b92SJiri Olsa return;
22771e181b92SJiri Olsa }
22786d18804bSIan Rogers
setup_nodes(struct perf_session * session)22796d18804bSIan Rogers static int setup_nodes(struct perf_session *session)
22801e181b92SJiri Olsa {
22811e181b92SJiri Olsa struct numa_node *n;
22821e181b92SJiri Olsa unsigned long **nodes;
22831e181b92SJiri Olsa int node, idx;
22841e181b92SJiri Olsa struct perf_cpu cpu;
22851e181b92SJiri Olsa int *cpu2node;
22861ea770f6SRavi Bangoria
22871e181b92SJiri Olsa if (c2c.node_info > 2)
22881e181b92SJiri Olsa c2c.node_info = 2;
22891e181b92SJiri Olsa
22901e181b92SJiri Olsa c2c.nodes_cnt = session->header.env.nr_numa_nodes;
22911e181b92SJiri Olsa c2c.cpus_cnt = session->header.env.nr_cpus_avail;
22921e181b92SJiri Olsa
22931e181b92SJiri Olsa n = session->header.env.numa_nodes;
22941e181b92SJiri Olsa if (!n)
22951e181b92SJiri Olsa return -EINVAL;
22961e181b92SJiri Olsa
22971e181b92SJiri Olsa nodes = zalloc(sizeof(unsigned long *) * c2c.nodes_cnt);
22981e181b92SJiri Olsa if (!nodes)
22991e181b92SJiri Olsa return -ENOMEM;
23001e181b92SJiri Olsa
23011e181b92SJiri Olsa c2c.nodes = nodes;
23026d18804bSIan Rogers
23036d18804bSIan Rogers cpu2node = zalloc(sizeof(int) * c2c.cpus_cnt);
23041e181b92SJiri Olsa if (!cpu2node)
23051e181b92SJiri Olsa return -ENOMEM;
23061e181b92SJiri Olsa
23071e181b92SJiri Olsa for (idx = 0; idx < c2c.cpus_cnt; idx++)
2308f854839bSJiri Olsa cpu2node[idx] = -1;
23091e181b92SJiri Olsa
23101e181b92SJiri Olsa c2c.cpu2node = cpu2node;
23117fc5b571SAndy Shevchenko
23121e181b92SJiri Olsa for (node = 0; node < c2c.nodes_cnt; node++) {
23131e181b92SJiri Olsa struct perf_cpu_map *map = n[node].map;
23141e181b92SJiri Olsa unsigned long *set;
2315e34c9402SJiri Olsa
2316e34c9402SJiri Olsa set = bitmap_zalloc(c2c.cpus_cnt);
2317e34c9402SJiri Olsa if (!set)
2318315c0a1fSJiri Olsa return -ENOMEM;
2319e34c9402SJiri Olsa
2320e34c9402SJiri Olsa nodes[node] = set;
232184d2f4f0SIan Rogers
232275d7ba32SSean Christopherson /* empty node, skip */
23231e181b92SJiri Olsa if (perf_cpu_map__empty(map))
23246d18804bSIan Rogers continue;
23251e181b92SJiri Olsa
23261e181b92SJiri Olsa perf_cpu_map__for_each_cpu(cpu, idx, map) {
23276d18804bSIan Rogers __set_bit(cpu.cpu, set);
23281e181b92SJiri Olsa
23291e181b92SJiri Olsa if (WARN_ONCE(cpu2node[cpu.cpu] != -1, "node/cpu topology bug"))
23301e181b92SJiri Olsa return -EINVAL;
23311e181b92SJiri Olsa
23321e181b92SJiri Olsa cpu2node[cpu.cpu] = node;
23331e181b92SJiri Olsa }
23341e181b92SJiri Olsa }
23357ef2efaaSJiri Olsa
2336f37c5d91SLeo Yan setup_nodes_header();
23377ef2efaaSJiri Olsa return 0;
23381834436eSLeo Yan }
23397ef2efaaSJiri Olsa
23407ef2efaaSJiri Olsa #define HAS_HITMS(__h) ((__h)->stats.lcl_hitm || (__h)->stats.rmt_hitm)
23417ef2efaaSJiri Olsa #define HAS_PEER(__h) ((__h)->stats.lcl_peer || (__h)->stats.rmt_peer)
23427ef2efaaSJiri Olsa
resort_shared_cl_cb(struct hist_entry * he,void * arg __maybe_unused)2343f37c5d91SLeo Yan static int resort_shared_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
23447ef2efaaSJiri Olsa {
23451834436eSLeo Yan struct c2c_hist_entry *c2c_he;
23467ef2efaaSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
23477ef2efaaSJiri Olsa
23487ef2efaaSJiri Olsa if (HAS_HITMS(c2c_he) || HAS_PEER(c2c_he)) {
23497ef2efaaSJiri Olsa c2c.shared_clines++;
23507ef2efaaSJiri Olsa c2c_add_stats(&c2c.shared_clines_stats, &c2c_he->stats);
23517ef2efaaSJiri Olsa }
23527ef2efaaSJiri Olsa
23532eb3d689SDavidlohr Bueso return 0;
23547ef2efaaSJiri Olsa }
23557ef2efaaSJiri Olsa
hists__iterate_cb(struct hists * hists,hists__resort_cb_t cb)23567ef2efaaSJiri Olsa static int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb)
23577ef2efaaSJiri Olsa {
23587ef2efaaSJiri Olsa struct rb_node *next = rb_first_cached(&hists->entries);
23597ef2efaaSJiri Olsa int ret = 0;
2360e4c38fd4SJiri Olsa
23617ef2efaaSJiri Olsa while (next) {
23627ef2efaaSJiri Olsa struct hist_entry *he;
23637ef2efaaSJiri Olsa
23647ef2efaaSJiri Olsa he = rb_entry(next, struct hist_entry, rb_node);
23657ef2efaaSJiri Olsa ret = cb(he, NULL);
23667ef2efaaSJiri Olsa if (ret)
23677ef2efaaSJiri Olsa break;
23687ef2efaaSJiri Olsa next = rb_next(&he->rb_node);
236974c63a25SJiri Olsa }
237074c63a25SJiri Olsa
237174c63a25SJiri Olsa return ret;
237274c63a25SJiri Olsa }
237374c63a25SJiri Olsa
print_c2c__display_stats(FILE * out)2374cf874a01SShang XiaoJing static void print_c2c__display_stats(FILE *out)
237574c63a25SJiri Olsa {
237674c63a25SJiri Olsa int llc_misses;
237774c63a25SJiri Olsa struct c2c_stats *stats = &c2c.hists.stats;
237874c63a25SJiri Olsa
237974c63a25SJiri Olsa llc_misses = get_load_llc_misses(stats);
238074c63a25SJiri Olsa
238174c63a25SJiri Olsa fprintf(out, "=================================================\n");
238274c63a25SJiri Olsa fprintf(out, " Trace Event Information \n");
238374c63a25SJiri Olsa fprintf(out, "=================================================\n");
238474c63a25SJiri Olsa fprintf(out, " Total records : %10d\n", stats->nr_entries);
238574c63a25SJiri Olsa fprintf(out, " Locked Load/Store Operations : %10d\n", stats->locks);
238674c63a25SJiri Olsa fprintf(out, " Load Operations : %10d\n", stats->load);
238774c63a25SJiri Olsa fprintf(out, " Loads - uncacheable : %10d\n", stats->ld_uncache);
238874c63a25SJiri Olsa fprintf(out, " Loads - IO : %10d\n", stats->ld_io);
238974c63a25SJiri Olsa fprintf(out, " Loads - Miss : %10d\n", stats->ld_miss);
239074c63a25SJiri Olsa fprintf(out, " Loads - no mapping : %10d\n", stats->ld_noadrs);
239174c63a25SJiri Olsa fprintf(out, " Load Fill Buffer Hit : %10d\n", stats->ld_fbhit);
239274c63a25SJiri Olsa fprintf(out, " Load L1D hit : %10d\n", stats->ld_l1hit);
239374c63a25SJiri Olsa fprintf(out, " Load L2D hit : %10d\n", stats->ld_l2hit);
239474c63a25SJiri Olsa fprintf(out, " Load LLC hit : %10d\n", stats->ld_llchit + stats->lcl_hitm);
239574c63a25SJiri Olsa fprintf(out, " Load Local HITM : %10d\n", stats->lcl_hitm);
239674c63a25SJiri Olsa fprintf(out, " Load Remote HITM : %10d\n", stats->rmt_hitm);
239774c63a25SJiri Olsa fprintf(out, " Load Remote HIT : %10d\n", stats->rmt_hit);
2398d9d5d767SKan Liang fprintf(out, " Load Local DRAM : %10d\n", stats->lcl_dram);
2399d9d5d767SKan Liang fprintf(out, " Load Remote DRAM : %10d\n", stats->rmt_dram);
24003ef1fc17SLeo Yan fprintf(out, " Load MESI State Exclusive : %10d\n", stats->ld_excl);
24013ef1fc17SLeo Yan fprintf(out, " Load MESI State Shared : %10d\n", stats->ld_shared);
240274c63a25SJiri Olsa fprintf(out, " Load LLC Misses : %10d\n", llc_misses);
240374c63a25SJiri Olsa fprintf(out, " Load access blocked by data : %10d\n", stats->blk_data);
240474c63a25SJiri Olsa fprintf(out, " Load access blocked by address : %10d\n", stats->blk_addr);
240574c63a25SJiri Olsa fprintf(out, " Load HIT Local Peer : %10d\n", stats->lcl_peer);
240674c63a25SJiri Olsa fprintf(out, " Load HIT Remote Peer : %10d\n", stats->rmt_peer);
240774c63a25SJiri Olsa fprintf(out, " LLC Misses to Local DRAM : %10.1f%%\n", ((double)stats->lcl_dram/(double)llc_misses) * 100.);
240874c63a25SJiri Olsa fprintf(out, " LLC Misses to Remote DRAM : %10.1f%%\n", ((double)stats->rmt_dram/(double)llc_misses) * 100.);
240974c63a25SJiri Olsa fprintf(out, " LLC Misses to Remote cache (HIT) : %10.1f%%\n", ((double)stats->rmt_hit /(double)llc_misses) * 100.);
241074c63a25SJiri Olsa fprintf(out, " LLC Misses to Remote cache (HITM) : %10.1f%%\n", ((double)stats->rmt_hitm/(double)llc_misses) * 100.);
2411550b4d6fSLeo Yan fprintf(out, " Store Operations : %10d\n", stats->store);
241274c63a25SJiri Olsa fprintf(out, " Store - uncacheable : %10d\n", stats->st_uncache);
241374c63a25SJiri Olsa fprintf(out, " Store - no mapping : %10d\n", stats->st_noadrs);
241474c63a25SJiri Olsa fprintf(out, " Store L1D Hit : %10d\n", stats->st_l1hit);
241574c63a25SJiri Olsa fprintf(out, " Store L1D Miss : %10d\n", stats->st_l1miss);
24167ef2efaaSJiri Olsa fprintf(out, " Store No available memory level : %10d\n", stats->st_na);
24177ef2efaaSJiri Olsa fprintf(out, " No Page Map Rejects : %10d\n", stats->nomap);
24181834436eSLeo Yan fprintf(out, " Unable to parse data source : %10d\n", stats->noparse);
24197ef2efaaSJiri Olsa }
24207ef2efaaSJiri Olsa
print_shared_cacheline_info(FILE * out)24217ef2efaaSJiri Olsa static void print_shared_cacheline_info(FILE *out)
24227ef2efaaSJiri Olsa {
24237ef2efaaSJiri Olsa struct c2c_stats *stats = &c2c.shared_clines_stats;
24247ef2efaaSJiri Olsa int hitm_cnt = stats->lcl_hitm + stats->rmt_hitm;
24257ef2efaaSJiri Olsa
24267ef2efaaSJiri Olsa fprintf(out, "=================================================\n");
24277ef2efaaSJiri Olsa fprintf(out, " Global Shared Cache Line Event Information \n");
24287ef2efaaSJiri Olsa fprintf(out, "=================================================\n");
24297ef2efaaSJiri Olsa fprintf(out, " Total Shared Cache Lines : %10d\n", c2c.shared_clines);
24303ef1fc17SLeo Yan fprintf(out, " Load HITs on shared lines : %10d\n", stats->load);
24317ef2efaaSJiri Olsa fprintf(out, " Fill Buffer Hits on shared lines : %10d\n", stats->ld_fbhit);
2432d9d5d767SKan Liang fprintf(out, " L1D hits on shared lines : %10d\n", stats->ld_l1hit);
24337ef2efaaSJiri Olsa fprintf(out, " L2D hits on shared lines : %10d\n", stats->ld_l2hit);
24347ef2efaaSJiri Olsa fprintf(out, " LLC hits on shared lines : %10d\n", stats->ld_llchit + stats->lcl_hitm);
2435550b4d6fSLeo Yan fprintf(out, " Load hits on peer cache or nodes : %10d\n", stats->lcl_peer + stats->rmt_peer);
24367ef2efaaSJiri Olsa fprintf(out, " Locked Access on shared lines : %10d\n", stats->locks);
24377ef2efaaSJiri Olsa fprintf(out, " Blocked Access on shared lines : %10d\n", stats->blk_data + stats->blk_addr);
24387ef2efaaSJiri Olsa fprintf(out, " Store HITs on shared lines : %10d\n", stats->store);
24392d388bd0SJiri Olsa fprintf(out, " Store L1D hits on shared lines : %10d\n", stats->st_l1hit);
24402d388bd0SJiri Olsa fprintf(out, " Store No available memory level : %10d\n", stats->st_na);
24412d388bd0SJiri Olsa fprintf(out, " Total Merged records : %10d\n", hitm_cnt + stats->store);
24422d388bd0SJiri Olsa }
24432d388bd0SJiri Olsa
print_cacheline(struct c2c_hists * c2c_hists,struct hist_entry * he_cl,struct perf_hpp_list * hpp_list,FILE * out)24442d388bd0SJiri Olsa static void print_cacheline(struct c2c_hists *c2c_hists,
24452d388bd0SJiri Olsa struct hist_entry *he_cl,
24462d388bd0SJiri Olsa struct perf_hpp_list *hpp_list,
24472d388bd0SJiri Olsa FILE *out)
24482d388bd0SJiri Olsa {
24492d388bd0SJiri Olsa char bf[1000];
24502d388bd0SJiri Olsa struct perf_hpp hpp = {
24512d388bd0SJiri Olsa .buf = bf,
24522d388bd0SJiri Olsa .size = 1000,
24532d388bd0SJiri Olsa };
24542d388bd0SJiri Olsa static bool once;
24552d388bd0SJiri Olsa
24562d388bd0SJiri Olsa if (!once) {
24572d388bd0SJiri Olsa hists__fprintf_headers(&c2c_hists->hists, out);
2458550b4d6fSLeo Yan once = true;
24592d388bd0SJiri Olsa } else {
24602d388bd0SJiri Olsa fprintf(out, "\n");
2461550b4d6fSLeo Yan }
24622d388bd0SJiri Olsa
2463e9de7e2fSArnaldo Carvalho de Melo fprintf(out, " ----------------------------------------------------------------------\n");
24642d388bd0SJiri Olsa __hist_entry__snprintf(he_cl, &hpp, hpp_list);
24652d388bd0SJiri Olsa fprintf(out, "%s\n", bf);
24662d388bd0SJiri Olsa fprintf(out, " ----------------------------------------------------------------------\n");
24672d388bd0SJiri Olsa
24682d388bd0SJiri Olsa hists__fprintf(&c2c_hists->hists, false, 0, 0, 0, out, false);
24692d388bd0SJiri Olsa }
24702d388bd0SJiri Olsa
print_pareto(FILE * out)24710998d960SLeo Yan static void print_pareto(FILE *out)
24722d388bd0SJiri Olsa {
2473f37c5d91SLeo Yan struct perf_hpp_list hpp_list;
24740998d960SLeo Yan struct rb_node *nd;
24752d388bd0SJiri Olsa int ret;
24762d388bd0SJiri Olsa const char *cl_output;
24772d388bd0SJiri Olsa
24782d388bd0SJiri Olsa if (c2c.display != DISPLAY_SNP_PEER)
2479550b4d6fSLeo Yan cl_output = "cl_num,"
24800998d960SLeo Yan "cl_rmt_hitm,"
2481f37c5d91SLeo Yan "cl_lcl_hitm,"
2482f37c5d91SLeo Yan "cl_stores_l1hit,"
2483f37c5d91SLeo Yan "cl_stores_l1miss,"
2484f37c5d91SLeo Yan "cl_stores_na,"
2485f37c5d91SLeo Yan "dcacheline";
2486f37c5d91SLeo Yan else
2487f37c5d91SLeo Yan cl_output = "cl_num,"
2488f37c5d91SLeo Yan "cl_rmt_peer,"
24890998d960SLeo Yan "cl_lcl_peer,"
24900998d960SLeo Yan "cl_stores_l1hit,"
24910998d960SLeo Yan "cl_stores_l1miss,"
24922d388bd0SJiri Olsa "cl_stores_na,"
24932d388bd0SJiri Olsa "dcacheline";
24942d388bd0SJiri Olsa
24952d388bd0SJiri Olsa perf_hpp_list__init(&hpp_list);
24962eb3d689SDavidlohr Bueso ret = hpp_list__parse(&hpp_list, cl_output, NULL);
24972d388bd0SJiri Olsa
24982d388bd0SJiri Olsa if (WARN_ONCE(ret, "failed to setup sort entries\n"))
24992d388bd0SJiri Olsa return;
25002d388bd0SJiri Olsa
25012d388bd0SJiri Olsa nd = rb_first_cached(&c2c.hists.hists.entries);
25022d388bd0SJiri Olsa
25032d388bd0SJiri Olsa for (; nd; nd = rb_next(nd)) {
25042d388bd0SJiri Olsa struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
25052d388bd0SJiri Olsa struct c2c_hist_entry *c2c_he;
25062d388bd0SJiri Olsa
25072d388bd0SJiri Olsa if (he->filtered)
25082d388bd0SJiri Olsa continue;
25092d388bd0SJiri Olsa
25102709b97dSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
25112709b97dSJiri Olsa print_cacheline(c2c_he->hists, he, &hpp_list, out);
251263503dbaSJiri Olsa }
251332dcd021SJiri Olsa }
25142709b97dSJiri Olsa
print_c2c_info(FILE * out,struct perf_session * session)25152709b97dSJiri Olsa static void print_c2c_info(FILE *out, struct perf_session *session)
25162709b97dSJiri Olsa {
25172709b97dSJiri Olsa struct evlist *evlist = session->evlist;
25182709b97dSJiri Olsa struct evsel *evsel;
25192709b97dSJiri Olsa bool first = true;
25202709b97dSJiri Olsa
25218ab2e96dSArnaldo Carvalho de Melo fprintf(out, "=================================================\n");
25222709b97dSJiri Olsa fprintf(out, " c2c details \n");
25232709b97dSJiri Olsa fprintf(out, "=================================================\n");
2524faa30dfaSLeo Yan
2525d940baccSJiri Olsa evlist__for_each_entry(evlist, evsel) {
2526fc9c630eSJiri Olsa fprintf(out, "%-36s: %s\n", first ? " Events" : "", evsel__name(evsel));
25272709b97dSJiri Olsa first = false;
25282709b97dSJiri Olsa }
25292709b97dSJiri Olsa fprintf(out, " Cachelines sort on : %s\n",
25302d388bd0SJiri Olsa display_str[c2c.display]);
25312d388bd0SJiri Olsa fprintf(out, " Cacheline data grouping : %s\n", c2c.cl_sort);
25322d388bd0SJiri Olsa }
253374c63a25SJiri Olsa
perf_c2c__hists_fprintf(FILE * out,struct perf_session * session)25347ef2efaaSJiri Olsa static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
25357ef2efaaSJiri Olsa {
25362709b97dSJiri Olsa setup_pager();
25372709b97dSJiri Olsa
253874c63a25SJiri Olsa print_c2c__display_stats(out);
253974c63a25SJiri Olsa fprintf(out, "\n");
254074c63a25SJiri Olsa print_shared_cacheline_info(out);
254174c63a25SJiri Olsa fprintf(out, "\n");
25422d388bd0SJiri Olsa print_c2c_info(out, session);
25432d388bd0SJiri Olsa
25442d388bd0SJiri Olsa if (c2c.stats_only)
25452d388bd0SJiri Olsa return;
25462d388bd0SJiri Olsa
25472d388bd0SJiri Olsa fprintf(out, "\n");
2548e9de7e2fSArnaldo Carvalho de Melo fprintf(out, "=================================================\n");
25492d388bd0SJiri Olsa fprintf(out, " Shared Data Cache Line Table \n");
25502d388bd0SJiri Olsa fprintf(out, "=================================================\n");
25512d388bd0SJiri Olsa fprintf(out, "#\n");
25522d388bd0SJiri Olsa
25532d388bd0SJiri Olsa hists__fprintf(&c2c.hists.hists, true, 0, 0, 0, stdout, true);
25542d388bd0SJiri Olsa
25552d388bd0SJiri Olsa fprintf(out, "\n");
25562d388bd0SJiri Olsa fprintf(out, "=================================================\n");
25572d388bd0SJiri Olsa fprintf(out, " Shared Cache Line Distribution Pareto \n");
25581e181b92SJiri Olsa fprintf(out, "=================================================\n");
25595a1a99cdSJiri Olsa fprintf(out, "#\n");
25605a1a99cdSJiri Olsa
25615a1a99cdSJiri Olsa print_pareto(out);
25625a1a99cdSJiri Olsa }
25632eb3d689SDavidlohr Bueso
25645a1a99cdSJiri Olsa #ifdef HAVE_SLANG_SUPPORT
c2c_browser__update_nr_entries(struct hist_browser * hb)25655a1a99cdSJiri Olsa static void c2c_browser__update_nr_entries(struct hist_browser *hb)
25665a1a99cdSJiri Olsa {
25675a1a99cdSJiri Olsa u64 nr_entries = 0;
25685a1a99cdSJiri Olsa struct rb_node *nd = rb_first_cached(&hb->hists->entries);
25695a1a99cdSJiri Olsa
25705a1a99cdSJiri Olsa while (nd) {
25715a1a99cdSJiri Olsa struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
25725a1a99cdSJiri Olsa
25735a1a99cdSJiri Olsa if (!he->filtered)
25745a1a99cdSJiri Olsa nr_entries++;
25755a1a99cdSJiri Olsa
25765a1a99cdSJiri Olsa nd = rb_next(nd);
2577f1c5fd4dSJiri Olsa }
2578f1c5fd4dSJiri Olsa
2579f1c5fd4dSJiri Olsa hb->nr_non_filtered_entries = nr_entries;
2580f1c5fd4dSJiri Olsa }
2581f1c5fd4dSJiri Olsa
2582f1c5fd4dSJiri Olsa struct c2c_cacheline_browser {
2583f1c5fd4dSJiri Olsa struct hist_browser hb;
2584f1c5fd4dSJiri Olsa struct hist_entry *he;
2585f1c5fd4dSJiri Olsa };
2586f1c5fd4dSJiri Olsa
2587f1c5fd4dSJiri Olsa static int
perf_c2c_cacheline_browser__title(struct hist_browser * browser,char * bf,size_t size)2588f1c5fd4dSJiri Olsa perf_c2c_cacheline_browser__title(struct hist_browser *browser,
2589f1c5fd4dSJiri Olsa char *bf, size_t size)
2590f1c5fd4dSJiri Olsa {
2591f1c5fd4dSJiri Olsa struct c2c_cacheline_browser *cl_browser;
2592f1c5fd4dSJiri Olsa struct hist_entry *he;
2593f1c5fd4dSJiri Olsa uint64_t addr = 0;
25941470a108SFeng Tang
2595f1c5fd4dSJiri Olsa cl_browser = container_of(browser, struct c2c_cacheline_browser, hb);
2596f1c5fd4dSJiri Olsa he = cl_browser->he;
2597f1c5fd4dSJiri Olsa
2598f1c5fd4dSJiri Olsa if (he->mem_info)
2599f1c5fd4dSJiri Olsa addr = cl_address(he->mem_info->daddr.addr, chk_double_cl);
2600f1c5fd4dSJiri Olsa
2601f1c5fd4dSJiri Olsa scnprintf(bf, size, "Cacheline 0x%lx", addr);
2602f1c5fd4dSJiri Olsa return 0;
2603f1c5fd4dSJiri Olsa }
2604f1c5fd4dSJiri Olsa
2605f1c5fd4dSJiri Olsa static struct c2c_cacheline_browser*
c2c_cacheline_browser__new(struct hists * hists,struct hist_entry * he)2606f1c5fd4dSJiri Olsa c2c_cacheline_browser__new(struct hists *hists, struct hist_entry *he)
2607f1c5fd4dSJiri Olsa {
2608f1c5fd4dSJiri Olsa struct c2c_cacheline_browser *browser;
2609f1c5fd4dSJiri Olsa
2610f1c5fd4dSJiri Olsa browser = zalloc(sizeof(*browser));
2611f1c5fd4dSJiri Olsa if (browser) {
2612f1c5fd4dSJiri Olsa hist_browser__init(&browser->hb, hists);
2613f1c5fd4dSJiri Olsa browser->hb.c2c_filter = true;
2614f1c5fd4dSJiri Olsa browser->hb.title = perf_c2c_cacheline_browser__title;
2615f1c5fd4dSJiri Olsa browser->he = he;
2616f1c5fd4dSJiri Olsa }
2617f1c5fd4dSJiri Olsa
2618f1c5fd4dSJiri Olsa return browser;
2619f1c5fd4dSJiri Olsa }
2620f1c5fd4dSJiri Olsa
perf_c2c__browse_cacheline(struct hist_entry * he)2621f1c5fd4dSJiri Olsa static int perf_c2c__browse_cacheline(struct hist_entry *he)
2622f1c5fd4dSJiri Olsa {
262349b8e2beSRasmus Villemoes struct c2c_hist_entry *c2c_he;
2624239fb4feSKim Phillips struct c2c_hists *c2c_hists;
2625239fb4feSKim Phillips struct c2c_cacheline_browser *cl_browser;
2626239fb4feSKim Phillips struct hist_browser *browser;
26279a406eb6SJiri Olsa int key = -1;
2628f1c5fd4dSJiri Olsa static const char help[] =
262973978332SJiri Olsa " ENTER Toggle callchains (if present) \n"
263073978332SJiri Olsa " n Toggle Node details info \n"
263173978332SJiri Olsa " s Toggle full length of symbol and source line columns \n"
2632590b6a3aSJiri Olsa " q Return back to cacheline list \n";
2633590b6a3aSJiri Olsa
2634590b6a3aSJiri Olsa if (!he)
2635f1c5fd4dSJiri Olsa return 0;
2636f1c5fd4dSJiri Olsa
2637f1c5fd4dSJiri Olsa /* Display compact version first. */
2638f1c5fd4dSJiri Olsa c2c.symbol_full = false;
2639f1c5fd4dSJiri Olsa
2640f1c5fd4dSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
2641f1c5fd4dSJiri Olsa c2c_hists = c2c_he->hists;
2642f1c5fd4dSJiri Olsa
2643f1c5fd4dSJiri Olsa cl_browser = c2c_cacheline_browser__new(&c2c_hists->hists, he);
2644f1c5fd4dSJiri Olsa if (cl_browser == NULL)
2645f1c5fd4dSJiri Olsa return -1;
2646f1c5fd4dSJiri Olsa
2647f1c5fd4dSJiri Olsa browser = &cl_browser->hb;
2648f1c5fd4dSJiri Olsa
2649f1c5fd4dSJiri Olsa /* reset abort key so that it can get Ctrl-C as a key */
2650f1c5fd4dSJiri Olsa SLang_reset_tty();
2651d10ec006SArnaldo Carvalho de Melo SLang_init_tty(0, 0, 0);
2652f1c5fd4dSJiri Olsa
2653f1c5fd4dSJiri Olsa c2c_browser__update_nr_entries(browser);
2654590b6a3aSJiri Olsa
2655590b6a3aSJiri Olsa while (1) {
2656590b6a3aSJiri Olsa key = hist_browser__run(browser, "? - help", true, 0);
26571a56a425SJiri Olsa
26581a56a425SJiri Olsa switch (key) {
26591a56a425SJiri Olsa case 's':
26601a56a425SJiri Olsa c2c.symbol_full = !c2c.symbol_full;
2661f1c5fd4dSJiri Olsa break;
2662f1c5fd4dSJiri Olsa case 'n':
26639a406eb6SJiri Olsa c2c.node_info = (c2c.node_info + 1) % 3;
26649a406eb6SJiri Olsa setup_nodes_header();
26659a406eb6SJiri Olsa break;
2666f1c5fd4dSJiri Olsa case 'q':
2667f1c5fd4dSJiri Olsa goto out;
2668f1c5fd4dSJiri Olsa case '?':
2669f1c5fd4dSJiri Olsa ui_browser__help_window(&browser->b, help);
2670f1c5fd4dSJiri Olsa break;
2671f1c5fd4dSJiri Olsa default:
2672f1c5fd4dSJiri Olsa break;
2673f1c5fd4dSJiri Olsa }
2674f1c5fd4dSJiri Olsa }
2675f1c5fd4dSJiri Olsa
26765a1a99cdSJiri Olsa out:
26775a1a99cdSJiri Olsa free(cl_browser);
26785a1a99cdSJiri Olsa return 0;
26795a1a99cdSJiri Olsa }
26805a1a99cdSJiri Olsa
perf_c2c_browser__title(struct hist_browser * browser,char * bf,size_t size)2681faa30dfaSLeo Yan static int perf_c2c_browser__title(struct hist_browser *browser,
268255b95776SJiri Olsa char *bf, size_t size)
2683d940baccSJiri Olsa {
26845a1a99cdSJiri Olsa scnprintf(bf, size,
26855a1a99cdSJiri Olsa "Shared Data Cache Line Table "
26865a1a99cdSJiri Olsa "(%lu entries, sorted on %s)",
26875a1a99cdSJiri Olsa browser->nr_non_filtered_entries,
26885a1a99cdSJiri Olsa display_str[c2c.display]);
26895a1a99cdSJiri Olsa return 0;
26905a1a99cdSJiri Olsa }
26915a1a99cdSJiri Olsa
26925a1a99cdSJiri Olsa static struct hist_browser*
perf_c2c_browser__new(struct hists * hists)26935a1a99cdSJiri Olsa perf_c2c_browser__new(struct hists *hists)
26945a1a99cdSJiri Olsa {
26955a1a99cdSJiri Olsa struct hist_browser *browser = hist_browser__new(hists);
26965a1a99cdSJiri Olsa
26975a1a99cdSJiri Olsa if (browser) {
26985a1a99cdSJiri Olsa browser->title = perf_c2c_browser__title;
26995a1a99cdSJiri Olsa browser->c2c_filter = true;
27005a1a99cdSJiri Olsa }
27015a1a99cdSJiri Olsa
27025a1a99cdSJiri Olsa return browser;
27035a1a99cdSJiri Olsa }
270449b8e2beSRasmus Villemoes
perf_c2c__hists_browse(struct hists * hists)27059a406eb6SJiri Olsa static int perf_c2c__hists_browse(struct hists *hists)
2706239fb4feSKim Phillips {
27079a406eb6SJiri Olsa struct hist_browser *browser;
27085a1a99cdSJiri Olsa int key = -1;
27095a1a99cdSJiri Olsa static const char help[] =
27105a1a99cdSJiri Olsa " d Display cacheline details \n"
27115a1a99cdSJiri Olsa " ENTER Toggle callchains (if present) \n"
27125a1a99cdSJiri Olsa " q Quit \n";
27135a1a99cdSJiri Olsa
27145a1a99cdSJiri Olsa browser = perf_c2c_browser__new(hists);
27155a1a99cdSJiri Olsa if (browser == NULL)
27165a1a99cdSJiri Olsa return -1;
27175a1a99cdSJiri Olsa
27185a1a99cdSJiri Olsa /* reset abort key so that it can get Ctrl-C as a key */
27195a1a99cdSJiri Olsa SLang_reset_tty();
2720d10ec006SArnaldo Carvalho de Melo SLang_init_tty(0, 0, 0);
27215a1a99cdSJiri Olsa
27225a1a99cdSJiri Olsa c2c_browser__update_nr_entries(browser);
27235a1a99cdSJiri Olsa
27245a1a99cdSJiri Olsa while (1) {
2725f1c5fd4dSJiri Olsa key = hist_browser__run(browser, "? - help", true, 0);
2726f1c5fd4dSJiri Olsa
2727f1c5fd4dSJiri Olsa switch (key) {
27289a406eb6SJiri Olsa case 'q':
27299a406eb6SJiri Olsa goto out;
27309a406eb6SJiri Olsa case 'd':
27315a1a99cdSJiri Olsa perf_c2c__browse_cacheline(browser->he_selection);
27325a1a99cdSJiri Olsa break;
27335a1a99cdSJiri Olsa case '?':
27345a1a99cdSJiri Olsa ui_browser__help_window(&browser->b, help);
27355a1a99cdSJiri Olsa break;
27365a1a99cdSJiri Olsa default:
27375a1a99cdSJiri Olsa break;
27385a1a99cdSJiri Olsa }
27395a1a99cdSJiri Olsa }
27405a1a99cdSJiri Olsa
27412709b97dSJiri Olsa out:
27425a1a99cdSJiri Olsa hist_browser__delete(browser);
27431936feaeSNamhyung Kim return 0;
27442709b97dSJiri Olsa }
27455a1a99cdSJiri Olsa
perf_c2c_display(struct perf_session * session)27465a1a99cdSJiri Olsa static void perf_c2c_display(struct perf_session *session)
27475a1a99cdSJiri Olsa {
27485a1a99cdSJiri Olsa if (use_browser == 0)
27492709b97dSJiri Olsa perf_c2c__hists_fprintf(stdout, session);
27505a1a99cdSJiri Olsa else
27515a1a99cdSJiri Olsa perf_c2c__hists_browse(&c2c.hists.hists);
27522709b97dSJiri Olsa }
27535a1a99cdSJiri Olsa #else
perf_c2c_display(struct perf_session * session)27545a1a99cdSJiri Olsa static void perf_c2c_display(struct perf_session *session)
27555a1a99cdSJiri Olsa {
2756d0802b1eSJiri Olsa use_browser = 0;
27575a1a99cdSJiri Olsa perf_c2c__hists_fprintf(stdout, session);
2758d0802b1eSJiri Olsa }
2759d0802b1eSJiri Olsa #endif /* HAVE_SLANG_SUPPORT */
2760d0802b1eSJiri Olsa
fill_line(const char * orig,int len)2761d0802b1eSJiri Olsa static char *fill_line(const char *orig, int len)
2762d0802b1eSJiri Olsa {
2763d0802b1eSJiri Olsa int i, j, olen = strlen(orig);
2764d0802b1eSJiri Olsa char *buf;
2765d0802b1eSJiri Olsa
2766d0802b1eSJiri Olsa buf = zalloc(len + 1);
2767d0802b1eSJiri Olsa if (!buf)
2768d0802b1eSJiri Olsa return NULL;
2769d0802b1eSJiri Olsa
2770d0802b1eSJiri Olsa j = len / 2 - olen / 2;
2771d0802b1eSJiri Olsa
2772d0802b1eSJiri Olsa for (i = 0; i < j - 1; i++)
2773d0802b1eSJiri Olsa buf[i] = '-';
2774d0802b1eSJiri Olsa
2775d0802b1eSJiri Olsa buf[i++] = ' ';
2776d0802b1eSJiri Olsa
2777d0802b1eSJiri Olsa strcpy(buf + i, orig);
2778d0802b1eSJiri Olsa
2779d0802b1eSJiri Olsa i += olen;
2780d0802b1eSJiri Olsa
2781d0802b1eSJiri Olsa buf[i++] = ' ';
2782d0802b1eSJiri Olsa
2783d0802b1eSJiri Olsa for (; i < len; i++)
2784d0802b1eSJiri Olsa buf[i] = '-';
2785d0802b1eSJiri Olsa
2786d0802b1eSJiri Olsa return buf;
2787d0802b1eSJiri Olsa }
2788d0802b1eSJiri Olsa
ui_quirks(void)27895a1a99cdSJiri Olsa static int ui_quirks(void)
27905a1a99cdSJiri Olsa {
27915a1a99cdSJiri Olsa const char *nodestr = "Data address";
27921470a108SFeng Tang char *buf;
27935a1a99cdSJiri Olsa
279455b95776SJiri Olsa if (!c2c.use_stdio) {
27952be0bc75SLeo Yan dim_offset.width = 5;
2796d0802b1eSJiri Olsa dim_offset.header = header_offset_tui;
2797d0802b1eSJiri Olsa nodestr = chk_double_cl ? "Double-CL" : "CL";
27981470a108SFeng Tang }
27991470a108SFeng Tang
280003d9fcb7SJiri Olsa dim_percent_costly_snoop.header = percent_costly_snoop_header[c2c.display];
280103d9fcb7SJiri Olsa
2802d0802b1eSJiri Olsa /* Fix the zero line for dcacheline column. */
2803d0802b1eSJiri Olsa buf = fill_line(chk_double_cl ? "Double-Cacheline" : "Cacheline",
2804d0802b1eSJiri Olsa dim_dcacheline.width +
2805d0802b1eSJiri Olsa dim_dcacheline_node.width +
2806d0802b1eSJiri Olsa dim_dcacheline_count.width + 4);
2807d0802b1eSJiri Olsa if (!buf)
2808d0802b1eSJiri Olsa return -ENOMEM;
280903d9fcb7SJiri Olsa
281003d9fcb7SJiri Olsa dim_dcacheline.header.line[0].text = buf;
2811d0802b1eSJiri Olsa
2812d0802b1eSJiri Olsa /* Fix the zero line for offset column. */
2813d0802b1eSJiri Olsa buf = fill_line(nodestr, dim_offset.width +
2814d0802b1eSJiri Olsa dim_offset_node.width +
2815d0802b1eSJiri Olsa dim_dcacheline_count.width + 4);
2816d0802b1eSJiri Olsa if (!buf)
28175a1a99cdSJiri Olsa return -ENOMEM;
28185a1a99cdSJiri Olsa
2819dd805768SJiri Olsa dim_offset.header.line[0].text = buf;
2820dd805768SJiri Olsa
2821dd805768SJiri Olsa return 0;
2822dd805768SJiri Olsa }
2823dd805768SJiri Olsa
2824dd805768SJiri Olsa #define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent"
2825dd805768SJiri Olsa
2826dd805768SJiri Olsa const char callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
2827dd805768SJiri Olsa CALLCHAIN_REPORT_HELP
2828dd805768SJiri Olsa "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
2829dd805768SJiri Olsa
2830dd805768SJiri Olsa static int
parse_callchain_opt(const struct option * opt,const char * arg,int unset)2831dd805768SJiri Olsa parse_callchain_opt(const struct option *opt, const char *arg, int unset)
2832dd805768SJiri Olsa {
2833dd805768SJiri Olsa struct callchain_param *callchain = opt->value;
2834dd805768SJiri Olsa
2835dd805768SJiri Olsa callchain->enabled = !unset;
2836dd805768SJiri Olsa /*
2837dd805768SJiri Olsa * --no-call-graph
2838dd805768SJiri Olsa */
2839dd805768SJiri Olsa if (unset) {
2840dd805768SJiri Olsa symbol_conf.use_callchain = false;
2841dd805768SJiri Olsa callchain->mode = CHAIN_NONE;
2842dd805768SJiri Olsa return 0;
284363503dbaSJiri Olsa }
2844dd805768SJiri Olsa
2845b3c2cc2bSArnaldo Carvalho de Melo return parse_callchain_report_opt(arg);
2846dd805768SJiri Olsa }
2847dd805768SJiri Olsa
setup_callchain(struct evlist * evlist)2848dd805768SJiri Olsa static int setup_callchain(struct evlist *evlist)
2849eabad8c6SArnaldo Carvalho de Melo {
2850dd805768SJiri Olsa u64 sample_type = evlist__combined_sample_type(evlist);
2851eabad8c6SArnaldo Carvalho de Melo enum perf_call_graph_mode mode = CALLCHAIN_NONE;
2852eabad8c6SArnaldo Carvalho de Melo
2853dd805768SJiri Olsa if ((sample_type & PERF_SAMPLE_REGS_USER) &&
2854dd805768SJiri Olsa (sample_type & PERF_SAMPLE_STACK_USER)) {
2855dd805768SJiri Olsa mode = CALLCHAIN_DWARF;
2856dd805768SJiri Olsa dwarf_callchain_users = true;
2857dd805768SJiri Olsa } else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
2858dd805768SJiri Olsa mode = CALLCHAIN_LBR;
2859dd805768SJiri Olsa else if (sample_type & PERF_SAMPLE_CALLCHAIN)
2860dd805768SJiri Olsa mode = CALLCHAIN_FP;
2861dd805768SJiri Olsa
2862dd805768SJiri Olsa if (!callchain_param.enabled &&
2863dd805768SJiri Olsa callchain_param.mode != CHAIN_NONE &&
2864dd805768SJiri Olsa mode != CALLCHAIN_NONE) {
2865dd805768SJiri Olsa symbol_conf.use_callchain = true;
2866dd805768SJiri Olsa if (callchain_register_param(&callchain_param) < 0) {
2867d80da766SKan Liang ui__error("Can't register callchain params.\n");
2868d80da766SKan Liang return -EINVAL;
2869d80da766SKan Liang }
2870d80da766SKan Liang }
2871d80da766SKan Liang
2872d80da766SKan Liang if (c2c.stitch_lbr && (mode != CALLCHAIN_LBR)) {
2873dd805768SJiri Olsa ui__warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"
2874dd805768SJiri Olsa "Please apply --call-graph lbr when recording.\n");
2875dd805768SJiri Olsa c2c.stitch_lbr = false;
2876dd805768SJiri Olsa }
2877dd805768SJiri Olsa
287855b95776SJiri Olsa callchain_param.record_mode = mode;
287955b95776SJiri Olsa callchain_param.min_percent = 0;
2880ead42a0fSLeo Yan return 0;
288155b95776SJiri Olsa }
2882d940baccSJiri Olsa
setup_display(const char * str)2883c82ccc3aSLeo Yan static int setup_display(const char *str)
2884d940baccSJiri Olsa {
2885c82ccc3aSLeo Yan const char *display = str;
288655b95776SJiri Olsa
2887c82ccc3aSLeo Yan if (!strcmp(display, "tot"))
2888f37c5d91SLeo Yan c2c.display = DISPLAY_TOT_HITM;
2889f37c5d91SLeo Yan else if (!strcmp(display, "rmt"))
289055b95776SJiri Olsa c2c.display = DISPLAY_RMT_HITM;
289155b95776SJiri Olsa else if (!strcmp(display, "lcl"))
289255b95776SJiri Olsa c2c.display = DISPLAY_LCL_HITM;
289355b95776SJiri Olsa else if (!strcmp(display, "peer"))
289455b95776SJiri Olsa c2c.display = DISPLAY_SNP_PEER;
289555b95776SJiri Olsa else {
289655b95776SJiri Olsa pr_err("failed: unknown display type: %s\n", str);
289755b95776SJiri Olsa return -1;
2898fc9c630eSJiri Olsa }
2899fc9c630eSJiri Olsa
2900fc9c630eSJiri Olsa return 0;
2901fc9c630eSJiri Olsa }
290218f278d2SJiri Olsa
2903fc9c630eSJiri Olsa #define for_each_token(__tok, __buf, __sep, __tmp) \
2904fc9c630eSJiri Olsa for (__tok = strtok_r(__buf, __sep, &__tmp); __tok; \
2905fc9c630eSJiri Olsa __tok = strtok_r(NULL, __sep, &__tmp))
2906fc9c630eSJiri Olsa
build_cl_output(char * cl_sort,bool no_source)2907fc9c630eSJiri Olsa static int build_cl_output(char *cl_sort, bool no_source)
2908fc9c630eSJiri Olsa {
2909fc9c630eSJiri Olsa char *tok, *tmp, *buf = strdup(cl_sort);
2910fc9c630eSJiri Olsa bool add_pid = false;
2911ae199c58SYunfeng Ye bool add_tid = false;
2912fc9c630eSJiri Olsa bool add_iaddr = false;
2913fc9c630eSJiri Olsa bool add_sym = false;
2914fc9c630eSJiri Olsa bool add_dso = false;
2915fc9c630eSJiri Olsa bool add_src = false;
2916fc9c630eSJiri Olsa int ret = 0;
2917fc9c630eSJiri Olsa
2918fc9c630eSJiri Olsa if (!buf)
2919fc9c630eSJiri Olsa return -ENOMEM;
2920fc9c630eSJiri Olsa
2921fc9c630eSJiri Olsa for_each_token(tok, buf, ",", tmp) {
2922fc9c630eSJiri Olsa if (!strcmp(tok, "tid")) {
2923fc9c630eSJiri Olsa add_tid = true;
2924fc9c630eSJiri Olsa } else if (!strcmp(tok, "pid")) {
292518f278d2SJiri Olsa add_pid = true;
2926fc9c630eSJiri Olsa } else if (!strcmp(tok, "iaddr")) {
2927fc9c630eSJiri Olsa add_iaddr = true;
2928fc9c630eSJiri Olsa add_sym = true;
2929fc9c630eSJiri Olsa add_dso = true;
2930ae199c58SYunfeng Ye add_src = no_source ? false : true;
2931ae199c58SYunfeng Ye } else if (!strcmp(tok, "dso")) {
2932fc9c630eSJiri Olsa add_dso = true;
2933fc9c630eSJiri Olsa } else if (strcmp(tok, "offset")) {
2934fc9c630eSJiri Olsa pr_err("unrecognized sort token: %s\n", tok);
2935fc9c630eSJiri Olsa ret = -EINVAL;
2936f37c5d91SLeo Yan goto err;
2937bb342daeSJiri Olsa }
2938f37c5d91SLeo Yan }
2939f37c5d91SLeo Yan
2940fc9c630eSJiri Olsa if (asprintf(&c2c.cl_output,
2941f37c5d91SLeo Yan "%s%s%s%s%s%s%s%s%s%s%s%s",
2942fc9c630eSJiri Olsa c2c.use_stdio ? "cl_num_empty," : "",
2943fc9c630eSJiri Olsa c2c.display == DISPLAY_SNP_PEER ? "percent_rmt_peer,"
2944550b4d6fSLeo Yan "percent_lcl_peer," :
294503d9fcb7SJiri Olsa "percent_rmt_hitm,"
2946fc9c630eSJiri Olsa "percent_lcl_hitm,",
2947fc9c630eSJiri Olsa "percent_stores_l1hit,"
2948fc9c630eSJiri Olsa "percent_stores_l1miss,"
2949f37c5d91SLeo Yan "percent_stores_na,"
2950f37c5d91SLeo Yan "offset,offset_node,dcacheline_count,",
2951fc9c630eSJiri Olsa add_pid ? "pid," : "",
2952f37c5d91SLeo Yan add_tid ? "tid," : "",
2953fc9c630eSJiri Olsa add_iaddr ? "iaddr," : "",
29548763e6acSJiri Olsa c2c.display == DISPLAY_SNP_PEER ? "mean_rmt_peer,"
2955fc9c630eSJiri Olsa "mean_lcl_peer," :
2956fc9c630eSJiri Olsa "mean_rmt,"
2957fc9c630eSJiri Olsa "mean_lcl,",
2958fc9c630eSJiri Olsa "mean_load,"
2959ae199c58SYunfeng Ye "tot_recs,"
2960ae199c58SYunfeng Ye "cpucnt,",
2961ae199c58SYunfeng Ye add_sym ? "symbol," : "",
2962ae199c58SYunfeng Ye add_dso ? "dso," : "",
2963fc9c630eSJiri Olsa add_src ? "cl_srcline," : "",
2964fc9c630eSJiri Olsa "node") < 0) {
2965ae199c58SYunfeng Ye ret = -ENOMEM;
2966fc9c630eSJiri Olsa goto err;
2967ae199c58SYunfeng Ye }
2968fc9c630eSJiri Olsa
2969fc9c630eSJiri Olsa c2c.show_src = add_src;
297018f278d2SJiri Olsa err:
2971fc9c630eSJiri Olsa free(buf);
2972fc9c630eSJiri Olsa return ret;
2973f37c5d91SLeo Yan }
2974fc9c630eSJiri Olsa
setup_coalesce(const char * coalesce,bool no_source)2975fc9c630eSJiri Olsa static int setup_coalesce(const char *coalesce, bool no_source)
2976fc9c630eSJiri Olsa {
2977fc9c630eSJiri Olsa const char *c = coalesce ?: coalesce_default;
297818f278d2SJiri Olsa const char *sort_str = NULL;
2979fc9c630eSJiri Olsa
2980fc9c630eSJiri Olsa if (asprintf(&c2c.cl_sort, "offset,%s", c) < 0)
2981f37c5d91SLeo Yan return -ENOMEM;
2982f37c5d91SLeo Yan
2983f37c5d91SLeo Yan if (build_cl_output(c2c.cl_sort, no_source))
2984f37c5d91SLeo Yan return -1;
2985f37c5d91SLeo Yan
2986f37c5d91SLeo Yan if (c2c.display == DISPLAY_TOT_HITM)
2987f37c5d91SLeo Yan sort_str = "tot_hitm";
2988f37c5d91SLeo Yan else if (c2c.display == DISPLAY_RMT_HITM)
2989f37c5d91SLeo Yan sort_str = "rmt_hitm,lcl_hitm";
2990f37c5d91SLeo Yan else if (c2c.display == DISPLAY_LCL_HITM)
2991fc9c630eSJiri Olsa sort_str = "lcl_hitm,rmt_hitm";
2992fc9c630eSJiri Olsa else if (c2c.display == DISPLAY_SNP_PEER)
2993fc9c630eSJiri Olsa sort_str = "tot_peer";
2994fc9c630eSJiri Olsa
2995fc9c630eSJiri Olsa if (asprintf(&c2c.cl_resort, "offset,%s", sort_str) < 0)
2996fc9c630eSJiri Olsa return -ENOMEM;
2997fc9c630eSJiri Olsa
2998fc9c630eSJiri Olsa pr_debug("coalesce sort fields: %s\n", c2c.cl_sort);
2999903a6f15SJiri Olsa pr_debug("coalesce resort fields: %s\n", c2c.cl_resort);
3000903a6f15SJiri Olsa pr_debug("coalesce output fields: %s\n", c2c.cl_output);
3001c825f788SLeo Yan return 0;
3002c825f788SLeo Yan }
3003c825f788SLeo Yan
perf_c2c__report(int argc,const char ** argv)3004c825f788SLeo Yan static int perf_c2c__report(int argc, const char **argv)
3005c825f788SLeo Yan {
3006c825f788SLeo Yan struct itrace_synth_opts itrace_synth_opts = {
3007903a6f15SJiri Olsa .set = true,
300878b27543SJiri Olsa .mem = true, /* Only enable memory event */
30098ceb41d7SJiri Olsa .default_no_sample = true,
3010903a6f15SJiri Olsa };
3011903a6f15SJiri Olsa
3012dd805768SJiri Olsa struct perf_session *session;
301355b95776SJiri Olsa struct ui_progress prog;
3014fc9c630eSJiri Olsa struct perf_data data = {
301518f278d2SJiri Olsa .mode = PERF_DATA_MODE_READ,
30163a5bfab6SJiri Olsa };
3017903a6f15SJiri Olsa char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
3018903a6f15SJiri Olsa const char *display = NULL;
3019903a6f15SJiri Olsa const char *coalesce = NULL;
3020903a6f15SJiri Olsa bool no_source = false;
30211e181b92SJiri Olsa const struct option options[] = {
30221e181b92SJiri Olsa OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
30235a1a99cdSJiri Olsa "file", "vmlinux pathname"),
302474c63a25SJiri Olsa OPT_STRING('i', "input", &input_name, "file",
3025f75d2895SNamhyung Kim "the input file to process"),
3026590b6a3aSJiri Olsa OPT_INCR('N', "node-info", &c2c.node_info,
3027590b6a3aSJiri Olsa "show extra node info in report (repeat for more info)"),
302818f278d2SJiri Olsa OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"),
302918f278d2SJiri Olsa OPT_BOOLEAN(0, "stats", &c2c.stats_only,
3030af09b2d3SJiri Olsa "Display only statistic tables (implies --stdio)"),
3031af09b2d3SJiri Olsa OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full,
3032dd805768SJiri Olsa "Display full length of symbols"),
3033dd805768SJiri Olsa OPT_BOOLEAN(0, "no-source", &no_source,
3034dd805768SJiri Olsa "Do not display Source Line column"),
3035dd805768SJiri Olsa OPT_BOOLEAN(0, "show-all", &c2c.show_all,
3036f37c5d91SLeo Yan "Show all captured HITM lines."),
3037fc9c630eSJiri Olsa OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
3038fc9c630eSJiri Olsa "print_type,threshold[,print_limit],order,sort_key[,branch],value",
3039b7ac4f9fSJiri Olsa callchain_help, &parse_callchain_opt,
3040d80da766SKan Liang callchain_default_opt),
3041d80da766SKan Liang OPT_STRING('d', "display", &display, "Switch HITM output type", "tot,lcl,rmt,peer"),
30421470a108SFeng Tang OPT_STRING('c', "coalesce", &coalesce, "coalesce fields",
30433a5bfab6SJiri Olsa "coalesce fields: pid,tid,iaddr,dso"),
3044903a6f15SJiri Olsa OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
3045903a6f15SJiri Olsa OPT_BOOLEAN(0, "stitch-lbr", &c2c.stitch_lbr,
3046903a6f15SJiri Olsa "Enable LBR callgraph stitching approach"),
30470998d960SLeo Yan OPT_BOOLEAN(0, "double-cl", &chk_double_cl, "Detect adjacent cacheline false sharing"),
3048903a6f15SJiri Olsa OPT_PARENT(c2c_options),
30493a5bfab6SJiri Olsa OPT_END()
3050903a6f15SJiri Olsa };
305178b27543SJiri Olsa int err = 0;
30523a5bfab6SJiri Olsa const char *output_str, *sort_str = NULL;
3053903a6f15SJiri Olsa
3054c4040212SLeo Yan argc = parse_options(argc, argv, options, report_c2c_usage,
3055c4040212SLeo Yan PARSE_OPT_STOP_AT_NON_OPTION);
3056c4040212SLeo Yan if (argc)
3057c4040212SLeo Yan usage_with_options(report_c2c_usage, options);
305874c63a25SJiri Olsa
305974c63a25SJiri Olsa #ifndef HAVE_SLANG_SUPPORT
306074c63a25SJiri Olsa c2c.use_stdio = true;
30617cc72553SJames Clark #endif
30627cc72553SJames Clark
30637cc72553SJames Clark if (c2c.stats_only)
30647cc72553SJames Clark c2c.use_stdio = true;
306578b27543SJiri Olsa
306678b27543SJiri Olsa err = symbol__validate_sym_arguments();
306778b27543SJiri Olsa if (err)
30682d4f2799SJiri Olsa goto out;
30698ceb41d7SJiri Olsa
3070903a6f15SJiri Olsa if (!input_name || !strlen(input_name))
30712681bd85SNamhyung Kim input_name = "perf.data";
30726ef81c55SMamatha Inamdar
30736ef81c55SMamatha Inamdar data.path = input_name;
30746ef81c55SMamatha Inamdar data.force = symbol_conf.force;
3075903a6f15SJiri Olsa
3076903a6f15SJiri Olsa session = perf_session__new(&data, &c2c.tool);
3077e8c5fe10SJiri Olsa if (IS_ERR(session)) {
3078ead42a0fSLeo Yan err = PTR_ERR(session);
3079ead42a0fSLeo Yan pr_debug("Error creating perf session\n");
3080ead42a0fSLeo Yan goto out;
3081ead42a0fSLeo Yan }
3082ead42a0fSLeo Yan
3083ead42a0fSLeo Yan /*
3084ead42a0fSLeo Yan * Use the 'tot' as default display type if user doesn't specify it;
3085ead42a0fSLeo Yan * since Arm64 platform doesn't support HITMs flag, use 'peer' as the
3086ead42a0fSLeo Yan * default display type.
3087ead42a0fSLeo Yan */
3088ead42a0fSLeo Yan if (!display) {
3089ead42a0fSLeo Yan if (!strcmp(perf_env__arch(&session->header.env), "arm64"))
3090ead42a0fSLeo Yan display = "peer";
3091ead42a0fSLeo Yan else
3092ead42a0fSLeo Yan display = "tot";
3093ead42a0fSLeo Yan }
3094ead42a0fSLeo Yan
3095ead42a0fSLeo Yan err = setup_display(display);
3096ead42a0fSLeo Yan if (err)
3097ead42a0fSLeo Yan goto out_session;
3098ead42a0fSLeo Yan
3099ead42a0fSLeo Yan err = setup_coalesce(coalesce, no_source);
3100ead42a0fSLeo Yan if (err) {
3101ead42a0fSLeo Yan pr_debug("Failed to initialize hists\n");
3102ead42a0fSLeo Yan goto out_session;
3103ead42a0fSLeo Yan }
3104ead42a0fSLeo Yan
3105ead42a0fSLeo Yan err = c2c_hists__init(&c2c.hists, "dcacheline", 2);
3106c825f788SLeo Yan if (err) {
3107c825f788SLeo Yan pr_debug("Failed to initialize hists\n");
31081e181b92SJiri Olsa goto out_session;
31091e181b92SJiri Olsa }
31101e181b92SJiri Olsa
3111ead42a0fSLeo Yan session->itrace_synth_opts = &itrace_synth_opts;
31121e181b92SJiri Olsa
3113903a6f15SJiri Olsa err = setup_nodes(session);
31147f834c2eSJiri Olsa if (err) {
3115dd805768SJiri Olsa pr_err("Failed setup nodes\n");
3116dd805768SJiri Olsa goto out_session;
3117dd805768SJiri Olsa }
31187f834c2eSJiri Olsa
31197f834c2eSJiri Olsa err = mem2node__init(&c2c.mem2node, &session->header.env);
31207f834c2eSJiri Olsa if (err)
31217f834c2eSJiri Olsa goto out_session;
3122903a6f15SJiri Olsa
31237f834c2eSJiri Olsa err = setup_callchain(session->evlist);
3124903a6f15SJiri Olsa if (err)
3125903a6f15SJiri Olsa goto out_mem2node;
31268ceb41d7SJiri Olsa
3127903a6f15SJiri Olsa if (symbol__init(&session->header.env) < 0)
31287f834c2eSJiri Olsa goto out_mem2node;
3129903a6f15SJiri Olsa
3130903a6f15SJiri Olsa /* No pipe support at the moment. */
3131e8c5fe10SJiri Olsa if (perf_data__is_pipe(session->data)) {
3132e8c5fe10SJiri Olsa pr_debug("No pipe support at the moment.\n");
3133e8c5fe10SJiri Olsa goto out_mem2node;
3134e8c5fe10SJiri Olsa }
3135e8c5fe10SJiri Olsa
3136e8c5fe10SJiri Olsa if (c2c.use_stdio)
3137e8c5fe10SJiri Olsa use_browser = 0;
313878b27543SJiri Olsa else
313978b27543SJiri Olsa use_browser = 1;
314078b27543SJiri Olsa
31417f834c2eSJiri Olsa setup_browser(false);
314278b27543SJiri Olsa
314378b27543SJiri Olsa err = perf_session__process_events(session);
3144f37c5d91SLeo Yan if (err) {
31450998d960SLeo Yan pr_err("failed to process sample\n");
314622dd59d1SJiri Olsa goto out_mem2node;
31477f834c2eSJiri Olsa }
314803d9fcb7SJiri Olsa
31492be0bc75SLeo Yan if (c2c.display != DISPLAY_SNP_PEER)
315022dd59d1SJiri Olsa output_str = "cl_idx,"
3151b596e979SLeo Yan "dcacheline,"
3152b596e979SLeo Yan "dcacheline_node,"
31534f28641bSLeo Yan "dcacheline_count,"
3154550b4d6fSLeo Yan "percent_costly_snoop,"
315522dd59d1SJiri Olsa "tot_hitm,lcl_hitm,rmt_hitm,"
315677c15869SLeo Yan "tot_recs,"
315791d933c2SLeo Yan "tot_loads,"
31580998d960SLeo Yan "tot_stores,"
3159f37c5d91SLeo Yan "stores_l1hit,stores_l1miss,stores_na,"
3160f37c5d91SLeo Yan "ld_fbhit,ld_l1hit,ld_l2hit,"
3161f37c5d91SLeo Yan "ld_lclhit,lcl_hitm,"
3162f37c5d91SLeo Yan "ld_rmthit,rmt_hitm,"
3163f37c5d91SLeo Yan "dram_lcl,dram_rmt";
3164f37c5d91SLeo Yan else
3165f37c5d91SLeo Yan output_str = "cl_idx,"
3166f37c5d91SLeo Yan "dcacheline,"
3167f37c5d91SLeo Yan "dcacheline_node,"
3168f37c5d91SLeo Yan "dcacheline_count,"
3169f37c5d91SLeo Yan "percent_costly_snoop,"
3170f37c5d91SLeo Yan "tot_peer,lcl_peer,rmt_peer,"
3171f37c5d91SLeo Yan "tot_recs,"
3172f37c5d91SLeo Yan "tot_loads,"
3173f37c5d91SLeo Yan "tot_stores,"
31740998d960SLeo Yan "stores_l1hit,stores_l1miss,stores_na,"
3175c82ccc3aSLeo Yan "ld_fbhit,ld_l1hit,ld_l2hit,"
31760998d960SLeo Yan "ld_lclhit,lcl_hitm,"
3177c82ccc3aSLeo Yan "ld_rmthit,rmt_hitm,"
31780998d960SLeo Yan "dram_lcl,dram_rmt";
3179c82ccc3aSLeo Yan
31800998d960SLeo Yan if (c2c.display == DISPLAY_TOT_HITM)
3181f37c5d91SLeo Yan sort_str = "tot_hitm";
3182f37c5d91SLeo Yan else if (c2c.display == DISPLAY_RMT_HITM)
31830998d960SLeo Yan sort_str = "rmt_hitm";
31840998d960SLeo Yan else if (c2c.display == DISPLAY_LCL_HITM)
318522dd59d1SJiri Olsa sort_str = "lcl_hitm";
318678b27543SJiri Olsa else if (c2c.display == DISPLAY_SNP_PEER)
318778b27543SJiri Olsa sort_str = "tot_peer";
318878b27543SJiri Olsa
31891834436eSLeo Yan c2c_hists__reinit(&c2c.hists, output_str, sort_str);
31907ef2efaaSJiri Olsa
319178b27543SJiri Olsa ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting...");
319278b27543SJiri Olsa
319378b27543SJiri Olsa hists__collapse_resort(&c2c.hists.hists, NULL);
3194d0802b1eSJiri Olsa hists__output_resort_cb(&c2c.hists.hists, &prog, resort_shared_cl_cb);
3195d0802b1eSJiri Olsa hists__iterate_cb(&c2c.hists.hists, resort_cl_cb);
3196d0802b1eSJiri Olsa
3197d0802b1eSJiri Olsa ui_progress__finish();
31985a1a99cdSJiri Olsa
31992709b97dSJiri Olsa if (ui_quirks()) {
32002d388bd0SJiri Olsa pr_err("failed to setup UI\n");
32017f834c2eSJiri Olsa goto out_mem2node;
32027f834c2eSJiri Olsa }
3203903a6f15SJiri Olsa
3204903a6f15SJiri Olsa perf_c2c_display(session);
3205903a6f15SJiri Olsa
3206903a6f15SJiri Olsa out_mem2node:
3207903a6f15SJiri Olsa mem2node__exit(&c2c.mem2node);
3208903a6f15SJiri Olsa out_session:
32097e6a7998SArnaldo Carvalho de Melo perf_session__delete(session);
321039bcd4a4SJiri Olsa out:
321139bcd4a4SJiri Olsa return err;
321239bcd4a4SJiri Olsa }
321339bcd4a4SJiri Olsa
parse_record_events(const struct option * opt,const char * str,int unset __maybe_unused)3214b027cc6fSIan Rogers static int parse_record_events(const struct option *opt,
3215b027cc6fSIan Rogers const char *str, int unset __maybe_unused)
3216b027cc6fSIan Rogers {
3217b027cc6fSIan Rogers bool *event_set = (bool *) opt->value;
3218b027cc6fSIan Rogers
3219b027cc6fSIan Rogers if (!strcmp(str, "list")) {
3220b027cc6fSIan Rogers perf_mem_events__list();
322139bcd4a4SJiri Olsa exit(0);
3222b027cc6fSIan Rogers }
322339bcd4a4SJiri Olsa if (perf_mem_events__parse(str))
322439bcd4a4SJiri Olsa exit(-1);
322539bcd4a4SJiri Olsa
322639bcd4a4SJiri Olsa *event_set = true;
322739bcd4a4SJiri Olsa return 0;
322839bcd4a4SJiri Olsa }
322939bcd4a4SJiri Olsa
323039bcd4a4SJiri Olsa
323139bcd4a4SJiri Olsa static const char * const __usage_record[] = {
323239bcd4a4SJiri Olsa "perf c2c record [<options>] [<command>]",
323339bcd4a4SJiri Olsa "perf c2c record [<options>] -- <command> [<options>]",
323439bcd4a4SJiri Olsa NULL
323539bcd4a4SJiri Olsa };
323679e157b0SJin Yao
323739bcd4a4SJiri Olsa static const char * const *record_mem_usage = __usage_record;
323879e157b0SJin Yao
perf_c2c__record(int argc,const char ** argv)323939bcd4a4SJiri Olsa static int perf_c2c__record(int argc, const char **argv)
324039bcd4a4SJiri Olsa {
324139bcd4a4SJiri Olsa int rec_argc, i = 0, j, rec_tmp_nr = 0;
3242eaf6aaeeSLeo Yan const char **rec_argv;
324339bcd4a4SJiri Olsa char **rec_tmp;
324439bcd4a4SJiri Olsa int ret;
3245edac75a2SLeo Yan bool all_user = false, all_kernel = false;
324639bcd4a4SJiri Olsa bool event_set = false;
324739bcd4a4SJiri Olsa struct perf_mem_event *e;
324839bcd4a4SJiri Olsa struct option options[] = {
324939bcd4a4SJiri Olsa OPT_CALLBACK('e', "event", &event_set, "event",
32503a5bfab6SJiri Olsa "event selector. Use 'perf c2c record -e list' to list available events",
325139bcd4a4SJiri Olsa parse_record_events),
325239bcd4a4SJiri Olsa OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"),
325339bcd4a4SJiri Olsa OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"),
325439bcd4a4SJiri Olsa OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"),
325539bcd4a4SJiri Olsa OPT_PARENT(c2c_options),
325639bcd4a4SJiri Olsa OPT_END()
325739bcd4a4SJiri Olsa };
325839bcd4a4SJiri Olsa
325939bcd4a4SJiri Olsa if (perf_mem_events__init()) {
326039bcd4a4SJiri Olsa pr_err("failed: memory events not supported\n");
326139bcd4a4SJiri Olsa return -1;
326279e157b0SJin Yao }
32638fab7843SJiri Olsa
326479e157b0SJin Yao argc = parse_options(argc, argv, options, record_mem_usage,
326579e157b0SJin Yao PARSE_OPT_KEEP_UNKNOWN);
326679e157b0SJin Yao
326739bcd4a4SJiri Olsa /* Max number of arguments multiplied by number of PMUs that can support them. */
326839bcd4a4SJiri Olsa rec_argc = argc + 11 * perf_pmus__num_mem_pmus();
326939bcd4a4SJiri Olsa
327039bcd4a4SJiri Olsa rec_argv = calloc(rec_argc + 1, sizeof(char *));
327179e157b0SJin Yao if (!rec_argv)
327279e157b0SJin Yao return -1;
327379e157b0SJin Yao
327479e157b0SJin Yao rec_tmp = calloc(rec_argc + 1, sizeof(char *));
327579e157b0SJin Yao if (!rec_tmp) {
327679e157b0SJin Yao free(rec_argv);
327739bcd4a4SJiri Olsa return -1;
327839bcd4a4SJiri Olsa }
327939bcd4a4SJiri Olsa
32808b8173b4SLeo Yan rec_argv[i++] = "record";
32818b8173b4SLeo Yan
32828b8173b4SLeo Yan if (!event_set) {
32838b8173b4SLeo Yan e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD_STORE);
32848b8173b4SLeo Yan /*
32858b8173b4SLeo Yan * The load and store operations are required, use the event
32868b8173b4SLeo Yan * PERF_MEM_EVENTS__LOAD_STORE if it is supported.
32874173cc05SRavi Bangoria */
32888b8173b4SLeo Yan if (e->tag) {
3289eaf6aaeeSLeo Yan e->record = true;
3290eaf6aaeeSLeo Yan rec_argv[i++] = "-W";
3291eaf6aaeeSLeo Yan } else {
3292eaf6aaeeSLeo Yan e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
3293eaf6aaeeSLeo Yan e->record = true;
329439bcd4a4SJiri Olsa
32958b8173b4SLeo Yan e = perf_mem_events__ptr(PERF_MEM_EVENTS__STORE);
329639bcd4a4SJiri Olsa e->record = true;
3297eaf6aaeeSLeo Yan }
3298eaf6aaeeSLeo Yan }
329939bcd4a4SJiri Olsa
330039bcd4a4SJiri Olsa e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
330139bcd4a4SJiri Olsa if (e->record)
33028fab7843SJiri Olsa rec_argv[i++] = "-W";
330339bcd4a4SJiri Olsa
330439bcd4a4SJiri Olsa rec_argv[i++] = "-d";
330579e157b0SJin Yao rec_argv[i++] = "--phys-data";
330679e157b0SJin Yao rec_argv[i++] = "--sample-cpu";
330779e157b0SJin Yao
330839bcd4a4SJiri Olsa ret = perf_mem_events__record_args(rec_argv, &i, rec_tmp, &rec_tmp_nr);
330939bcd4a4SJiri Olsa if (ret)
331039bcd4a4SJiri Olsa goto out;
331139bcd4a4SJiri Olsa
331239bcd4a4SJiri Olsa if (all_user)
331339bcd4a4SJiri Olsa rec_argv[i++] = "--all-user";
331439bcd4a4SJiri Olsa
331539bcd4a4SJiri Olsa if (all_kernel)
331639bcd4a4SJiri Olsa rec_argv[i++] = "--all-kernel";
331739bcd4a4SJiri Olsa
331839bcd4a4SJiri Olsa for (j = 0; j < argc; j++, i++)
331939bcd4a4SJiri Olsa rec_argv[i] = argv[j];
332039bcd4a4SJiri Olsa
332139bcd4a4SJiri Olsa if (verbose > 0) {
332239bcd4a4SJiri Olsa pr_debug("calling: ");
332339bcd4a4SJiri Olsa
332439bcd4a4SJiri Olsa j = 0;
332539bcd4a4SJiri Olsa
332639bcd4a4SJiri Olsa while (rec_argv[j]) {
332739bcd4a4SJiri Olsa pr_debug("%s ", rec_argv[j]);
332839bcd4a4SJiri Olsa j++;
332939bcd4a4SJiri Olsa }
3330b0ad8ea6SArnaldo Carvalho de Melo pr_debug("\n");
333179e157b0SJin Yao }
333279e157b0SJin Yao
333379e157b0SJin Yao ret = cmd_record(i, rec_argv);
333479e157b0SJin Yao out:
333579e157b0SJin Yao for (i = 0; i < rec_tmp_nr; i++)
333639bcd4a4SJiri Olsa free(rec_tmp[i]);
333739bcd4a4SJiri Olsa
333839bcd4a4SJiri Olsa free(rec_tmp);
333939bcd4a4SJiri Olsa free(rec_argv);
3340b0ad8ea6SArnaldo Carvalho de Melo return ret;
33417aef3bf3SJiri Olsa }
33427aef3bf3SJiri Olsa
cmd_c2c(int argc,const char ** argv)33437aef3bf3SJiri Olsa int cmd_c2c(int argc, const char **argv)
334439bcd4a4SJiri Olsa {
334539bcd4a4SJiri Olsa argc = parse_options(argc, argv, c2c_options, c2c_usage,
334639bcd4a4SJiri Olsa PARSE_OPT_STOP_AT_NON_OPTION);
334739bcd4a4SJiri Olsa
3348ae0f4eb3SWei Li if (!argc)
334939bcd4a4SJiri Olsa usage_with_options(c2c_usage, c2c_options);
3350ae0f4eb3SWei Li
3351903a6f15SJiri Olsa if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
335239bcd4a4SJiri Olsa return perf_c2c__record(argc, argv);
335339bcd4a4SJiri Olsa } else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) {
335439bcd4a4SJiri Olsa return perf_c2c__report(argc, argv);
335539bcd4a4SJiri Olsa } else {
33567aef3bf3SJiri Olsa usage_with_options(c2c_usage, c2c_options);
33577aef3bf3SJiri Olsa }
3358
3359 return 0;
3360 }
3361