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"
441eaf496eSIan Rogers #include "pmus.h"
45ae0f4eb3SWei Li #include "string2.h"
46f12ad272SIan Rogers #include "util/util.h"
47903a6f15SJiri Olsa
48c75540e3SJiri Olsa struct c2c_hists {
49c75540e3SJiri Olsa struct hists hists;
50c75540e3SJiri Olsa struct perf_hpp_list list;
51b2252ae6SJiri Olsa struct c2c_stats stats;
52c75540e3SJiri Olsa };
53c75540e3SJiri Olsa
5492062d54SJiri Olsa struct compute_stats {
5592062d54SJiri Olsa struct stats lcl_hitm;
5692062d54SJiri Olsa struct stats rmt_hitm;
57682352e5SLeo Yan struct stats lcl_peer;
58682352e5SLeo Yan struct stats rmt_peer;
5992062d54SJiri Olsa struct stats load;
6092062d54SJiri Olsa };
6192062d54SJiri Olsa
6278b27543SJiri Olsa struct c2c_hist_entry {
6378b27543SJiri Olsa struct c2c_hists *hists;
64b2252ae6SJiri Olsa struct c2c_stats stats;
651e181b92SJiri Olsa unsigned long *cpuset;
667f834c2eSJiri Olsa unsigned long *nodeset;
671e181b92SJiri Olsa struct c2c_stats *node_stats;
68bb342daeSJiri Olsa unsigned int cacheline_idx;
6992062d54SJiri Olsa
7092062d54SJiri Olsa struct compute_stats cstats;
7192062d54SJiri Olsa
724c820527SJiri Olsa unsigned long paddr;
734c820527SJiri Olsa unsigned long paddr_cnt;
744c820527SJiri Olsa bool paddr_zero;
754c820527SJiri Olsa char *nodestr;
764c820527SJiri Olsa
7778b27543SJiri 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
84423701a0SJiri Olsa static char const *coalesce_default = "iaddr";
85fc9c630eSJiri Olsa
86903a6f15SJiri Olsa struct perf_c2c {
87903a6f15SJiri Olsa struct perf_tool tool;
88c75540e3SJiri Olsa struct c2c_hists hists;
897f834c2eSJiri Olsa struct mem2node mem2node;
901e181b92SJiri 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;
9689d9ba8fSJiri Olsa
9789d9ba8fSJiri Olsa bool show_src;
98af09b2d3SJiri Olsa bool show_all;
995a1a99cdSJiri Olsa bool use_stdio;
10074c63a25SJiri Olsa bool stats_only;
101590b6a3aSJiri Olsa bool symbol_full;
102d80da766SKan Liang bool stitch_lbr;
1037ef2efaaSJiri Olsa
1041834436eSLeo Yan /* Shared cache line stats */
1051834436eSLeo Yan struct c2c_stats shared_clines_stats;
1067ef2efaaSJiri Olsa int shared_clines;
10755b95776SJiri Olsa
10855b95776SJiri Olsa int display;
109fc9c630eSJiri Olsa
110fc9c630eSJiri Olsa const char *coalesce;
111fc9c630eSJiri Olsa char *cl_sort;
112fc9c630eSJiri Olsa char *cl_resort;
113fc9c630eSJiri Olsa char *cl_output;
11455b95776SJiri Olsa };
11555b95776SJiri Olsa
11655b95776SJiri Olsa enum {
117c82ccc3aSLeo Yan DISPLAY_LCL_HITM,
118c82ccc3aSLeo Yan DISPLAY_RMT_HITM,
119c82ccc3aSLeo Yan DISPLAY_TOT_HITM,
120f37c5d91SLeo Yan DISPLAY_SNP_PEER,
121d940baccSJiri Olsa DISPLAY_MAX,
122d940baccSJiri Olsa };
123d940baccSJiri Olsa
124d940baccSJiri Olsa static const char *display_str[DISPLAY_MAX] = {
125faa30dfaSLeo Yan [DISPLAY_LCL_HITM] = "Local HITMs",
126faa30dfaSLeo Yan [DISPLAY_RMT_HITM] = "Remote HITMs",
127faa30dfaSLeo Yan [DISPLAY_TOT_HITM] = "Total HITMs",
128f37c5d91SLeo Yan [DISPLAY_SNP_PEER] = "Peer Snoop",
129903a6f15SJiri Olsa };
130903a6f15SJiri Olsa
1313a5bfab6SJiri 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
136903a6f15SJiri Olsa static struct perf_c2c c2c;
1377aef3bf3SJiri Olsa
c2c_he_zalloc(size_t size)13878b27543SJiri 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
1467fc5b571SAndy Shevchenko c2c_he->cpuset = bitmap_zalloc(c2c.cpus_cnt);
1471e181b92SJiri Olsa if (!c2c_he->cpuset)
1484efa8e31SShang XiaoJing goto out_free;
1491e181b92SJiri Olsa
1507fc5b571SAndy Shevchenko c2c_he->nodeset = bitmap_zalloc(c2c.nodes_cnt);
1517f834c2eSJiri Olsa if (!c2c_he->nodeset)
1524efa8e31SShang XiaoJing goto out_free;
1537f834c2eSJiri Olsa
1541e181b92SJiri Olsa c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
1551e181b92SJiri Olsa if (!c2c_he->node_stats)
1564efa8e31SShang XiaoJing goto out_free;
1571e181b92SJiri Olsa
15892062d54SJiri Olsa init_stats(&c2c_he->cstats.lcl_hitm);
15992062d54SJiri Olsa init_stats(&c2c_he->cstats.rmt_hitm);
160682352e5SLeo Yan init_stats(&c2c_he->cstats.lcl_peer);
161682352e5SLeo Yan init_stats(&c2c_he->cstats.rmt_peer);
16292062d54SJiri Olsa init_stats(&c2c_he->cstats.load);
16392062d54SJiri Olsa
16478b27543SJiri Olsa return &c2c_he->he;
1654efa8e31SShang XiaoJing
1664efa8e31SShang XiaoJing out_free:
167190de754SArnaldo Carvalho de Melo zfree(&c2c_he->nodeset);
168190de754SArnaldo Carvalho de Melo zfree(&c2c_he->cpuset);
1694efa8e31SShang XiaoJing free(c2c_he);
1704efa8e31SShang XiaoJing return NULL;
17178b27543SJiri Olsa }
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);
180190de754SArnaldo Carvalho de Melo zfree(&c2c_he->hists);
18178b27543SJiri Olsa }
18278b27543SJiri Olsa
183190de754SArnaldo Carvalho de Melo zfree(&c2c_he->cpuset);
184190de754SArnaldo Carvalho de Melo zfree(&c2c_he->nodeset);
185190de754SArnaldo Carvalho de Melo zfree(&c2c_he->nodestr);
186190de754SArnaldo Carvalho de Melo zfree(&c2c_he->node_stats);
18778b27543SJiri Olsa 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
195ec06f9b9SJiri Olsa static int c2c_hists__init(struct c2c_hists *hists,
1961d62fcd6SJiri Olsa const char *sort,
1971d62fcd6SJiri Olsa int nr_header_lines);
198ec06f9b9SJiri Olsa
199b2252ae6SJiri 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,
2011d62fcd6SJiri Olsa const char *sort,
2021d62fcd6SJiri Olsa int nr_header_lines)
203ec06f9b9SJiri 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)
210b2252ae6SJiri Olsa return c2c_he->hists;
211ec06f9b9SJiri Olsa
212ec06f9b9SJiri Olsa hists = c2c_he->hists = zalloc(sizeof(*hists));
213ec06f9b9SJiri Olsa if (!hists)
214ec06f9b9SJiri Olsa return NULL;
215ec06f9b9SJiri Olsa
2161d62fcd6SJiri Olsa ret = c2c_hists__init(hists, sort, nr_header_lines);
217ec06f9b9SJiri Olsa if (ret) {
218ec06f9b9SJiri Olsa free(hists);
219ec06f9b9SJiri Olsa return NULL;
220ec06f9b9SJiri Olsa }
221ec06f9b9SJiri Olsa
222b2252ae6SJiri Olsa return hists;
223ec06f9b9SJiri Olsa }
224ec06f9b9SJiri Olsa
c2c_he__set_cpu(struct c2c_hist_entry * c2c_he,struct perf_sample * sample)2251e181b92SJiri 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
23275d7ba32SSean Christopherson __set_bit(sample->cpu, c2c_he->cpuset);
2331e181b92SJiri Olsa }
2341e181b92SJiri Olsa
c2c_he__set_node(struct c2c_hist_entry * c2c_he,struct perf_sample * sample)2357f834c2eSJiri 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
24975d7ba32SSean Christopherson __set_bit(node, c2c_he->nodeset);
2507f834c2eSJiri Olsa
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)25792062d54SJiri 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);
267682352e5SLeo Yan 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);
27192062d54SJiri Olsa 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)27578b27543SJiri Olsa static int process_sample_event(struct perf_tool *tool __maybe_unused,
27678b27543SJiri Olsa union perf_event *event,
27778b27543SJiri Olsa struct perf_sample *sample,
27832dcd021SJiri Olsa struct evsel *evsel,
27978b27543SJiri Olsa struct machine *machine)
28078b27543SJiri Olsa {
281b2252ae6SJiri 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, };
28478b27543SJiri Olsa struct hist_entry *he;
28578b27543SJiri Olsa struct addr_location al;
286ec06f9b9SJiri Olsa struct mem_info *mi, *mi_dup;
287*8ab12a20SIan Rogers struct callchain_cursor *cursor;
28878b27543SJiri Olsa int ret;
28978b27543SJiri Olsa
2900dd5041cSIan Rogers 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);
2940dd5041cSIan Rogers ret = -1;
2950dd5041cSIan Rogers goto out;
29678b27543SJiri Olsa }
29778b27543SJiri Olsa
298d80da766SKan Liang if (c2c.stitch_lbr)
299ee84a303SIan Rogers thread__set_lbr_stitch_enable(al.thread, true);
300d80da766SKan Liang
301*8ab12a20SIan Rogers cursor = get_tls_callchain_cursor();
302*8ab12a20SIan Rogers ret = sample__resolve_callchain(sample, cursor, NULL,
303dd805768SJiri Olsa evsel, &al, sysctl_perf_event_max_stack);
304dd805768SJiri Olsa if (ret)
305dd805768SJiri Olsa goto out;
306dd805768SJiri Olsa
30778b27543SJiri Olsa mi = sample__resolve_mem(sample, &al);
3080dd5041cSIan Rogers if (mi == NULL) {
3090dd5041cSIan Rogers ret = -ENOMEM;
3100dd5041cSIan Rogers goto out;
3110dd5041cSIan Rogers }
31278b27543SJiri Olsa
3135cedb413SJiri Olsa /*
3145cedb413SJiri Olsa * The mi object is released in hists__add_entry_ops,
3155cedb413SJiri Olsa * if it gets sorted out into existing data, so we need
3165cedb413SJiri Olsa * to take the copy now.
3175cedb413SJiri Olsa */
3185cedb413SJiri Olsa mi_dup = mem_info__get(mi);
319ec06f9b9SJiri Olsa
320b2252ae6SJiri Olsa c2c_decode_stats(&stats, mi);
321b2252ae6SJiri Olsa
322b2252ae6SJiri Olsa he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
323ebf39d29SLeo Yan &al, NULL, NULL, mi, NULL,
32478b27543SJiri Olsa sample, true);
325ec06f9b9SJiri Olsa if (he == NULL)
3265cedb413SJiri Olsa goto free_mi;
32778b27543SJiri Olsa
328b2252ae6SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
329b2252ae6SJiri Olsa c2c_add_stats(&c2c_he->stats, &stats);
330b2252ae6SJiri Olsa c2c_add_stats(&c2c_hists->stats, &stats);
331b2252ae6SJiri Olsa
3321e181b92SJiri Olsa c2c_he__set_cpu(c2c_he, sample);
3337f834c2eSJiri Olsa c2c_he__set_node(c2c_he, sample);
3341e181b92SJiri Olsa
335b2252ae6SJiri Olsa hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
33678b27543SJiri Olsa ret = hist_entry__append_callchain(he, sample);
33778b27543SJiri Olsa
338ec06f9b9SJiri 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 *
3451e181b92SJiri Olsa * Doing node stats only for single callchain data.
3461e181b92SJiri Olsa */
3471e181b92SJiri Olsa int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu;
3481e181b92SJiri Olsa int node = c2c.cpu2node[cpu];
3491e181b92SJiri Olsa
350ec06f9b9SJiri Olsa mi = mi_dup;
351ec06f9b9SJiri Olsa
352fc9c630eSJiri Olsa c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
353b2252ae6SJiri Olsa if (!c2c_hists)
3545cedb413SJiri Olsa goto free_mi;
355ec06f9b9SJiri Olsa
356b2252ae6SJiri Olsa he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
357ebf39d29SLeo Yan &al, NULL, NULL, mi, NULL,
358ec06f9b9SJiri Olsa sample, true);
359ec06f9b9SJiri Olsa if (he == NULL)
3605cedb413SJiri Olsa goto free_mi;
361ec06f9b9SJiri Olsa
362b2252ae6SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
363b2252ae6SJiri Olsa c2c_add_stats(&c2c_he->stats, &stats);
364b2252ae6SJiri Olsa c2c_add_stats(&c2c_hists->stats, &stats);
3651e181b92SJiri Olsa c2c_add_stats(&c2c_he->node_stats[node], &stats);
3661e181b92SJiri Olsa
36792062d54SJiri Olsa compute_stats(c2c_he, &stats, sample->weight);
36892062d54SJiri Olsa
3691e181b92SJiri Olsa c2c_he__set_cpu(c2c_he, sample);
3707f834c2eSJiri Olsa c2c_he__set_node(c2c_he, sample);
371b2252ae6SJiri Olsa
372b2252ae6SJiri Olsa hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
373ec06f9b9SJiri Olsa ret = hist_entry__append_callchain(he, sample);
374ec06f9b9SJiri Olsa }
375ec06f9b9SJiri Olsa
376ec06f9b9SJiri Olsa out:
3770dd5041cSIan Rogers addr_location__exit(&al);
37878b27543SJiri Olsa return ret;
379ec06f9b9SJiri Olsa
380ec06f9b9SJiri Olsa free_mi:
3815cedb413SJiri Olsa mem_info__put(mi_dup);
3825cedb413SJiri Olsa mem_info__put(mi);
383ec06f9b9SJiri Olsa ret = -ENOMEM;
384ec06f9b9SJiri 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,
39178b27543SJiri Olsa .mmap2 = perf_event__process_mmap2,
39278b27543SJiri Olsa .comm = perf_event__process_comm,
39378b27543SJiri Olsa .exit = perf_event__process_exit,
39478b27543SJiri Olsa .fork = perf_event__process_fork,
39578b27543SJiri Olsa .lost = perf_event__process_lost,
396c825f788SLeo Yan .attr = perf_event__process_attr,
397c825f788SLeo Yan .auxtrace_info = perf_event__process_auxtrace_info,
398c825f788SLeo Yan .auxtrace = perf_event__process_auxtrace,
399c825f788SLeo Yan .auxtrace_error = perf_event__process_auxtrace_error,
40078b27543SJiri Olsa .ordered_events = true,
40178b27543SJiri Olsa .ordering_requires_timestamps = true,
40278b27543SJiri Olsa },
40378b27543SJiri Olsa };
40478b27543SJiri Olsa
4057aef3bf3SJiri Olsa static const char * const c2c_usage[] = {
406903a6f15SJiri Olsa "perf c2c {record|report}",
4077aef3bf3SJiri Olsa NULL
4087aef3bf3SJiri Olsa };
4097aef3bf3SJiri Olsa
410903a6f15SJiri Olsa static const char * const __usage_report[] = {
411903a6f15SJiri Olsa "perf c2c report",
412903a6f15SJiri Olsa NULL
413903a6f15SJiri Olsa };
414903a6f15SJiri Olsa
415903a6f15SJiri Olsa static const char * const *report_c2c_usage = __usage_report;
416903a6f15SJiri 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 };
425c75540e3SJiri Olsa
426c75540e3SJiri Olsa struct c2c_dimension {
427c75540e3SJiri Olsa struct c2c_header header;
428c75540e3SJiri Olsa const char *name;
429c75540e3SJiri Olsa int width;
4308d3f938dSJiri 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
440c75540e3SJiri Olsa struct c2c_fmt {
441c75540e3SJiri Olsa struct perf_hpp_fmt fmt;
442c75540e3SJiri Olsa struct c2c_dimension *dim;
443c75540e3SJiri Olsa };
444c75540e3SJiri 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)
455590b6a3aSJiri Olsa width = MIN(width, SYMBOL_WIDTH);
456590b6a3aSJiri Olsa
457590b6a3aSJiri Olsa return width;
458590b6a3aSJiri Olsa }
459590b6a3aSJiri 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,
4627e6a7998SArnaldo Carvalho de Melo struct hists *hists)
463c75540e3SJiri Olsa {
464c75540e3SJiri Olsa struct c2c_fmt *c2c_fmt;
465c75540e3SJiri Olsa struct c2c_dimension *dim;
466c75540e3SJiri Olsa
467c75540e3SJiri Olsa c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
468c75540e3SJiri Olsa dim = c2c_fmt->dim;
469c75540e3SJiri Olsa
470590b6a3aSJiri Olsa if (dim == &dim_symbol || dim == &dim_srcline)
471590b6a3aSJiri Olsa return symbol_width(hists, dim->se);
472590b6a3aSJiri 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);
4858d3f938dSJiri 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) {
490c75540e3SJiri Olsa text = dim->header.line[line].text;
4918d3f938dSJiri Olsa /* Use the last line from sort_entry if not defined. */
4928d3f938dSJiri Olsa if (!text && (line == hpp_list->nr_header_lines - 1))
4938d3f938dSJiri Olsa text = dim->se->se_header;
4948d3f938dSJiri Olsa } else {
4958d3f938dSJiri Olsa text = dim->header.line[line].text;
496c75540e3SJiri Olsa
497c75540e3SJiri Olsa if (*span) {
498c75540e3SJiri Olsa (*span)--;
499c75540e3SJiri Olsa return 0;
500c75540e3SJiri Olsa } else {
501c75540e3SJiri Olsa *span = dim->header.line[line].span;
502c75540e3SJiri Olsa }
5038d3f938dSJiri Olsa }
504c75540e3SJiri Olsa
5058d3f938dSJiri Olsa if (text == NULL)
5068d3f938dSJiri Olsa text = "";
5078d3f938dSJiri Olsa
5088d3f938dSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, text);
509c75540e3SJiri Olsa }
510c75540e3SJiri 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 {
527cbb88500SJiri Olsa 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)
5321470a108SFeng Tang addr = cl_address(he->mem_info->daddr.addr, chk_double_cl);
533cbb88500SJiri Olsa
534cbb88500SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
535cbb88500SJiri Olsa }
536cbb88500SJiri 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))
5467f834c2eSJiri Olsa return 0;
5477f834c2eSJiri Olsa
5487f834c2eSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, c2c_he->nodestr);
5497f834c2eSJiri Olsa }
5507f834c2eSJiri 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);
55703d9fcb7SJiri Olsa
55803d9fcb7SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
55903d9fcb7SJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*lu", width, c2c_he->paddr_cnt);
56003d9fcb7SJiri Olsa }
56103d9fcb7SJiri 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 {
56548acdebdSJiri Olsa 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)
5701470a108SFeng Tang 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,
57748acdebdSJiri Olsa struct hist_entry *left, struct hist_entry *right)
57848acdebdSJiri Olsa {
57948acdebdSJiri Olsa uint64_t l = 0, r = 0;
58048acdebdSJiri Olsa
58148acdebdSJiri Olsa if (left->mem_info)
5821470a108SFeng Tang l = cl_offset(left->mem_info->daddr.addr, chk_double_cl);
5831470a108SFeng Tang
58448acdebdSJiri Olsa if (right->mem_info)
5851470a108SFeng Tang r = cl_offset(right->mem_info->daddr.addr, chk_double_cl);
58648acdebdSJiri Olsa
58748acdebdSJiri Olsa return (int64_t)(r - l);
58848acdebdSJiri Olsa }
58948acdebdSJiri 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,
60643575a95SJiri Olsa struct hist_entry *left, struct hist_entry *right)
60743575a95SJiri Olsa {
60843575a95SJiri Olsa return sort__iaddr_cmp(left, right);
60943575a95SJiri Olsa }
61043575a95SJiri 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)62697cb486eSJiri Olsa tot_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
62797cb486eSJiri Olsa 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;
631c1c8013eSAndres Freund uint64_t tot_hitm_left;
632c1c8013eSAndres Freund 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) \
66097cb486eSJiri Olsa { \
66197cb486eSJiri Olsa 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); \
665c1c8013eSAndres Freund return (uint64_t) c2c_left->stats.__f - \
666c1c8013eSAndres Freund (uint64_t) c2c_right->stats.__f; \
66797cb486eSJiri Olsa }
66897cb486eSJiri Olsa
66997cb486eSJiri Olsa #define STAT_FN(__f) \
67097cb486eSJiri Olsa STAT_FN_ENTRY(__f) \
67197cb486eSJiri Olsa STAT_FN_CMP(__f)
67297cb486eSJiri Olsa
67397cb486eSJiri Olsa STAT_FN(rmt_hitm)
STAT_FN(lcl_hitm)67497cb486eSJiri Olsa STAT_FN(lcl_hitm)
67563e74ab5SLeo Yan STAT_FN(rmt_peer)
67663e74ab5SLeo Yan STAT_FN(lcl_peer)
67763e74ab5SLeo Yan STAT_FN(tot_peer)
6780f18896dSJiri Olsa STAT_FN(store)
6790f18896dSJiri Olsa STAT_FN(st_l1hit)
6800f18896dSJiri Olsa STAT_FN(st_l1miss)
681550b4d6fSLeo Yan STAT_FN(st_na)
6821295f685SJiri Olsa STAT_FN(ld_fbhit)
6831295f685SJiri Olsa STAT_FN(ld_l1hit)
6841295f685SJiri Olsa STAT_FN(ld_l2hit)
6854d08910cSJiri Olsa STAT_FN(ld_llchit)
6864d08910cSJiri Olsa STAT_FN(rmt_hit)
68797cb486eSJiri Olsa
688cf874a01SShang XiaoJing static uint64_t get_load_llc_misses(struct c2c_stats *stats)
68901b84d76SJiri Olsa {
690cf874a01SShang XiaoJing return stats->lcl_dram +
69101b84d76SJiri Olsa stats->rmt_dram +
69201b84d76SJiri Olsa stats->rmt_hitm +
69301b84d76SJiri Olsa stats->rmt_hit;
694cf874a01SShang XiaoJing }
69501b84d76SJiri Olsa
get_load_cache_hits(struct c2c_stats * stats)696cf874a01SShang XiaoJing static uint64_t get_load_cache_hits(struct c2c_stats *stats)
697cf874a01SShang XiaoJing {
698cf874a01SShang XiaoJing return stats->ld_fbhit +
69901b84d76SJiri Olsa stats->ld_l1hit +
70001b84d76SJiri Olsa stats->ld_l2hit +
70101b84d76SJiri Olsa stats->ld_llchit +
70201b84d76SJiri Olsa stats->lcl_hitm;
703cf874a01SShang XiaoJing }
70401b84d76SJiri Olsa
get_stores(struct c2c_stats * stats)705cf874a01SShang XiaoJing static uint64_t get_stores(struct c2c_stats *stats)
706cf874a01SShang XiaoJing {
707cf874a01SShang XiaoJing return stats->st_l1hit +
708550b4d6fSLeo Yan stats->st_l1miss +
709550b4d6fSLeo Yan stats->st_na;
710cf874a01SShang XiaoJing }
71101b84d76SJiri Olsa
total_records(struct c2c_stats * stats)712cf874a01SShang XiaoJing static uint64_t total_records(struct c2c_stats *stats)
713cf874a01SShang XiaoJing {
714cf874a01SShang XiaoJing return get_load_llc_misses(stats) +
715cf874a01SShang XiaoJing get_load_cache_hits(stats) +
716cf874a01SShang XiaoJing 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);
74601b84d76SJiri Olsa tot_recs_right = total_records(&c2c_right->stats);
74701b84d76SJiri Olsa
74801b84d76SJiri Olsa return tot_recs_left - tot_recs_right;
74901b84d76SJiri Olsa }
75001b84d76SJiri Olsa
total_loads(struct c2c_stats * stats)75155177c4eSJiri Olsa static uint64_t total_loads(struct c2c_stats *stats)
75255177c4eSJiri Olsa {
753cf874a01SShang XiaoJing return get_load_llc_misses(stats) +
754cf874a01SShang XiaoJing 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);
78455177c4eSJiri Olsa tot_recs_right = total_loads(&c2c_right->stats);
78555177c4eSJiri Olsa
78655177c4eSJiri Olsa return tot_recs_left - tot_recs_right;
78755177c4eSJiri Olsa }
78855177c4eSJiri 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);
797f0c50c15SJiri Olsa double per;
798f0c50c15SJiri Olsa
799f0c50c15SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
800f0c50c15SJiri Olsa per = get_percent(c2c_he);
801f0c50c15SJiri Olsa
8025a1a99cdSJiri Olsa #ifdef HAVE_SLANG_SUPPORT
8035a1a99cdSJiri Olsa if (use_browser)
8045a1a99cdSJiri Olsa return __hpp__slsmg_color_printf(hpp, "%*.2f%%", width - 1, per);
8055a1a99cdSJiri 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)8092be0bc75SLeo Yan 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;
81455b95776SJiri Olsa int tot = 0, st = 0;
815f0c50c15SJiri Olsa double p;
816f0c50c15SJiri Olsa
817f0c50c15SJiri Olsa hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
818f0c50c15SJiri Olsa stats = &c2c_he->stats;
819f0c50c15SJiri Olsa total = &hists->stats;
820f0c50c15SJiri Olsa
82155b95776SJiri Olsa switch (c2c.display) {
822c82ccc3aSLeo Yan case DISPLAY_RMT_HITM:
823f0c50c15SJiri Olsa st = stats->rmt_hitm;
824f0c50c15SJiri Olsa tot = total->rmt_hitm;
82555b95776SJiri Olsa break;
826c82ccc3aSLeo Yan case DISPLAY_LCL_HITM:
82755b95776SJiri Olsa st = stats->lcl_hitm;
82855b95776SJiri Olsa tot = total->lcl_hitm;
829d940baccSJiri Olsa break;
830c82ccc3aSLeo Yan case DISPLAY_TOT_HITM:
831d940baccSJiri Olsa st = stats->tot_hitm;
832d940baccSJiri Olsa tot = total->tot_hitm;
833f37c5d91SLeo Yan break;
834f37c5d91SLeo Yan case DISPLAY_SNP_PEER:
835f37c5d91SLeo Yan st = stats->tot_peer;
836f37c5d91SLeo Yan tot = total->tot_peer;
837f37c5d91SLeo Yan break;
83855b95776SJiri Olsa default:
83955b95776SJiri Olsa break;
84055b95776SJiri 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 ({ \
849f0c50c15SJiri Olsa 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)8542be0bc75SLeo Yan 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;
858f0c50c15SJiri Olsa 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 }
866f0c50c15SJiri Olsa
867f0c50c15SJiri Olsa static int
percent_costly_snoop_color(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)8682be0bc75SLeo Yan percent_costly_snoop_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
869f0c50c15SJiri Olsa struct hist_entry *he)
870f0c50c15SJiri Olsa {
8712be0bc75SLeo Yan 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)8752be0bc75SLeo Yan 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;
881f0c50c15SJiri Olsa double per_right;
882f0c50c15SJiri Olsa
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
8862be0bc75SLeo Yan per_left = percent_costly_snoop(c2c_left);
8872be0bc75SLeo Yan per_right = percent_costly_snoop(c2c_right);
888f0c50c15SJiri Olsa
889f0c50c15SJiri Olsa return per_left - per_right;
890f0c50c15SJiri Olsa }
891f0c50c15SJiri 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;
9039cb3500aSJiri Olsa
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)908111c1415SLeo Yan 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); \
9219cb3500aSJiri Olsa return percent(c2c_he->stats.__f, hists->stats.__f); \
9229cb3500aSJiri Olsa }
9239cb3500aSJiri Olsa
9249cb3500aSJiri Olsa PERCENT_FN(rmt_hitm)
PERCENT_FN(lcl_hitm)9259cb3500aSJiri Olsa PERCENT_FN(lcl_hitm)
9269082282fSLeo Yan PERCENT_FN(rmt_peer)
9279082282fSLeo Yan PERCENT_FN(lcl_peer)
9289cb3500aSJiri Olsa PERCENT_FN(st_l1hit)
9299cb3500aSJiri Olsa PERCENT_FN(st_l1miss)
930550b4d6fSLeo Yan 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,
9529cb3500aSJiri Olsa struct hist_entry *left, struct hist_entry *right)
9539cb3500aSJiri Olsa {
9549cb3500aSJiri Olsa double per_left;
9559cb3500aSJiri Olsa double per_right;
9569cb3500aSJiri Olsa
957b24192a1SLeo Yan per_left = PERCENT(left, rmt_hitm);
958b24192a1SLeo Yan 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);
9909cb3500aSJiri Olsa
9919cb3500aSJiri Olsa return per_left - per_right;
9929cb3500aSJiri Olsa }
9939cb3500aSJiri Olsa
9949cb3500aSJiri Olsa 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);
10529082282fSLeo Yan
10539082282fSLeo Yan return per_left - per_right;
10549082282fSLeo Yan }
10559082282fSLeo Yan
10569082282fSLeo Yan 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);
11139cb3500aSJiri Olsa per_right = PERCENT(right, st_l1miss);
11149cb3500aSJiri Olsa
11159cb3500aSJiri Olsa return per_left - per_right;
11169cb3500aSJiri Olsa }
11179cb3500aSJiri Olsa
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);
1144550b4d6fSLeo Yan per_right = PERCENT(right, st_na);
1145550b4d6fSLeo Yan
1146550b4d6fSLeo Yan return per_left - per_right;
1147550b4d6fSLeo Yan }
1148550b4d6fSLeo Yan
11496c70f54cSJiri Olsa STAT_FN(lcl_dram)
STAT_FN(rmt_dram)11506c70f54cSJiri Olsa STAT_FN(rmt_dram)
11516c70f54cSJiri 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
1158ee84a303SIan Rogers 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,
116336d3deb9SJiri Olsa struct hist_entry *left, struct hist_entry *right)
116436d3deb9SJiri Olsa {
1165ee84a303SIan Rogers return thread__pid(left->thread) - thread__pid(right->thread);
116636d3deb9SJiri Olsa }
116736d3deb9SJiri 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,
11711e181b92SJiri Olsa struct hist_entry *right __maybe_unused)
11721e181b92SJiri Olsa {
11731e181b92SJiri Olsa return 0;
11741e181b92SJiri Olsa }
11751e181b92SJiri Olsa
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
1184f3d0a551SLeo Yan ret = scnprintf(hpp->buf, hpp->size, "%6s ", "n/a");
1185f3d0a551SLeo Yan
1186f3d0a551SLeo Yan return ret;
1187f3d0a551SLeo Yan }
1188f3d0a551SLeo Yan
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++) {
12011e181b92SJiri Olsa 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
12061006c5c1SYury Norov 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:
12211e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%2d", node);
12221e181b92SJiri Olsa advance_hpp(hpp, ret);
12231e181b92SJiri Olsa break;
12241e181b92SJiri Olsa case 1:
12251e181b92SJiri Olsa {
122667260e8cSJiri Olsa int num = bitmap_weight(set, c2c.cpus_cnt);
12271e181b92SJiri Olsa struct c2c_stats *stats = &c2c_he->node_stats[node];
12281e181b92SJiri Olsa
12291e181b92SJiri Olsa ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num);
12301e181b92SJiri Olsa advance_hpp(hpp, ret);
12311e181b92SJiri Olsa
123255b95776SJiri Olsa switch (c2c.display) {
1233c82ccc3aSLeo Yan case DISPLAY_RMT_HITM:
1234f3d0a551SLeo Yan ret = display_metrics(hpp, stats->rmt_hitm,
1235f3d0a551SLeo Yan c2c_he->stats.rmt_hitm);
123655b95776SJiri Olsa break;
1237c82ccc3aSLeo Yan case DISPLAY_LCL_HITM:
1238f3d0a551SLeo Yan ret = display_metrics(hpp, stats->lcl_hitm,
1239f3d0a551SLeo Yan c2c_he->stats.lcl_hitm);
1240d940baccSJiri Olsa break;
1241c82ccc3aSLeo Yan case DISPLAY_TOT_HITM:
1242f3d0a551SLeo Yan ret = display_metrics(hpp, stats->tot_hitm,
1243f3d0a551SLeo Yan c2c_he->stats.tot_hitm);
1244f3d0a551SLeo Yan break;
1245f37c5d91SLeo Yan case DISPLAY_SNP_PEER:
1246f37c5d91SLeo Yan ret = display_metrics(hpp, stats->tot_peer,
1247f37c5d91SLeo Yan c2c_he->stats.tot_peer);
1248f37c5d91SLeo Yan break;
124955b95776SJiri Olsa default:
125055b95776SJiri Olsa break;
125155b95776SJiri Olsa }
125255b95776SJiri 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;
12801e181b92SJiri Olsa }
12811e181b92SJiri Olsa
12821e181b92SJiri Olsa return 0;
12831e181b92SJiri Olsa }
12841e181b92SJiri 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)); \
130392062d54SJiri Olsa }
130492062d54SJiri Olsa
130592062d54SJiri Olsa MEAN_ENTRY(mean_rmt_entry, rmt_hitm);
130692062d54SJiri Olsa MEAN_ENTRY(mean_lcl_entry, lcl_hitm);
130792062d54SJiri Olsa MEAN_ENTRY(mean_load_entry, load);
1308682352e5SLeo Yan MEAN_ENTRY(mean_rmt_peer_entry, rmt_peer);
1309682352e5SLeo Yan MEAN_ENTRY(mean_lcl_peer_entry, lcl_peer);
131092062d54SJiri Olsa
1311b6fe2bbcSJiri Olsa static int
cpucnt_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)13127e6a7998SArnaldo Carvalho de Melo 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);
1320b6fe2bbcSJiri Olsa
1321b6fe2bbcSJiri Olsa scnprintf(buf, 10, "%d", bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt));
1322b6fe2bbcSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
1323b6fe2bbcSJiri Olsa }
1324b6fe2bbcSJiri Olsa
1325bb342daeSJiri Olsa static int
cl_idx_entry(struct perf_hpp_fmt * fmt,struct perf_hpp * hpp,struct hist_entry * he)13267e6a7998SArnaldo Carvalho de Melo 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
1335bb342daeSJiri Olsa 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)13407e6a7998SArnaldo Carvalho de Melo cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1341bb342daeSJiri Olsa struct hist_entry *he)
1342bb342daeSJiri Olsa {
1343bb342daeSJiri Olsa int width = c2c_width(fmt, hpp, he->hists);
1344bb342daeSJiri Olsa
1345bb342daeSJiri Olsa return scnprintf(hpp->buf, hpp->size, "%*s", width, "");
1346bb342daeSJiri Olsa }
1347bb342daeSJiri 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 { \
1378600a8cf4SJiri Olsa .line[1] = { \
1379600a8cf4SJiri Olsa .text = __h, \
1380600a8cf4SJiri Olsa }, \
1381600a8cf4SJiri Olsa }
1382600a8cf4SJiri Olsa
1383cbb88500SJiri Olsa static struct c2c_dimension dim_dcacheline = {
138403d9fcb7SJiri Olsa .header = HEADER_SPAN("--- Cacheline ----", "Address", 2),
1385cbb88500SJiri Olsa .name = "dcacheline",
1386cbb88500SJiri Olsa .cmp = dcacheline_cmp,
1387cbb88500SJiri Olsa .entry = dcacheline_entry,
1388cbb88500SJiri Olsa .width = 18,
1389cbb88500SJiri Olsa };
1390cbb88500SJiri Olsa
13917f834c2eSJiri Olsa static struct c2c_dimension dim_dcacheline_node = {
13927f834c2eSJiri Olsa .header = HEADER_LOW("Node"),
13937f834c2eSJiri Olsa .name = "dcacheline_node",
13947f834c2eSJiri Olsa .cmp = empty_cmp,
13957f834c2eSJiri Olsa .entry = dcacheline_node_entry,
13967f834c2eSJiri Olsa .width = 4,
13977f834c2eSJiri Olsa };
13987f834c2eSJiri 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,
140303d9fcb7SJiri Olsa .entry = dcacheline_node_count,
140403d9fcb7SJiri Olsa .width = 6,
140503d9fcb7SJiri Olsa };
140603d9fcb7SJiri Olsa
140703d9fcb7SJiri Olsa static struct c2c_header header_offset_tui = HEADER_SPAN("-----", "Off", 2);
14085a1a99cdSJiri Olsa
140948acdebdSJiri Olsa static struct c2c_dimension dim_offset = {
141003d9fcb7SJiri Olsa .header = HEADER_SPAN("--- Data address -", "Offset", 2),
141148acdebdSJiri Olsa .name = "offset",
141248acdebdSJiri Olsa .cmp = offset_cmp,
141348acdebdSJiri Olsa .entry = offset_entry,
141448acdebdSJiri Olsa .width = 18,
141548acdebdSJiri Olsa };
141648acdebdSJiri Olsa
14177f834c2eSJiri Olsa static struct c2c_dimension dim_offset_node = {
14187f834c2eSJiri Olsa .header = HEADER_LOW("Node"),
14197f834c2eSJiri Olsa .name = "offset_node",
14207f834c2eSJiri Olsa .cmp = empty_cmp,
14217f834c2eSJiri Olsa .entry = dcacheline_node_entry,
14227f834c2eSJiri Olsa .width = 4,
14237f834c2eSJiri Olsa };
14247f834c2eSJiri Olsa
142543575a95SJiri Olsa static struct c2c_dimension dim_iaddr = {
142643575a95SJiri Olsa .header = HEADER_LOW("Code address"),
142743575a95SJiri Olsa .name = "iaddr",
142843575a95SJiri Olsa .cmp = iaddr_cmp,
142943575a95SJiri Olsa .entry = iaddr_entry,
143043575a95SJiri Olsa .width = 18,
143143575a95SJiri Olsa };
143243575a95SJiri Olsa
143397cb486eSJiri Olsa static struct c2c_dimension dim_tot_hitm = {
1434fdd32d7eSLeo Yan .header = HEADER_SPAN("------- Load Hitm -------", "Total", 2),
143597cb486eSJiri Olsa .name = "tot_hitm",
143697cb486eSJiri Olsa .cmp = tot_hitm_cmp,
143797cb486eSJiri Olsa .entry = tot_hitm_entry,
143897cb486eSJiri Olsa .width = 7,
143997cb486eSJiri Olsa };
144097cb486eSJiri Olsa
144197cb486eSJiri Olsa static struct c2c_dimension dim_lcl_hitm = {
14420fbe2fe9SLeo Yan .header = HEADER_SPAN_LOW("LclHitm"),
144397cb486eSJiri Olsa .name = "lcl_hitm",
144497cb486eSJiri Olsa .cmp = lcl_hitm_cmp,
144597cb486eSJiri Olsa .entry = lcl_hitm_entry,
144697cb486eSJiri Olsa .width = 7,
144797cb486eSJiri Olsa };
144897cb486eSJiri Olsa
144997cb486eSJiri Olsa static struct c2c_dimension dim_rmt_hitm = {
14500fbe2fe9SLeo Yan .header = HEADER_SPAN_LOW("RmtHitm"),
145197cb486eSJiri Olsa .name = "rmt_hitm",
145297cb486eSJiri Olsa .cmp = rmt_hitm_cmp,
145397cb486eSJiri Olsa .entry = rmt_hitm_entry,
145497cb486eSJiri Olsa .width = 7,
145597cb486eSJiri Olsa };
145697cb486eSJiri Olsa
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",
147663e74ab5SLeo Yan .cmp = rmt_peer_cmp,
147763e74ab5SLeo Yan .entry = rmt_peer_entry,
147863e74ab5SLeo Yan .width = 7,
147963e74ab5SLeo Yan };
148063e74ab5SLeo Yan
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",
149297cb486eSJiri Olsa .cmp = lcl_hitm_cmp,
149397cb486eSJiri Olsa .entry = lcl_hitm_entry,
149497cb486eSJiri Olsa .width = 7,
149597cb486eSJiri Olsa };
149697cb486eSJiri Olsa
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",
15089082282fSLeo Yan .cmp = lcl_peer_cmp,
15099082282fSLeo Yan .entry = lcl_peer_entry,
15109082282fSLeo Yan .width = 7,
15119082282fSLeo Yan };
15129082282fSLeo Yan
15134f28641bSLeo Yan static struct c2c_dimension dim_tot_stores = {
15144f28641bSLeo Yan .header = HEADER_BOTH("Total", "Stores"),
15154f28641bSLeo Yan .name = "tot_stores",
15160f18896dSJiri Olsa .cmp = store_cmp,
15170f18896dSJiri Olsa .entry = store_entry,
15180f18896dSJiri Olsa .width = 7,
15190f18896dSJiri Olsa };
15200f18896dSJiri Olsa
15210f18896dSJiri Olsa static struct c2c_dimension dim_stores_l1hit = {
1522550b4d6fSLeo Yan .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",
15320f18896dSJiri Olsa .cmp = st_l1miss_cmp,
15330f18896dSJiri Olsa .entry = st_l1miss_entry,
15340f18896dSJiri Olsa .width = 7,
15350f18896dSJiri Olsa };
15360f18896dSJiri Olsa
1537550b4d6fSLeo Yan static struct c2c_dimension dim_stores_na = {
1538550b4d6fSLeo Yan .header = HEADER_SPAN_LOW("N/A"),
1539550b4d6fSLeo Yan .name = "stores_na",
1540550b4d6fSLeo Yan .cmp = st_na_cmp,
1541550b4d6fSLeo Yan .entry = st_na_entry,
1542550b4d6fSLeo Yan .width = 7,
1543550b4d6fSLeo Yan };
1544550b4d6fSLeo Yan
15450f18896dSJiri Olsa static struct c2c_dimension dim_cl_stores_l1hit = {
1546550b4d6fSLeo Yan .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",
15560f18896dSJiri Olsa .cmp = st_l1miss_cmp,
15570f18896dSJiri Olsa .entry = st_l1miss_entry,
15580f18896dSJiri Olsa .width = 7,
15590f18896dSJiri Olsa };
15600f18896dSJiri Olsa
1561550b4d6fSLeo Yan static struct c2c_dimension dim_cl_stores_na = {
1562550b4d6fSLeo Yan .header = HEADER_SPAN_LOW("N/A"),
1563550b4d6fSLeo Yan .name = "cl_stores_na",
1564550b4d6fSLeo Yan .cmp = st_na_cmp,
1565550b4d6fSLeo Yan .entry = st_na_entry,
1566550b4d6fSLeo Yan .width = 7,
1567550b4d6fSLeo Yan };
1568550b4d6fSLeo Yan
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",
15881295f685SJiri Olsa .cmp = ld_l2hit_cmp,
15891295f685SJiri Olsa .entry = ld_l2hit_entry,
15901295f685SJiri Olsa .width = 7,
15911295f685SJiri Olsa };
15921295f685SJiri Olsa
15934d08910cSJiri Olsa static struct c2c_dimension dim_ld_llchit = {
159477c15869SLeo Yan .header = HEADER_SPAN("- LLC Load Hit --", "LclHit", 1),
15954d08910cSJiri Olsa .name = "ld_lclhit",
15964d08910cSJiri Olsa .cmp = ld_llchit_cmp,
15974d08910cSJiri Olsa .entry = ld_llchit_entry,
15984d08910cSJiri Olsa .width = 8,
15994d08910cSJiri Olsa };
16004d08910cSJiri Olsa
16014d08910cSJiri Olsa static struct c2c_dimension dim_ld_rmthit = {
160291d933c2SLeo Yan .header = HEADER_SPAN("- RMT Load Hit --", "RmtHit", 1),
16034d08910cSJiri Olsa .name = "ld_rmthit",
16044d08910cSJiri Olsa .cmp = rmt_hit_cmp,
16054d08910cSJiri Olsa .entry = rmt_hit_entry,
16064d08910cSJiri Olsa .width = 8,
16074d08910cSJiri Olsa };
16084d08910cSJiri Olsa
160901b84d76SJiri Olsa static struct c2c_dimension dim_tot_recs = {
161001b84d76SJiri Olsa .header = HEADER_BOTH("Total", "records"),
161101b84d76SJiri Olsa .name = "tot_recs",
161201b84d76SJiri Olsa .cmp = tot_recs_cmp,
161301b84d76SJiri Olsa .entry = tot_recs_entry,
161401b84d76SJiri Olsa .width = 7,
161501b84d76SJiri Olsa };
161601b84d76SJiri Olsa
161755177c4eSJiri Olsa static struct c2c_dimension dim_tot_loads = {
161855177c4eSJiri Olsa .header = HEADER_BOTH("Total", "Loads"),
161955177c4eSJiri Olsa .name = "tot_loads",
162055177c4eSJiri Olsa .cmp = tot_loads_cmp,
162155177c4eSJiri Olsa .entry = tot_loads_entry,
162255177c4eSJiri Olsa .width = 7,
162355177c4eSJiri Olsa };
162455177c4eSJiri Olsa
16252be0bc75SLeo Yan static struct c2c_header percent_costly_snoop_header[] = {
1626c82ccc3aSLeo Yan [DISPLAY_LCL_HITM] = HEADER_BOTH("Lcl", "Hitm"),
1627c82ccc3aSLeo Yan [DISPLAY_RMT_HITM] = HEADER_BOTH("Rmt", "Hitm"),
1628c82ccc3aSLeo Yan [DISPLAY_TOT_HITM] = HEADER_BOTH("Tot", "Hitm"),
1629f37c5d91SLeo Yan [DISPLAY_SNP_PEER] = HEADER_BOTH("Peer", "Snoop"),
163055b95776SJiri Olsa };
163155b95776SJiri Olsa
16322be0bc75SLeo Yan static struct c2c_dimension dim_percent_costly_snoop = {
16332be0bc75SLeo Yan .name = "percent_costly_snoop",
16342be0bc75SLeo Yan .cmp = percent_costly_snoop_cmp,
16352be0bc75SLeo Yan .entry = percent_costly_snoop_entry,
16362be0bc75SLeo Yan .color = percent_costly_snoop_color,
1637f0c50c15SJiri Olsa .width = 7,
1638f0c50c15SJiri Olsa };
1639f0c50c15SJiri Olsa
16409cb3500aSJiri Olsa static struct c2c_dimension dim_percent_rmt_hitm = {
16410fbe2fe9SLeo Yan .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,
16459cb3500aSJiri Olsa .color = percent_rmt_hitm_color,
16469cb3500aSJiri Olsa .width = 7,
16479cb3500aSJiri Olsa };
16489cb3500aSJiri Olsa
16499cb3500aSJiri Olsa static struct c2c_dimension dim_percent_lcl_hitm = {
16500fbe2fe9SLeo Yan .header = HEADER_SPAN_LOW("LclHitm"),
16519cb3500aSJiri Olsa .name = "percent_lcl_hitm",
16529cb3500aSJiri Olsa .cmp = percent_lcl_hitm_cmp,
16539cb3500aSJiri Olsa .entry = percent_lcl_hitm_entry,
16549cb3500aSJiri Olsa .color = percent_lcl_hitm_color,
16559cb3500aSJiri Olsa .width = 7,
16569cb3500aSJiri Olsa };
16579cb3500aSJiri Olsa
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,
16719082282fSLeo Yan .entry = percent_lcl_peer_entry,
16729082282fSLeo Yan .color = percent_lcl_peer_color,
16739082282fSLeo Yan .width = 7,
16749082282fSLeo Yan };
16759082282fSLeo Yan
16769cb3500aSJiri Olsa static struct c2c_dimension dim_percent_stores_l1hit = {
1677550b4d6fSLeo Yan .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,
16899cb3500aSJiri Olsa .entry = percent_stores_l1miss_entry,
16909cb3500aSJiri Olsa .color = percent_stores_l1miss_color,
16919cb3500aSJiri Olsa .width = 7,
16929cb3500aSJiri Olsa };
16939cb3500aSJiri Olsa
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,
1698550b4d6fSLeo Yan .entry = percent_stores_na_entry,
1699550b4d6fSLeo Yan .color = percent_stores_na_color,
1700550b4d6fSLeo Yan .width = 7,
1701550b4d6fSLeo Yan };
1702550b4d6fSLeo Yan
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",
17146c70f54cSJiri Olsa .cmp = rmt_dram_cmp,
17156c70f54cSJiri Olsa .entry = rmt_dram_entry,
17166c70f54cSJiri Olsa .width = 8,
17176c70f54cSJiri Olsa };
17186c70f54cSJiri Olsa
171936d3deb9SJiri Olsa static struct c2c_dimension dim_pid = {
172036d3deb9SJiri Olsa .header = HEADER_LOW("Pid"),
172136d3deb9SJiri Olsa .name = "pid",
172236d3deb9SJiri Olsa .cmp = pid_cmp,
172336d3deb9SJiri Olsa .entry = pid_entry,
172436d3deb9SJiri Olsa .width = 7,
172536d3deb9SJiri Olsa };
172636d3deb9SJiri Olsa
1727e87019c5SJiri Olsa static struct c2c_dimension dim_tid = {
1728e87019c5SJiri Olsa .header = HEADER_LOW("Tid"),
1729e87019c5SJiri Olsa .name = "tid",
1730e87019c5SJiri Olsa .se = &sort_thread,
1731e87019c5SJiri Olsa };
1732e87019c5SJiri 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 = {
173951dedaa4SJiri Olsa .header = HEADER_BOTH("Shared", "Object"),
174051dedaa4SJiri Olsa .name = "dso",
174151dedaa4SJiri Olsa .se = &sort_dso,
174251dedaa4SJiri Olsa };
174351dedaa4SJiri Olsa
17441e181b92SJiri Olsa static struct c2c_dimension dim_node = {
17451e181b92SJiri Olsa .name = "node",
17461e181b92SJiri Olsa .cmp = empty_cmp,
17471e181b92SJiri Olsa .entry = node_entry,
17481e181b92SJiri Olsa .width = 4,
17491e181b92SJiri Olsa };
17501e181b92SJiri 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",
177092062d54SJiri Olsa .cmp = empty_cmp,
177192062d54SJiri Olsa .entry = mean_load_entry,
177292062d54SJiri Olsa .width = 8,
177392062d54SJiri Olsa };
177492062d54SJiri Olsa
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",
1786682352e5SLeo Yan .cmp = empty_cmp,
1787682352e5SLeo Yan .entry = mean_lcl_peer_entry,
1788682352e5SLeo Yan .width = 8,
1789682352e5SLeo Yan };
1790682352e5SLeo Yan
1791b6fe2bbcSJiri Olsa static struct c2c_dimension dim_cpucnt = {
1792b6fe2bbcSJiri Olsa .header = HEADER_BOTH("cpu", "cnt"),
1793b6fe2bbcSJiri Olsa .name = "cpucnt",
1794b6fe2bbcSJiri Olsa .cmp = empty_cmp,
1795b6fe2bbcSJiri Olsa .entry = cpucnt_entry,
1796b6fe2bbcSJiri Olsa .width = 8,
1797b6fe2bbcSJiri Olsa };
1798b6fe2bbcSJiri Olsa
179989d9ba8fSJiri Olsa static struct c2c_dimension dim_srcline = {
180089d9ba8fSJiri Olsa .name = "cl_srcline",
180189d9ba8fSJiri Olsa .se = &sort_srcline,
180289d9ba8fSJiri Olsa };
180389d9ba8fSJiri 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",
1823bb342daeSJiri Olsa .cmp = empty_cmp,
1824bb342daeSJiri Olsa .entry = cl_idx_empty_entry,
1825bb342daeSJiri Olsa .width = 5,
1826bb342daeSJiri Olsa };
1827bb342daeSJiri Olsa
1828c75540e3SJiri Olsa static struct c2c_dimension *dimensions[] = {
1829cbb88500SJiri Olsa &dim_dcacheline,
18307f834c2eSJiri Olsa &dim_dcacheline_node,
183103d9fcb7SJiri Olsa &dim_dcacheline_count,
183248acdebdSJiri Olsa &dim_offset,
18337f834c2eSJiri Olsa &dim_offset_node,
183443575a95SJiri Olsa &dim_iaddr,
183597cb486eSJiri Olsa &dim_tot_hitm,
183697cb486eSJiri Olsa &dim_lcl_hitm,
183797cb486eSJiri Olsa &dim_rmt_hitm,
183863e74ab5SLeo Yan &dim_tot_peer,
183963e74ab5SLeo Yan &dim_lcl_peer,
184063e74ab5SLeo Yan &dim_rmt_peer,
184197cb486eSJiri Olsa &dim_cl_lcl_hitm,
184297cb486eSJiri Olsa &dim_cl_rmt_hitm,
18439082282fSLeo Yan &dim_cl_lcl_peer,
18449082282fSLeo Yan &dim_cl_rmt_peer,
18454f28641bSLeo Yan &dim_tot_stores,
18460f18896dSJiri Olsa &dim_stores_l1hit,
18470f18896dSJiri Olsa &dim_stores_l1miss,
1848550b4d6fSLeo Yan &dim_stores_na,
18490f18896dSJiri Olsa &dim_cl_stores_l1hit,
18500f18896dSJiri Olsa &dim_cl_stores_l1miss,
1851550b4d6fSLeo Yan &dim_cl_stores_na,
18521295f685SJiri Olsa &dim_ld_fbhit,
18531295f685SJiri Olsa &dim_ld_l1hit,
18541295f685SJiri Olsa &dim_ld_l2hit,
18554d08910cSJiri Olsa &dim_ld_llchit,
18564d08910cSJiri Olsa &dim_ld_rmthit,
185701b84d76SJiri Olsa &dim_tot_recs,
185855177c4eSJiri Olsa &dim_tot_loads,
18592be0bc75SLeo Yan &dim_percent_costly_snoop,
18609cb3500aSJiri Olsa &dim_percent_rmt_hitm,
18619cb3500aSJiri Olsa &dim_percent_lcl_hitm,
18629082282fSLeo Yan &dim_percent_rmt_peer,
18639082282fSLeo Yan &dim_percent_lcl_peer,
18649cb3500aSJiri Olsa &dim_percent_stores_l1hit,
18659cb3500aSJiri Olsa &dim_percent_stores_l1miss,
1866550b4d6fSLeo Yan &dim_percent_stores_na,
18676c70f54cSJiri Olsa &dim_dram_lcl,
18686c70f54cSJiri Olsa &dim_dram_rmt,
186936d3deb9SJiri Olsa &dim_pid,
1870e87019c5SJiri Olsa &dim_tid,
187151dedaa4SJiri Olsa &dim_symbol,
187251dedaa4SJiri Olsa &dim_dso,
18731e181b92SJiri Olsa &dim_node,
187492062d54SJiri Olsa &dim_mean_rmt,
187592062d54SJiri Olsa &dim_mean_lcl,
1876682352e5SLeo Yan &dim_mean_rmt_peer,
1877682352e5SLeo Yan &dim_mean_lcl_peer,
187892062d54SJiri Olsa &dim_mean_load,
1879b6fe2bbcSJiri Olsa &dim_cpucnt,
188089d9ba8fSJiri Olsa &dim_srcline,
1881bb342daeSJiri Olsa &dim_dcacheline_idx,
1882bb342daeSJiri Olsa &dim_dcacheline_num,
1883bb342daeSJiri 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
1907c75540e3SJiri Olsa 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;
19122cca512aSZou Wei }
1913c75540e3SJiri Olsa
1914c75540e3SJiri Olsa return NULL;
1915c75540e3SJiri Olsa }
1916c75540e3SJiri 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)
19198d3f938dSJiri Olsa {
19208d3f938dSJiri Olsa struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
19218d3f938dSJiri Olsa struct c2c_dimension *dim = c2c_fmt->dim;
19228d3f938dSJiri Olsa size_t len = fmt->user_len;
19238d3f938dSJiri Olsa
1924590b6a3aSJiri Olsa if (!len) {
19258d3f938dSJiri Olsa len = hists__col_len(he->hists, dim->se->se_width_idx);
19268d3f938dSJiri Olsa
1927590b6a3aSJiri Olsa if (dim == &dim_symbol || dim == &dim_srcline)
1928590b6a3aSJiri Olsa len = symbol_width(he->hists, dim->se);
1929590b6a3aSJiri Olsa }
1930590b6a3aSJiri 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 *);
19498d3f938dSJiri Olsa
19508d3f938dSJiri Olsa collapse_fn = dim->se->se_collapse ?: dim->se->se_cmp;
19518d3f938dSJiri Olsa return collapse_fn(a, b);
19528d3f938dSJiri Olsa }
19538d3f938dSJiri 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;
1968c75540e3SJiri Olsa
1969c75540e3SJiri Olsa fmt = &c2c_fmt->fmt;
1970c75540e3SJiri Olsa INIT_LIST_HEAD(&fmt->list);
1971c75540e3SJiri Olsa INIT_LIST_HEAD(&fmt->sort_list);
1972c75540e3SJiri Olsa
19738d3f938dSJiri Olsa fmt->cmp = dim->se ? c2c_se_cmp : dim->cmp;
19748d3f938dSJiri Olsa fmt->sort = dim->se ? c2c_se_cmp : dim->cmp;
19759cb3500aSJiri Olsa fmt->color = dim->se ? NULL : dim->color;
19768d3f938dSJiri Olsa fmt->entry = dim->se ? c2c_se_entry : dim->entry;
1977c75540e3SJiri Olsa fmt->header = c2c_header;
1978c75540e3SJiri Olsa fmt->width = c2c_width;
19798d3f938dSJiri 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 }
1985c75540e3SJiri Olsa
c2c_hists__init_output(struct perf_hpp_list * hpp_list,char * name)1986c75540e3SJiri Olsa static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
1987c75540e3SJiri Olsa {
1988c75540e3SJiri Olsa struct c2c_fmt *c2c_fmt = get_format(name);
1989c75540e3SJiri Olsa
19905f2eca83SJiri Olsa if (!c2c_fmt) {
19915f2eca83SJiri Olsa reset_dimensions();
19925f2eca83SJiri Olsa return output_field_add(hpp_list, name);
19935f2eca83SJiri Olsa }
1994c75540e3SJiri Olsa
1995c75540e3SJiri Olsa perf_hpp_list__column_register(hpp_list, &c2c_fmt->fmt);
1996c75540e3SJiri Olsa return 0;
1997c75540e3SJiri Olsa }
1998c75540e3SJiri Olsa
c2c_hists__init_sort(struct perf_hpp_list * hpp_list,char * name)1999c75540e3SJiri Olsa static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
2000c75540e3SJiri Olsa {
2001c75540e3SJiri Olsa struct c2c_fmt *c2c_fmt = get_format(name);
200251dedaa4SJiri Olsa struct c2c_dimension *dim;
2003c75540e3SJiri Olsa
20045f2eca83SJiri Olsa if (!c2c_fmt) {
20055f2eca83SJiri Olsa reset_dimensions();
20065f2eca83SJiri Olsa return sort_dimension__add(hpp_list, name, NULL, 0);
20075f2eca83SJiri Olsa }
2008c75540e3SJiri Olsa
200951dedaa4SJiri Olsa dim = c2c_fmt->dim;
201051dedaa4SJiri Olsa if (dim == &dim_dso)
201151dedaa4SJiri Olsa hpp_list->dso = 1;
201251dedaa4SJiri 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; \
2024c75540e3SJiri Olsa \
2025c75540e3SJiri Olsa for (tok = strtok_r((char *)_list, ", ", &tmp); \
2026c75540e3SJiri Olsa tok; tok = strtok_r(NULL, ", ", &tmp)) { \
2027c75540e3SJiri Olsa ret = _fn(hpp_list, tok); \
2028c75540e3SJiri Olsa if (ret == -EINVAL) { \
202962d94b00SArnaldo Carvalho de Melo pr_err("Invalid --fields key: `%s'", tok); \
2030c75540e3SJiri Olsa break; \
2031c75540e3SJiri Olsa } else if (ret == -ESRCH) { \
203262d94b00SArnaldo Carvalho de Melo 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);
2065c75540e3SJiri Olsa free(sort);
2066c75540e3SJiri 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,
20701d62fcd6SJiri Olsa const char *sort,
20711d62fcd6SJiri 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
2077c75540e3SJiri Olsa * later anyway, and that's where we add output fields
2078c75540e3SJiri Olsa * as well.
2079c75540e3SJiri Olsa */
2080c75540e3SJiri Olsa perf_hpp_list__init(&hists->list);
2081c75540e3SJiri Olsa
20821d62fcd6SJiri Olsa /* Overload number of header lines.*/
20831d62fcd6SJiri Olsa hists->list.nr_header_lines = nr_header_lines;
20841d62fcd6SJiri 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)
2091c75540e3SJiri Olsa {
2092c75540e3SJiri Olsa perf_hpp__reset_output_field(&c2c_hists->list);
2093c75540e3SJiri Olsa return hpp_list__parse(&c2c_hists->list, output, sort);
2094c75540e3SJiri Olsa }
2095c75540e3SJiri Olsa
2096c4a75bb9SJiri Olsa #define DISPLAY_LINE_LIMIT 0.001
20979857b717SJiri Olsa
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)
210169a95bfdSLeo Yan return HIST_FILTER__C2C;
210269a95bfdSLeo Yan
210369a95bfdSLeo Yan return 0;
210469a95bfdSLeo Yan }
210569a95bfdSLeo Yan
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
2110af09b2d3SJiri Olsa if (c2c.show_all)
21119857b717SJiri Olsa return true;
21129857b717SJiri Olsa
21139857b717SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
21149857b717SJiri Olsa
211555b95776SJiri Olsa switch (c2c.display) {
2116c82ccc3aSLeo Yan case DISPLAY_LCL_HITM:
211769a95bfdSLeo Yan he->filtered = filter_display(c2c_he->stats.lcl_hitm,
211869a95bfdSLeo Yan stats->lcl_hitm);
211955b95776SJiri Olsa break;
2120c82ccc3aSLeo Yan case DISPLAY_RMT_HITM:
212169a95bfdSLeo Yan he->filtered = filter_display(c2c_he->stats.rmt_hitm,
212269a95bfdSLeo Yan stats->rmt_hitm);
2123d940baccSJiri Olsa break;
2124c82ccc3aSLeo Yan case DISPLAY_TOT_HITM:
212569a95bfdSLeo Yan he->filtered = filter_display(c2c_he->stats.tot_hitm,
212669a95bfdSLeo Yan stats->tot_hitm);
212769a95bfdSLeo Yan break;
2128f37c5d91SLeo Yan case DISPLAY_SNP_PEER:
2129f37c5d91SLeo Yan he->filtered = filter_display(c2c_he->stats.tot_peer,
2130f37c5d91SLeo Yan stats->tot_peer);
2131f37c5d91SLeo Yan break;
213255b95776SJiri Olsa default:
213355b95776SJiri Olsa break;
21342cca512aSZou Wei }
213555b95776SJiri Olsa
21369857b717SJiri Olsa return he->filtered == 0;
21379857b717SJiri Olsa }
21389857b717SJiri Olsa
is_valid_hist_entry(struct hist_entry * he)21392290e1d6SLeo Yan static inline bool is_valid_hist_entry(struct hist_entry *he)
21409857b717SJiri Olsa {
21419857b717SJiri Olsa struct c2c_hist_entry *c2c_he;
21422290e1d6SLeo Yan bool has_record = false;
21439857b717SJiri Olsa
21449857b717SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
21452290e1d6SLeo Yan
21462290e1d6SLeo Yan /* It's a valid entry if contains stores */
21472290e1d6SLeo Yan if (c2c_he->stats.store)
21482290e1d6SLeo Yan return true;
21492290e1d6SLeo Yan
21502290e1d6SLeo Yan switch (c2c.display) {
2151c82ccc3aSLeo Yan case DISPLAY_LCL_HITM:
21522290e1d6SLeo Yan has_record = !!c2c_he->stats.lcl_hitm;
21532290e1d6SLeo Yan break;
2154c82ccc3aSLeo Yan case DISPLAY_RMT_HITM:
21552290e1d6SLeo Yan has_record = !!c2c_he->stats.rmt_hitm;
21562290e1d6SLeo Yan break;
2157c82ccc3aSLeo Yan case DISPLAY_TOT_HITM:
21582290e1d6SLeo Yan has_record = !!c2c_he->stats.tot_hitm;
21592290e1d6SLeo Yan break;
2160f37c5d91SLeo Yan case DISPLAY_SNP_PEER:
2161f37c5d91SLeo Yan has_record = !!c2c_he->stats.tot_peer;
21622290e1d6SLeo Yan default:
21632290e1d6SLeo Yan break;
21642290e1d6SLeo Yan }
21652290e1d6SLeo Yan
21662290e1d6SLeo Yan return has_record;
21679857b717SJiri Olsa }
21689857b717SJiri 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];
21837f834c2eSJiri Olsa int len;
21847f834c2eSJiri Olsa
21857f834c2eSJiri Olsa if (c2c_he->nodestr)
21867f834c2eSJiri Olsa return 0;
21877f834c2eSJiri Olsa
21881006c5c1SYury Norov 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
21957f834c2eSJiri Olsa set_node_width(c2c_he, len);
21967f834c2eSJiri Olsa c2c_he->nodestr = strdup(buf);
21977f834c2eSJiri Olsa return c2c_he->nodestr ? 0 : -ENOMEM;
21987f834c2eSJiri Olsa }
21997f834c2eSJiri Olsa
calc_width(struct c2c_hist_entry * c2c_he)220037731388SJiri Olsa static void calc_width(struct c2c_hist_entry *c2c_he)
220125aa84e3SJiri Olsa {
220225aa84e3SJiri Olsa struct c2c_hists *c2c_hists;
220325aa84e3SJiri Olsa
220437731388SJiri Olsa c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
220537731388SJiri Olsa hists__calc_col_len(&c2c_hists->hists, &c2c_he->he);
22067f834c2eSJiri Olsa set_nodestr(c2c_he);
220725aa84e3SJiri Olsa }
220825aa84e3SJiri Olsa
filter_cb(struct hist_entry * he,void * arg __maybe_unused)2209e4c38fd4SJiri Olsa static int filter_cb(struct hist_entry *he, void *arg __maybe_unused)
2210ec06f9b9SJiri Olsa {
221137731388SJiri Olsa struct c2c_hist_entry *c2c_he;
221237731388SJiri Olsa
221337731388SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
221437731388SJiri Olsa
221589d9ba8fSJiri Olsa if (c2c.show_src && !he->srcline)
22166a53da05SArnaldo Carvalho de Melo he->srcline = hist_entry__srcline(he);
221789d9ba8fSJiri Olsa
221837731388SJiri Olsa calc_width(c2c_he);
221925aa84e3SJiri Olsa
22202290e1d6SLeo Yan if (!is_valid_hist_entry(he))
22219857b717SJiri Olsa he->filtered = HIST_FILTER__C2C;
22229857b717SJiri Olsa
2223ec06f9b9SJiri Olsa return 0;
2224ec06f9b9SJiri Olsa }
2225ec06f9b9SJiri Olsa
resort_cl_cb(struct hist_entry * he,void * arg __maybe_unused)2226e4c38fd4SJiri 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;
22301834436eSLeo Yan bool display = he__display(he, &c2c.shared_clines_stats);
2231ec06f9b9SJiri Olsa
2232ec06f9b9SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
2233ec06f9b9SJiri Olsa c2c_hists = c2c_he->hists;
2234ec06f9b9SJiri Olsa
22359857b717SJiri Olsa if (display && c2c_hists) {
2236bb342daeSJiri Olsa static unsigned int idx;
2237bb342daeSJiri Olsa
2238bb342daeSJiri Olsa c2c_he->cacheline_idx = idx++;
2239bc229c21SJiri Olsa calc_width(c2c_he);
2240bb342daeSJiri Olsa
2241fc9c630eSJiri Olsa c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
224222dd59d1SJiri Olsa
2243ec06f9b9SJiri Olsa hists__collapse_resort(&c2c_hists->hists, NULL);
2244ec06f9b9SJiri Olsa hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb);
2245ec06f9b9SJiri Olsa }
2246ec06f9b9SJiri Olsa
2247ec06f9b9SJiri Olsa return 0;
2248ec06f9b9SJiri Olsa }
2249ec06f9b9SJiri Olsa
22507c10b65aSLeo Yan static struct c2c_header header_node_0 = HEADER_LOW("Node");
2251f37c5d91SLeo Yan static struct c2c_header header_node_1_hitms_stores =
2252f37c5d91SLeo Yan HEADER_LOW("Node{cpus %hitms %stores}");
2253f37c5d91SLeo Yan static struct c2c_header header_node_1_peers_stores =
2254f37c5d91SLeo 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)22571e181b92SJiri Olsa static void setup_nodes_header(void)
22581e181b92SJiri Olsa {
22597c10b65aSLeo Yan switch (c2c.node_info) {
22607c10b65aSLeo Yan case 0:
22617c10b65aSLeo Yan dim_node.header = header_node_0;
22627c10b65aSLeo Yan break;
22637c10b65aSLeo Yan case 1:
2264f37c5d91SLeo Yan if (c2c.display == DISPLAY_SNP_PEER)
2265f37c5d91SLeo Yan dim_node.header = header_node_1_peers_stores;
2266f37c5d91SLeo Yan else
2267f37c5d91SLeo 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;
22727c10b65aSLeo Yan default:
22737c10b65aSLeo Yan break;
22747c10b65aSLeo Yan }
22757c10b65aSLeo Yan
22767c10b65aSLeo Yan return;
22771e181b92SJiri Olsa }
22781e181b92SJiri Olsa
setup_nodes(struct perf_session * session)22791e181b92SJiri Olsa static int setup_nodes(struct perf_session *session)
22801e181b92SJiri Olsa {
22811e181b92SJiri Olsa struct numa_node *n;
22821e181b92SJiri Olsa unsigned long **nodes;
22836d18804bSIan Rogers int node, idx;
22846d18804bSIan Rogers struct perf_cpu cpu;
22851e181b92SJiri Olsa int *cpu2node;
22861e181b92SJiri Olsa
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;
22911ea770f6SRavi Bangoria 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;
23021e181b92SJiri Olsa
23031e181b92SJiri Olsa cpu2node = zalloc(sizeof(int) * c2c.cpus_cnt);
23041e181b92SJiri Olsa if (!cpu2node)
23051e181b92SJiri Olsa return -ENOMEM;
23061e181b92SJiri Olsa
23076d18804bSIan Rogers for (idx = 0; idx < c2c.cpus_cnt; idx++)
23086d18804bSIan Rogers cpu2node[idx] = -1;
23091e181b92SJiri Olsa
23101e181b92SJiri Olsa c2c.cpu2node = cpu2node;
23111e181b92SJiri Olsa
23121e181b92SJiri Olsa for (node = 0; node < c2c.nodes_cnt; node++) {
2313f854839bSJiri Olsa struct perf_cpu_map *map = n[node].map;
23141e181b92SJiri Olsa unsigned long *set;
23151e181b92SJiri Olsa
23167fc5b571SAndy Shevchenko set = bitmap_zalloc(c2c.cpus_cnt);
23171e181b92SJiri Olsa if (!set)
23181e181b92SJiri Olsa return -ENOMEM;
23191e181b92SJiri Olsa
2320e34c9402SJiri Olsa nodes[node] = set;
2321e34c9402SJiri Olsa
2322e34c9402SJiri Olsa /* empty node, skip */
2323315c0a1fSJiri Olsa if (perf_cpu_map__empty(map))
2324e34c9402SJiri Olsa continue;
2325e34c9402SJiri Olsa
232684d2f4f0SIan Rogers perf_cpu_map__for_each_cpu(cpu, idx, map) {
232775d7ba32SSean Christopherson __set_bit(cpu.cpu, set);
23281e181b92SJiri Olsa
23296d18804bSIan Rogers if (WARN_ONCE(cpu2node[cpu.cpu] != -1, "node/cpu topology bug"))
23301e181b92SJiri Olsa return -EINVAL;
23311e181b92SJiri Olsa
23326d18804bSIan Rogers cpu2node[cpu.cpu] = node;
23331e181b92SJiri Olsa }
23341e181b92SJiri Olsa }
23351e181b92SJiri Olsa
23361e181b92SJiri Olsa setup_nodes_header();
23371e181b92SJiri Olsa return 0;
23381e181b92SJiri Olsa }
23391e181b92SJiri Olsa
23407ef2efaaSJiri Olsa #define HAS_HITMS(__h) ((__h)->stats.lcl_hitm || (__h)->stats.rmt_hitm)
2341f37c5d91SLeo Yan #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)23431834436eSLeo Yan static int resort_shared_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
23447ef2efaaSJiri Olsa {
23457ef2efaaSJiri Olsa struct c2c_hist_entry *c2c_he;
23467ef2efaaSJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
23477ef2efaaSJiri Olsa
2348f37c5d91SLeo Yan if (HAS_HITMS(c2c_he) || HAS_PEER(c2c_he)) {
23497ef2efaaSJiri Olsa c2c.shared_clines++;
23501834436eSLeo Yan c2c_add_stats(&c2c.shared_clines_stats, &c2c_he->stats);
23517ef2efaaSJiri Olsa }
23527ef2efaaSJiri Olsa
23537ef2efaaSJiri Olsa 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 {
23582eb3d689SDavidlohr Bueso struct rb_node *next = rb_first_cached(&hists->entries);
23597ef2efaaSJiri Olsa int ret = 0;
23607ef2efaaSJiri Olsa
23617ef2efaaSJiri Olsa while (next) {
23627ef2efaaSJiri Olsa struct hist_entry *he;
23637ef2efaaSJiri Olsa
23647ef2efaaSJiri Olsa he = rb_entry(next, struct hist_entry, rb_node);
2365e4c38fd4SJiri Olsa ret = cb(he, NULL);
23667ef2efaaSJiri Olsa if (ret)
23677ef2efaaSJiri Olsa break;
23687ef2efaaSJiri Olsa next = rb_next(&he->rb_node);
23697ef2efaaSJiri Olsa }
23707ef2efaaSJiri Olsa
23717ef2efaaSJiri Olsa return ret;
23727ef2efaaSJiri Olsa }
23737ef2efaaSJiri Olsa
print_c2c__display_stats(FILE * out)237474c63a25SJiri Olsa 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
2379cf874a01SShang XiaoJing 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);
239874c63a25SJiri Olsa fprintf(out, " Load Local DRAM : %10d\n", stats->lcl_dram);
239974c63a25SJiri Olsa fprintf(out, " Load Remote DRAM : %10d\n", stats->rmt_dram);
240074c63a25SJiri Olsa fprintf(out, " Load MESI State Exclusive : %10d\n", stats->ld_excl);
240174c63a25SJiri Olsa fprintf(out, " Load MESI State Shared : %10d\n", stats->ld_shared);
240274c63a25SJiri Olsa fprintf(out, " Load LLC Misses : %10d\n", llc_misses);
2403d9d5d767SKan Liang fprintf(out, " Load access blocked by data : %10d\n", stats->blk_data);
2404d9d5d767SKan Liang fprintf(out, " Load access blocked by address : %10d\n", stats->blk_addr);
24053ef1fc17SLeo Yan fprintf(out, " Load HIT Local Peer : %10d\n", stats->lcl_peer);
24063ef1fc17SLeo Yan 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.);
241174c63a25SJiri Olsa 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);
2416550b4d6fSLeo Yan fprintf(out, " Store No available memory level : %10d\n", stats->st_na);
241774c63a25SJiri Olsa fprintf(out, " No Page Map Rejects : %10d\n", stats->nomap);
241874c63a25SJiri Olsa fprintf(out, " Unable to parse data source : %10d\n", stats->noparse);
241974c63a25SJiri Olsa }
242074c63a25SJiri Olsa
print_shared_cacheline_info(FILE * out)24217ef2efaaSJiri Olsa static void print_shared_cacheline_info(FILE *out)
24227ef2efaaSJiri Olsa {
24231834436eSLeo Yan 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);
24307ef2efaaSJiri Olsa 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);
24327ef2efaaSJiri Olsa 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);
24353ef1fc17SLeo 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);
2437d9d5d767SKan Liang 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);
24397ef2efaaSJiri Olsa fprintf(out, " Store L1D hits on shared lines : %10d\n", stats->st_l1hit);
2440550b4d6fSLeo Yan fprintf(out, " Store No available memory level : %10d\n", stats->st_na);
24417ef2efaaSJiri Olsa fprintf(out, " Total Merged records : %10d\n", hitm_cnt + stats->store);
24427ef2efaaSJiri Olsa }
24437ef2efaaSJiri 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);
24582d388bd0SJiri Olsa once = true;
24592d388bd0SJiri Olsa } else {
24602d388bd0SJiri Olsa fprintf(out, "\n");
24612d388bd0SJiri Olsa }
24622d388bd0SJiri Olsa
2463550b4d6fSLeo Yan fprintf(out, " ----------------------------------------------------------------------\n");
24642d388bd0SJiri Olsa __hist_entry__snprintf(he_cl, &hpp, hpp_list);
24652d388bd0SJiri Olsa fprintf(out, "%s\n", bf);
2466550b4d6fSLeo Yan fprintf(out, " ----------------------------------------------------------------------\n");
24672d388bd0SJiri Olsa
2468e9de7e2fSArnaldo Carvalho de Melo hists__fprintf(&c2c_hists->hists, false, 0, 0, 0, out, false);
24692d388bd0SJiri Olsa }
24702d388bd0SJiri Olsa
print_pareto(FILE * out)24712d388bd0SJiri Olsa static void print_pareto(FILE *out)
24722d388bd0SJiri Olsa {
24732d388bd0SJiri Olsa struct perf_hpp_list hpp_list;
24742d388bd0SJiri Olsa struct rb_node *nd;
24752d388bd0SJiri Olsa int ret;
24760998d960SLeo Yan const char *cl_output;
24772d388bd0SJiri Olsa
2478f37c5d91SLeo Yan if (c2c.display != DISPLAY_SNP_PEER)
24790998d960SLeo Yan cl_output = "cl_num,"
24802d388bd0SJiri Olsa "cl_rmt_hitm,"
24812d388bd0SJiri Olsa "cl_lcl_hitm,"
24822d388bd0SJiri Olsa "cl_stores_l1hit,"
24832d388bd0SJiri Olsa "cl_stores_l1miss,"
2484550b4d6fSLeo Yan "cl_stores_na,"
24850998d960SLeo Yan "dcacheline";
2486f37c5d91SLeo Yan else
2487f37c5d91SLeo Yan cl_output = "cl_num,"
2488f37c5d91SLeo Yan "cl_rmt_peer,"
2489f37c5d91SLeo Yan "cl_lcl_peer,"
2490f37c5d91SLeo Yan "cl_stores_l1hit,"
2491f37c5d91SLeo Yan "cl_stores_l1miss,"
2492f37c5d91SLeo Yan "cl_stores_na,"
2493f37c5d91SLeo Yan "dcacheline";
24940998d960SLeo Yan
24950998d960SLeo Yan perf_hpp_list__init(&hpp_list);
24960998d960SLeo Yan 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
25012eb3d689SDavidlohr Bueso 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
25102d388bd0SJiri Olsa c2c_he = container_of(he, struct c2c_hist_entry, he);
25112d388bd0SJiri Olsa print_cacheline(c2c_he->hists, he, &hpp_list, out);
25122d388bd0SJiri Olsa }
25132d388bd0SJiri Olsa }
25142d388bd0SJiri 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 {
251763503dbaSJiri Olsa struct evlist *evlist = session->evlist;
251832dcd021SJiri Olsa struct evsel *evsel;
25192709b97dSJiri Olsa bool first = true;
25202709b97dSJiri Olsa
25212709b97dSJiri Olsa fprintf(out, "=================================================\n");
25222709b97dSJiri Olsa fprintf(out, " c2c details \n");
25232709b97dSJiri Olsa fprintf(out, "=================================================\n");
25242709b97dSJiri Olsa
25252709b97dSJiri Olsa evlist__for_each_entry(evlist, evsel) {
25268ab2e96dSArnaldo Carvalho de Melo fprintf(out, "%-36s: %s\n", first ? " Events" : "", evsel__name(evsel));
25272709b97dSJiri Olsa first = false;
25282709b97dSJiri Olsa }
2529faa30dfaSLeo Yan fprintf(out, " Cachelines sort on : %s\n",
2530d940baccSJiri Olsa display_str[c2c.display]);
2531fc9c630eSJiri Olsa fprintf(out, " Cacheline data grouping : %s\n", c2c.cl_sort);
25322709b97dSJiri Olsa }
25332709b97dSJiri Olsa
perf_c2c__hists_fprintf(FILE * out,struct perf_session * session)25342709b97dSJiri Olsa static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
25352d388bd0SJiri Olsa {
25362d388bd0SJiri Olsa setup_pager();
25372d388bd0SJiri Olsa
253874c63a25SJiri Olsa print_c2c__display_stats(out);
25397ef2efaaSJiri Olsa fprintf(out, "\n");
25407ef2efaaSJiri Olsa print_shared_cacheline_info(out);
25412709b97dSJiri Olsa fprintf(out, "\n");
25422709b97dSJiri Olsa print_c2c_info(out, session);
254374c63a25SJiri Olsa
254474c63a25SJiri Olsa if (c2c.stats_only)
254574c63a25SJiri Olsa return;
254674c63a25SJiri Olsa
25472d388bd0SJiri Olsa fprintf(out, "\n");
25482d388bd0SJiri Olsa 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
2553e9de7e2fSArnaldo Carvalho de Melo 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");
25582d388bd0SJiri Olsa fprintf(out, "=================================================\n");
25592d388bd0SJiri Olsa fprintf(out, "#\n");
25602d388bd0SJiri Olsa
25612d388bd0SJiri Olsa print_pareto(out);
25622d388bd0SJiri Olsa }
25631e181b92SJiri Olsa
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;
25682eb3d689SDavidlohr Bueso 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);
25775a1a99cdSJiri Olsa }
25785a1a99cdSJiri Olsa
25795a1a99cdSJiri Olsa hb->nr_non_filtered_entries = nr_entries;
25805a1a99cdSJiri Olsa }
25815a1a99cdSJiri 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;
2594f1c5fd4dSJiri Olsa
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)
25991470a108SFeng Tang 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 {
2623f1c5fd4dSJiri Olsa struct c2c_hist_entry *c2c_he;
2624f1c5fd4dSJiri Olsa struct c2c_hists *c2c_hists;
2625f1c5fd4dSJiri Olsa struct c2c_cacheline_browser *cl_browser;
2626f1c5fd4dSJiri Olsa struct hist_browser *browser;
2627f1c5fd4dSJiri Olsa int key = -1;
262849b8e2beSRasmus Villemoes static const char help[] =
2629239fb4feSKim Phillips " ENTER Toggle callchains (if present) \n"
2630239fb4feSKim Phillips " n Toggle Node details info \n"
2631239fb4feSKim Phillips " s Toggle full length of symbol and source line columns \n"
26329a406eb6SJiri Olsa " q Return back to cacheline list \n";
2633f1c5fd4dSJiri Olsa
263473978332SJiri Olsa if (!he)
263573978332SJiri Olsa return 0;
263673978332SJiri Olsa
2637590b6a3aSJiri Olsa /* Display compact version first. */
2638590b6a3aSJiri Olsa c2c.symbol_full = false;
2639590b6a3aSJiri 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();
2651f1c5fd4dSJiri Olsa SLang_init_tty(0, 0, 0);
2652f1c5fd4dSJiri Olsa
2653f1c5fd4dSJiri Olsa c2c_browser__update_nr_entries(browser);
2654f1c5fd4dSJiri Olsa
2655f1c5fd4dSJiri Olsa while (1) {
2656d10ec006SArnaldo Carvalho de Melo key = hist_browser__run(browser, "? - help", true, 0);
2657f1c5fd4dSJiri Olsa
2658f1c5fd4dSJiri Olsa switch (key) {
2659590b6a3aSJiri Olsa case 's':
2660590b6a3aSJiri Olsa c2c.symbol_full = !c2c.symbol_full;
2661590b6a3aSJiri Olsa break;
26621a56a425SJiri Olsa case 'n':
26631a56a425SJiri Olsa c2c.node_info = (c2c.node_info + 1) % 3;
26641a56a425SJiri Olsa setup_nodes_header();
26651a56a425SJiri Olsa break;
2666f1c5fd4dSJiri Olsa case 'q':
2667f1c5fd4dSJiri Olsa goto out;
26689a406eb6SJiri Olsa case '?':
26699a406eb6SJiri Olsa ui_browser__help_window(&browser->b, help);
26709a406eb6SJiri Olsa break;
2671f1c5fd4dSJiri Olsa default:
2672f1c5fd4dSJiri Olsa break;
2673f1c5fd4dSJiri Olsa }
2674f1c5fd4dSJiri Olsa }
2675f1c5fd4dSJiri Olsa
2676f1c5fd4dSJiri Olsa out:
2677f1c5fd4dSJiri Olsa free(cl_browser);
2678f1c5fd4dSJiri Olsa return 0;
2679f1c5fd4dSJiri Olsa }
2680f1c5fd4dSJiri Olsa
perf_c2c_browser__title(struct hist_browser * browser,char * bf,size_t size)26815a1a99cdSJiri Olsa static int perf_c2c_browser__title(struct hist_browser *browser,
26825a1a99cdSJiri Olsa char *bf, size_t size)
26835a1a99cdSJiri Olsa {
26845a1a99cdSJiri Olsa scnprintf(bf, size,
26855a1a99cdSJiri Olsa "Shared Data Cache Line Table "
2686faa30dfaSLeo Yan "(%lu entries, sorted on %s)",
268755b95776SJiri Olsa browser->nr_non_filtered_entries,
2688d940baccSJiri 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 }
27045a1a99cdSJiri Olsa
perf_c2c__hists_browse(struct hists * hists)27055a1a99cdSJiri Olsa static int perf_c2c__hists_browse(struct hists *hists)
27065a1a99cdSJiri Olsa {
27075a1a99cdSJiri Olsa struct hist_browser *browser;
27085a1a99cdSJiri Olsa int key = -1;
270949b8e2beSRasmus Villemoes static const char help[] =
27109a406eb6SJiri Olsa " d Display cacheline details \n"
2711239fb4feSKim Phillips " ENTER Toggle callchains (if present) \n"
27129a406eb6SJiri 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();
27205a1a99cdSJiri Olsa SLang_init_tty(0, 0, 0);
27215a1a99cdSJiri Olsa
27225a1a99cdSJiri Olsa c2c_browser__update_nr_entries(browser);
27235a1a99cdSJiri Olsa
27245a1a99cdSJiri Olsa while (1) {
2725d10ec006SArnaldo Carvalho de Melo key = hist_browser__run(browser, "? - help", true, 0);
27265a1a99cdSJiri Olsa
27275a1a99cdSJiri Olsa switch (key) {
27285a1a99cdSJiri Olsa case 'q':
27295a1a99cdSJiri Olsa goto out;
2730f1c5fd4dSJiri Olsa case 'd':
2731f1c5fd4dSJiri Olsa perf_c2c__browse_cacheline(browser->he_selection);
2732f1c5fd4dSJiri Olsa break;
27339a406eb6SJiri Olsa case '?':
27349a406eb6SJiri Olsa ui_browser__help_window(&browser->b, help);
27359a406eb6SJiri Olsa break;
27365a1a99cdSJiri Olsa default:
27375a1a99cdSJiri Olsa break;
27385a1a99cdSJiri Olsa }
27395a1a99cdSJiri Olsa }
27405a1a99cdSJiri Olsa
27415a1a99cdSJiri Olsa out:
27425a1a99cdSJiri Olsa hist_browser__delete(browser);
27435a1a99cdSJiri Olsa return 0;
27445a1a99cdSJiri Olsa }
27455a1a99cdSJiri Olsa
perf_c2c_display(struct perf_session * session)27462709b97dSJiri Olsa static void perf_c2c_display(struct perf_session *session)
27475a1a99cdSJiri Olsa {
27481936feaeSNamhyung Kim if (use_browser == 0)
27492709b97dSJiri Olsa perf_c2c__hists_fprintf(stdout, session);
27505a1a99cdSJiri Olsa else
27515a1a99cdSJiri Olsa perf_c2c__hists_browse(&c2c.hists.hists);
27525a1a99cdSJiri Olsa }
27535a1a99cdSJiri Olsa #else
perf_c2c_display(struct perf_session * session)27542709b97dSJiri Olsa static void perf_c2c_display(struct perf_session *session)
27555a1a99cdSJiri Olsa {
27565a1a99cdSJiri Olsa use_browser = 0;
27572709b97dSJiri Olsa perf_c2c__hists_fprintf(stdout, session);
27585a1a99cdSJiri Olsa }
27595a1a99cdSJiri Olsa #endif /* HAVE_SLANG_SUPPORT */
27605a1a99cdSJiri Olsa
fill_line(const char * orig,int len)2761d0802b1eSJiri Olsa static char *fill_line(const char *orig, int len)
27625a1a99cdSJiri 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)2789d0802b1eSJiri Olsa static int ui_quirks(void)
2790d0802b1eSJiri Olsa {
2791d0802b1eSJiri Olsa const char *nodestr = "Data address";
2792d0802b1eSJiri Olsa char *buf;
2793d0802b1eSJiri Olsa
27945a1a99cdSJiri Olsa if (!c2c.use_stdio) {
27955a1a99cdSJiri Olsa dim_offset.width = 5;
27965a1a99cdSJiri Olsa dim_offset.header = header_offset_tui;
27971470a108SFeng Tang nodestr = chk_double_cl ? "Double-CL" : "CL";
27985a1a99cdSJiri Olsa }
279955b95776SJiri Olsa
28002be0bc75SLeo Yan dim_percent_costly_snoop.header = percent_costly_snoop_header[c2c.display];
2801d0802b1eSJiri Olsa
2802d0802b1eSJiri Olsa /* Fix the zero line for dcacheline column. */
28031470a108SFeng Tang buf = fill_line(chk_double_cl ? "Double-Cacheline" : "Cacheline",
28041470a108SFeng Tang dim_dcacheline.width +
280503d9fcb7SJiri Olsa dim_dcacheline_node.width +
280603d9fcb7SJiri Olsa dim_dcacheline_count.width + 4);
2807d0802b1eSJiri Olsa if (!buf)
2808d0802b1eSJiri Olsa return -ENOMEM;
2809d0802b1eSJiri Olsa
2810d0802b1eSJiri 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 +
281403d9fcb7SJiri Olsa dim_offset_node.width +
281503d9fcb7SJiri Olsa dim_dcacheline_count.width + 4);
2816d0802b1eSJiri Olsa if (!buf)
2817d0802b1eSJiri Olsa return -ENOMEM;
2818d0802b1eSJiri Olsa
2819d0802b1eSJiri Olsa dim_offset.header.line[0].text = buf;
2820d0802b1eSJiri Olsa
2821d0802b1eSJiri Olsa return 0;
28225a1a99cdSJiri Olsa }
28235a1a99cdSJiri 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;
2843dd805768SJiri Olsa }
2844dd805768SJiri Olsa
2845dd805768SJiri Olsa return parse_callchain_report_opt(arg);
2846dd805768SJiri Olsa }
2847dd805768SJiri Olsa
setup_callchain(struct evlist * evlist)284863503dbaSJiri Olsa static int setup_callchain(struct evlist *evlist)
2849dd805768SJiri Olsa {
2850b3c2cc2bSArnaldo Carvalho de Melo u64 sample_type = evlist__combined_sample_type(evlist);
2851dd805768SJiri Olsa enum perf_call_graph_mode mode = CALLCHAIN_NONE;
2852dd805768SJiri Olsa
2853dd805768SJiri Olsa if ((sample_type & PERF_SAMPLE_REGS_USER) &&
2854eabad8c6SArnaldo Carvalho de Melo (sample_type & PERF_SAMPLE_STACK_USER)) {
2855dd805768SJiri Olsa mode = CALLCHAIN_DWARF;
2856eabad8c6SArnaldo Carvalho de Melo dwarf_callchain_users = true;
2857eabad8c6SArnaldo Carvalho de Melo } 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) {
2867dd805768SJiri Olsa ui__error("Can't register callchain params.\n");
2868dd805768SJiri Olsa return -EINVAL;
2869dd805768SJiri Olsa }
2870dd805768SJiri Olsa }
2871dd805768SJiri Olsa
2872d80da766SKan Liang if (c2c.stitch_lbr && (mode != CALLCHAIN_LBR)) {
2873d80da766SKan Liang ui__warning("Can't find LBR callchain. Switch off --stitch-lbr.\n"
2874d80da766SKan Liang "Please apply --call-graph lbr when recording.\n");
2875d80da766SKan Liang c2c.stitch_lbr = false;
2876d80da766SKan Liang }
2877d80da766SKan Liang
2878dd805768SJiri Olsa callchain_param.record_mode = mode;
2879dd805768SJiri Olsa callchain_param.min_percent = 0;
2880dd805768SJiri Olsa return 0;
2881dd805768SJiri Olsa }
2882dd805768SJiri Olsa
setup_display(const char * str)288355b95776SJiri Olsa static int setup_display(const char *str)
288455b95776SJiri Olsa {
2885ead42a0fSLeo Yan const char *display = str;
288655b95776SJiri Olsa
2887d940baccSJiri Olsa if (!strcmp(display, "tot"))
2888c82ccc3aSLeo Yan c2c.display = DISPLAY_TOT_HITM;
2889d940baccSJiri Olsa else if (!strcmp(display, "rmt"))
2890c82ccc3aSLeo Yan c2c.display = DISPLAY_RMT_HITM;
289155b95776SJiri Olsa else if (!strcmp(display, "lcl"))
2892c82ccc3aSLeo Yan c2c.display = DISPLAY_LCL_HITM;
2893f37c5d91SLeo Yan else if (!strcmp(display, "peer"))
2894f37c5d91SLeo Yan c2c.display = DISPLAY_SNP_PEER;
289555b95776SJiri Olsa else {
289655b95776SJiri Olsa pr_err("failed: unknown display type: %s\n", str);
289755b95776SJiri Olsa return -1;
289855b95776SJiri Olsa }
289955b95776SJiri Olsa
290055b95776SJiri Olsa return 0;
290155b95776SJiri Olsa }
290255b95776SJiri 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)290718f278d2SJiri 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;
2911fc9c630eSJiri Olsa 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;
2916ae199c58SYunfeng Ye 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")) {
2925fc9c630eSJiri 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;
293018f278d2SJiri Olsa add_src = no_source ? false : true;
2931fc9c630eSJiri Olsa } 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);
2935ae199c58SYunfeng Ye ret = -EINVAL;
2936ae199c58SYunfeng Ye goto err;
2937fc9c630eSJiri Olsa }
2938fc9c630eSJiri Olsa }
2939fc9c630eSJiri Olsa
2940fc9c630eSJiri Olsa if (asprintf(&c2c.cl_output,
2941f37c5d91SLeo Yan "%s%s%s%s%s%s%s%s%s%s%s%s",
2942bb342daeSJiri Olsa c2c.use_stdio ? "cl_num_empty," : "",
2943f37c5d91SLeo Yan c2c.display == DISPLAY_SNP_PEER ? "percent_rmt_peer,"
2944f37c5d91SLeo Yan "percent_lcl_peer," :
2945fc9c630eSJiri Olsa "percent_rmt_hitm,"
2946f37c5d91SLeo Yan "percent_lcl_hitm,",
2947fc9c630eSJiri Olsa "percent_stores_l1hit,"
2948fc9c630eSJiri Olsa "percent_stores_l1miss,"
2949550b4d6fSLeo Yan "percent_stores_na,"
295003d9fcb7SJiri Olsa "offset,offset_node,dcacheline_count,",
2951fc9c630eSJiri Olsa add_pid ? "pid," : "",
2952fc9c630eSJiri Olsa add_tid ? "tid," : "",
2953fc9c630eSJiri Olsa add_iaddr ? "iaddr," : "",
2954f37c5d91SLeo Yan c2c.display == DISPLAY_SNP_PEER ? "mean_rmt_peer,"
2955f37c5d91SLeo Yan "mean_lcl_peer," :
2956fc9c630eSJiri Olsa "mean_rmt,"
2957f37c5d91SLeo Yan "mean_lcl,",
2958fc9c630eSJiri Olsa "mean_load,"
29598763e6acSJiri Olsa "tot_recs,"
2960fc9c630eSJiri Olsa "cpucnt,",
2961fc9c630eSJiri Olsa add_sym ? "symbol," : "",
2962fc9c630eSJiri Olsa add_dso ? "dso," : "",
2963fc9c630eSJiri Olsa add_src ? "cl_srcline," : "",
2964ae199c58SYunfeng Ye "node") < 0) {
2965ae199c58SYunfeng Ye ret = -ENOMEM;
2966ae199c58SYunfeng Ye goto err;
2967ae199c58SYunfeng Ye }
2968fc9c630eSJiri Olsa
2969fc9c630eSJiri Olsa c2c.show_src = add_src;
2970ae199c58SYunfeng Ye err:
2971fc9c630eSJiri Olsa free(buf);
2972ae199c58SYunfeng Ye return ret;
2973fc9c630eSJiri Olsa }
2974fc9c630eSJiri Olsa
setup_coalesce(const char * coalesce,bool no_source)297518f278d2SJiri Olsa static int setup_coalesce(const char *coalesce, bool no_source)
2976fc9c630eSJiri Olsa {
2977fc9c630eSJiri Olsa const char *c = coalesce ?: coalesce_default;
2978f37c5d91SLeo Yan const char *sort_str = NULL;
2979fc9c630eSJiri Olsa
2980fc9c630eSJiri Olsa if (asprintf(&c2c.cl_sort, "offset,%s", c) < 0)
2981fc9c630eSJiri Olsa return -ENOMEM;
2982fc9c630eSJiri Olsa
298318f278d2SJiri Olsa if (build_cl_output(c2c.cl_sort, no_source))
2984fc9c630eSJiri Olsa return -1;
2985fc9c630eSJiri Olsa
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)
2991f37c5d91SLeo Yan sort_str = "lcl_hitm,rmt_hitm";
2992f37c5d91SLeo Yan else if (c2c.display == DISPLAY_SNP_PEER)
2993f37c5d91SLeo Yan sort_str = "tot_peer";
2994f37c5d91SLeo Yan
2995f37c5d91SLeo Yan 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);
2999fc9c630eSJiri Olsa pr_debug("coalesce resort fields: %s\n", c2c.cl_resort);
3000fc9c630eSJiri Olsa pr_debug("coalesce output fields: %s\n", c2c.cl_output);
3001fc9c630eSJiri Olsa return 0;
3002fc9c630eSJiri Olsa }
3003fc9c630eSJiri Olsa
perf_c2c__report(int argc,const char ** argv)3004903a6f15SJiri Olsa static int perf_c2c__report(int argc, const char **argv)
3005903a6f15SJiri Olsa {
3006c825f788SLeo Yan struct itrace_synth_opts itrace_synth_opts = {
3007c825f788SLeo Yan .set = true,
3008c825f788SLeo Yan .mem = true, /* Only enable memory event */
3009c825f788SLeo Yan .default_no_sample = true,
3010c825f788SLeo Yan };
3011c825f788SLeo Yan
3012903a6f15SJiri Olsa struct perf_session *session;
301378b27543SJiri Olsa struct ui_progress prog;
30148ceb41d7SJiri Olsa struct perf_data data = {
3015903a6f15SJiri Olsa .mode = PERF_DATA_MODE_READ,
3016903a6f15SJiri Olsa };
3017dd805768SJiri Olsa char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
301855b95776SJiri Olsa const char *display = NULL;
3019fc9c630eSJiri Olsa const char *coalesce = NULL;
302018f278d2SJiri Olsa bool no_source = false;
30213a5bfab6SJiri Olsa const struct option options[] = {
3022903a6f15SJiri Olsa OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
3023903a6f15SJiri Olsa "file", "vmlinux pathname"),
3024903a6f15SJiri Olsa OPT_STRING('i', "input", &input_name, "file",
3025903a6f15SJiri Olsa "the input file to process"),
30261e181b92SJiri Olsa OPT_INCR('N', "node-info", &c2c.node_info,
30271e181b92SJiri Olsa "show extra node info in report (repeat for more info)"),
30285a1a99cdSJiri Olsa OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"),
302974c63a25SJiri Olsa OPT_BOOLEAN(0, "stats", &c2c.stats_only,
3030f75d2895SNamhyung Kim "Display only statistic tables (implies --stdio)"),
3031590b6a3aSJiri Olsa OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full,
3032590b6a3aSJiri Olsa "Display full length of symbols"),
303318f278d2SJiri Olsa OPT_BOOLEAN(0, "no-source", &no_source,
303418f278d2SJiri Olsa "Do not display Source Line column"),
3035af09b2d3SJiri Olsa OPT_BOOLEAN(0, "show-all", &c2c.show_all,
3036af09b2d3SJiri Olsa "Show all captured HITM lines."),
3037dd805768SJiri Olsa OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
3038dd805768SJiri Olsa "print_type,threshold[,print_limit],order,sort_key[,branch],value",
3039dd805768SJiri Olsa callchain_help, &parse_callchain_opt,
3040dd805768SJiri Olsa callchain_default_opt),
3041f37c5d91SLeo Yan OPT_STRING('d', "display", &display, "Switch HITM output type", "tot,lcl,rmt,peer"),
3042fc9c630eSJiri Olsa OPT_STRING('c', "coalesce", &coalesce, "coalesce fields",
3043fc9c630eSJiri Olsa "coalesce fields: pid,tid,iaddr,dso"),
3044b7ac4f9fSJiri Olsa OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
3045d80da766SKan Liang OPT_BOOLEAN(0, "stitch-lbr", &c2c.stitch_lbr,
3046d80da766SKan Liang "Enable LBR callgraph stitching approach"),
30471470a108SFeng Tang OPT_BOOLEAN(0, "double-cl", &chk_double_cl, "Detect adjacent cacheline false sharing"),
30483a5bfab6SJiri Olsa OPT_PARENT(c2c_options),
3049903a6f15SJiri Olsa OPT_END()
3050903a6f15SJiri Olsa };
3051903a6f15SJiri Olsa int err = 0;
30520998d960SLeo Yan const char *output_str, *sort_str = NULL;
3053903a6f15SJiri Olsa
30543a5bfab6SJiri Olsa argc = parse_options(argc, argv, options, report_c2c_usage,
3055903a6f15SJiri Olsa PARSE_OPT_STOP_AT_NON_OPTION);
305678b27543SJiri Olsa if (argc)
30573a5bfab6SJiri Olsa usage_with_options(report_c2c_usage, options);
3058903a6f15SJiri Olsa
3059c4040212SLeo Yan #ifndef HAVE_SLANG_SUPPORT
3060c4040212SLeo Yan c2c.use_stdio = true;
3061c4040212SLeo Yan #endif
3062c4040212SLeo Yan
306374c63a25SJiri Olsa if (c2c.stats_only)
306474c63a25SJiri Olsa c2c.use_stdio = true;
306574c63a25SJiri Olsa
30667cc72553SJames Clark err = symbol__validate_sym_arguments();
30677cc72553SJames Clark if (err)
30687cc72553SJames Clark goto out;
30697cc72553SJames Clark
307078b27543SJiri Olsa if (!input_name || !strlen(input_name))
307178b27543SJiri Olsa input_name = "perf.data";
307278b27543SJiri Olsa
30732d4f2799SJiri Olsa data.path = input_name;
30748ceb41d7SJiri Olsa data.force = symbol_conf.force;
3075903a6f15SJiri Olsa
30762681bd85SNamhyung Kim session = perf_session__new(&data, &c2c.tool);
30776ef81c55SMamatha Inamdar if (IS_ERR(session)) {
30786ef81c55SMamatha Inamdar err = PTR_ERR(session);
30796ef81c55SMamatha Inamdar pr_debug("Error creating perf session\n");
3080903a6f15SJiri Olsa goto out;
3081903a6f15SJiri Olsa }
3082e8c5fe10SJiri Olsa
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);
3106ead42a0fSLeo Yan if (err) {
3107ead42a0fSLeo Yan pr_debug("Failed to initialize hists\n");
3108ead42a0fSLeo Yan goto out_session;
3109ead42a0fSLeo Yan }
3110ead42a0fSLeo Yan
3111c825f788SLeo Yan session->itrace_synth_opts = &itrace_synth_opts;
3112c825f788SLeo Yan
31131e181b92SJiri Olsa err = setup_nodes(session);
31141e181b92SJiri Olsa if (err) {
31151e181b92SJiri Olsa pr_err("Failed setup nodes\n");
3116ead42a0fSLeo Yan goto out_session;
31171e181b92SJiri Olsa }
3118903a6f15SJiri Olsa
31197f834c2eSJiri Olsa err = mem2node__init(&c2c.mem2node, &session->header.env);
3120dd805768SJiri Olsa if (err)
3121dd805768SJiri Olsa goto out_session;
3122dd805768SJiri Olsa
31237f834c2eSJiri Olsa err = setup_callchain(session->evlist);
31247f834c2eSJiri Olsa if (err)
31257f834c2eSJiri Olsa goto out_mem2node;
31267f834c2eSJiri 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. */
31318ceb41d7SJiri Olsa if (perf_data__is_pipe(session->data)) {
3132903a6f15SJiri Olsa pr_debug("No pipe support at the moment.\n");
31337f834c2eSJiri Olsa goto out_mem2node;
3134903a6f15SJiri Olsa }
3135903a6f15SJiri Olsa
3136e8c5fe10SJiri Olsa if (c2c.use_stdio)
3137e8c5fe10SJiri Olsa use_browser = 0;
3138e8c5fe10SJiri Olsa else
3139e8c5fe10SJiri Olsa use_browser = 1;
3140e8c5fe10SJiri Olsa
3141e8c5fe10SJiri Olsa setup_browser(false);
3142e8c5fe10SJiri Olsa
314378b27543SJiri Olsa err = perf_session__process_events(session);
314478b27543SJiri Olsa if (err) {
314578b27543SJiri Olsa pr_err("failed to process sample\n");
31467f834c2eSJiri Olsa goto out_mem2node;
314778b27543SJiri Olsa }
314878b27543SJiri Olsa
3149f37c5d91SLeo Yan if (c2c.display != DISPLAY_SNP_PEER)
31500998d960SLeo Yan output_str = "cl_idx,"
315122dd59d1SJiri Olsa "dcacheline,"
31527f834c2eSJiri Olsa "dcacheline_node,"
315303d9fcb7SJiri Olsa "dcacheline_count,"
31542be0bc75SLeo Yan "percent_costly_snoop,"
315522dd59d1SJiri Olsa "tot_hitm,lcl_hitm,rmt_hitm,"
3156b596e979SLeo Yan "tot_recs,"
3157b596e979SLeo Yan "tot_loads,"
31584f28641bSLeo Yan "tot_stores,"
3159550b4d6fSLeo Yan "stores_l1hit,stores_l1miss,stores_na,"
316022dd59d1SJiri Olsa "ld_fbhit,ld_l1hit,ld_l2hit,"
316177c15869SLeo Yan "ld_lclhit,lcl_hitm,"
316291d933c2SLeo Yan "ld_rmthit,rmt_hitm,"
31630998d960SLeo 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,"
3174f37c5d91SLeo Yan "stores_l1hit,stores_l1miss,stores_na,"
3175f37c5d91SLeo Yan "ld_fbhit,ld_l1hit,ld_l2hit,"
3176f37c5d91SLeo Yan "ld_lclhit,lcl_hitm,"
3177f37c5d91SLeo Yan "ld_rmthit,rmt_hitm,"
3178f37c5d91SLeo Yan "dram_lcl,dram_rmt";
31790998d960SLeo Yan
3180c82ccc3aSLeo Yan if (c2c.display == DISPLAY_TOT_HITM)
31810998d960SLeo Yan sort_str = "tot_hitm";
3182c82ccc3aSLeo Yan else if (c2c.display == DISPLAY_RMT_HITM)
31830998d960SLeo Yan sort_str = "rmt_hitm";
3184c82ccc3aSLeo Yan else if (c2c.display == DISPLAY_LCL_HITM)
31850998d960SLeo Yan sort_str = "lcl_hitm";
3186f37c5d91SLeo Yan else if (c2c.display == DISPLAY_SNP_PEER)
3187f37c5d91SLeo Yan sort_str = "tot_peer";
31880998d960SLeo Yan
31890998d960SLeo Yan c2c_hists__reinit(&c2c.hists, output_str, sort_str);
319022dd59d1SJiri Olsa
319178b27543SJiri Olsa ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting...");
319278b27543SJiri Olsa
319378b27543SJiri Olsa hists__collapse_resort(&c2c.hists.hists, NULL);
31941834436eSLeo Yan hists__output_resort_cb(&c2c.hists.hists, &prog, resort_shared_cl_cb);
31957ef2efaaSJiri Olsa hists__iterate_cb(&c2c.hists.hists, resort_cl_cb);
319678b27543SJiri Olsa
319778b27543SJiri Olsa ui_progress__finish();
319878b27543SJiri Olsa
3199d0802b1eSJiri Olsa if (ui_quirks()) {
3200d0802b1eSJiri Olsa pr_err("failed to setup UI\n");
3201d0802b1eSJiri Olsa goto out_mem2node;
3202d0802b1eSJiri Olsa }
32035a1a99cdSJiri Olsa
32042709b97dSJiri Olsa perf_c2c_display(session);
32052d388bd0SJiri Olsa
32067f834c2eSJiri Olsa out_mem2node:
32077f834c2eSJiri Olsa mem2node__exit(&c2c.mem2node);
3208903a6f15SJiri Olsa out_session:
3209903a6f15SJiri Olsa perf_session__delete(session);
3210903a6f15SJiri Olsa out:
3211903a6f15SJiri Olsa return err;
3212903a6f15SJiri Olsa }
3213903a6f15SJiri Olsa
parse_record_events(const struct option * opt,const char * str,int unset __maybe_unused)32147e6a7998SArnaldo Carvalho de Melo static int parse_record_events(const struct option *opt,
321539bcd4a4SJiri Olsa const char *str, int unset __maybe_unused)
321639bcd4a4SJiri Olsa {
321739bcd4a4SJiri Olsa bool *event_set = (bool *) opt->value;
321839bcd4a4SJiri Olsa
3219b027cc6fSIan Rogers if (!strcmp(str, "list")) {
3220b027cc6fSIan Rogers perf_mem_events__list();
3221b027cc6fSIan Rogers exit(0);
3222b027cc6fSIan Rogers }
3223b027cc6fSIan Rogers if (perf_mem_events__parse(str))
3224b027cc6fSIan Rogers exit(-1);
3225b027cc6fSIan Rogers
322639bcd4a4SJiri Olsa *event_set = true;
3227b027cc6fSIan Rogers 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 };
323639bcd4a4SJiri Olsa
323739bcd4a4SJiri Olsa static const char * const *record_mem_usage = __usage_record;
323839bcd4a4SJiri Olsa
perf_c2c__record(int argc,const char ** argv)323939bcd4a4SJiri Olsa static int perf_c2c__record(int argc, const char **argv)
324039bcd4a4SJiri Olsa {
324179e157b0SJin Yao int rec_argc, i = 0, j, rec_tmp_nr = 0;
324239bcd4a4SJiri Olsa const char **rec_argv;
324379e157b0SJin Yao char **rec_tmp;
324439bcd4a4SJiri Olsa int ret;
324539bcd4a4SJiri Olsa bool all_user = false, all_kernel = false;
324639bcd4a4SJiri Olsa bool event_set = false;
3247eaf6aaeeSLeo Yan struct perf_mem_event *e;
324839bcd4a4SJiri Olsa struct option options[] = {
324939bcd4a4SJiri Olsa OPT_CALLBACK('e', "event", &event_set, "event",
3250edac75a2SLeo Yan "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"),
32553a5bfab6SJiri 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;
326239bcd4a4SJiri Olsa }
326339bcd4a4SJiri Olsa
326439bcd4a4SJiri Olsa argc = parse_options(argc, argv, options, record_mem_usage,
326539bcd4a4SJiri Olsa PARSE_OPT_KEEP_UNKNOWN);
326639bcd4a4SJiri Olsa
3267abe9544eSIan Rogers /* Max number of arguments multiplied by number of PMUs that can support them. */
32681eaf496eSIan Rogers rec_argc = argc + 11 * perf_pmus__num_mem_pmus();
326979e157b0SJin Yao
327039bcd4a4SJiri Olsa rec_argv = calloc(rec_argc + 1, sizeof(char *));
327139bcd4a4SJiri Olsa if (!rec_argv)
327239bcd4a4SJiri Olsa return -1;
327339bcd4a4SJiri Olsa
327479e157b0SJin Yao rec_tmp = calloc(rec_argc + 1, sizeof(char *));
327579e157b0SJin Yao if (!rec_tmp) {
327679e157b0SJin Yao free(rec_argv);
327779e157b0SJin Yao return -1;
327879e157b0SJin Yao }
327979e157b0SJin Yao
328039bcd4a4SJiri Olsa rec_argv[i++] = "record";
328139bcd4a4SJiri Olsa
328239bcd4a4SJiri Olsa 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.
32878b8173b4SLeo Yan */
32888b8173b4SLeo Yan if (e->tag) {
32898b8173b4SLeo Yan e->record = true;
32904173cc05SRavi Bangoria rec_argv[i++] = "-W";
32918b8173b4SLeo Yan } else {
3292eaf6aaeeSLeo Yan e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
3293eaf6aaeeSLeo Yan e->record = true;
3294eaf6aaeeSLeo Yan
3295eaf6aaeeSLeo Yan e = perf_mem_events__ptr(PERF_MEM_EVENTS__STORE);
3296eaf6aaeeSLeo Yan e->record = true;
329739bcd4a4SJiri Olsa }
32988b8173b4SLeo Yan }
329939bcd4a4SJiri Olsa
3300eaf6aaeeSLeo Yan e = perf_mem_events__ptr(PERF_MEM_EVENTS__LOAD);
3301eaf6aaeeSLeo Yan if (e->record)
330239bcd4a4SJiri Olsa rec_argv[i++] = "-W";
330339bcd4a4SJiri Olsa
330439bcd4a4SJiri Olsa rec_argv[i++] = "-d";
33058fab7843SJiri Olsa rec_argv[i++] = "--phys-data";
330639bcd4a4SJiri Olsa rec_argv[i++] = "--sample-cpu";
330739bcd4a4SJiri Olsa
330879e157b0SJin Yao ret = perf_mem_events__record_args(rec_argv, &i, rec_tmp, &rec_tmp_nr);
330979e157b0SJin Yao if (ret)
331079e157b0SJin Yao 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 }
333039bcd4a4SJiri Olsa pr_debug("\n");
333139bcd4a4SJiri Olsa }
333239bcd4a4SJiri Olsa
3333b0ad8ea6SArnaldo Carvalho de Melo ret = cmd_record(i, rec_argv);
333479e157b0SJin Yao out:
333579e157b0SJin Yao for (i = 0; i < rec_tmp_nr; i++)
333679e157b0SJin Yao free(rec_tmp[i]);
333779e157b0SJin Yao
333879e157b0SJin Yao free(rec_tmp);
333939bcd4a4SJiri Olsa free(rec_argv);
334039bcd4a4SJiri Olsa return ret;
334139bcd4a4SJiri Olsa }
334239bcd4a4SJiri Olsa
cmd_c2c(int argc,const char ** argv)3343b0ad8ea6SArnaldo Carvalho de Melo int cmd_c2c(int argc, const char **argv)
33447aef3bf3SJiri Olsa {
33457aef3bf3SJiri Olsa argc = parse_options(argc, argv, c2c_options, c2c_usage,
33467aef3bf3SJiri Olsa PARSE_OPT_STOP_AT_NON_OPTION);
334739bcd4a4SJiri Olsa
334839bcd4a4SJiri Olsa if (!argc)
334939bcd4a4SJiri Olsa usage_with_options(c2c_usage, c2c_options);
335039bcd4a4SJiri Olsa
3351ae0f4eb3SWei Li if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) {
335239bcd4a4SJiri Olsa return perf_c2c__record(argc, argv);
3353ae0f4eb3SWei Li } else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) {
3354903a6f15SJiri Olsa return perf_c2c__report(argc, argv);
335539bcd4a4SJiri Olsa } else {
335639bcd4a4SJiri Olsa usage_with_options(c2c_usage, c2c_options);
335739bcd4a4SJiri Olsa }
335839bcd4a4SJiri Olsa
33597aef3bf3SJiri Olsa return 0;
33607aef3bf3SJiri Olsa }
3361