xref: /openbmc/linux/tools/perf/builtin-c2c.c (revision 8ab12a20)
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