Blame view

tools/perf/builtin-c2c.c 69.7 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
465f27a3b   Jiri Olsa   perf c2c: Add man...
2
3
4
5
6
7
8
9
10
11
12
  /*
   * This is rewrite of original c2c tool introduced in here:
   *   http://lwn.net/Articles/588866/
   *
   * The original tool was changed to fit in current perf state.
   *
   * Original authors:
   *   Don Zickus <dzickus@redhat.com>
   *   Dick Fowles <fowles@inreach.com>
   *   Joe Mario <jmario@redhat.com>
   */
a43783aee   Arnaldo Carvalho de Melo   perf tools: Inclu...
13
  #include <errno.h>
fd20e8111   Arnaldo Carvalho de Melo   perf tools: Inclu...
14
  #include <inttypes.h>
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
15
  #include <linux/compiler.h>
6ef81c55a   Mamatha Inamdar   perf session: Ret...
16
  #include <linux/err.h>
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
17
  #include <linux/kernel.h>
cbb88500a   Jiri Olsa   perf c2c report: ...
18
  #include <linux/stringify.h>
7f7c536f2   Arnaldo Carvalho de Melo   tools lib: Adopt ...
19
  #include <linux/zalloc.h>
1e181b92a   Jiri Olsa   perf c2c report: ...
20
  #include <asm/bug.h>
391e42060   Arnaldo Carvalho de Melo   perf tools: Inclu...
21
  #include <sys/param.h>
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
22
23
  #include "debug.h"
  #include "builtin.h"
87ffb6c64   Arnaldo Carvalho de Melo   perf env: Remove ...
24
  #include <perf/cpumap.h>
8520a98db   Arnaldo Carvalho de Melo   perf debug: Remov...
25
  #include <subcmd/pager.h>
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
26
  #include <subcmd/parse-options.h>
d3300a3c4   Arnaldo Carvalho de Melo   perf symbols: Mov...
27
  #include "map_symbol.h"
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
28
  #include "mem-events.h"
903a6f15b   Jiri Olsa   perf c2c: Add rep...
29
30
  #include "session.h"
  #include "hist.h"
cbb88500a   Jiri Olsa   perf c2c report: ...
31
  #include "sort.h"
903a6f15b   Jiri Olsa   perf c2c: Add rep...
32
  #include "tool.h"
125009026   Arnaldo Carvalho de Melo   perf cacheline: M...
33
  #include "cacheline.h"
903a6f15b   Jiri Olsa   perf c2c: Add rep...
34
  #include "data.h"
5ab8c689f   Arnaldo Carvalho de Melo   perf tools: Move ...
35
  #include "event.h"
2709b97dc   Jiri Olsa   perf c2c report: ...
36
37
  #include "evlist.h"
  #include "evsel.h"
5a1a99cd2   Jiri Olsa   perf c2c report: ...
38
  #include "ui/browsers/hists.h"
e7ff8920e   Arnaldo Carvalho de Melo   perf tools: Use j...
39
  #include "thread.h"
7f834c2e8   Jiri Olsa   perf c2c report: ...
40
  #include "mem2node.h"
daecf9e0f   Arnaldo Carvalho de Melo   perf tools: Add m...
41
  #include "symbol.h"
8520a98db   Arnaldo Carvalho de Melo   perf debug: Remov...
42
  #include "ui/ui.h"
171f7474b   Arnaldo Carvalho de Melo   perf hist: Remove...
43
  #include "ui/progress.h"
c1a604dff   Arnaldo Carvalho de Melo   perf tools: Remov...
44
  #include "../perf.h"
903a6f15b   Jiri Olsa   perf c2c: Add rep...
45

c75540e31   Jiri Olsa   perf c2c report: ...
46
47
48
  struct c2c_hists {
  	struct hists		hists;
  	struct perf_hpp_list	list;
b2252ae67   Jiri Olsa   perf c2c report: ...
49
  	struct c2c_stats	stats;
c75540e31   Jiri Olsa   perf c2c report: ...
50
  };
92062d543   Jiri Olsa   perf c2c report: ...
51
52
53
54
55
  struct compute_stats {
  	struct stats		 lcl_hitm;
  	struct stats		 rmt_hitm;
  	struct stats		 load;
  };
78b275437   Jiri Olsa   perf c2c report: ...
56
57
  struct c2c_hist_entry {
  	struct c2c_hists	*hists;
b2252ae67   Jiri Olsa   perf c2c report: ...
58
  	struct c2c_stats	 stats;
1e181b92a   Jiri Olsa   perf c2c report: ...
59
  	unsigned long		*cpuset;
7f834c2e8   Jiri Olsa   perf c2c report: ...
60
  	unsigned long		*nodeset;
1e181b92a   Jiri Olsa   perf c2c report: ...
61
  	struct c2c_stats	*node_stats;
bb342daed   Jiri Olsa   perf c2c report: ...
62
  	unsigned int		 cacheline_idx;
92062d543   Jiri Olsa   perf c2c report: ...
63
64
  
  	struct compute_stats	 cstats;
4c8205273   Jiri Olsa   perf c2c: Keep st...
65
66
67
68
  	unsigned long		 paddr;
  	unsigned long		 paddr_cnt;
  	bool			 paddr_zero;
  	char			*nodestr;
78b275437   Jiri Olsa   perf c2c report: ...
69
70
71
72
73
74
  	/*
  	 * must be at the end,
  	 * because of its callchain dynamic entry
  	 */
  	struct hist_entry	he;
  };
423701a0c   Jiri Olsa   perf c2c: Change ...
75
  static char const *coalesce_default = "iaddr";
fc9c630e8   Jiri Olsa   perf c2c report: ...
76

903a6f15b   Jiri Olsa   perf c2c: Add rep...
77
  struct perf_c2c {
c75540e31   Jiri Olsa   perf c2c report: ...
78
79
  	struct perf_tool	tool;
  	struct c2c_hists	hists;
7f834c2e8   Jiri Olsa   perf c2c report: ...
80
  	struct mem2node		mem2node;
1e181b92a   Jiri Olsa   perf c2c report: ...
81
82
83
84
85
86
  
  	unsigned long		**nodes;
  	int			 nodes_cnt;
  	int			 cpus_cnt;
  	int			*cpu2node;
  	int			 node_info;
89d9ba8f5   Jiri Olsa   perf c2c report: ...
87
88
  
  	bool			 show_src;
af09b2d35   Jiri Olsa   perf c2c report: ...
89
  	bool			 show_all;
5a1a99cd2   Jiri Olsa   perf c2c report: ...
90
  	bool			 use_stdio;
74c63a25f   Jiri Olsa   perf c2c report: ...
91
  	bool			 stats_only;
590b6a3ac   Jiri Olsa   perf c2c report: ...
92
  	bool			 symbol_full;
d80da766d   Kan Liang   perf c2c: Add opt...
93
  	bool			 stitch_lbr;
7ef2efaab   Jiri Olsa   perf c2c report: ...
94
95
96
97
  
  	/* HITM shared clines stats */
  	struct c2c_stats	hitm_stats;
  	int			shared_clines;
55b957767   Jiri Olsa   perf c2c report: ...
98
99
  
  	int			 display;
fc9c630e8   Jiri Olsa   perf c2c report: ...
100
101
102
103
104
  
  	const char		*coalesce;
  	char			*cl_sort;
  	char			*cl_resort;
  	char			*cl_output;
55b957767   Jiri Olsa   perf c2c report: ...
105
106
107
108
109
  };
  
  enum {
  	DISPLAY_LCL,
  	DISPLAY_RMT,
d940baccc   Jiri Olsa   perf c2c report: ...
110
111
112
113
114
115
116
117
  	DISPLAY_TOT,
  	DISPLAY_MAX,
  };
  
  static const char *display_str[DISPLAY_MAX] = {
  	[DISPLAY_LCL] = "Local",
  	[DISPLAY_RMT] = "Remote",
  	[DISPLAY_TOT] = "Total",
903a6f15b   Jiri Olsa   perf c2c: Add rep...
118
  };
3a5bfab60   Jiri Olsa   perf c2c: Support...
119
120
121
122
  static const struct option c2c_options[] = {
  	OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"),
  	OPT_END()
  };
903a6f15b   Jiri Olsa   perf c2c: Add rep...
123
  static struct perf_c2c c2c;
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
124

78b275437   Jiri Olsa   perf c2c report: ...
125
126
127
128
129
130
131
  static void *c2c_he_zalloc(size_t size)
  {
  	struct c2c_hist_entry *c2c_he;
  
  	c2c_he = zalloc(size + sizeof(*c2c_he));
  	if (!c2c_he)
  		return NULL;
1e181b92a   Jiri Olsa   perf c2c report: ...
132
133
134
  	c2c_he->cpuset = bitmap_alloc(c2c.cpus_cnt);
  	if (!c2c_he->cpuset)
  		return NULL;
7f834c2e8   Jiri Olsa   perf c2c report: ...
135
136
137
  	c2c_he->nodeset = bitmap_alloc(c2c.nodes_cnt);
  	if (!c2c_he->nodeset)
  		return NULL;
1e181b92a   Jiri Olsa   perf c2c report: ...
138
139
140
  	c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats));
  	if (!c2c_he->node_stats)
  		return NULL;
92062d543   Jiri Olsa   perf c2c report: ...
141
142
143
  	init_stats(&c2c_he->cstats.lcl_hitm);
  	init_stats(&c2c_he->cstats.rmt_hitm);
  	init_stats(&c2c_he->cstats.load);
78b275437   Jiri Olsa   perf c2c report: ...
144
145
146
147
148
149
150
151
152
153
154
155
  	return &c2c_he->he;
  }
  
  static void c2c_he_free(void *he)
  {
  	struct c2c_hist_entry *c2c_he;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	if (c2c_he->hists) {
  		hists__delete_entries(&c2c_he->hists->hists);
  		free(c2c_he->hists);
  	}
1e181b92a   Jiri Olsa   perf c2c report: ...
156
  	free(c2c_he->cpuset);
7f834c2e8   Jiri Olsa   perf c2c report: ...
157
158
  	free(c2c_he->nodeset);
  	free(c2c_he->nodestr);
1e181b92a   Jiri Olsa   perf c2c report: ...
159
  	free(c2c_he->node_stats);
78b275437   Jiri Olsa   perf c2c report: ...
160
161
162
163
164
165
166
  	free(c2c_he);
  }
  
  static struct hist_entry_ops c2c_entry_ops = {
  	.new	= c2c_he_zalloc,
  	.free	= c2c_he_free,
  };
ec06f9b9b   Jiri Olsa   perf c2c report: ...
167
  static int c2c_hists__init(struct c2c_hists *hists,
1d62fcd69   Jiri Olsa   perf c2c report: ...
168
169
  			   const char *sort,
  			   int nr_header_lines);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
170

b2252ae67   Jiri Olsa   perf c2c report: ...
171
172
  static struct c2c_hists*
  he__get_c2c_hists(struct hist_entry *he,
1d62fcd69   Jiri Olsa   perf c2c report: ...
173
174
  		  const char *sort,
  		  int nr_header_lines)
ec06f9b9b   Jiri Olsa   perf c2c report: ...
175
176
177
178
179
180
181
  {
  	struct c2c_hist_entry *c2c_he;
  	struct c2c_hists *hists;
  	int ret;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	if (c2c_he->hists)
b2252ae67   Jiri Olsa   perf c2c report: ...
182
  		return c2c_he->hists;
ec06f9b9b   Jiri Olsa   perf c2c report: ...
183
184
185
186
  
  	hists = c2c_he->hists = zalloc(sizeof(*hists));
  	if (!hists)
  		return NULL;
1d62fcd69   Jiri Olsa   perf c2c report: ...
187
  	ret = c2c_hists__init(hists, sort, nr_header_lines);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
188
189
190
191
  	if (ret) {
  		free(hists);
  		return NULL;
  	}
b2252ae67   Jiri Olsa   perf c2c report: ...
192
  	return hists;
ec06f9b9b   Jiri Olsa   perf c2c report: ...
193
  }
1e181b92a   Jiri Olsa   perf c2c report: ...
194
195
196
197
198
199
200
201
202
  static void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he,
  			    struct perf_sample *sample)
  {
  	if (WARN_ONCE(sample->cpu == (unsigned int) -1,
  		      "WARNING: no sample cpu value"))
  		return;
  
  	set_bit(sample->cpu, c2c_he->cpuset);
  }
7f834c2e8   Jiri Olsa   perf c2c report: ...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
  static void c2c_he__set_node(struct c2c_hist_entry *c2c_he,
  			     struct perf_sample *sample)
  {
  	int node;
  
  	if (!sample->phys_addr) {
  		c2c_he->paddr_zero = true;
  		return;
  	}
  
  	node = mem2node__node(&c2c.mem2node, sample->phys_addr);
  	if (WARN_ONCE(node < 0, "WARNING: failed to find node
  "))
  		return;
  
  	set_bit(node, c2c_he->nodeset);
  
  	if (c2c_he->paddr != sample->phys_addr) {
  		c2c_he->paddr_cnt++;
  		c2c_he->paddr = sample->phys_addr;
  	}
  }
92062d543   Jiri Olsa   perf c2c report: ...
225
226
227
228
229
230
231
232
233
234
235
236
237
  static void compute_stats(struct c2c_hist_entry *c2c_he,
  			  struct c2c_stats *stats,
  			  u64 weight)
  {
  	struct compute_stats *cstats = &c2c_he->cstats;
  
  	if (stats->rmt_hitm)
  		update_stats(&cstats->rmt_hitm, weight);
  	else if (stats->lcl_hitm)
  		update_stats(&cstats->lcl_hitm, weight);
  	else if (stats->load)
  		update_stats(&cstats->load, weight);
  }
78b275437   Jiri Olsa   perf c2c report: ...
238
239
240
  static int process_sample_event(struct perf_tool *tool __maybe_unused,
  				union perf_event *event,
  				struct perf_sample *sample,
32dcd021d   Jiri Olsa   perf evsel: Renam...
241
  				struct evsel *evsel,
78b275437   Jiri Olsa   perf c2c report: ...
242
243
  				struct machine *machine)
  {
b2252ae67   Jiri Olsa   perf c2c report: ...
244
245
246
  	struct c2c_hists *c2c_hists = &c2c.hists;
  	struct c2c_hist_entry *c2c_he;
  	struct c2c_stats stats = { .nr_entries = 0, };
78b275437   Jiri Olsa   perf c2c report: ...
247
248
  	struct hist_entry *he;
  	struct addr_location al;
ec06f9b9b   Jiri Olsa   perf c2c report: ...
249
  	struct mem_info *mi, *mi_dup;
78b275437   Jiri Olsa   perf c2c report: ...
250
251
252
253
254
255
256
257
  	int ret;
  
  	if (machine__resolve(machine, &al, sample) < 0) {
  		pr_debug("problem processing %d event, skipping it.
  ",
  			 event->header.type);
  		return -1;
  	}
d80da766d   Kan Liang   perf c2c: Add opt...
258
259
  	if (c2c.stitch_lbr)
  		al.thread->lbr_stitch_enable = true;
dd805768f   Jiri Olsa   perf c2c report: ...
260
261
262
263
  	ret = sample__resolve_callchain(sample, &callchain_cursor, NULL,
  					evsel, &al, sysctl_perf_event_max_stack);
  	if (ret)
  		goto out;
78b275437   Jiri Olsa   perf c2c report: ...
264
265
266
  	mi = sample__resolve_mem(sample, &al);
  	if (mi == NULL)
  		return -ENOMEM;
5cedb413a   Jiri Olsa   perf c2c: Use mem...
267
268
269
270
271
272
  	/*
  	 * The mi object is released in hists__add_entry_ops,
  	 * if it gets sorted out into existing data, so we need
  	 * to take the copy now.
  	 */
  	mi_dup = mem_info__get(mi);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
273

b2252ae67   Jiri Olsa   perf c2c report: ...
274
275
276
  	c2c_decode_stats(&stats, mi);
  
  	he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
78b275437   Jiri Olsa   perf c2c report: ...
277
278
  				  &al, NULL, NULL, mi,
  				  sample, true);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
279
  	if (he == NULL)
5cedb413a   Jiri Olsa   perf c2c: Use mem...
280
  		goto free_mi;
78b275437   Jiri Olsa   perf c2c report: ...
281

b2252ae67   Jiri Olsa   perf c2c report: ...
282
283
284
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	c2c_add_stats(&c2c_he->stats, &stats);
  	c2c_add_stats(&c2c_hists->stats, &stats);
1e181b92a   Jiri Olsa   perf c2c report: ...
285
  	c2c_he__set_cpu(c2c_he, sample);
7f834c2e8   Jiri Olsa   perf c2c report: ...
286
  	c2c_he__set_node(c2c_he, sample);
1e181b92a   Jiri Olsa   perf c2c report: ...
287

b2252ae67   Jiri Olsa   perf c2c report: ...
288
  	hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
78b275437   Jiri Olsa   perf c2c report: ...
289
  	ret = hist_entry__append_callchain(he, sample);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
290
  	if (!ret) {
1e181b92a   Jiri Olsa   perf c2c report: ...
291
292
293
294
295
296
297
298
299
300
  		/*
  		 * There's already been warning about missing
  		 * sample's cpu value. Let's account all to
  		 * node 0 in this case, without any further
  		 * warning.
  		 *
  		 * Doing node stats only for single callchain data.
  		 */
  		int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu;
  		int node = c2c.cpu2node[cpu];
ec06f9b9b   Jiri Olsa   perf c2c report: ...
301
  		mi = mi_dup;
fc9c630e8   Jiri Olsa   perf c2c report: ...
302
  		c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2);
b2252ae67   Jiri Olsa   perf c2c report: ...
303
  		if (!c2c_hists)
5cedb413a   Jiri Olsa   perf c2c: Use mem...
304
  			goto free_mi;
ec06f9b9b   Jiri Olsa   perf c2c report: ...
305

b2252ae67   Jiri Olsa   perf c2c report: ...
306
  		he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops,
ec06f9b9b   Jiri Olsa   perf c2c report: ...
307
308
309
  					  &al, NULL, NULL, mi,
  					  sample, true);
  		if (he == NULL)
5cedb413a   Jiri Olsa   perf c2c: Use mem...
310
  			goto free_mi;
ec06f9b9b   Jiri Olsa   perf c2c report: ...
311

b2252ae67   Jiri Olsa   perf c2c report: ...
312
313
314
  		c2c_he = container_of(he, struct c2c_hist_entry, he);
  		c2c_add_stats(&c2c_he->stats, &stats);
  		c2c_add_stats(&c2c_hists->stats, &stats);
1e181b92a   Jiri Olsa   perf c2c report: ...
315
  		c2c_add_stats(&c2c_he->node_stats[node], &stats);
92062d543   Jiri Olsa   perf c2c report: ...
316
  		compute_stats(c2c_he, &stats, sample->weight);
1e181b92a   Jiri Olsa   perf c2c report: ...
317
  		c2c_he__set_cpu(c2c_he, sample);
7f834c2e8   Jiri Olsa   perf c2c report: ...
318
  		c2c_he__set_node(c2c_he, sample);
b2252ae67   Jiri Olsa   perf c2c report: ...
319
320
  
  		hists__inc_nr_samples(&c2c_hists->hists, he->filtered);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
321
322
323
324
  		ret = hist_entry__append_callchain(he, sample);
  	}
  
  out:
78b275437   Jiri Olsa   perf c2c report: ...
325
326
  	addr_location__put(&al);
  	return ret;
ec06f9b9b   Jiri Olsa   perf c2c report: ...
327

ec06f9b9b   Jiri Olsa   perf c2c report: ...
328
  free_mi:
5cedb413a   Jiri Olsa   perf c2c: Use mem...
329
330
  	mem_info__put(mi_dup);
  	mem_info__put(mi);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
331
332
  	ret = -ENOMEM;
  	goto out;
78b275437   Jiri Olsa   perf c2c report: ...
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  }
  
  static struct perf_c2c c2c = {
  	.tool = {
  		.sample		= process_sample_event,
  		.mmap		= perf_event__process_mmap,
  		.mmap2		= perf_event__process_mmap2,
  		.comm		= perf_event__process_comm,
  		.exit		= perf_event__process_exit,
  		.fork		= perf_event__process_fork,
  		.lost		= perf_event__process_lost,
  		.ordered_events	= true,
  		.ordering_requires_timestamps = true,
  	},
  };
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
348
  static const char * const c2c_usage[] = {
903a6f15b   Jiri Olsa   perf c2c: Add rep...
349
  	"perf c2c {record|report}",
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
350
351
  	NULL
  };
903a6f15b   Jiri Olsa   perf c2c: Add rep...
352
353
354
355
356
357
  static const char * const __usage_report[] = {
  	"perf c2c report",
  	NULL
  };
  
  static const char * const *report_c2c_usage = __usage_report;
c75540e31   Jiri Olsa   perf c2c report: ...
358
359
360
361
362
363
364
365
366
367
368
369
370
  #define C2C_HEADER_MAX 2
  
  struct c2c_header {
  	struct {
  		const char *text;
  		int	    span;
  	} line[C2C_HEADER_MAX];
  };
  
  struct c2c_dimension {
  	struct c2c_header	 header;
  	const char		*name;
  	int			 width;
8d3f938dc   Jiri Olsa   perf c2c report: ...
371
  	struct sort_entry	*se;
c75540e31   Jiri Olsa   perf c2c report: ...
372
373
374
375
376
377
378
379
380
381
382
383
384
  
  	int64_t (*cmp)(struct perf_hpp_fmt *fmt,
  		       struct hist_entry *, struct hist_entry *);
  	int   (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		       struct hist_entry *he);
  	int   (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		       struct hist_entry *he);
  };
  
  struct c2c_fmt {
  	struct perf_hpp_fmt	 fmt;
  	struct c2c_dimension	*dim;
  };
590b6a3ac   Jiri Olsa   perf c2c report: ...
385
386
387
388
389
390
391
392
393
394
395
396
397
398
  #define SYMBOL_WIDTH 30
  
  static struct c2c_dimension dim_symbol;
  static struct c2c_dimension dim_srcline;
  
  static int symbol_width(struct hists *hists, struct sort_entry *se)
  {
  	int width = hists__col_len(hists, se->se_width_idx);
  
  	if (!c2c.symbol_full)
  		width = MIN(width, SYMBOL_WIDTH);
  
  	return width;
  }
c75540e31   Jiri Olsa   perf c2c report: ...
399
400
  static int c2c_width(struct perf_hpp_fmt *fmt,
  		     struct perf_hpp *hpp __maybe_unused,
7e6a79981   Arnaldo Carvalho de Melo   perf tools: Remov...
401
  		     struct hists *hists)
c75540e31   Jiri Olsa   perf c2c report: ...
402
403
  {
  	struct c2c_fmt *c2c_fmt;
8d3f938dc   Jiri Olsa   perf c2c report: ...
404
  	struct c2c_dimension *dim;
c75540e31   Jiri Olsa   perf c2c report: ...
405
406
  
  	c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
8d3f938dc   Jiri Olsa   perf c2c report: ...
407
  	dim = c2c_fmt->dim;
590b6a3ac   Jiri Olsa   perf c2c report: ...
408
409
  	if (dim == &dim_symbol || dim == &dim_srcline)
  		return symbol_width(hists, dim->se);
8d3f938dc   Jiri Olsa   perf c2c report: ...
410
411
  	return dim->se ? hists__col_len(hists, dim->se->se_width_idx) :
  			 c2c_fmt->dim->width;
c75540e31   Jiri Olsa   perf c2c report: ...
412
413
414
  }
  
  static int c2c_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
8d3f938dc   Jiri Olsa   perf c2c report: ...
415
  		      struct hists *hists, int line, int *span)
c75540e31   Jiri Olsa   perf c2c report: ...
416
  {
8d3f938dc   Jiri Olsa   perf c2c report: ...
417
  	struct perf_hpp_list *hpp_list = hists->hpp_list;
c75540e31   Jiri Olsa   perf c2c report: ...
418
419
  	struct c2c_fmt *c2c_fmt;
  	struct c2c_dimension *dim;
8d3f938dc   Jiri Olsa   perf c2c report: ...
420
421
  	const char *text = NULL;
  	int width = c2c_width(fmt, hpp, hists);
c75540e31   Jiri Olsa   perf c2c report: ...
422
423
424
  
  	c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
  	dim = c2c_fmt->dim;
8d3f938dc   Jiri Olsa   perf c2c report: ...
425
426
427
428
429
  	if (dim->se) {
  		text = dim->header.line[line].text;
  		/* Use the last line from sort_entry if not defined. */
  		if (!text && (line == hpp_list->nr_header_lines - 1))
  			text = dim->se->se_header;
c75540e31   Jiri Olsa   perf c2c report: ...
430
  	} else {
8d3f938dc   Jiri Olsa   perf c2c report: ...
431
432
433
434
435
436
437
438
  		text = dim->header.line[line].text;
  
  		if (*span) {
  			(*span)--;
  			return 0;
  		} else {
  			*span = dim->header.line[line].span;
  		}
c75540e31   Jiri Olsa   perf c2c report: ...
439
  	}
8d3f938dc   Jiri Olsa   perf c2c report: ...
440
441
442
443
  	if (text == NULL)
  		text = "";
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, text);
c75540e31   Jiri Olsa   perf c2c report: ...
444
  }
cbb88500a   Jiri Olsa   perf c2c report: ...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
  #define HEX_STR(__s, __v)				\
  ({							\
  	scnprintf(__s, sizeof(__s), "0x%" PRIx64, __v);	\
  	__s;						\
  })
  
  static int64_t
  dcacheline_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	       struct hist_entry *left, struct hist_entry *right)
  {
  	return sort__dcacheline_cmp(left, right);
  }
  
  static int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  			    struct hist_entry *he)
  {
  	uint64_t addr = 0;
  	int width = c2c_width(fmt, hpp, he->hists);
  	char buf[20];
  
  	if (he->mem_info)
  		addr = cl_address(he->mem_info->daddr.addr);
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
  }
7f834c2e8   Jiri Olsa   perf c2c report: ...
470
471
472
473
474
475
476
477
478
479
480
481
482
  static int
  dcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		      struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	if (WARN_ON_ONCE(!c2c_he->nodestr))
  		return 0;
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, c2c_he->nodestr);
  }
03d9fcb70   Jiri Olsa   perf c2c report: ...
483
484
485
486
487
488
489
490
491
492
  static int
  dcacheline_node_count(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		      struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	return scnprintf(hpp->buf, hpp->size, "%*lu", width, c2c_he->paddr_cnt);
  }
48acdebdc   Jiri Olsa   perf c2c report: ...
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
  static int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  			struct hist_entry *he)
  {
  	uint64_t addr = 0;
  	int width = c2c_width(fmt, hpp, he->hists);
  	char buf[20];
  
  	if (he->mem_info)
  		addr = cl_offset(he->mem_info->daddr.al_addr);
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
  }
  
  static int64_t
  offset_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	   struct hist_entry *left, struct hist_entry *right)
  {
  	uint64_t l = 0, r = 0;
  
  	if (left->mem_info)
  		l = cl_offset(left->mem_info->daddr.addr);
  	if (right->mem_info)
  		r = cl_offset(right->mem_info->daddr.addr);
  
  	return (int64_t)(r - l);
  }
43575a952   Jiri Olsa   perf c2c report: ...
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  static int
  iaddr_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  	    struct hist_entry *he)
  {
  	uint64_t addr = 0;
  	int width = c2c_width(fmt, hpp, he->hists);
  	char buf[20];
  
  	if (he->mem_info)
  		addr = he->mem_info->iaddr.addr;
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr));
  }
  
  static int64_t
  iaddr_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	  struct hist_entry *left, struct hist_entry *right)
  {
  	return sort__iaddr_cmp(left, right);
  }
97cb486e4   Jiri Olsa   perf c2c report: ...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
  static int
  tot_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  	       struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  	unsigned int tot_hitm;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	tot_hitm = c2c_he->stats.lcl_hitm + c2c_he->stats.rmt_hitm;
  
  	return scnprintf(hpp->buf, hpp->size, "%*u", width, tot_hitm);
  }
  
  static int64_t
  tot_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	     struct hist_entry *left, struct hist_entry *right)
  {
  	struct c2c_hist_entry *c2c_left;
  	struct c2c_hist_entry *c2c_right;
c1c8013ec   Andres Freund   perf c2c: Fix ret...
559
560
  	uint64_t tot_hitm_left;
  	uint64_t tot_hitm_right;
97cb486e4   Jiri Olsa   perf c2c report: ...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
  
  	c2c_left  = container_of(left, struct c2c_hist_entry, he);
  	c2c_right = container_of(right, struct c2c_hist_entry, he);
  
  	tot_hitm_left  = c2c_left->stats.lcl_hitm + c2c_left->stats.rmt_hitm;
  	tot_hitm_right = c2c_right->stats.lcl_hitm + c2c_right->stats.rmt_hitm;
  
  	return tot_hitm_left - tot_hitm_right;
  }
  
  #define STAT_FN_ENTRY(__f)					\
  static int							\
  __f ## _entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,	\
  	      struct hist_entry *he)				\
  {								\
  	struct c2c_hist_entry *c2c_he;				\
  	int width = c2c_width(fmt, hpp, he->hists);		\
  								\
  	c2c_he = container_of(he, struct c2c_hist_entry, he);	\
  	return scnprintf(hpp->buf, hpp->size, "%*u", width,	\
  			 c2c_he->stats.__f);			\
  }
  
  #define STAT_FN_CMP(__f)						\
  static int64_t								\
  __f ## _cmp(struct perf_hpp_fmt *fmt __maybe_unused,			\
  	    struct hist_entry *left, struct hist_entry *right)		\
  {									\
  	struct c2c_hist_entry *c2c_left, *c2c_right;			\
  									\
  	c2c_left  = container_of(left, struct c2c_hist_entry, he);	\
  	c2c_right = container_of(right, struct c2c_hist_entry, he);	\
c1c8013ec   Andres Freund   perf c2c: Fix ret...
593
594
  	return (uint64_t) c2c_left->stats.__f -				\
  	       (uint64_t) c2c_right->stats.__f;				\
97cb486e4   Jiri Olsa   perf c2c report: ...
595
596
597
598
599
600
601
602
  }
  
  #define STAT_FN(__f)		\
  	STAT_FN_ENTRY(__f)	\
  	STAT_FN_CMP(__f)
  
  STAT_FN(rmt_hitm)
  STAT_FN(lcl_hitm)
0f18896de   Jiri Olsa   perf c2c report: ...
603
604
605
  STAT_FN(store)
  STAT_FN(st_l1hit)
  STAT_FN(st_l1miss)
1295f6854   Jiri Olsa   perf c2c report: ...
606
607
608
  STAT_FN(ld_fbhit)
  STAT_FN(ld_l1hit)
  STAT_FN(ld_l2hit)
4d08910c9   Jiri Olsa   perf c2c report: ...
609
610
  STAT_FN(ld_llchit)
  STAT_FN(rmt_hit)
97cb486e4   Jiri Olsa   perf c2c report: ...
611

01b84d769   Jiri Olsa   perf c2c report: ...
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
  static uint64_t total_records(struct c2c_stats *stats)
  {
  	uint64_t lclmiss, ldcnt, total;
  
  	lclmiss  = stats->lcl_dram +
  		   stats->rmt_dram +
  		   stats->rmt_hitm +
  		   stats->rmt_hit;
  
  	ldcnt    = lclmiss +
  		   stats->ld_fbhit +
  		   stats->ld_l1hit +
  		   stats->ld_l2hit +
  		   stats->ld_llchit +
  		   stats->lcl_hitm;
  
  	total    = ldcnt +
  		   stats->st_l1hit +
  		   stats->st_l1miss;
  
  	return total;
  }
  
  static int
  tot_recs_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  	uint64_t tot_recs;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	tot_recs = total_records(&c2c_he->stats);
  
  	return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs);
  }
  
  static int64_t
  tot_recs_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	     struct hist_entry *left, struct hist_entry *right)
  {
  	struct c2c_hist_entry *c2c_left;
  	struct c2c_hist_entry *c2c_right;
  	uint64_t tot_recs_left;
  	uint64_t tot_recs_right;
  
  	c2c_left  = container_of(left, struct c2c_hist_entry, he);
  	c2c_right = container_of(right, struct c2c_hist_entry, he);
  
  	tot_recs_left  = total_records(&c2c_left->stats);
  	tot_recs_right = total_records(&c2c_right->stats);
  
  	return tot_recs_left - tot_recs_right;
  }
55177c4ea   Jiri Olsa   perf c2c report: ...
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
  static uint64_t total_loads(struct c2c_stats *stats)
  {
  	uint64_t lclmiss, ldcnt;
  
  	lclmiss  = stats->lcl_dram +
  		   stats->rmt_dram +
  		   stats->rmt_hitm +
  		   stats->rmt_hit;
  
  	ldcnt    = lclmiss +
  		   stats->ld_fbhit +
  		   stats->ld_l1hit +
  		   stats->ld_l2hit +
  		   stats->ld_llchit +
  		   stats->lcl_hitm;
  
  	return ldcnt;
  }
  
  static int
  tot_loads_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  	uint64_t tot_recs;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	tot_recs = total_loads(&c2c_he->stats);
  
  	return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs);
  }
  
  static int64_t
  tot_loads_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	      struct hist_entry *left, struct hist_entry *right)
  {
  	struct c2c_hist_entry *c2c_left;
  	struct c2c_hist_entry *c2c_right;
  	uint64_t tot_recs_left;
  	uint64_t tot_recs_right;
  
  	c2c_left  = container_of(left, struct c2c_hist_entry, he);
  	c2c_right = container_of(right, struct c2c_hist_entry, he);
  
  	tot_recs_left  = total_loads(&c2c_left->stats);
  	tot_recs_right = total_loads(&c2c_right->stats);
  
  	return tot_recs_left - tot_recs_right;
  }
f0c50c159   Jiri Olsa   perf c2c report: ...
716
717
718
719
720
721
722
723
724
725
726
727
  typedef double (get_percent_cb)(struct c2c_hist_entry *);
  
  static int
  percent_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  	      struct hist_entry *he, get_percent_cb get_percent)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  	double per;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	per = get_percent(c2c_he);
5a1a99cd2   Jiri Olsa   perf c2c report: ...
728
729
730
731
  #ifdef HAVE_SLANG_SUPPORT
  	if (use_browser)
  		return __hpp__slsmg_color_printf(hpp, "%*.2f%%", width - 1, per);
  #endif
f0c50c159   Jiri Olsa   perf c2c report: ...
732
733
734
735
736
737
738
739
  	return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, per);
  }
  
  static double percent_hitm(struct c2c_hist_entry *c2c_he)
  {
  	struct c2c_hists *hists;
  	struct c2c_stats *stats;
  	struct c2c_stats *total;
55b957767   Jiri Olsa   perf c2c report: ...
740
  	int tot = 0, st = 0;
f0c50c159   Jiri Olsa   perf c2c report: ...
741
742
743
744
745
  	double p;
  
  	hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
  	stats = &c2c_he->stats;
  	total = &hists->stats;
55b957767   Jiri Olsa   perf c2c report: ...
746
747
748
749
750
751
752
753
  	switch (c2c.display) {
  	case DISPLAY_RMT:
  		st  = stats->rmt_hitm;
  		tot = total->rmt_hitm;
  		break;
  	case DISPLAY_LCL:
  		st  = stats->lcl_hitm;
  		tot = total->lcl_hitm;
d940baccc   Jiri Olsa   perf c2c report: ...
754
755
756
757
  		break;
  	case DISPLAY_TOT:
  		st  = stats->tot_hitm;
  		tot = total->tot_hitm;
55b957767   Jiri Olsa   perf c2c report: ...
758
759
760
  	default:
  		break;
  	}
f0c50c159   Jiri Olsa   perf c2c report: ...
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
  
  	p = tot ? (double) st / tot : 0;
  
  	return 100 * p;
  }
  
  #define PERC_STR(__s, __v)				\
  ({							\
  	scnprintf(__s, sizeof(__s), "%.2F%%", __v);	\
  	__s;						\
  })
  
  static int
  percent_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		   struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  	char buf[10];
  	double per;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	per = percent_hitm(c2c_he);
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
  }
  
  static int
  percent_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		   struct hist_entry *he)
  {
  	return percent_color(fmt, hpp, he, percent_hitm);
  }
  
  static int64_t
  percent_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  		 struct hist_entry *left, struct hist_entry *right)
  {
  	struct c2c_hist_entry *c2c_left;
  	struct c2c_hist_entry *c2c_right;
  	double per_left;
  	double per_right;
  
  	c2c_left  = container_of(left, struct c2c_hist_entry, he);
  	c2c_right = container_of(right, struct c2c_hist_entry, he);
  
  	per_left  = percent_hitm(c2c_left);
  	per_right = percent_hitm(c2c_right);
  
  	return per_left - per_right;
  }
9cb3500af   Jiri Olsa   perf c2c report: ...
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
  static struct c2c_stats *he_stats(struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	return &c2c_he->stats;
  }
  
  static struct c2c_stats *total_stats(struct hist_entry *he)
  {
  	struct c2c_hists *hists;
  
  	hists = container_of(he->hists, struct c2c_hists, hists);
  	return &hists->stats;
  }
  
  static double percent(int st, int tot)
  {
  	return tot ? 100. * (double) st / (double) tot : 0;
  }
  
  #define PERCENT(__h, __f) percent(he_stats(__h)->__f, total_stats(__h)->__f)
  
  #define PERCENT_FN(__f)								\
  static double percent_ ## __f(struct c2c_hist_entry *c2c_he)			\
  {										\
  	struct c2c_hists *hists;						\
  										\
  	hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);	\
  	return percent(c2c_he->stats.__f, hists->stats.__f);			\
  }
  
  PERCENT_FN(rmt_hitm)
  PERCENT_FN(lcl_hitm)
  PERCENT_FN(st_l1hit)
  PERCENT_FN(st_l1miss)
  
  static int
  percent_rmt_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		       struct hist_entry *he)
  {
  	int width = c2c_width(fmt, hpp, he->hists);
  	double per = PERCENT(he, rmt_hitm);
  	char buf[10];
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
  }
  
  static int
  percent_rmt_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		       struct hist_entry *he)
  {
  	return percent_color(fmt, hpp, he, percent_rmt_hitm);
  }
  
  static int64_t
  percent_rmt_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  		     struct hist_entry *left, struct hist_entry *right)
  {
  	double per_left;
  	double per_right;
  
  	per_left  = PERCENT(left, lcl_hitm);
  	per_right = PERCENT(right, lcl_hitm);
  
  	return per_left - per_right;
  }
  
  static int
  percent_lcl_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		       struct hist_entry *he)
  {
  	int width = c2c_width(fmt, hpp, he->hists);
  	double per = PERCENT(he, lcl_hitm);
  	char buf[10];
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
  }
  
  static int
  percent_lcl_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  		       struct hist_entry *he)
  {
  	return percent_color(fmt, hpp, he, percent_lcl_hitm);
  }
  
  static int64_t
  percent_lcl_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  		     struct hist_entry *left, struct hist_entry *right)
  {
  	double per_left;
  	double per_right;
  
  	per_left  = PERCENT(left, lcl_hitm);
  	per_right = PERCENT(right, lcl_hitm);
  
  	return per_left - per_right;
  }
  
  static int
  percent_stores_l1hit_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  			   struct hist_entry *he)
  {
  	int width = c2c_width(fmt, hpp, he->hists);
  	double per = PERCENT(he, st_l1hit);
  	char buf[10];
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
  }
  
  static int
  percent_stores_l1hit_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  			   struct hist_entry *he)
  {
  	return percent_color(fmt, hpp, he, percent_st_l1hit);
  }
  
  static int64_t
  percent_stores_l1hit_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  			struct hist_entry *left, struct hist_entry *right)
  {
  	double per_left;
  	double per_right;
  
  	per_left  = PERCENT(left, st_l1hit);
  	per_right = PERCENT(right, st_l1hit);
  
  	return per_left - per_right;
  }
  
  static int
  percent_stores_l1miss_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  			   struct hist_entry *he)
  {
  	int width = c2c_width(fmt, hpp, he->hists);
  	double per = PERCENT(he, st_l1miss);
  	char buf[10];
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per));
  }
  
  static int
  percent_stores_l1miss_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  			    struct hist_entry *he)
  {
  	return percent_color(fmt, hpp, he, percent_st_l1miss);
  }
  
  static int64_t
  percent_stores_l1miss_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  			  struct hist_entry *left, struct hist_entry *right)
  {
  	double per_left;
  	double per_right;
  
  	per_left  = PERCENT(left, st_l1miss);
  	per_right = PERCENT(right, st_l1miss);
  
  	return per_left - per_right;
  }
6c70f54cf   Jiri Olsa   perf c2c report: ...
971
972
  STAT_FN(lcl_dram)
  STAT_FN(rmt_dram)
36d3deb9d   Jiri Olsa   perf c2c report: ...
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
  static int
  pid_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  	  struct hist_entry *he)
  {
  	int width = c2c_width(fmt, hpp, he->hists);
  
  	return scnprintf(hpp->buf, hpp->size, "%*d", width, he->thread->pid_);
  }
  
  static int64_t
  pid_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	struct hist_entry *left, struct hist_entry *right)
  {
  	return left->thread->pid_ - right->thread->pid_;
  }
1e181b92a   Jiri Olsa   perf c2c report: ...
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
  static int64_t
  empty_cmp(struct perf_hpp_fmt *fmt __maybe_unused,
  	  struct hist_entry *left __maybe_unused,
  	  struct hist_entry *right __maybe_unused)
  {
  	return 0;
  }
  
  static int
  node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp,
  	   struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	bool first = true;
  	int node;
  	int ret = 0;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  
  	for (node = 0; node < c2c.nodes_cnt; node++) {
  		DECLARE_BITMAP(set, c2c.cpus_cnt);
  
  		bitmap_zero(set, c2c.cpus_cnt);
  		bitmap_and(set, c2c_he->cpuset, c2c.nodes[node], c2c.cpus_cnt);
  
  		if (!bitmap_weight(set, c2c.cpus_cnt)) {
  			if (c2c.node_info == 1) {
  				ret = scnprintf(hpp->buf, hpp->size, "%21s", " ");
  				advance_hpp(hpp, ret);
  			}
  			continue;
  		}
  
  		if (!first) {
  			ret = scnprintf(hpp->buf, hpp->size, " ");
  			advance_hpp(hpp, ret);
  		}
  
  		switch (c2c.node_info) {
  		case 0:
  			ret = scnprintf(hpp->buf, hpp->size, "%2d", node);
  			advance_hpp(hpp, ret);
  			break;
  		case 1:
  		{
67260e8c0   Jiri Olsa   perf c2c: Display...
1033
  			int num = bitmap_weight(set, c2c.cpus_cnt);
1e181b92a   Jiri Olsa   perf c2c report: ...
1034
1035
1036
1037
  			struct c2c_stats *stats = &c2c_he->node_stats[node];
  
  			ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num);
  			advance_hpp(hpp, ret);
55b957767   Jiri Olsa   perf c2c report: ...
1038
1039
1040
1041
1042
1043
1044
  		#define DISPLAY_HITM(__h)						\
  			if (c2c_he->stats.__h> 0) {					\
  				ret = scnprintf(hpp->buf, hpp->size, "%5.1f%% ",	\
  						percent(stats->__h, c2c_he->stats.__h));\
  			} else {							\
  				ret = scnprintf(hpp->buf, hpp->size, "%6s ", "n/a");	\
  			}
1e181b92a   Jiri Olsa   perf c2c report: ...
1045

55b957767   Jiri Olsa   perf c2c report: ...
1046
1047
1048
1049
1050
1051
  			switch (c2c.display) {
  			case DISPLAY_RMT:
  				DISPLAY_HITM(rmt_hitm);
  				break;
  			case DISPLAY_LCL:
  				DISPLAY_HITM(lcl_hitm);
d940baccc   Jiri Olsa   perf c2c report: ...
1052
1053
1054
  				break;
  			case DISPLAY_TOT:
  				DISPLAY_HITM(tot_hitm);
55b957767   Jiri Olsa   perf c2c report: ...
1055
1056
  			default:
  				break;
1e181b92a   Jiri Olsa   perf c2c report: ...
1057
  			}
55b957767   Jiri Olsa   perf c2c report: ...
1058
  		#undef DISPLAY_HITM
1e181b92a   Jiri Olsa   perf c2c report: ...
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
  			advance_hpp(hpp, ret);
  
  			if (c2c_he->stats.store > 0) {
  				ret = scnprintf(hpp->buf, hpp->size, "%5.1f%%}",
  						percent(stats->store, c2c_he->stats.store));
  			} else {
  				ret = scnprintf(hpp->buf, hpp->size, "%6s}", "n/a");
  			}
  
  			advance_hpp(hpp, ret);
  			break;
  		}
  		case 2:
  			ret = scnprintf(hpp->buf, hpp->size, "%2d{", node);
  			advance_hpp(hpp, ret);
  
  			ret = bitmap_scnprintf(set, c2c.cpus_cnt, hpp->buf, hpp->size);
  			advance_hpp(hpp, ret);
  
  			ret = scnprintf(hpp->buf, hpp->size, "}");
  			advance_hpp(hpp, ret);
  			break;
  		default:
  			break;
  		}
  
  		first = false;
  	}
  
  	return 0;
  }
92062d543   Jiri Olsa   perf c2c report: ...
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  static int
  mean_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  	   struct hist_entry *he, double mean)
  {
  	int width = c2c_width(fmt, hpp, he->hists);
  	char buf[10];
  
  	scnprintf(buf, 10, "%6.0f", mean);
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
  }
  
  #define MEAN_ENTRY(__func, __val)						\
  static int									\
  __func(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he)	\
  {										\
  	struct c2c_hist_entry *c2c_he;						\
  	c2c_he = container_of(he, struct c2c_hist_entry, he);			\
  	return mean_entry(fmt, hpp, he, avg_stats(&c2c_he->cstats.__val));	\
  }
  
  MEAN_ENTRY(mean_rmt_entry,  rmt_hitm);
  MEAN_ENTRY(mean_lcl_entry,  lcl_hitm);
  MEAN_ENTRY(mean_load_entry, load);
b6fe2bbc3   Jiri Olsa   perf c2c report: ...
1113
  static int
7e6a79981   Arnaldo Carvalho de Melo   perf tools: Remov...
1114
  cpucnt_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
b6fe2bbc3   Jiri Olsa   perf c2c report: ...
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
  	     struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  	char buf[10];
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  
  	scnprintf(buf, 10, "%d", bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt));
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
  }
bb342daed   Jiri Olsa   perf c2c report: ...
1126
  static int
7e6a79981   Arnaldo Carvalho de Melo   perf tools: Remov...
1127
  cl_idx_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
bb342daed   Jiri Olsa   perf c2c report: ...
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
  	     struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	int width = c2c_width(fmt, hpp, he->hists);
  	char buf[10];
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  
  	scnprintf(buf, 10, "%u", c2c_he->cacheline_idx);
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, buf);
  }
  
  static int
7e6a79981   Arnaldo Carvalho de Melo   perf tools: Remov...
1141
  cl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
bb342daed   Jiri Olsa   perf c2c report: ...
1142
1143
1144
1145
1146
1147
  		   struct hist_entry *he)
  {
  	int width = c2c_width(fmt, hpp, he->hists);
  
  	return scnprintf(hpp->buf, hpp->size, "%*s", width, "");
  }
600a8cf45   Jiri Olsa   perf c2c report: ...
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
  #define HEADER_LOW(__h)			\
  	{				\
  		.line[1] = {		\
  			.text = __h,	\
  		},			\
  	}
  
  #define HEADER_BOTH(__h0, __h1)		\
  	{				\
  		.line[0] = {		\
  			.text = __h0,	\
  		},			\
  		.line[1] = {		\
  			.text = __h1,	\
  		},			\
  	}
  
  #define HEADER_SPAN(__h0, __h1, __s)	\
  	{				\
  		.line[0] = {		\
  			.text = __h0,	\
  			.span = __s,	\
  		},			\
  		.line[1] = {		\
  			.text = __h1,	\
  		},			\
  	}
  
  #define HEADER_SPAN_LOW(__h)		\
  	{				\
  		.line[1] = {		\
  			.text = __h,	\
  		},			\
  	}
cbb88500a   Jiri Olsa   perf c2c report: ...
1182
  static struct c2c_dimension dim_dcacheline = {
03d9fcb70   Jiri Olsa   perf c2c report: ...
1183
  	.header		= HEADER_SPAN("--- Cacheline ----", "Address", 2),
cbb88500a   Jiri Olsa   perf c2c report: ...
1184
1185
1186
1187
1188
  	.name		= "dcacheline",
  	.cmp		= dcacheline_cmp,
  	.entry		= dcacheline_entry,
  	.width		= 18,
  };
7f834c2e8   Jiri Olsa   perf c2c report: ...
1189
1190
1191
1192
1193
1194
1195
  static struct c2c_dimension dim_dcacheline_node = {
  	.header		= HEADER_LOW("Node"),
  	.name		= "dcacheline_node",
  	.cmp		= empty_cmp,
  	.entry		= dcacheline_node_entry,
  	.width		= 4,
  };
03d9fcb70   Jiri Olsa   perf c2c report: ...
1196
1197
1198
1199
1200
1201
1202
1203
1204
  static struct c2c_dimension dim_dcacheline_count = {
  	.header		= HEADER_LOW("PA cnt"),
  	.name		= "dcacheline_count",
  	.cmp		= empty_cmp,
  	.entry		= dcacheline_node_count,
  	.width		= 6,
  };
  
  static struct c2c_header header_offset_tui = HEADER_SPAN("-----", "Off", 2);
5a1a99cd2   Jiri Olsa   perf c2c report: ...
1205

48acdebdc   Jiri Olsa   perf c2c report: ...
1206
  static struct c2c_dimension dim_offset = {
03d9fcb70   Jiri Olsa   perf c2c report: ...
1207
  	.header		= HEADER_SPAN("--- Data address -", "Offset", 2),
48acdebdc   Jiri Olsa   perf c2c report: ...
1208
1209
1210
1211
1212
  	.name		= "offset",
  	.cmp		= offset_cmp,
  	.entry		= offset_entry,
  	.width		= 18,
  };
7f834c2e8   Jiri Olsa   perf c2c report: ...
1213
1214
1215
1216
1217
1218
1219
  static struct c2c_dimension dim_offset_node = {
  	.header		= HEADER_LOW("Node"),
  	.name		= "offset_node",
  	.cmp		= empty_cmp,
  	.entry		= dcacheline_node_entry,
  	.width		= 4,
  };
43575a952   Jiri Olsa   perf c2c report: ...
1220
1221
1222
1223
1224
1225
1226
  static struct c2c_dimension dim_iaddr = {
  	.header		= HEADER_LOW("Code address"),
  	.name		= "iaddr",
  	.cmp		= iaddr_cmp,
  	.entry		= iaddr_entry,
  	.width		= 18,
  };
97cb486e4   Jiri Olsa   perf c2c report: ...
1227
  static struct c2c_dimension dim_tot_hitm = {
fdd32d7e8   Leo Yan   perf c2c: Change ...
1228
  	.header		= HEADER_SPAN("------- Load Hitm -------", "Total", 2),
97cb486e4   Jiri Olsa   perf c2c report: ...
1229
1230
1231
1232
1233
1234
1235
  	.name		= "tot_hitm",
  	.cmp		= tot_hitm_cmp,
  	.entry		= tot_hitm_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_lcl_hitm = {
0fbe2fe96   Leo Yan   perf c2c: Use mor...
1236
  	.header		= HEADER_SPAN_LOW("LclHitm"),
97cb486e4   Jiri Olsa   perf c2c report: ...
1237
1238
1239
1240
1241
1242
1243
  	.name		= "lcl_hitm",
  	.cmp		= lcl_hitm_cmp,
  	.entry		= lcl_hitm_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_rmt_hitm = {
0fbe2fe96   Leo Yan   perf c2c: Use mor...
1244
  	.header		= HEADER_SPAN_LOW("RmtHitm"),
97cb486e4   Jiri Olsa   perf c2c report: ...
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
  	.name		= "rmt_hitm",
  	.cmp		= rmt_hitm_cmp,
  	.entry		= rmt_hitm_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_cl_rmt_hitm = {
  	.header		= HEADER_SPAN("----- HITM -----", "Rmt", 1),
  	.name		= "cl_rmt_hitm",
  	.cmp		= rmt_hitm_cmp,
  	.entry		= rmt_hitm_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_cl_lcl_hitm = {
  	.header		= HEADER_SPAN_LOW("Lcl"),
  	.name		= "cl_lcl_hitm",
  	.cmp		= lcl_hitm_cmp,
  	.entry		= lcl_hitm_entry,
  	.width		= 7,
  };
4f28641bd   Leo Yan   perf c2c: Display...
1266
1267
1268
  static struct c2c_dimension dim_tot_stores = {
  	.header		= HEADER_BOTH("Total", "Stores"),
  	.name		= "tot_stores",
0f18896de   Jiri Olsa   perf c2c report: ...
1269
1270
1271
1272
1273
1274
  	.cmp		= store_cmp,
  	.entry		= store_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_stores_l1hit = {
4f28641bd   Leo Yan   perf c2c: Display...
1275
  	.header		= HEADER_SPAN("---- Stores ----", "L1Hit", 1),
0f18896de   Jiri Olsa   perf c2c report: ...
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
  	.name		= "stores_l1hit",
  	.cmp		= st_l1hit_cmp,
  	.entry		= st_l1hit_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_stores_l1miss = {
  	.header		= HEADER_SPAN_LOW("L1Miss"),
  	.name		= "stores_l1miss",
  	.cmp		= st_l1miss_cmp,
  	.entry		= st_l1miss_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_cl_stores_l1hit = {
  	.header		= HEADER_SPAN("-- Store Refs --", "L1 Hit", 1),
  	.name		= "cl_stores_l1hit",
  	.cmp		= st_l1hit_cmp,
  	.entry		= st_l1hit_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_cl_stores_l1miss = {
  	.header		= HEADER_SPAN_LOW("L1 Miss"),
  	.name		= "cl_stores_l1miss",
  	.cmp		= st_l1miss_cmp,
  	.entry		= st_l1miss_entry,
  	.width		= 7,
  };
1295f6854   Jiri Olsa   perf c2c report: ...
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
  static struct c2c_dimension dim_ld_fbhit = {
  	.header		= HEADER_SPAN("----- Core Load Hit -----", "FB", 2),
  	.name		= "ld_fbhit",
  	.cmp		= ld_fbhit_cmp,
  	.entry		= ld_fbhit_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_ld_l1hit = {
  	.header		= HEADER_SPAN_LOW("L1"),
  	.name		= "ld_l1hit",
  	.cmp		= ld_l1hit_cmp,
  	.entry		= ld_l1hit_entry,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_ld_l2hit = {
  	.header		= HEADER_SPAN_LOW("L2"),
  	.name		= "ld_l2hit",
  	.cmp		= ld_l2hit_cmp,
  	.entry		= ld_l2hit_entry,
  	.width		= 7,
  };
4d08910c9   Jiri Olsa   perf c2c report: ...
1328
  static struct c2c_dimension dim_ld_llchit = {
77c158698   Leo Yan   perf c2c: Correct...
1329
  	.header		= HEADER_SPAN("- LLC Load Hit --", "LclHit", 1),
4d08910c9   Jiri Olsa   perf c2c report: ...
1330
1331
1332
1333
1334
1335
1336
  	.name		= "ld_lclhit",
  	.cmp		= ld_llchit_cmp,
  	.entry		= ld_llchit_entry,
  	.width		= 8,
  };
  
  static struct c2c_dimension dim_ld_rmthit = {
91d933c22   Leo Yan   perf c2c: Add met...
1337
  	.header		= HEADER_SPAN("- RMT Load Hit --", "RmtHit", 1),
4d08910c9   Jiri Olsa   perf c2c report: ...
1338
1339
1340
1341
1342
  	.name		= "ld_rmthit",
  	.cmp		= rmt_hit_cmp,
  	.entry		= rmt_hit_entry,
  	.width		= 8,
  };
01b84d769   Jiri Olsa   perf c2c report: ...
1343
1344
1345
1346
1347
1348
1349
  static struct c2c_dimension dim_tot_recs = {
  	.header		= HEADER_BOTH("Total", "records"),
  	.name		= "tot_recs",
  	.cmp		= tot_recs_cmp,
  	.entry		= tot_recs_entry,
  	.width		= 7,
  };
55177c4ea   Jiri Olsa   perf c2c report: ...
1350
1351
1352
1353
1354
1355
1356
  static struct c2c_dimension dim_tot_loads = {
  	.header		= HEADER_BOTH("Total", "Loads"),
  	.name		= "tot_loads",
  	.cmp		= tot_loads_cmp,
  	.entry		= tot_loads_entry,
  	.width		= 7,
  };
55b957767   Jiri Olsa   perf c2c report: ...
1357
1358
1359
  static struct c2c_header percent_hitm_header[] = {
  	[DISPLAY_LCL] = HEADER_BOTH("Lcl", "Hitm"),
  	[DISPLAY_RMT] = HEADER_BOTH("Rmt", "Hitm"),
d940baccc   Jiri Olsa   perf c2c report: ...
1360
  	[DISPLAY_TOT] = HEADER_BOTH("Tot", "Hitm"),
55b957767   Jiri Olsa   perf c2c report: ...
1361
  };
f0c50c159   Jiri Olsa   perf c2c report: ...
1362
  static struct c2c_dimension dim_percent_hitm = {
f0c50c159   Jiri Olsa   perf c2c report: ...
1363
1364
1365
1366
1367
1368
  	.name		= "percent_hitm",
  	.cmp		= percent_hitm_cmp,
  	.entry		= percent_hitm_entry,
  	.color		= percent_hitm_color,
  	.width		= 7,
  };
9cb3500af   Jiri Olsa   perf c2c report: ...
1369
  static struct c2c_dimension dim_percent_rmt_hitm = {
0fbe2fe96   Leo Yan   perf c2c: Use mor...
1370
  	.header		= HEADER_SPAN("----- HITM -----", "RmtHitm", 1),
9cb3500af   Jiri Olsa   perf c2c report: ...
1371
1372
1373
1374
1375
1376
1377
1378
  	.name		= "percent_rmt_hitm",
  	.cmp		= percent_rmt_hitm_cmp,
  	.entry		= percent_rmt_hitm_entry,
  	.color		= percent_rmt_hitm_color,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_percent_lcl_hitm = {
0fbe2fe96   Leo Yan   perf c2c: Use mor...
1379
  	.header		= HEADER_SPAN_LOW("LclHitm"),
9cb3500af   Jiri Olsa   perf c2c report: ...
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
  	.name		= "percent_lcl_hitm",
  	.cmp		= percent_lcl_hitm_cmp,
  	.entry		= percent_lcl_hitm_entry,
  	.color		= percent_lcl_hitm_color,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_percent_stores_l1hit = {
  	.header		= HEADER_SPAN("-- Store Refs --", "L1 Hit", 1),
  	.name		= "percent_stores_l1hit",
  	.cmp		= percent_stores_l1hit_cmp,
  	.entry		= percent_stores_l1hit_entry,
  	.color		= percent_stores_l1hit_color,
  	.width		= 7,
  };
  
  static struct c2c_dimension dim_percent_stores_l1miss = {
  	.header		= HEADER_SPAN_LOW("L1 Miss"),
  	.name		= "percent_stores_l1miss",
  	.cmp		= percent_stores_l1miss_cmp,
  	.entry		= percent_stores_l1miss_entry,
  	.color		= percent_stores_l1miss_color,
  	.width		= 7,
  };
6c70f54cf   Jiri Olsa   perf c2c report: ...
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
  static struct c2c_dimension dim_dram_lcl = {
  	.header		= HEADER_SPAN("--- Load Dram ----", "Lcl", 1),
  	.name		= "dram_lcl",
  	.cmp		= lcl_dram_cmp,
  	.entry		= lcl_dram_entry,
  	.width		= 8,
  };
  
  static struct c2c_dimension dim_dram_rmt = {
  	.header		= HEADER_SPAN_LOW("Rmt"),
  	.name		= "dram_rmt",
  	.cmp		= rmt_dram_cmp,
  	.entry		= rmt_dram_entry,
  	.width		= 8,
  };
36d3deb9d   Jiri Olsa   perf c2c report: ...
1419
1420
1421
1422
1423
1424
1425
  static struct c2c_dimension dim_pid = {
  	.header		= HEADER_LOW("Pid"),
  	.name		= "pid",
  	.cmp		= pid_cmp,
  	.entry		= pid_entry,
  	.width		= 7,
  };
e87019c5e   Jiri Olsa   perf c2c report: ...
1426
1427
1428
1429
1430
  static struct c2c_dimension dim_tid = {
  	.header		= HEADER_LOW("Tid"),
  	.name		= "tid",
  	.se		= &sort_thread,
  };
51dedaa44   Jiri Olsa   perf c2c report: ...
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
  static struct c2c_dimension dim_symbol = {
  	.name		= "symbol",
  	.se		= &sort_sym,
  };
  
  static struct c2c_dimension dim_dso = {
  	.header		= HEADER_BOTH("Shared", "Object"),
  	.name		= "dso",
  	.se		= &sort_dso,
  };
1e181b92a   Jiri Olsa   perf c2c report: ...
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
  static struct c2c_header header_node[3] = {
  	HEADER_LOW("Node"),
  	HEADER_LOW("Node{cpus %hitms %stores}"),
  	HEADER_LOW("Node{cpu list}"),
  };
  
  static struct c2c_dimension dim_node = {
  	.name		= "node",
  	.cmp		= empty_cmp,
  	.entry		= node_entry,
  	.width		= 4,
  };
92062d543   Jiri Olsa   perf c2c report: ...
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
  static struct c2c_dimension dim_mean_rmt = {
  	.header		= HEADER_SPAN("---------- cycles ----------", "rmt hitm", 2),
  	.name		= "mean_rmt",
  	.cmp		= empty_cmp,
  	.entry		= mean_rmt_entry,
  	.width		= 8,
  };
  
  static struct c2c_dimension dim_mean_lcl = {
  	.header		= HEADER_SPAN_LOW("lcl hitm"),
  	.name		= "mean_lcl",
  	.cmp		= empty_cmp,
  	.entry		= mean_lcl_entry,
  	.width		= 8,
  };
  
  static struct c2c_dimension dim_mean_load = {
  	.header		= HEADER_SPAN_LOW("load"),
  	.name		= "mean_load",
  	.cmp		= empty_cmp,
  	.entry		= mean_load_entry,
  	.width		= 8,
  };
b6fe2bbc3   Jiri Olsa   perf c2c report: ...
1476
1477
1478
1479
1480
1481
1482
  static struct c2c_dimension dim_cpucnt = {
  	.header		= HEADER_BOTH("cpu", "cnt"),
  	.name		= "cpucnt",
  	.cmp		= empty_cmp,
  	.entry		= cpucnt_entry,
  	.width		= 8,
  };
89d9ba8f5   Jiri Olsa   perf c2c report: ...
1483
1484
1485
1486
  static struct c2c_dimension dim_srcline = {
  	.name		= "cl_srcline",
  	.se		= &sort_srcline,
  };
bb342daed   Jiri Olsa   perf c2c report: ...
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
  static struct c2c_dimension dim_dcacheline_idx = {
  	.header		= HEADER_LOW("Index"),
  	.name		= "cl_idx",
  	.cmp		= empty_cmp,
  	.entry		= cl_idx_entry,
  	.width		= 5,
  };
  
  static struct c2c_dimension dim_dcacheline_num = {
  	.header		= HEADER_LOW("Num"),
  	.name		= "cl_num",
  	.cmp		= empty_cmp,
  	.entry		= cl_idx_entry,
  	.width		= 5,
  };
  
  static struct c2c_dimension dim_dcacheline_num_empty = {
  	.header		= HEADER_LOW("Num"),
  	.name		= "cl_num_empty",
  	.cmp		= empty_cmp,
  	.entry		= cl_idx_empty_entry,
  	.width		= 5,
  };
c75540e31   Jiri Olsa   perf c2c report: ...
1510
  static struct c2c_dimension *dimensions[] = {
cbb88500a   Jiri Olsa   perf c2c report: ...
1511
  	&dim_dcacheline,
7f834c2e8   Jiri Olsa   perf c2c report: ...
1512
  	&dim_dcacheline_node,
03d9fcb70   Jiri Olsa   perf c2c report: ...
1513
  	&dim_dcacheline_count,
48acdebdc   Jiri Olsa   perf c2c report: ...
1514
  	&dim_offset,
7f834c2e8   Jiri Olsa   perf c2c report: ...
1515
  	&dim_offset_node,
43575a952   Jiri Olsa   perf c2c report: ...
1516
  	&dim_iaddr,
97cb486e4   Jiri Olsa   perf c2c report: ...
1517
1518
1519
1520
1521
  	&dim_tot_hitm,
  	&dim_lcl_hitm,
  	&dim_rmt_hitm,
  	&dim_cl_lcl_hitm,
  	&dim_cl_rmt_hitm,
4f28641bd   Leo Yan   perf c2c: Display...
1522
  	&dim_tot_stores,
0f18896de   Jiri Olsa   perf c2c report: ...
1523
1524
1525
1526
  	&dim_stores_l1hit,
  	&dim_stores_l1miss,
  	&dim_cl_stores_l1hit,
  	&dim_cl_stores_l1miss,
1295f6854   Jiri Olsa   perf c2c report: ...
1527
1528
1529
  	&dim_ld_fbhit,
  	&dim_ld_l1hit,
  	&dim_ld_l2hit,
4d08910c9   Jiri Olsa   perf c2c report: ...
1530
1531
  	&dim_ld_llchit,
  	&dim_ld_rmthit,
01b84d769   Jiri Olsa   perf c2c report: ...
1532
  	&dim_tot_recs,
55177c4ea   Jiri Olsa   perf c2c report: ...
1533
  	&dim_tot_loads,
f0c50c159   Jiri Olsa   perf c2c report: ...
1534
  	&dim_percent_hitm,
9cb3500af   Jiri Olsa   perf c2c report: ...
1535
1536
1537
1538
  	&dim_percent_rmt_hitm,
  	&dim_percent_lcl_hitm,
  	&dim_percent_stores_l1hit,
  	&dim_percent_stores_l1miss,
6c70f54cf   Jiri Olsa   perf c2c report: ...
1539
1540
  	&dim_dram_lcl,
  	&dim_dram_rmt,
36d3deb9d   Jiri Olsa   perf c2c report: ...
1541
  	&dim_pid,
e87019c5e   Jiri Olsa   perf c2c report: ...
1542
  	&dim_tid,
51dedaa44   Jiri Olsa   perf c2c report: ...
1543
1544
  	&dim_symbol,
  	&dim_dso,
1e181b92a   Jiri Olsa   perf c2c report: ...
1545
  	&dim_node,
92062d543   Jiri Olsa   perf c2c report: ...
1546
1547
1548
  	&dim_mean_rmt,
  	&dim_mean_lcl,
  	&dim_mean_load,
b6fe2bbc3   Jiri Olsa   perf c2c report: ...
1549
  	&dim_cpucnt,
89d9ba8f5   Jiri Olsa   perf c2c report: ...
1550
  	&dim_srcline,
bb342daed   Jiri Olsa   perf c2c report: ...
1551
1552
1553
  	&dim_dcacheline_idx,
  	&dim_dcacheline_num,
  	&dim_dcacheline_num_empty,
c75540e31   Jiri Olsa   perf c2c report: ...
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
  	NULL,
  };
  
  static void fmt_free(struct perf_hpp_fmt *fmt)
  {
  	struct c2c_fmt *c2c_fmt;
  
  	c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
  	free(c2c_fmt);
  }
  
  static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
  {
  	struct c2c_fmt *c2c_a = container_of(a, struct c2c_fmt, fmt);
  	struct c2c_fmt *c2c_b = container_of(b, struct c2c_fmt, fmt);
  
  	return c2c_a->dim == c2c_b->dim;
  }
  
  static struct c2c_dimension *get_dimension(const char *name)
  {
  	unsigned int i;
  
  	for (i = 0; dimensions[i]; i++) {
  		struct c2c_dimension *dim = dimensions[i];
  
  		if (!strcmp(dim->name, name))
  			return dim;
2cca512ad   Zou Wei   perf c2c: Remove ...
1582
  	}
c75540e31   Jiri Olsa   perf c2c report: ...
1583
1584
1585
  
  	return NULL;
  }
8d3f938dc   Jiri Olsa   perf c2c report: ...
1586
1587
1588
1589
1590
1591
  static int c2c_se_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
  			struct hist_entry *he)
  {
  	struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
  	struct c2c_dimension *dim = c2c_fmt->dim;
  	size_t len = fmt->user_len;
590b6a3ac   Jiri Olsa   perf c2c report: ...
1592
  	if (!len) {
8d3f938dc   Jiri Olsa   perf c2c report: ...
1593
  		len = hists__col_len(he->hists, dim->se->se_width_idx);
590b6a3ac   Jiri Olsa   perf c2c report: ...
1594
1595
1596
  		if (dim == &dim_symbol || dim == &dim_srcline)
  			len = symbol_width(he->hists, dim->se);
  	}
8d3f938dc   Jiri Olsa   perf c2c report: ...
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
  	return dim->se->se_snprintf(he, hpp->buf, hpp->size, len);
  }
  
  static int64_t c2c_se_cmp(struct perf_hpp_fmt *fmt,
  			  struct hist_entry *a, struct hist_entry *b)
  {
  	struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
  	struct c2c_dimension *dim = c2c_fmt->dim;
  
  	return dim->se->se_cmp(a, b);
  }
  
  static int64_t c2c_se_collapse(struct perf_hpp_fmt *fmt,
  			       struct hist_entry *a, struct hist_entry *b)
  {
  	struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
  	struct c2c_dimension *dim = c2c_fmt->dim;
  	int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *);
  
  	collapse_fn = dim->se->se_collapse ?: dim->se->se_cmp;
  	return collapse_fn(a, b);
  }
c75540e31   Jiri Olsa   perf c2c report: ...
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
  static struct c2c_fmt *get_format(const char *name)
  {
  	struct c2c_dimension *dim = get_dimension(name);
  	struct c2c_fmt *c2c_fmt;
  	struct perf_hpp_fmt *fmt;
  
  	if (!dim)
  		return NULL;
  
  	c2c_fmt = zalloc(sizeof(*c2c_fmt));
  	if (!c2c_fmt)
  		return NULL;
  
  	c2c_fmt->dim = dim;
  
  	fmt = &c2c_fmt->fmt;
  	INIT_LIST_HEAD(&fmt->list);
  	INIT_LIST_HEAD(&fmt->sort_list);
8d3f938dc   Jiri Olsa   perf c2c report: ...
1637
1638
  	fmt->cmp	= dim->se ? c2c_se_cmp   : dim->cmp;
  	fmt->sort	= dim->se ? c2c_se_cmp   : dim->cmp;
9cb3500af   Jiri Olsa   perf c2c report: ...
1639
  	fmt->color	= dim->se ? NULL	 : dim->color;
8d3f938dc   Jiri Olsa   perf c2c report: ...
1640
  	fmt->entry	= dim->se ? c2c_se_entry : dim->entry;
c75540e31   Jiri Olsa   perf c2c report: ...
1641
1642
  	fmt->header	= c2c_header;
  	fmt->width	= c2c_width;
8d3f938dc   Jiri Olsa   perf c2c report: ...
1643
  	fmt->collapse	= dim->se ? c2c_se_collapse : dim->cmp;
c75540e31   Jiri Olsa   perf c2c report: ...
1644
1645
1646
1647
1648
1649
1650
1651
1652
  	fmt->equal	= fmt_equal;
  	fmt->free	= fmt_free;
  
  	return c2c_fmt;
  }
  
  static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
  {
  	struct c2c_fmt *c2c_fmt = get_format(name);
5f2eca833   Jiri Olsa   perf c2c report: ...
1653
1654
1655
1656
  	if (!c2c_fmt) {
  		reset_dimensions();
  		return output_field_add(hpp_list, name);
  	}
c75540e31   Jiri Olsa   perf c2c report: ...
1657
1658
1659
1660
1661
1662
1663
1664
  
  	perf_hpp_list__column_register(hpp_list, &c2c_fmt->fmt);
  	return 0;
  }
  
  static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
  {
  	struct c2c_fmt *c2c_fmt = get_format(name);
51dedaa44   Jiri Olsa   perf c2c report: ...
1665
  	struct c2c_dimension *dim;
c75540e31   Jiri Olsa   perf c2c report: ...
1666

5f2eca833   Jiri Olsa   perf c2c report: ...
1667
1668
1669
1670
  	if (!c2c_fmt) {
  		reset_dimensions();
  		return sort_dimension__add(hpp_list, name, NULL, 0);
  	}
c75540e31   Jiri Olsa   perf c2c report: ...
1671

51dedaa44   Jiri Olsa   perf c2c report: ...
1672
1673
1674
  	dim = c2c_fmt->dim;
  	if (dim == &dim_dso)
  		hpp_list->dso = 1;
c75540e31   Jiri Olsa   perf c2c report: ...
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
  	perf_hpp_list__register_sort_field(hpp_list, &c2c_fmt->fmt);
  	return 0;
  }
  
  #define PARSE_LIST(_list, _fn)							\
  	do {									\
  		char *tmp, *tok;						\
  		ret = 0;							\
  										\
  		if (!_list)							\
  			break;							\
  										\
  		for (tok = strtok_r((char *)_list, ", ", &tmp);			\
  				tok; tok = strtok_r(NULL, ", ", &tmp)) {	\
  			ret = _fn(hpp_list, tok);				\
  			if (ret == -EINVAL) {					\
62d94b00f   Arnaldo Carvalho de Melo   perf tools: Repla...
1691
  				pr_err("Invalid --fields key: `%s'", tok);	\
c75540e31   Jiri Olsa   perf c2c report: ...
1692
1693
  				break;						\
  			} else if (ret == -ESRCH) {				\
62d94b00f   Arnaldo Carvalho de Melo   perf tools: Repla...
1694
  				pr_err("Unknown --fields key: `%s'", tok);	\
c75540e31   Jiri Olsa   perf c2c report: ...
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
  				break;						\
  			}							\
  		}								\
  	} while (0)
  
  static int hpp_list__parse(struct perf_hpp_list *hpp_list,
  			   const char *output_,
  			   const char *sort_)
  {
  	char *output = output_ ? strdup(output_) : NULL;
  	char *sort   = sort_   ? strdup(sort_) : NULL;
  	int ret;
  
  	PARSE_LIST(output, c2c_hists__init_output);
  	PARSE_LIST(sort,   c2c_hists__init_sort);
  
  	/* copy sort keys to output fields */
  	perf_hpp__setup_output_field(hpp_list);
  
  	/*
  	 * We dont need other sorting keys other than those
  	 * we already specified. It also really slows down
  	 * the processing a lot with big number of output
  	 * fields, so switching this off for c2c.
  	 */
  
  #if 0
  	/* and then copy output fields to sort keys */
  	perf_hpp__append_sort_keys(&hists->list);
  #endif
  
  	free(output);
  	free(sort);
  	return ret;
  }
  
  static int c2c_hists__init(struct c2c_hists *hists,
1d62fcd69   Jiri Olsa   perf c2c report: ...
1732
1733
  			   const char *sort,
  			   int nr_header_lines)
c75540e31   Jiri Olsa   perf c2c report: ...
1734
1735
1736
1737
1738
1739
1740
1741
1742
  {
  	__hists__init(&hists->hists, &hists->list);
  
  	/*
  	 * Initialize only with sort fields, we need to resort
  	 * later anyway, and that's where we add output fields
  	 * as well.
  	 */
  	perf_hpp_list__init(&hists->list);
1d62fcd69   Jiri Olsa   perf c2c report: ...
1743
1744
  	/* Overload number of header lines.*/
  	hists->list.nr_header_lines = nr_header_lines;
c75540e31   Jiri Olsa   perf c2c report: ...
1745
1746
  	return hpp_list__parse(&hists->list, NULL, sort);
  }
c75540e31   Jiri Olsa   perf c2c report: ...
1747
1748
1749
1750
1751
1752
1753
  static int c2c_hists__reinit(struct c2c_hists *c2c_hists,
  			     const char *output,
  			     const char *sort)
  {
  	perf_hpp__reset_output_field(&c2c_hists->list);
  	return hpp_list__parse(&c2c_hists->list, output, sort);
  }
c4a75bb94   Jiri Olsa   perf c2c: Increas...
1754
  #define DISPLAY_LINE_LIMIT  0.001
9857b7173   Jiri Olsa   perf c2c report: ...
1755
1756
1757
1758
1759
  
  static bool he__display(struct hist_entry *he, struct c2c_stats *stats)
  {
  	struct c2c_hist_entry *c2c_he;
  	double ld_dist;
af09b2d35   Jiri Olsa   perf c2c report: ...
1760
1761
  	if (c2c.show_all)
  		return true;
9857b7173   Jiri Olsa   perf c2c report: ...
1762
1763
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
55b957767   Jiri Olsa   perf c2c report: ...
1764
1765
1766
1767
1768
1769
1770
  #define FILTER_HITM(__h)						\
  	if (stats->__h) {						\
  		ld_dist = ((double)c2c_he->stats.__h / stats->__h);	\
  		if (ld_dist < DISPLAY_LINE_LIMIT)			\
  			he->filtered = HIST_FILTER__C2C;		\
  	} else {							\
  		he->filtered = HIST_FILTER__C2C;			\
9857b7173   Jiri Olsa   perf c2c report: ...
1771
  	}
55b957767   Jiri Olsa   perf c2c report: ...
1772
1773
1774
1775
1776
1777
  	switch (c2c.display) {
  	case DISPLAY_LCL:
  		FILTER_HITM(lcl_hitm);
  		break;
  	case DISPLAY_RMT:
  		FILTER_HITM(rmt_hitm);
d940baccc   Jiri Olsa   perf c2c report: ...
1778
1779
1780
  		break;
  	case DISPLAY_TOT:
  		FILTER_HITM(tot_hitm);
55b957767   Jiri Olsa   perf c2c report: ...
1781
1782
  	default:
  		break;
2cca512ad   Zou Wei   perf c2c: Remove ...
1783
  	}
55b957767   Jiri Olsa   perf c2c report: ...
1784
1785
  
  #undef FILTER_HITM
9857b7173   Jiri Olsa   perf c2c report: ...
1786
1787
1788
1789
1790
1791
  	return he->filtered == 0;
  }
  
  static inline int valid_hitm_or_store(struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
55b957767   Jiri Olsa   perf c2c report: ...
1792
  	bool has_hitm;
9857b7173   Jiri Olsa   perf c2c report: ...
1793
1794
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
d940baccc   Jiri Olsa   perf c2c report: ...
1795
1796
1797
  	has_hitm = c2c.display == DISPLAY_TOT ? c2c_he->stats.tot_hitm :
  		   c2c.display == DISPLAY_LCL ? c2c_he->stats.lcl_hitm :
  						c2c_he->stats.rmt_hitm;
55b957767   Jiri Olsa   perf c2c report: ...
1798
  	return has_hitm || c2c_he->stats.store;
9857b7173   Jiri Olsa   perf c2c report: ...
1799
  }
7f834c2e8   Jiri Olsa   perf c2c report: ...
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
  static void set_node_width(struct c2c_hist_entry *c2c_he, int len)
  {
  	struct c2c_dimension *dim;
  
  	dim = &c2c.hists == c2c_he->hists ?
  	      &dim_dcacheline_node : &dim_offset_node;
  
  	if (len > dim->width)
  		dim->width = len;
  }
  
  static int set_nodestr(struct c2c_hist_entry *c2c_he)
  {
  	char buf[30];
  	int len;
  
  	if (c2c_he->nodestr)
  		return 0;
  
  	if (bitmap_weight(c2c_he->nodeset, c2c.nodes_cnt)) {
  		len = bitmap_scnprintf(c2c_he->nodeset, c2c.nodes_cnt,
  				      buf, sizeof(buf));
  	} else {
  		len = scnprintf(buf, sizeof(buf), "N/A");
  	}
  
  	set_node_width(c2c_he, len);
  	c2c_he->nodestr = strdup(buf);
  	return c2c_he->nodestr ? 0 : -ENOMEM;
  }
377313882   Jiri Olsa   perf c2c report: ...
1830
  static void calc_width(struct c2c_hist_entry *c2c_he)
25aa84e32   Jiri Olsa   perf c2c report: ...
1831
1832
  {
  	struct c2c_hists *c2c_hists;
377313882   Jiri Olsa   perf c2c report: ...
1833
1834
  	c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists);
  	hists__calc_col_len(&c2c_hists->hists, &c2c_he->he);
7f834c2e8   Jiri Olsa   perf c2c report: ...
1835
  	set_nodestr(c2c_he);
25aa84e32   Jiri Olsa   perf c2c report: ...
1836
  }
e4c38fd4a   Jiri Olsa   perf hists: Add a...
1837
  static int filter_cb(struct hist_entry *he, void *arg __maybe_unused)
ec06f9b9b   Jiri Olsa   perf c2c report: ...
1838
  {
377313882   Jiri Olsa   perf c2c report: ...
1839
1840
1841
  	struct c2c_hist_entry *c2c_he;
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
89d9ba8f5   Jiri Olsa   perf c2c report: ...
1842
  	if (c2c.show_src && !he->srcline)
6a53da05c   Arnaldo Carvalho de Melo   perf srcline: Mak...
1843
  		he->srcline = hist_entry__srcline(he);
89d9ba8f5   Jiri Olsa   perf c2c report: ...
1844

377313882   Jiri Olsa   perf c2c report: ...
1845
  	calc_width(c2c_he);
25aa84e32   Jiri Olsa   perf c2c report: ...
1846

9857b7173   Jiri Olsa   perf c2c report: ...
1847
1848
  	if (!valid_hitm_or_store(he))
  		he->filtered = HIST_FILTER__C2C;
ec06f9b9b   Jiri Olsa   perf c2c report: ...
1849
1850
  	return 0;
  }
e4c38fd4a   Jiri Olsa   perf hists: Add a...
1851
  static int resort_cl_cb(struct hist_entry *he, void *arg __maybe_unused)
ec06f9b9b   Jiri Olsa   perf c2c report: ...
1852
1853
1854
  {
  	struct c2c_hist_entry *c2c_he;
  	struct c2c_hists *c2c_hists;
9857b7173   Jiri Olsa   perf c2c report: ...
1855
  	bool display = he__display(he, &c2c.hitm_stats);
ec06f9b9b   Jiri Olsa   perf c2c report: ...
1856
1857
1858
  
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	c2c_hists = c2c_he->hists;
9857b7173   Jiri Olsa   perf c2c report: ...
1859
  	if (display && c2c_hists) {
bb342daed   Jiri Olsa   perf c2c report: ...
1860
1861
1862
  		static unsigned int idx;
  
  		c2c_he->cacheline_idx = idx++;
bc229c21f   Jiri Olsa   perf c2c report: ...
1863
  		calc_width(c2c_he);
bb342daed   Jiri Olsa   perf c2c report: ...
1864

fc9c630e8   Jiri Olsa   perf c2c report: ...
1865
  		c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort);
22dd59d14   Jiri Olsa   perf c2c report: ...
1866

ec06f9b9b   Jiri Olsa   perf c2c report: ...
1867
1868
1869
1870
1871
1872
  		hists__collapse_resort(&c2c_hists->hists, NULL);
  		hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb);
  	}
  
  	return 0;
  }
1e181b92a   Jiri Olsa   perf c2c report: ...
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
  static void setup_nodes_header(void)
  {
  	dim_node.header = header_node[c2c.node_info];
  }
  
  static int setup_nodes(struct perf_session *session)
  {
  	struct numa_node *n;
  	unsigned long **nodes;
  	int node, cpu;
  	int *cpu2node;
  
  	if (c2c.node_info > 2)
  		c2c.node_info = 2;
  
  	c2c.nodes_cnt = session->header.env.nr_numa_nodes;
1ea770f6c   Ravi Bangoria   perf c2c: Fix rep...
1889
  	c2c.cpus_cnt  = session->header.env.nr_cpus_avail;
1e181b92a   Jiri Olsa   perf c2c report: ...
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
  
  	n = session->header.env.numa_nodes;
  	if (!n)
  		return -EINVAL;
  
  	nodes = zalloc(sizeof(unsigned long *) * c2c.nodes_cnt);
  	if (!nodes)
  		return -ENOMEM;
  
  	c2c.nodes = nodes;
  
  	cpu2node = zalloc(sizeof(int) * c2c.cpus_cnt);
  	if (!cpu2node)
  		return -ENOMEM;
  
  	for (cpu = 0; cpu < c2c.cpus_cnt; cpu++)
  		cpu2node[cpu] = -1;
  
  	c2c.cpu2node = cpu2node;
  
  	for (node = 0; node < c2c.nodes_cnt; node++) {
f854839ba   Jiri Olsa   perf cpu_map: Ren...
1911
  		struct perf_cpu_map *map = n[node].map;
1e181b92a   Jiri Olsa   perf c2c report: ...
1912
1913
1914
1915
1916
  		unsigned long *set;
  
  		set = bitmap_alloc(c2c.cpus_cnt);
  		if (!set)
  			return -ENOMEM;
e34c94024   Jiri Olsa   perf c2c: Fix c2c...
1917
1918
1919
  		nodes[node] = set;
  
  		/* empty node, skip */
315c0a1f0   Jiri Olsa   libperf: Move per...
1920
  		if (perf_cpu_map__empty(map))
e34c94024   Jiri Olsa   perf c2c: Fix c2c...
1921
  			continue;
1e181b92a   Jiri Olsa   perf c2c report: ...
1922
1923
1924
1925
1926
1927
1928
1929
  		for (cpu = 0; cpu < map->nr; cpu++) {
  			set_bit(map->map[cpu], set);
  
  			if (WARN_ONCE(cpu2node[map->map[cpu]] != -1, "node/cpu topology bug"))
  				return -EINVAL;
  
  			cpu2node[map->map[cpu]] = node;
  		}
1e181b92a   Jiri Olsa   perf c2c report: ...
1930
1931
1932
1933
1934
  	}
  
  	setup_nodes_header();
  	return 0;
  }
7ef2efaab   Jiri Olsa   perf c2c report: ...
1935
  #define HAS_HITMS(__h) ((__h)->stats.lcl_hitm || (__h)->stats.rmt_hitm)
e4c38fd4a   Jiri Olsa   perf hists: Add a...
1936
  static int resort_hitm_cb(struct hist_entry *he, void *arg __maybe_unused)
7ef2efaab   Jiri Olsa   perf c2c report: ...
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
  {
  	struct c2c_hist_entry *c2c_he;
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  
  	if (HAS_HITMS(c2c_he)) {
  		c2c.shared_clines++;
  		c2c_add_stats(&c2c.hitm_stats, &c2c_he->stats);
  	}
  
  	return 0;
  }
  
  static int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb)
  {
2eb3d6894   Davidlohr Bueso   perf hist: Use ca...
1951
  	struct rb_node *next = rb_first_cached(&hists->entries);
7ef2efaab   Jiri Olsa   perf c2c report: ...
1952
1953
1954
1955
1956
1957
  	int ret = 0;
  
  	while (next) {
  		struct hist_entry *he;
  
  		he = rb_entry(next, struct hist_entry, rb_node);
e4c38fd4a   Jiri Olsa   perf hists: Add a...
1958
  		ret = cb(he, NULL);
7ef2efaab   Jiri Olsa   perf c2c report: ...
1959
1960
1961
1962
1963
1964
1965
  		if (ret)
  			break;
  		next = rb_next(&he->rb_node);
  	}
  
  	return ret;
  }
74c63a25f   Jiri Olsa   perf c2c report: ...
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
  static void print_c2c__display_stats(FILE *out)
  {
  	int llc_misses;
  	struct c2c_stats *stats = &c2c.hists.stats;
  
  	llc_misses = stats->lcl_dram +
  		     stats->rmt_dram +
  		     stats->rmt_hit +
  		     stats->rmt_hitm;
  
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "            Trace Event Information              
  ");
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "  Total records                     : %10d
  ", stats->nr_entries);
  	fprintf(out, "  Locked Load/Store Operations      : %10d
  ", stats->locks);
  	fprintf(out, "  Load Operations                   : %10d
  ", stats->load);
  	fprintf(out, "  Loads - uncacheable               : %10d
  ", stats->ld_uncache);
  	fprintf(out, "  Loads - IO                        : %10d
  ", stats->ld_io);
  	fprintf(out, "  Loads - Miss                      : %10d
  ", stats->ld_miss);
  	fprintf(out, "  Loads - no mapping                : %10d
  ", stats->ld_noadrs);
  	fprintf(out, "  Load Fill Buffer Hit              : %10d
  ", stats->ld_fbhit);
  	fprintf(out, "  Load L1D hit                      : %10d
  ", stats->ld_l1hit);
  	fprintf(out, "  Load L2D hit                      : %10d
  ", stats->ld_l2hit);
  	fprintf(out, "  Load LLC hit                      : %10d
  ", stats->ld_llchit + stats->lcl_hitm);
  	fprintf(out, "  Load Local HITM                   : %10d
  ", stats->lcl_hitm);
  	fprintf(out, "  Load Remote HITM                  : %10d
  ", stats->rmt_hitm);
  	fprintf(out, "  Load Remote HIT                   : %10d
  ", stats->rmt_hit);
  	fprintf(out, "  Load Local DRAM                   : %10d
  ", stats->lcl_dram);
  	fprintf(out, "  Load Remote DRAM                  : %10d
  ", stats->rmt_dram);
  	fprintf(out, "  Load MESI State Exclusive         : %10d
  ", stats->ld_excl);
  	fprintf(out, "  Load MESI State Shared            : %10d
  ", stats->ld_shared);
  	fprintf(out, "  Load LLC Misses                   : %10d
  ", llc_misses);
  	fprintf(out, "  LLC Misses to Local DRAM          : %10.1f%%
  ", ((double)stats->lcl_dram/(double)llc_misses) * 100.);
  	fprintf(out, "  LLC Misses to Remote DRAM         : %10.1f%%
  ", ((double)stats->rmt_dram/(double)llc_misses) * 100.);
  	fprintf(out, "  LLC Misses to Remote cache (HIT)  : %10.1f%%
  ", ((double)stats->rmt_hit /(double)llc_misses) * 100.);
  	fprintf(out, "  LLC Misses to Remote cache (HITM) : %10.1f%%
  ", ((double)stats->rmt_hitm/(double)llc_misses) * 100.);
  	fprintf(out, "  Store Operations                  : %10d
  ", stats->store);
  	fprintf(out, "  Store - uncacheable               : %10d
  ", stats->st_uncache);
  	fprintf(out, "  Store - no mapping                : %10d
  ", stats->st_noadrs);
  	fprintf(out, "  Store L1D Hit                     : %10d
  ", stats->st_l1hit);
  	fprintf(out, "  Store L1D Miss                    : %10d
  ", stats->st_l1miss);
  	fprintf(out, "  No Page Map Rejects               : %10d
  ", stats->nomap);
  	fprintf(out, "  Unable to parse data source       : %10d
  ", stats->noparse);
  }
7ef2efaab   Jiri Olsa   perf c2c report: ...
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
  static void print_shared_cacheline_info(FILE *out)
  {
  	struct c2c_stats *stats = &c2c.hitm_stats;
  	int hitm_cnt = stats->lcl_hitm + stats->rmt_hitm;
  
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "    Global Shared Cache Line Event Information   
  ");
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "  Total Shared Cache Lines          : %10d
  ", c2c.shared_clines);
  	fprintf(out, "  Load HITs on shared lines         : %10d
  ", stats->load);
  	fprintf(out, "  Fill Buffer Hits on shared lines  : %10d
  ", stats->ld_fbhit);
  	fprintf(out, "  L1D hits on shared lines          : %10d
  ", stats->ld_l1hit);
  	fprintf(out, "  L2D hits on shared lines          : %10d
  ", stats->ld_l2hit);
  	fprintf(out, "  LLC hits on shared lines          : %10d
  ", stats->ld_llchit + stats->lcl_hitm);
  	fprintf(out, "  Locked Access on shared lines     : %10d
  ", stats->locks);
  	fprintf(out, "  Store HITs on shared lines        : %10d
  ", stats->store);
  	fprintf(out, "  Store L1D hits on shared lines    : %10d
  ", stats->st_l1hit);
  	fprintf(out, "  Total Merged records              : %10d
  ", hitm_cnt + stats->store);
  }
2d388bd0c   Jiri Olsa   perf c2c report: ...
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
  static void print_cacheline(struct c2c_hists *c2c_hists,
  			    struct hist_entry *he_cl,
  			    struct perf_hpp_list *hpp_list,
  			    FILE *out)
  {
  	char bf[1000];
  	struct perf_hpp hpp = {
  		.buf            = bf,
  		.size           = 1000,
  	};
  	static bool once;
  
  	if (!once) {
  		hists__fprintf_headers(&c2c_hists->hists, out);
  		once = true;
  	} else {
  		fprintf(out, "
  ");
  	}
bb342daed   Jiri Olsa   perf c2c report: ...
2094
2095
  	fprintf(out, "  -------------------------------------------------------------
  ");
2d388bd0c   Jiri Olsa   perf c2c report: ...
2096
2097
2098
  	__hist_entry__snprintf(he_cl, &hpp, hpp_list);
  	fprintf(out, "%s
  ", bf);
bb342daed   Jiri Olsa   perf c2c report: ...
2099
2100
  	fprintf(out, "  -------------------------------------------------------------
  ");
2d388bd0c   Jiri Olsa   perf c2c report: ...
2101

e9de7e2f7   Arnaldo Carvalho de Melo   perf hists: Clari...
2102
  	hists__fprintf(&c2c_hists->hists, false, 0, 0, 0, out, false);
2d388bd0c   Jiri Olsa   perf c2c report: ...
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
  }
  
  static void print_pareto(FILE *out)
  {
  	struct perf_hpp_list hpp_list;
  	struct rb_node *nd;
  	int ret;
  
  	perf_hpp_list__init(&hpp_list);
  	ret = hpp_list__parse(&hpp_list,
bb342daed   Jiri Olsa   perf c2c report: ...
2113
  				"cl_num,"
2d388bd0c   Jiri Olsa   perf c2c report: ...
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
  				"cl_rmt_hitm,"
  				"cl_lcl_hitm,"
  				"cl_stores_l1hit,"
  				"cl_stores_l1miss,"
  				"dcacheline",
  				NULL);
  
  	if (WARN_ONCE(ret, "failed to setup sort entries
  "))
  		return;
2eb3d6894   Davidlohr Bueso   perf hist: Use ca...
2124
  	nd = rb_first_cached(&c2c.hists.hists.entries);
2d388bd0c   Jiri Olsa   perf c2c report: ...
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
  
  	for (; nd; nd = rb_next(nd)) {
  		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
  		struct c2c_hist_entry *c2c_he;
  
  		if (he->filtered)
  			continue;
  
  		c2c_he = container_of(he, struct c2c_hist_entry, he);
  		print_cacheline(c2c_he->hists, he, &hpp_list, out);
  	}
  }
2709b97dc   Jiri Olsa   perf c2c report: ...
2137
2138
  static void print_c2c_info(FILE *out, struct perf_session *session)
  {
63503dba8   Jiri Olsa   perf evlist: Rena...
2139
  	struct evlist *evlist = session->evlist;
32dcd021d   Jiri Olsa   perf evsel: Renam...
2140
  	struct evsel *evsel;
2709b97dc   Jiri Olsa   perf c2c report: ...
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
  	bool first = true;
  
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "                 c2c details                     
  ");
  	fprintf(out, "=================================================
  ");
  
  	evlist__for_each_entry(evlist, evsel) {
8ab2e96d8   Arnaldo Carvalho de Melo   perf evsel: Renam...
2151
2152
  		fprintf(out, "%-36s: %s
  ", first ? "  Events" : "", evsel__name(evsel));
2709b97dc   Jiri Olsa   perf c2c report: ...
2153
2154
  		first = false;
  	}
55b957767   Jiri Olsa   perf c2c report: ...
2155
2156
  	fprintf(out, "  Cachelines sort on                : %s HITMs
  ",
d940baccc   Jiri Olsa   perf c2c report: ...
2157
  		display_str[c2c.display]);
fc9c630e8   Jiri Olsa   perf c2c report: ...
2158
2159
  	fprintf(out, "  Cacheline data grouping           : %s
  ", c2c.cl_sort);
2709b97dc   Jiri Olsa   perf c2c report: ...
2160
2161
2162
  }
  
  static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
2d388bd0c   Jiri Olsa   perf c2c report: ...
2163
2164
  {
  	setup_pager();
74c63a25f   Jiri Olsa   perf c2c report: ...
2165
  	print_c2c__display_stats(out);
7ef2efaab   Jiri Olsa   perf c2c report: ...
2166
2167
2168
  	fprintf(out, "
  ");
  	print_shared_cacheline_info(out);
2709b97dc   Jiri Olsa   perf c2c report: ...
2169
2170
2171
  	fprintf(out, "
  ");
  	print_c2c_info(out, session);
74c63a25f   Jiri Olsa   perf c2c report: ...
2172
2173
2174
  
  	if (c2c.stats_only)
  		return;
2d388bd0c   Jiri Olsa   perf c2c report: ...
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
  	fprintf(out, "
  ");
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "           Shared Data Cache Line Table          
  ");
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "#
  ");
e9de7e2f7   Arnaldo Carvalho de Melo   perf hists: Clari...
2185
  	hists__fprintf(&c2c.hists.hists, true, 0, 0, 0, stdout, true);
2d388bd0c   Jiri Olsa   perf c2c report: ...
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
  
  	fprintf(out, "
  ");
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "      Shared Cache Line Distribution Pareto      
  ");
  	fprintf(out, "=================================================
  ");
  	fprintf(out, "#
  ");
  
  	print_pareto(out);
  }
1e181b92a   Jiri Olsa   perf c2c report: ...
2200

5a1a99cd2   Jiri Olsa   perf c2c report: ...
2201
2202
2203
2204
  #ifdef HAVE_SLANG_SUPPORT
  static void c2c_browser__update_nr_entries(struct hist_browser *hb)
  {
  	u64 nr_entries = 0;
2eb3d6894   Davidlohr Bueso   perf hist: Use ca...
2205
  	struct rb_node *nd = rb_first_cached(&hb->hists->entries);
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
  
  	while (nd) {
  		struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
  
  		if (!he->filtered)
  			nr_entries++;
  
  		nd = rb_next(nd);
  	}
  
  	hb->nr_non_filtered_entries = nr_entries;
  }
f1c5fd4d0   Jiri Olsa   perf c2c report: ...
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
  struct c2c_cacheline_browser {
  	struct hist_browser	 hb;
  	struct hist_entry	*he;
  };
  
  static int
  perf_c2c_cacheline_browser__title(struct hist_browser *browser,
  				  char *bf, size_t size)
  {
  	struct c2c_cacheline_browser *cl_browser;
  	struct hist_entry *he;
  	uint64_t addr = 0;
  
  	cl_browser = container_of(browser, struct c2c_cacheline_browser, hb);
  	he = cl_browser->he;
  
  	if (he->mem_info)
  		addr = cl_address(he->mem_info->daddr.addr);
  
  	scnprintf(bf, size, "Cacheline 0x%lx", addr);
  	return 0;
  }
  
  static struct c2c_cacheline_browser*
  c2c_cacheline_browser__new(struct hists *hists, struct hist_entry *he)
  {
  	struct c2c_cacheline_browser *browser;
  
  	browser = zalloc(sizeof(*browser));
  	if (browser) {
  		hist_browser__init(&browser->hb, hists);
  		browser->hb.c2c_filter	= true;
  		browser->hb.title	= perf_c2c_cacheline_browser__title;
  		browser->he		= he;
  	}
  
  	return browser;
  }
  
  static int perf_c2c__browse_cacheline(struct hist_entry *he)
  {
  	struct c2c_hist_entry *c2c_he;
  	struct c2c_hists *c2c_hists;
  	struct c2c_cacheline_browser *cl_browser;
  	struct hist_browser *browser;
  	int key = -1;
49b8e2bec   Rasmus Villemoes   perf tools: Repla...
2264
  	static const char help[] =
239fb4fed   Kim Phillips   perf c2c: Fix spe...
2265
2266
2267
2268
2269
2270
  	" ENTER         Toggle callchains (if present) 
  "
  	" n             Toggle Node details info 
  "
  	" s             Toggle full length of symbol and source line columns 
  "
9a406eb61   Jiri Olsa   perf c2c report: ...
2271
2272
  	" q             Return back to cacheline list 
  ";
739783325   Jiri Olsa   perf c2c report: ...
2273
2274
2275
  
  	if (!he)
  		return 0;
f1c5fd4d0   Jiri Olsa   perf c2c report: ...
2276

590b6a3ac   Jiri Olsa   perf c2c report: ...
2277
2278
  	/* Display compact version first. */
  	c2c.symbol_full = false;
f1c5fd4d0   Jiri Olsa   perf c2c report: ...
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
  	c2c_he = container_of(he, struct c2c_hist_entry, he);
  	c2c_hists = c2c_he->hists;
  
  	cl_browser = c2c_cacheline_browser__new(&c2c_hists->hists, he);
  	if (cl_browser == NULL)
  		return -1;
  
  	browser = &cl_browser->hb;
  
  	/* reset abort key so that it can get Ctrl-C as a key */
  	SLang_reset_tty();
  	SLang_init_tty(0, 0, 0);
  
  	c2c_browser__update_nr_entries(browser);
  
  	while (1) {
d10ec006d   Arnaldo Carvalho de Melo   perf hists browse...
2295
  		key = hist_browser__run(browser, "? - help", true, 0);
f1c5fd4d0   Jiri Olsa   perf c2c report: ...
2296
2297
  
  		switch (key) {
590b6a3ac   Jiri Olsa   perf c2c report: ...
2298
2299
2300
  		case 's':
  			c2c.symbol_full = !c2c.symbol_full;
  			break;
1a56a4253   Jiri Olsa   perf c2c report: ...
2301
2302
2303
2304
  		case 'n':
  			c2c.node_info = (c2c.node_info + 1) % 3;
  			setup_nodes_header();
  			break;
f1c5fd4d0   Jiri Olsa   perf c2c report: ...
2305
2306
  		case 'q':
  			goto out;
9a406eb61   Jiri Olsa   perf c2c report: ...
2307
2308
2309
  		case '?':
  			ui_browser__help_window(&browser->b, help);
  			break;
f1c5fd4d0   Jiri Olsa   perf c2c report: ...
2310
2311
2312
2313
2314
2315
2316
2317
2318
  		default:
  			break;
  		}
  	}
  
  out:
  	free(cl_browser);
  	return 0;
  }
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2319
2320
2321
2322
  static int perf_c2c_browser__title(struct hist_browser *browser,
  				   char *bf, size_t size)
  {
  	scnprintf(bf, size,
55b957767   Jiri Olsa   perf c2c report: ...
2323
2324
2325
  		  "Shared Data Cache Line Table     "
  		  "(%lu entries, sorted on %s HITMs)",
  		  browser->nr_non_filtered_entries,
d940baccc   Jiri Olsa   perf c2c report: ...
2326
  		  display_str[c2c.display]);
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
  	return 0;
  }
  
  static struct hist_browser*
  perf_c2c_browser__new(struct hists *hists)
  {
  	struct hist_browser *browser = hist_browser__new(hists);
  
  	if (browser) {
  		browser->title = perf_c2c_browser__title;
  		browser->c2c_filter = true;
  	}
  
  	return browser;
  }
  
  static int perf_c2c__hists_browse(struct hists *hists)
  {
  	struct hist_browser *browser;
  	int key = -1;
49b8e2bec   Rasmus Villemoes   perf tools: Repla...
2347
  	static const char help[] =
9a406eb61   Jiri Olsa   perf c2c report: ...
2348
2349
  	" d             Display cacheline details 
  "
239fb4fed   Kim Phillips   perf c2c: Fix spe...
2350
2351
  	" ENTER         Toggle callchains (if present) 
  "
9a406eb61   Jiri Olsa   perf c2c report: ...
2352
2353
  	" q             Quit 
  ";
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
  
  	browser = perf_c2c_browser__new(hists);
  	if (browser == NULL)
  		return -1;
  
  	/* reset abort key so that it can get Ctrl-C as a key */
  	SLang_reset_tty();
  	SLang_init_tty(0, 0, 0);
  
  	c2c_browser__update_nr_entries(browser);
  
  	while (1) {
d10ec006d   Arnaldo Carvalho de Melo   perf hists browse...
2366
  		key = hist_browser__run(browser, "? - help", true, 0);
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2367
2368
2369
2370
  
  		switch (key) {
  		case 'q':
  			goto out;
f1c5fd4d0   Jiri Olsa   perf c2c report: ...
2371
2372
2373
  		case 'd':
  			perf_c2c__browse_cacheline(browser->he_selection);
  			break;
9a406eb61   Jiri Olsa   perf c2c report: ...
2374
2375
2376
  		case '?':
  			ui_browser__help_window(&browser->b, help);
  			break;
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2377
2378
2379
2380
2381
2382
2383
2384
2385
  		default:
  			break;
  		}
  	}
  
  out:
  	hist_browser__delete(browser);
  	return 0;
  }
2709b97dc   Jiri Olsa   perf c2c report: ...
2386
  static void perf_c2c_display(struct perf_session *session)
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2387
  {
1936feae5   Namhyung Kim   perf c2c: Fix dis...
2388
  	if (use_browser == 0)
2709b97dc   Jiri Olsa   perf c2c report: ...
2389
  		perf_c2c__hists_fprintf(stdout, session);
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2390
2391
2392
2393
  	else
  		perf_c2c__hists_browse(&c2c.hists.hists);
  }
  #else
2709b97dc   Jiri Olsa   perf c2c report: ...
2394
  static void perf_c2c_display(struct perf_session *session)
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2395
2396
  {
  	use_browser = 0;
2709b97dc   Jiri Olsa   perf c2c report: ...
2397
  	perf_c2c__hists_fprintf(stdout, session);
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2398
2399
  }
  #endif /* HAVE_SLANG_SUPPORT */
d0802b1ee   Jiri Olsa   perf c2c report: ...
2400
  static char *fill_line(const char *orig, int len)
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2401
  {
d0802b1ee   Jiri Olsa   perf c2c report: ...
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
  	int i, j, olen = strlen(orig);
  	char *buf;
  
  	buf = zalloc(len + 1);
  	if (!buf)
  		return NULL;
  
  	j = len / 2 - olen / 2;
  
  	for (i = 0; i < j - 1; i++)
  		buf[i] = '-';
  
  	buf[i++] = ' ';
  
  	strcpy(buf + i, orig);
  
  	i += olen;
  
  	buf[i++] = ' ';
  
  	for (; i < len; i++)
  		buf[i] = '-';
  
  	return buf;
  }
  
  static int ui_quirks(void)
  {
  	const char *nodestr = "Data address";
  	char *buf;
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2432
2433
2434
  	if (!c2c.use_stdio) {
  		dim_offset.width  = 5;
  		dim_offset.header = header_offset_tui;
d0802b1ee   Jiri Olsa   perf c2c report: ...
2435
  		nodestr = "CL";
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2436
  	}
55b957767   Jiri Olsa   perf c2c report: ...
2437
2438
  
  	dim_percent_hitm.header = percent_hitm_header[c2c.display];
d0802b1ee   Jiri Olsa   perf c2c report: ...
2439
2440
2441
  
  	/* Fix the zero line for dcacheline column. */
  	buf = fill_line("Cacheline", dim_dcacheline.width +
03d9fcb70   Jiri Olsa   perf c2c report: ...
2442
2443
  				     dim_dcacheline_node.width +
  				     dim_dcacheline_count.width + 4);
d0802b1ee   Jiri Olsa   perf c2c report: ...
2444
2445
2446
2447
2448
2449
2450
  	if (!buf)
  		return -ENOMEM;
  
  	dim_dcacheline.header.line[0].text = buf;
  
  	/* Fix the zero line for offset column. */
  	buf = fill_line(nodestr, dim_offset.width +
03d9fcb70   Jiri Olsa   perf c2c report: ...
2451
2452
  			         dim_offset_node.width +
  				 dim_dcacheline_count.width + 4);
d0802b1ee   Jiri Olsa   perf c2c report: ...
2453
2454
2455
2456
2457
2458
  	if (!buf)
  		return -ENOMEM;
  
  	dim_offset.header.line[0].text = buf;
  
  	return 0;
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2459
  }
dd805768f   Jiri Olsa   perf c2c report: ...
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
  #define CALLCHAIN_DEFAULT_OPT  "graph,0.5,caller,function,percent"
  
  const char callchain_help[] = "Display call graph (stack chain/backtrace):
  
  "
  				CALLCHAIN_REPORT_HELP
  				"
  \t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT;
  
  static int
  parse_callchain_opt(const struct option *opt, const char *arg, int unset)
  {
  	struct callchain_param *callchain = opt->value;
  
  	callchain->enabled = !unset;
  	/*
  	 * --no-call-graph
  	 */
  	if (unset) {
  		symbol_conf.use_callchain = false;
  		callchain->mode = CHAIN_NONE;
  		return 0;
  	}
  
  	return parse_callchain_report_opt(arg);
  }
63503dba8   Jiri Olsa   perf evlist: Rena...
2486
  static int setup_callchain(struct evlist *evlist)
dd805768f   Jiri Olsa   perf c2c report: ...
2487
  {
b3c2cc2bd   Arnaldo Carvalho de Melo   perf evlist: Fix ...
2488
  	u64 sample_type = evlist__combined_sample_type(evlist);
dd805768f   Jiri Olsa   perf c2c report: ...
2489
2490
2491
  	enum perf_call_graph_mode mode = CALLCHAIN_NONE;
  
  	if ((sample_type & PERF_SAMPLE_REGS_USER) &&
eabad8c68   Arnaldo Carvalho de Melo   perf unwind: Do n...
2492
  	    (sample_type & PERF_SAMPLE_STACK_USER)) {
dd805768f   Jiri Olsa   perf c2c report: ...
2493
  		mode = CALLCHAIN_DWARF;
eabad8c68   Arnaldo Carvalho de Melo   perf unwind: Do n...
2494
2495
  		dwarf_callchain_users = true;
  	} else if (sample_type & PERF_SAMPLE_BRANCH_STACK)
dd805768f   Jiri Olsa   perf c2c report: ...
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
  		mode = CALLCHAIN_LBR;
  	else if (sample_type & PERF_SAMPLE_CALLCHAIN)
  		mode = CALLCHAIN_FP;
  
  	if (!callchain_param.enabled &&
  	    callchain_param.mode != CHAIN_NONE &&
  	    mode != CALLCHAIN_NONE) {
  		symbol_conf.use_callchain = true;
  		if (callchain_register_param(&callchain_param) < 0) {
  			ui__error("Can't register callchain params.
  ");
  			return -EINVAL;
  		}
  	}
d80da766d   Kan Liang   perf c2c: Add opt...
2510
2511
2512
2513
2514
2515
2516
  	if (c2c.stitch_lbr && (mode != CALLCHAIN_LBR)) {
  		ui__warning("Can't find LBR callchain. Switch off --stitch-lbr.
  "
  			    "Please apply --call-graph lbr when recording.
  ");
  		c2c.stitch_lbr = false;
  	}
dd805768f   Jiri Olsa   perf c2c report: ...
2517
2518
2519
2520
  	callchain_param.record_mode = mode;
  	callchain_param.min_percent = 0;
  	return 0;
  }
55b957767   Jiri Olsa   perf c2c report: ...
2521
2522
  static int setup_display(const char *str)
  {
d940baccc   Jiri Olsa   perf c2c report: ...
2523
  	const char *display = str ?: "tot";
55b957767   Jiri Olsa   perf c2c report: ...
2524

d940baccc   Jiri Olsa   perf c2c report: ...
2525
2526
2527
  	if (!strcmp(display, "tot"))
  		c2c.display = DISPLAY_TOT;
  	else if (!strcmp(display, "rmt"))
55b957767   Jiri Olsa   perf c2c report: ...
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
  		c2c.display = DISPLAY_RMT;
  	else if (!strcmp(display, "lcl"))
  		c2c.display = DISPLAY_LCL;
  	else {
  		pr_err("failed: unknown display type: %s
  ", str);
  		return -1;
  	}
  
  	return 0;
  }
fc9c630e8   Jiri Olsa   perf c2c report: ...
2539
2540
2541
  #define for_each_token(__tok, __buf, __sep, __tmp)		\
  	for (__tok = strtok_r(__buf, __sep, &__tmp); __tok;	\
  	     __tok = strtok_r(NULL,  __sep, &__tmp))
18f278d2d   Jiri Olsa   perf c2c report: ...
2542
  static int build_cl_output(char *cl_sort, bool no_source)
fc9c630e8   Jiri Olsa   perf c2c report: ...
2543
2544
2545
2546
2547
2548
2549
2550
  {
  	char *tok, *tmp, *buf = strdup(cl_sort);
  	bool add_pid   = false;
  	bool add_tid   = false;
  	bool add_iaddr = false;
  	bool add_sym   = false;
  	bool add_dso   = false;
  	bool add_src   = false;
ae199c580   Yunfeng Ye   perf c2c: Fix mem...
2551
  	int ret = 0;
fc9c630e8   Jiri Olsa   perf c2c report: ...
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
  
  	if (!buf)
  		return -ENOMEM;
  
  	for_each_token(tok, buf, ",", tmp) {
  		if (!strcmp(tok, "tid")) {
  			add_tid = true;
  		} else if (!strcmp(tok, "pid")) {
  			add_pid = true;
  		} else if (!strcmp(tok, "iaddr")) {
  			add_iaddr = true;
  			add_sym   = true;
  			add_dso   = true;
18f278d2d   Jiri Olsa   perf c2c report: ...
2565
  			add_src   = no_source ? false : true;
fc9c630e8   Jiri Olsa   perf c2c report: ...
2566
2567
2568
2569
2570
  		} else if (!strcmp(tok, "dso")) {
  			add_dso = true;
  		} else if (strcmp(tok, "offset")) {
  			pr_err("unrecognized sort token: %s
  ", tok);
ae199c580   Yunfeng Ye   perf c2c: Fix mem...
2571
2572
  			ret = -EINVAL;
  			goto err;
fc9c630e8   Jiri Olsa   perf c2c report: ...
2573
2574
2575
2576
  		}
  	}
  
  	if (asprintf(&c2c.cl_output,
bb342daed   Jiri Olsa   perf c2c report: ...
2577
2578
  		"%s%s%s%s%s%s%s%s%s%s",
  		c2c.use_stdio ? "cl_num_empty," : "",
fc9c630e8   Jiri Olsa   perf c2c report: ...
2579
2580
2581
2582
  		"percent_rmt_hitm,"
  		"percent_lcl_hitm,"
  		"percent_stores_l1hit,"
  		"percent_stores_l1miss,"
03d9fcb70   Jiri Olsa   perf c2c report: ...
2583
  		"offset,offset_node,dcacheline_count,",
fc9c630e8   Jiri Olsa   perf c2c report: ...
2584
2585
2586
2587
2588
2589
  		add_pid   ? "pid," : "",
  		add_tid   ? "tid," : "",
  		add_iaddr ? "iaddr," : "",
  		"mean_rmt,"
  		"mean_lcl,"
  		"mean_load,"
8763e6ac2   Jiri Olsa   perf c2c report: ...
2590
  		"tot_recs,"
fc9c630e8   Jiri Olsa   perf c2c report: ...
2591
2592
2593
2594
  		"cpucnt,",
  		add_sym ? "symbol," : "",
  		add_dso ? "dso," : "",
  		add_src ? "cl_srcline," : "",
ae199c580   Yunfeng Ye   perf c2c: Fix mem...
2595
2596
2597
2598
  		"node") < 0) {
  		ret = -ENOMEM;
  		goto err;
  	}
fc9c630e8   Jiri Olsa   perf c2c report: ...
2599
2600
  
  	c2c.show_src = add_src;
ae199c580   Yunfeng Ye   perf c2c: Fix mem...
2601
  err:
fc9c630e8   Jiri Olsa   perf c2c report: ...
2602
  	free(buf);
ae199c580   Yunfeng Ye   perf c2c: Fix mem...
2603
  	return ret;
fc9c630e8   Jiri Olsa   perf c2c report: ...
2604
  }
18f278d2d   Jiri Olsa   perf c2c report: ...
2605
  static int setup_coalesce(const char *coalesce, bool no_source)
fc9c630e8   Jiri Olsa   perf c2c report: ...
2606
2607
2608
2609
2610
  {
  	const char *c = coalesce ?: coalesce_default;
  
  	if (asprintf(&c2c.cl_sort, "offset,%s", c) < 0)
  		return -ENOMEM;
18f278d2d   Jiri Olsa   perf c2c report: ...
2611
  	if (build_cl_output(c2c.cl_sort, no_source))
fc9c630e8   Jiri Olsa   perf c2c report: ...
2612
2613
2614
  		return -1;
  
  	if (asprintf(&c2c.cl_resort, "offset,%s",
d940baccc   Jiri Olsa   perf c2c report: ...
2615
2616
  		     c2c.display == DISPLAY_TOT ?
  		     "tot_hitm" :
fc9c630e8   Jiri Olsa   perf c2c report: ...
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
  		     c2c.display == DISPLAY_RMT ?
  		     "rmt_hitm,lcl_hitm" :
  		     "lcl_hitm,rmt_hitm") < 0)
  		return -ENOMEM;
  
  	pr_debug("coalesce sort   fields: %s
  ", c2c.cl_sort);
  	pr_debug("coalesce resort fields: %s
  ", c2c.cl_resort);
  	pr_debug("coalesce output fields: %s
  ", c2c.cl_output);
  	return 0;
  }
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2630
2631
2632
  static int perf_c2c__report(int argc, const char **argv)
  {
  	struct perf_session *session;
78b275437   Jiri Olsa   perf c2c report: ...
2633
  	struct ui_progress prog;
8ceb41d7e   Jiri Olsa   perf tools: Renam...
2634
  	struct perf_data data = {
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2635
2636
  		.mode = PERF_DATA_MODE_READ,
  	};
dd805768f   Jiri Olsa   perf c2c report: ...
2637
  	char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT;
55b957767   Jiri Olsa   perf c2c report: ...
2638
  	const char *display = NULL;
fc9c630e8   Jiri Olsa   perf c2c report: ...
2639
  	const char *coalesce = NULL;
18f278d2d   Jiri Olsa   perf c2c report: ...
2640
  	bool no_source = false;
3a5bfab60   Jiri Olsa   perf c2c: Support...
2641
  	const struct option options[] = {
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2642
2643
  	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
  		   "file", "vmlinux pathname"),
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2644
2645
  	OPT_STRING('i', "input", &input_name, "file",
  		   "the input file to process"),
1e181b92a   Jiri Olsa   perf c2c report: ...
2646
2647
  	OPT_INCR('N', "node-info", &c2c.node_info,
  		 "show extra node info in report (repeat for more info)"),
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2648
2649
2650
  #ifdef HAVE_SLANG_SUPPORT
  	OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"),
  #endif
74c63a25f   Jiri Olsa   perf c2c report: ...
2651
  	OPT_BOOLEAN(0, "stats", &c2c.stats_only,
f75d2895e   Namhyung Kim   perf c2c: Clarify...
2652
  		    "Display only statistic tables (implies --stdio)"),
590b6a3ac   Jiri Olsa   perf c2c report: ...
2653
2654
  	OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full,
  		    "Display full length of symbols"),
18f278d2d   Jiri Olsa   perf c2c report: ...
2655
2656
  	OPT_BOOLEAN(0, "no-source", &no_source,
  		    "Do not display Source Line column"),
af09b2d35   Jiri Olsa   perf c2c report: ...
2657
2658
  	OPT_BOOLEAN(0, "show-all", &c2c.show_all,
  		    "Show all captured HITM lines."),
dd805768f   Jiri Olsa   perf c2c report: ...
2659
2660
2661
2662
  	OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
  			     "print_type,threshold[,print_limit],order,sort_key[,branch],value",
  			     callchain_help, &parse_callchain_opt,
  			     callchain_default_opt),
d940baccc   Jiri Olsa   perf c2c report: ...
2663
  	OPT_STRING('d', "display", &display, "Switch HITM output type", "lcl,rmt"),
fc9c630e8   Jiri Olsa   perf c2c report: ...
2664
2665
  	OPT_STRING('c', "coalesce", &coalesce, "coalesce fields",
  		   "coalesce fields: pid,tid,iaddr,dso"),
b7ac4f9f3   Jiri Olsa   perf c2c report: ...
2666
  	OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"),
d80da766d   Kan Liang   perf c2c: Add opt...
2667
2668
  	OPT_BOOLEAN(0, "stitch-lbr", &c2c.stitch_lbr,
  		    "Enable LBR callgraph stitching approach"),
3a5bfab60   Jiri Olsa   perf c2c: Support...
2669
  	OPT_PARENT(c2c_options),
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2670
2671
2672
  	OPT_END()
  	};
  	int err = 0;
3a5bfab60   Jiri Olsa   perf c2c: Support...
2673
  	argc = parse_options(argc, argv, options, report_c2c_usage,
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2674
  			     PARSE_OPT_STOP_AT_NON_OPTION);
78b275437   Jiri Olsa   perf c2c report: ...
2675
  	if (argc)
3a5bfab60   Jiri Olsa   perf c2c: Support...
2676
  		usage_with_options(report_c2c_usage, options);
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2677

74c63a25f   Jiri Olsa   perf c2c report: ...
2678
2679
  	if (c2c.stats_only)
  		c2c.use_stdio = true;
78b275437   Jiri Olsa   perf c2c report: ...
2680
2681
  	if (!input_name || !strlen(input_name))
  		input_name = "perf.data";
2d4f27999   Jiri Olsa   perf data: Add gl...
2682
2683
  	data.path  = input_name;
  	data.force = symbol_conf.force;
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2684

55b957767   Jiri Olsa   perf c2c report: ...
2685
2686
2687
  	err = setup_display(display);
  	if (err)
  		goto out;
18f278d2d   Jiri Olsa   perf c2c report: ...
2688
  	err = setup_coalesce(coalesce, no_source);
fc9c630e8   Jiri Olsa   perf c2c report: ...
2689
2690
2691
2692
2693
  	if (err) {
  		pr_debug("Failed to initialize hists
  ");
  		goto out;
  	}
1d62fcd69   Jiri Olsa   perf c2c report: ...
2694
  	err = c2c_hists__init(&c2c.hists, "dcacheline", 2);
c75540e31   Jiri Olsa   perf c2c report: ...
2695
2696
2697
2698
2699
  	if (err) {
  		pr_debug("Failed to initialize hists
  ");
  		goto out;
  	}
8ceb41d7e   Jiri Olsa   perf tools: Renam...
2700
  	session = perf_session__new(&data, 0, &c2c.tool);
6ef81c55a   Mamatha Inamdar   perf session: Ret...
2701
2702
2703
2704
  	if (IS_ERR(session)) {
  		err = PTR_ERR(session);
  		pr_debug("Error creating perf session
  ");
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2705
2706
  		goto out;
  	}
e8c5fe101   Jiri Olsa   perf c2c report: ...
2707

1e181b92a   Jiri Olsa   perf c2c report: ...
2708
2709
2710
2711
2712
2713
  	err = setup_nodes(session);
  	if (err) {
  		pr_err("Failed setup nodes
  ");
  		goto out;
  	}
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2714

7f834c2e8   Jiri Olsa   perf c2c report: ...
2715
  	err = mem2node__init(&c2c.mem2node, &session->header.env);
dd805768f   Jiri Olsa   perf c2c report: ...
2716
2717
  	if (err)
  		goto out_session;
7f834c2e8   Jiri Olsa   perf c2c report: ...
2718
2719
2720
  	err = setup_callchain(session->evlist);
  	if (err)
  		goto out_mem2node;
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2721
  	if (symbol__init(&session->header.env) < 0)
7f834c2e8   Jiri Olsa   perf c2c report: ...
2722
  		goto out_mem2node;
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2723
2724
  
  	/* No pipe support at the moment. */
8ceb41d7e   Jiri Olsa   perf tools: Renam...
2725
  	if (perf_data__is_pipe(session->data)) {
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2726
2727
  		pr_debug("No pipe support at the moment.
  ");
7f834c2e8   Jiri Olsa   perf c2c report: ...
2728
  		goto out_mem2node;
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2729
  	}
e8c5fe101   Jiri Olsa   perf c2c report: ...
2730
2731
2732
2733
2734
2735
  	if (c2c.use_stdio)
  		use_browser = 0;
  	else
  		use_browser = 1;
  
  	setup_browser(false);
78b275437   Jiri Olsa   perf c2c report: ...
2736
2737
2738
2739
  	err = perf_session__process_events(session);
  	if (err) {
  		pr_err("failed to process sample
  ");
7f834c2e8   Jiri Olsa   perf c2c report: ...
2740
  		goto out_mem2node;
78b275437   Jiri Olsa   perf c2c report: ...
2741
  	}
22dd59d14   Jiri Olsa   perf c2c report: ...
2742
  	c2c_hists__reinit(&c2c.hists,
bb342daed   Jiri Olsa   perf c2c report: ...
2743
  			"cl_idx,"
22dd59d14   Jiri Olsa   perf c2c report: ...
2744
  			"dcacheline,"
7f834c2e8   Jiri Olsa   perf c2c report: ...
2745
  			"dcacheline_node,"
03d9fcb70   Jiri Olsa   perf c2c report: ...
2746
  			"dcacheline_count,"
22dd59d14   Jiri Olsa   perf c2c report: ...
2747
2748
  			"percent_hitm,"
  			"tot_hitm,lcl_hitm,rmt_hitm,"
b596e979c   Leo Yan   perf c2c: Display...
2749
2750
  			"tot_recs,"
  			"tot_loads,"
4f28641bd   Leo Yan   perf c2c: Display...
2751
2752
  			"tot_stores,"
  			"stores_l1hit,stores_l1miss,"
22dd59d14   Jiri Olsa   perf c2c report: ...
2753
  			"ld_fbhit,ld_l1hit,ld_l2hit,"
77c158698   Leo Yan   perf c2c: Correct...
2754
  			"ld_lclhit,lcl_hitm,"
91d933c22   Leo Yan   perf c2c: Add met...
2755
  			"ld_rmthit,rmt_hitm,"
6d662d730   Leo Yan   perf c2c: Organiz...
2756
  			"dram_lcl,dram_rmt",
d940baccc   Jiri Olsa   perf c2c report: ...
2757
  			c2c.display == DISPLAY_TOT ? "tot_hitm" :
55b957767   Jiri Olsa   perf c2c report: ...
2758
  			c2c.display == DISPLAY_LCL ? "lcl_hitm" : "rmt_hitm"
22dd59d14   Jiri Olsa   perf c2c report: ...
2759
  			);
78b275437   Jiri Olsa   perf c2c report: ...
2760
2761
2762
  	ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting...");
  
  	hists__collapse_resort(&c2c.hists.hists, NULL);
7ef2efaab   Jiri Olsa   perf c2c report: ...
2763
2764
  	hists__output_resort_cb(&c2c.hists.hists, &prog, resort_hitm_cb);
  	hists__iterate_cb(&c2c.hists.hists, resort_cl_cb);
78b275437   Jiri Olsa   perf c2c report: ...
2765
2766
  
  	ui_progress__finish();
d0802b1ee   Jiri Olsa   perf c2c report: ...
2767
2768
2769
2770
2771
  	if (ui_quirks()) {
  		pr_err("failed to setup UI
  ");
  		goto out_mem2node;
  	}
5a1a99cd2   Jiri Olsa   perf c2c report: ...
2772

2709b97dc   Jiri Olsa   perf c2c report: ...
2773
  	perf_c2c_display(session);
2d388bd0c   Jiri Olsa   perf c2c report: ...
2774

7f834c2e8   Jiri Olsa   perf c2c report: ...
2775
2776
  out_mem2node:
  	mem2node__exit(&c2c.mem2node);
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2777
2778
2779
2780
2781
  out_session:
  	perf_session__delete(session);
  out:
  	return err;
  }
7e6a79981   Arnaldo Carvalho de Melo   perf tools: Remov...
2782
  static int parse_record_events(const struct option *opt,
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2783
2784
2785
  			       const char *str, int unset __maybe_unused)
  {
  	bool *event_set = (bool *) opt->value;
b027cc6fd   Ian Rogers   perf c2c: Fix 'pe...
2786
2787
2788
2789
2790
2791
  	if (!strcmp(str, "list")) {
  		perf_mem_events__list();
  		exit(0);
  	}
  	if (perf_mem_events__parse(str))
  		exit(-1);
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2792
  	*event_set = true;
b027cc6fd   Ian Rogers   perf c2c: Fix 'pe...
2793
  	return 0;
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
  }
  
  
  static const char * const __usage_record[] = {
  	"perf c2c record [<options>] [<command>]",
  	"perf c2c record [<options>] -- <command> [<options>]",
  	NULL
  };
  
  static const char * const *record_mem_usage = __usage_record;
  
  static int perf_c2c__record(int argc, const char **argv)
  {
  	int rec_argc, i = 0, j;
  	const char **rec_argv;
  	int ret;
  	bool all_user = false, all_kernel = false;
  	bool event_set = false;
  	struct option options[] = {
  	OPT_CALLBACK('e', "event", &event_set, "event",
edac75a2f   Leo Yan   perf c2c: Update ...
2814
  		     "event selector. Use 'perf c2c record -e list' to list available events",
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2815
  		     parse_record_events),
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2816
2817
2818
  	OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"),
  	OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"),
  	OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"),
3a5bfab60   Jiri Olsa   perf c2c: Support...
2819
  	OPT_PARENT(c2c_options),
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
  	OPT_END()
  	};
  
  	if (perf_mem_events__init()) {
  		pr_err("failed: memory events not supported
  ");
  		return -1;
  	}
  
  	argc = parse_options(argc, argv, options, record_mem_usage,
  			     PARSE_OPT_KEEP_UNKNOWN);
8fab7843a   Jiri Olsa   perf c2c record: ...
2831
  	rec_argc = argc + 11; /* max number of arguments */
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
  	rec_argv = calloc(rec_argc + 1, sizeof(char *));
  	if (!rec_argv)
  		return -1;
  
  	rec_argv[i++] = "record";
  
  	if (!event_set) {
  		perf_mem_events[PERF_MEM_EVENTS__LOAD].record  = true;
  		perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
  	}
  
  	if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
  		rec_argv[i++] = "-W";
  
  	rec_argv[i++] = "-d";
8fab7843a   Jiri Olsa   perf c2c record: ...
2847
  	rec_argv[i++] = "--phys-data";
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
  	rec_argv[i++] = "--sample-cpu";
  
  	for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) {
  		if (!perf_mem_events[j].record)
  			continue;
  
  		if (!perf_mem_events[j].supported) {
  			pr_err("failed: event '%s' not supported
  ",
  			       perf_mem_events[j].name);
c896f85a7   Martin Kepplinger   perf tools: Fix l...
2858
  			free(rec_argv);
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2859
2860
2861
2862
2863
  			return -1;
  		}
  
  		rec_argv[i++] = "-e";
  		rec_argv[i++] = perf_mem_events__name(j);
2cca512ad   Zou Wei   perf c2c: Remove ...
2864
  	}
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
  
  	if (all_user)
  		rec_argv[i++] = "--all-user";
  
  	if (all_kernel)
  		rec_argv[i++] = "--all-kernel";
  
  	for (j = 0; j < argc; j++, i++)
  		rec_argv[i] = argv[j];
  
  	if (verbose > 0) {
  		pr_debug("calling: ");
  
  		j = 0;
  
  		while (rec_argv[j]) {
  			pr_debug("%s ", rec_argv[j]);
  			j++;
  		}
  		pr_debug("
  ");
  	}
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
2887
  	ret = cmd_record(i, rec_argv);
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2888
2889
2890
  	free(rec_argv);
  	return ret;
  }
b0ad8ea66   Arnaldo Carvalho de Melo   perf tools: Remov...
2891
  int cmd_c2c(int argc, const char **argv)
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
2892
  {
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
2893
2894
  	argc = parse_options(argc, argv, c2c_options, c2c_usage,
  			     PARSE_OPT_STOP_AT_NON_OPTION);
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2895
2896
2897
2898
2899
2900
  
  	if (!argc)
  		usage_with_options(c2c_usage, c2c_options);
  
  	if (!strncmp(argv[0], "rec", 3)) {
  		return perf_c2c__record(argc, argv);
903a6f15b   Jiri Olsa   perf c2c: Add rep...
2901
2902
  	} else if (!strncmp(argv[0], "rep", 3)) {
  		return perf_c2c__report(argc, argv);
39bcd4a4e   Jiri Olsa   perf c2c: Add rec...
2903
2904
2905
  	} else {
  		usage_with_options(c2c_usage, c2c_options);
  	}
7aef3bf3d   Jiri Olsa   perf c2c: Add c2c...
2906
2907
  	return 0;
  }