18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * This is rewrite of original c2c tool introduced in here: 48c2ecf20Sopenharmony_ci * http://lwn.net/Articles/588866/ 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * The original tool was changed to fit in current perf state. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Original authors: 98c2ecf20Sopenharmony_ci * Don Zickus <dzickus@redhat.com> 108c2ecf20Sopenharmony_ci * Dick Fowles <fowles@inreach.com> 118c2ecf20Sopenharmony_ci * Joe Mario <jmario@redhat.com> 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci#include <errno.h> 148c2ecf20Sopenharmony_ci#include <inttypes.h> 158c2ecf20Sopenharmony_ci#include <linux/compiler.h> 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci#include <linux/kernel.h> 188c2ecf20Sopenharmony_ci#include <linux/stringify.h> 198c2ecf20Sopenharmony_ci#include <linux/zalloc.h> 208c2ecf20Sopenharmony_ci#include <asm/bug.h> 218c2ecf20Sopenharmony_ci#include <sys/param.h> 228c2ecf20Sopenharmony_ci#include "debug.h" 238c2ecf20Sopenharmony_ci#include "builtin.h" 248c2ecf20Sopenharmony_ci#include <perf/cpumap.h> 258c2ecf20Sopenharmony_ci#include <subcmd/pager.h> 268c2ecf20Sopenharmony_ci#include <subcmd/parse-options.h> 278c2ecf20Sopenharmony_ci#include "map_symbol.h" 288c2ecf20Sopenharmony_ci#include "mem-events.h" 298c2ecf20Sopenharmony_ci#include "session.h" 308c2ecf20Sopenharmony_ci#include "hist.h" 318c2ecf20Sopenharmony_ci#include "sort.h" 328c2ecf20Sopenharmony_ci#include "tool.h" 338c2ecf20Sopenharmony_ci#include "cacheline.h" 348c2ecf20Sopenharmony_ci#include "data.h" 358c2ecf20Sopenharmony_ci#include "event.h" 368c2ecf20Sopenharmony_ci#include "evlist.h" 378c2ecf20Sopenharmony_ci#include "evsel.h" 388c2ecf20Sopenharmony_ci#include "ui/browsers/hists.h" 398c2ecf20Sopenharmony_ci#include "thread.h" 408c2ecf20Sopenharmony_ci#include "mem2node.h" 418c2ecf20Sopenharmony_ci#include "symbol.h" 428c2ecf20Sopenharmony_ci#include "ui/ui.h" 438c2ecf20Sopenharmony_ci#include "ui/progress.h" 448c2ecf20Sopenharmony_ci#include "../perf.h" 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistruct c2c_hists { 478c2ecf20Sopenharmony_ci struct hists hists; 488c2ecf20Sopenharmony_ci struct perf_hpp_list list; 498c2ecf20Sopenharmony_ci struct c2c_stats stats; 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistruct compute_stats { 538c2ecf20Sopenharmony_ci struct stats lcl_hitm; 548c2ecf20Sopenharmony_ci struct stats rmt_hitm; 558c2ecf20Sopenharmony_ci struct stats load; 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct c2c_hist_entry { 598c2ecf20Sopenharmony_ci struct c2c_hists *hists; 608c2ecf20Sopenharmony_ci struct c2c_stats stats; 618c2ecf20Sopenharmony_ci unsigned long *cpuset; 628c2ecf20Sopenharmony_ci unsigned long *nodeset; 638c2ecf20Sopenharmony_ci struct c2c_stats *node_stats; 648c2ecf20Sopenharmony_ci unsigned int cacheline_idx; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci struct compute_stats cstats; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci unsigned long paddr; 698c2ecf20Sopenharmony_ci unsigned long paddr_cnt; 708c2ecf20Sopenharmony_ci bool paddr_zero; 718c2ecf20Sopenharmony_ci char *nodestr; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci /* 748c2ecf20Sopenharmony_ci * must be at the end, 758c2ecf20Sopenharmony_ci * because of its callchain dynamic entry 768c2ecf20Sopenharmony_ci */ 778c2ecf20Sopenharmony_ci struct hist_entry he; 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic char const *coalesce_default = "iaddr"; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistruct perf_c2c { 838c2ecf20Sopenharmony_ci struct perf_tool tool; 848c2ecf20Sopenharmony_ci struct c2c_hists hists; 858c2ecf20Sopenharmony_ci struct mem2node mem2node; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci unsigned long **nodes; 888c2ecf20Sopenharmony_ci int nodes_cnt; 898c2ecf20Sopenharmony_ci int cpus_cnt; 908c2ecf20Sopenharmony_ci int *cpu2node; 918c2ecf20Sopenharmony_ci int node_info; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci bool show_src; 948c2ecf20Sopenharmony_ci bool show_all; 958c2ecf20Sopenharmony_ci bool use_stdio; 968c2ecf20Sopenharmony_ci bool stats_only; 978c2ecf20Sopenharmony_ci bool symbol_full; 988c2ecf20Sopenharmony_ci bool stitch_lbr; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* HITM shared clines stats */ 1018c2ecf20Sopenharmony_ci struct c2c_stats hitm_stats; 1028c2ecf20Sopenharmony_ci int shared_clines; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci int display; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci const char *coalesce; 1078c2ecf20Sopenharmony_ci char *cl_sort; 1088c2ecf20Sopenharmony_ci char *cl_resort; 1098c2ecf20Sopenharmony_ci char *cl_output; 1108c2ecf20Sopenharmony_ci}; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cienum { 1138c2ecf20Sopenharmony_ci DISPLAY_LCL, 1148c2ecf20Sopenharmony_ci DISPLAY_RMT, 1158c2ecf20Sopenharmony_ci DISPLAY_TOT, 1168c2ecf20Sopenharmony_ci DISPLAY_MAX, 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic const char *display_str[DISPLAY_MAX] = { 1208c2ecf20Sopenharmony_ci [DISPLAY_LCL] = "Local", 1218c2ecf20Sopenharmony_ci [DISPLAY_RMT] = "Remote", 1228c2ecf20Sopenharmony_ci [DISPLAY_TOT] = "Total", 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic const struct option c2c_options[] = { 1268c2ecf20Sopenharmony_ci OPT_INCR('v', "verbose", &verbose, "be more verbose (show counter open errors, etc)"), 1278c2ecf20Sopenharmony_ci OPT_END() 1288c2ecf20Sopenharmony_ci}; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic struct perf_c2c c2c; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic void *c2c_he_zalloc(size_t size) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci c2c_he = zalloc(size + sizeof(*c2c_he)); 1378c2ecf20Sopenharmony_ci if (!c2c_he) 1388c2ecf20Sopenharmony_ci return NULL; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci c2c_he->cpuset = bitmap_alloc(c2c.cpus_cnt); 1418c2ecf20Sopenharmony_ci if (!c2c_he->cpuset) 1428c2ecf20Sopenharmony_ci return NULL; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci c2c_he->nodeset = bitmap_alloc(c2c.nodes_cnt); 1458c2ecf20Sopenharmony_ci if (!c2c_he->nodeset) 1468c2ecf20Sopenharmony_ci return NULL; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci c2c_he->node_stats = zalloc(c2c.nodes_cnt * sizeof(*c2c_he->node_stats)); 1498c2ecf20Sopenharmony_ci if (!c2c_he->node_stats) 1508c2ecf20Sopenharmony_ci return NULL; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci init_stats(&c2c_he->cstats.lcl_hitm); 1538c2ecf20Sopenharmony_ci init_stats(&c2c_he->cstats.rmt_hitm); 1548c2ecf20Sopenharmony_ci init_stats(&c2c_he->cstats.load); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return &c2c_he->he; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic void c2c_he_free(void *he) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 1648c2ecf20Sopenharmony_ci if (c2c_he->hists) { 1658c2ecf20Sopenharmony_ci hists__delete_entries(&c2c_he->hists->hists); 1668c2ecf20Sopenharmony_ci free(c2c_he->hists); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci free(c2c_he->cpuset); 1708c2ecf20Sopenharmony_ci free(c2c_he->nodeset); 1718c2ecf20Sopenharmony_ci free(c2c_he->nodestr); 1728c2ecf20Sopenharmony_ci free(c2c_he->node_stats); 1738c2ecf20Sopenharmony_ci free(c2c_he); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic struct hist_entry_ops c2c_entry_ops = { 1778c2ecf20Sopenharmony_ci .new = c2c_he_zalloc, 1788c2ecf20Sopenharmony_ci .free = c2c_he_free, 1798c2ecf20Sopenharmony_ci}; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic int c2c_hists__init(struct c2c_hists *hists, 1828c2ecf20Sopenharmony_ci const char *sort, 1838c2ecf20Sopenharmony_ci int nr_header_lines); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_cistatic struct c2c_hists* 1868c2ecf20Sopenharmony_cihe__get_c2c_hists(struct hist_entry *he, 1878c2ecf20Sopenharmony_ci const char *sort, 1888c2ecf20Sopenharmony_ci int nr_header_lines) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 1918c2ecf20Sopenharmony_ci struct c2c_hists *hists; 1928c2ecf20Sopenharmony_ci int ret; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 1958c2ecf20Sopenharmony_ci if (c2c_he->hists) 1968c2ecf20Sopenharmony_ci return c2c_he->hists; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci hists = c2c_he->hists = zalloc(sizeof(*hists)); 1998c2ecf20Sopenharmony_ci if (!hists) 2008c2ecf20Sopenharmony_ci return NULL; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci ret = c2c_hists__init(hists, sort, nr_header_lines); 2038c2ecf20Sopenharmony_ci if (ret) { 2048c2ecf20Sopenharmony_ci free(hists); 2058c2ecf20Sopenharmony_ci return NULL; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci return hists; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic void c2c_he__set_cpu(struct c2c_hist_entry *c2c_he, 2128c2ecf20Sopenharmony_ci struct perf_sample *sample) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci if (WARN_ONCE(sample->cpu == (unsigned int) -1, 2158c2ecf20Sopenharmony_ci "WARNING: no sample cpu value")) 2168c2ecf20Sopenharmony_ci return; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci set_bit(sample->cpu, c2c_he->cpuset); 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic void c2c_he__set_node(struct c2c_hist_entry *c2c_he, 2228c2ecf20Sopenharmony_ci struct perf_sample *sample) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci int node; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci if (!sample->phys_addr) { 2278c2ecf20Sopenharmony_ci c2c_he->paddr_zero = true; 2288c2ecf20Sopenharmony_ci return; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci node = mem2node__node(&c2c.mem2node, sample->phys_addr); 2328c2ecf20Sopenharmony_ci if (WARN_ONCE(node < 0, "WARNING: failed to find node\n")) 2338c2ecf20Sopenharmony_ci return; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci set_bit(node, c2c_he->nodeset); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci if (c2c_he->paddr != sample->phys_addr) { 2388c2ecf20Sopenharmony_ci c2c_he->paddr_cnt++; 2398c2ecf20Sopenharmony_ci c2c_he->paddr = sample->phys_addr; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic void compute_stats(struct c2c_hist_entry *c2c_he, 2448c2ecf20Sopenharmony_ci struct c2c_stats *stats, 2458c2ecf20Sopenharmony_ci u64 weight) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci struct compute_stats *cstats = &c2c_he->cstats; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (stats->rmt_hitm) 2508c2ecf20Sopenharmony_ci update_stats(&cstats->rmt_hitm, weight); 2518c2ecf20Sopenharmony_ci else if (stats->lcl_hitm) 2528c2ecf20Sopenharmony_ci update_stats(&cstats->lcl_hitm, weight); 2538c2ecf20Sopenharmony_ci else if (stats->load) 2548c2ecf20Sopenharmony_ci update_stats(&cstats->load, weight); 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic int process_sample_event(struct perf_tool *tool __maybe_unused, 2588c2ecf20Sopenharmony_ci union perf_event *event, 2598c2ecf20Sopenharmony_ci struct perf_sample *sample, 2608c2ecf20Sopenharmony_ci struct evsel *evsel, 2618c2ecf20Sopenharmony_ci struct machine *machine) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci struct c2c_hists *c2c_hists = &c2c.hists; 2648c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 2658c2ecf20Sopenharmony_ci struct c2c_stats stats = { .nr_entries = 0, }; 2668c2ecf20Sopenharmony_ci struct hist_entry *he; 2678c2ecf20Sopenharmony_ci struct addr_location al; 2688c2ecf20Sopenharmony_ci struct mem_info *mi, *mi_dup; 2698c2ecf20Sopenharmony_ci int ret; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (machine__resolve(machine, &al, sample) < 0) { 2728c2ecf20Sopenharmony_ci pr_debug("problem processing %d event, skipping it.\n", 2738c2ecf20Sopenharmony_ci event->header.type); 2748c2ecf20Sopenharmony_ci return -1; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (c2c.stitch_lbr) 2788c2ecf20Sopenharmony_ci al.thread->lbr_stitch_enable = true; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci ret = sample__resolve_callchain(sample, &callchain_cursor, NULL, 2818c2ecf20Sopenharmony_ci evsel, &al, sysctl_perf_event_max_stack); 2828c2ecf20Sopenharmony_ci if (ret) 2838c2ecf20Sopenharmony_ci goto out; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci mi = sample__resolve_mem(sample, &al); 2868c2ecf20Sopenharmony_ci if (mi == NULL) 2878c2ecf20Sopenharmony_ci return -ENOMEM; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci /* 2908c2ecf20Sopenharmony_ci * The mi object is released in hists__add_entry_ops, 2918c2ecf20Sopenharmony_ci * if it gets sorted out into existing data, so we need 2928c2ecf20Sopenharmony_ci * to take the copy now. 2938c2ecf20Sopenharmony_ci */ 2948c2ecf20Sopenharmony_ci mi_dup = mem_info__get(mi); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci c2c_decode_stats(&stats, mi); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops, 2998c2ecf20Sopenharmony_ci &al, NULL, NULL, mi, 3008c2ecf20Sopenharmony_ci sample, true); 3018c2ecf20Sopenharmony_ci if (he == NULL) 3028c2ecf20Sopenharmony_ci goto free_mi; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 3058c2ecf20Sopenharmony_ci c2c_add_stats(&c2c_he->stats, &stats); 3068c2ecf20Sopenharmony_ci c2c_add_stats(&c2c_hists->stats, &stats); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci c2c_he__set_cpu(c2c_he, sample); 3098c2ecf20Sopenharmony_ci c2c_he__set_node(c2c_he, sample); 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 3128c2ecf20Sopenharmony_ci ret = hist_entry__append_callchain(he, sample); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci if (!ret) { 3158c2ecf20Sopenharmony_ci /* 3168c2ecf20Sopenharmony_ci * There's already been warning about missing 3178c2ecf20Sopenharmony_ci * sample's cpu value. Let's account all to 3188c2ecf20Sopenharmony_ci * node 0 in this case, without any further 3198c2ecf20Sopenharmony_ci * warning. 3208c2ecf20Sopenharmony_ci * 3218c2ecf20Sopenharmony_ci * Doing node stats only for single callchain data. 3228c2ecf20Sopenharmony_ci */ 3238c2ecf20Sopenharmony_ci int cpu = sample->cpu == (unsigned int) -1 ? 0 : sample->cpu; 3248c2ecf20Sopenharmony_ci int node = c2c.cpu2node[cpu]; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci mi = mi_dup; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci c2c_hists = he__get_c2c_hists(he, c2c.cl_sort, 2); 3298c2ecf20Sopenharmony_ci if (!c2c_hists) 3308c2ecf20Sopenharmony_ci goto free_mi; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci he = hists__add_entry_ops(&c2c_hists->hists, &c2c_entry_ops, 3338c2ecf20Sopenharmony_ci &al, NULL, NULL, mi, 3348c2ecf20Sopenharmony_ci sample, true); 3358c2ecf20Sopenharmony_ci if (he == NULL) 3368c2ecf20Sopenharmony_ci goto free_mi; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 3398c2ecf20Sopenharmony_ci c2c_add_stats(&c2c_he->stats, &stats); 3408c2ecf20Sopenharmony_ci c2c_add_stats(&c2c_hists->stats, &stats); 3418c2ecf20Sopenharmony_ci c2c_add_stats(&c2c_he->node_stats[node], &stats); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci compute_stats(c2c_he, &stats, sample->weight); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci c2c_he__set_cpu(c2c_he, sample); 3468c2ecf20Sopenharmony_ci c2c_he__set_node(c2c_he, sample); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci hists__inc_nr_samples(&c2c_hists->hists, he->filtered); 3498c2ecf20Sopenharmony_ci ret = hist_entry__append_callchain(he, sample); 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ciout: 3538c2ecf20Sopenharmony_ci addr_location__put(&al); 3548c2ecf20Sopenharmony_ci return ret; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cifree_mi: 3578c2ecf20Sopenharmony_ci mem_info__put(mi_dup); 3588c2ecf20Sopenharmony_ci mem_info__put(mi); 3598c2ecf20Sopenharmony_ci ret = -ENOMEM; 3608c2ecf20Sopenharmony_ci goto out; 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic struct perf_c2c c2c = { 3648c2ecf20Sopenharmony_ci .tool = { 3658c2ecf20Sopenharmony_ci .sample = process_sample_event, 3668c2ecf20Sopenharmony_ci .mmap = perf_event__process_mmap, 3678c2ecf20Sopenharmony_ci .mmap2 = perf_event__process_mmap2, 3688c2ecf20Sopenharmony_ci .comm = perf_event__process_comm, 3698c2ecf20Sopenharmony_ci .exit = perf_event__process_exit, 3708c2ecf20Sopenharmony_ci .fork = perf_event__process_fork, 3718c2ecf20Sopenharmony_ci .lost = perf_event__process_lost, 3728c2ecf20Sopenharmony_ci .ordered_events = true, 3738c2ecf20Sopenharmony_ci .ordering_requires_timestamps = true, 3748c2ecf20Sopenharmony_ci }, 3758c2ecf20Sopenharmony_ci}; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic const char * const c2c_usage[] = { 3788c2ecf20Sopenharmony_ci "perf c2c {record|report}", 3798c2ecf20Sopenharmony_ci NULL 3808c2ecf20Sopenharmony_ci}; 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cistatic const char * const __usage_report[] = { 3838c2ecf20Sopenharmony_ci "perf c2c report", 3848c2ecf20Sopenharmony_ci NULL 3858c2ecf20Sopenharmony_ci}; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic const char * const *report_c2c_usage = __usage_report; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci#define C2C_HEADER_MAX 2 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistruct c2c_header { 3928c2ecf20Sopenharmony_ci struct { 3938c2ecf20Sopenharmony_ci const char *text; 3948c2ecf20Sopenharmony_ci int span; 3958c2ecf20Sopenharmony_ci } line[C2C_HEADER_MAX]; 3968c2ecf20Sopenharmony_ci}; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistruct c2c_dimension { 3998c2ecf20Sopenharmony_ci struct c2c_header header; 4008c2ecf20Sopenharmony_ci const char *name; 4018c2ecf20Sopenharmony_ci int width; 4028c2ecf20Sopenharmony_ci struct sort_entry *se; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci int64_t (*cmp)(struct perf_hpp_fmt *fmt, 4058c2ecf20Sopenharmony_ci struct hist_entry *, struct hist_entry *); 4068c2ecf20Sopenharmony_ci int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 4078c2ecf20Sopenharmony_ci struct hist_entry *he); 4088c2ecf20Sopenharmony_ci int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 4098c2ecf20Sopenharmony_ci struct hist_entry *he); 4108c2ecf20Sopenharmony_ci}; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistruct c2c_fmt { 4138c2ecf20Sopenharmony_ci struct perf_hpp_fmt fmt; 4148c2ecf20Sopenharmony_ci struct c2c_dimension *dim; 4158c2ecf20Sopenharmony_ci}; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci#define SYMBOL_WIDTH 30 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_symbol; 4208c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_srcline; 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic int symbol_width(struct hists *hists, struct sort_entry *se) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci int width = hists__col_len(hists, se->se_width_idx); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci if (!c2c.symbol_full) 4278c2ecf20Sopenharmony_ci width = MIN(width, SYMBOL_WIDTH); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci return width; 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic int c2c_width(struct perf_hpp_fmt *fmt, 4338c2ecf20Sopenharmony_ci struct perf_hpp *hpp __maybe_unused, 4348c2ecf20Sopenharmony_ci struct hists *hists) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt; 4378c2ecf20Sopenharmony_ci struct c2c_dimension *dim; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci c2c_fmt = container_of(fmt, struct c2c_fmt, fmt); 4408c2ecf20Sopenharmony_ci dim = c2c_fmt->dim; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci if (dim == &dim_symbol || dim == &dim_srcline) 4438c2ecf20Sopenharmony_ci return symbol_width(hists, dim->se); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci return dim->se ? hists__col_len(hists, dim->se->se_width_idx) : 4468c2ecf20Sopenharmony_ci c2c_fmt->dim->width; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic int c2c_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 4508c2ecf20Sopenharmony_ci struct hists *hists, int line, int *span) 4518c2ecf20Sopenharmony_ci{ 4528c2ecf20Sopenharmony_ci struct perf_hpp_list *hpp_list = hists->hpp_list; 4538c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt; 4548c2ecf20Sopenharmony_ci struct c2c_dimension *dim; 4558c2ecf20Sopenharmony_ci const char *text = NULL; 4568c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, hists); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci c2c_fmt = container_of(fmt, struct c2c_fmt, fmt); 4598c2ecf20Sopenharmony_ci dim = c2c_fmt->dim; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci if (dim->se) { 4628c2ecf20Sopenharmony_ci text = dim->header.line[line].text; 4638c2ecf20Sopenharmony_ci /* Use the last line from sort_entry if not defined. */ 4648c2ecf20Sopenharmony_ci if (!text && (line == hpp_list->nr_header_lines - 1)) 4658c2ecf20Sopenharmony_ci text = dim->se->se_header; 4668c2ecf20Sopenharmony_ci } else { 4678c2ecf20Sopenharmony_ci text = dim->header.line[line].text; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci if (*span) { 4708c2ecf20Sopenharmony_ci (*span)--; 4718c2ecf20Sopenharmony_ci return 0; 4728c2ecf20Sopenharmony_ci } else { 4738c2ecf20Sopenharmony_ci *span = dim->header.line[line].span; 4748c2ecf20Sopenharmony_ci } 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci if (text == NULL) 4788c2ecf20Sopenharmony_ci text = ""; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, text); 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci#define HEX_STR(__s, __v) \ 4848c2ecf20Sopenharmony_ci({ \ 4858c2ecf20Sopenharmony_ci scnprintf(__s, sizeof(__s), "0x%" PRIx64, __v); \ 4868c2ecf20Sopenharmony_ci __s; \ 4878c2ecf20Sopenharmony_ci}) 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cistatic int64_t 4908c2ecf20Sopenharmony_cidcacheline_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 4918c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci return sort__dcacheline_cmp(left, right); 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic int dcacheline_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 4978c2ecf20Sopenharmony_ci struct hist_entry *he) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci uint64_t addr = 0; 5008c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 5018c2ecf20Sopenharmony_ci char buf[20]; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci if (he->mem_info) 5048c2ecf20Sopenharmony_ci addr = cl_address(he->mem_info->daddr.addr); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr)); 5078c2ecf20Sopenharmony_ci} 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_cistatic int 5108c2ecf20Sopenharmony_cidcacheline_node_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 5118c2ecf20Sopenharmony_ci struct hist_entry *he) 5128c2ecf20Sopenharmony_ci{ 5138c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 5148c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 5178c2ecf20Sopenharmony_ci if (WARN_ON_ONCE(!c2c_he->nodestr)) 5188c2ecf20Sopenharmony_ci return 0; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, c2c_he->nodestr); 5218c2ecf20Sopenharmony_ci} 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic int 5248c2ecf20Sopenharmony_cidcacheline_node_count(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 5258c2ecf20Sopenharmony_ci struct hist_entry *he) 5268c2ecf20Sopenharmony_ci{ 5278c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 5288c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 5318c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*lu", width, c2c_he->paddr_cnt); 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic int offset_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 5358c2ecf20Sopenharmony_ci struct hist_entry *he) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci uint64_t addr = 0; 5388c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 5398c2ecf20Sopenharmony_ci char buf[20]; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci if (he->mem_info) 5428c2ecf20Sopenharmony_ci addr = cl_offset(he->mem_info->daddr.al_addr); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr)); 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_cistatic int64_t 5488c2ecf20Sopenharmony_cioffset_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 5498c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 5508c2ecf20Sopenharmony_ci{ 5518c2ecf20Sopenharmony_ci uint64_t l = 0, r = 0; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci if (left->mem_info) 5548c2ecf20Sopenharmony_ci l = cl_offset(left->mem_info->daddr.addr); 5558c2ecf20Sopenharmony_ci if (right->mem_info) 5568c2ecf20Sopenharmony_ci r = cl_offset(right->mem_info->daddr.addr); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci return (int64_t)(r - l); 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic int 5628c2ecf20Sopenharmony_ciiaddr_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 5638c2ecf20Sopenharmony_ci struct hist_entry *he) 5648c2ecf20Sopenharmony_ci{ 5658c2ecf20Sopenharmony_ci uint64_t addr = 0; 5668c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 5678c2ecf20Sopenharmony_ci char buf[20]; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci if (he->mem_info) 5708c2ecf20Sopenharmony_ci addr = he->mem_info->iaddr.addr; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, HEX_STR(buf, addr)); 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_cistatic int64_t 5768c2ecf20Sopenharmony_ciiaddr_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 5778c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci return sort__iaddr_cmp(left, right); 5808c2ecf20Sopenharmony_ci} 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_cistatic int 5838c2ecf20Sopenharmony_citot_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 5848c2ecf20Sopenharmony_ci struct hist_entry *he) 5858c2ecf20Sopenharmony_ci{ 5868c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 5878c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 5888c2ecf20Sopenharmony_ci unsigned int tot_hitm; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 5918c2ecf20Sopenharmony_ci tot_hitm = c2c_he->stats.lcl_hitm + c2c_he->stats.rmt_hitm; 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*u", width, tot_hitm); 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_cistatic int64_t 5978c2ecf20Sopenharmony_citot_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 5988c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_left; 6018c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_right; 6028c2ecf20Sopenharmony_ci uint64_t tot_hitm_left; 6038c2ecf20Sopenharmony_ci uint64_t tot_hitm_right; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci c2c_left = container_of(left, struct c2c_hist_entry, he); 6068c2ecf20Sopenharmony_ci c2c_right = container_of(right, struct c2c_hist_entry, he); 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci tot_hitm_left = c2c_left->stats.lcl_hitm + c2c_left->stats.rmt_hitm; 6098c2ecf20Sopenharmony_ci tot_hitm_right = c2c_right->stats.lcl_hitm + c2c_right->stats.rmt_hitm; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci return tot_hitm_left - tot_hitm_right; 6128c2ecf20Sopenharmony_ci} 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci#define STAT_FN_ENTRY(__f) \ 6158c2ecf20Sopenharmony_cistatic int \ 6168c2ecf20Sopenharmony_ci__f ## _entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, \ 6178c2ecf20Sopenharmony_ci struct hist_entry *he) \ 6188c2ecf20Sopenharmony_ci{ \ 6198c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; \ 6208c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); \ 6218c2ecf20Sopenharmony_ci \ 6228c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); \ 6238c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*u", width, \ 6248c2ecf20Sopenharmony_ci c2c_he->stats.__f); \ 6258c2ecf20Sopenharmony_ci} 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci#define STAT_FN_CMP(__f) \ 6288c2ecf20Sopenharmony_cistatic int64_t \ 6298c2ecf20Sopenharmony_ci__f ## _cmp(struct perf_hpp_fmt *fmt __maybe_unused, \ 6308c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) \ 6318c2ecf20Sopenharmony_ci{ \ 6328c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_left, *c2c_right; \ 6338c2ecf20Sopenharmony_ci \ 6348c2ecf20Sopenharmony_ci c2c_left = container_of(left, struct c2c_hist_entry, he); \ 6358c2ecf20Sopenharmony_ci c2c_right = container_of(right, struct c2c_hist_entry, he); \ 6368c2ecf20Sopenharmony_ci return (uint64_t) c2c_left->stats.__f - \ 6378c2ecf20Sopenharmony_ci (uint64_t) c2c_right->stats.__f; \ 6388c2ecf20Sopenharmony_ci} 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci#define STAT_FN(__f) \ 6418c2ecf20Sopenharmony_ci STAT_FN_ENTRY(__f) \ 6428c2ecf20Sopenharmony_ci STAT_FN_CMP(__f) 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ciSTAT_FN(rmt_hitm) 6458c2ecf20Sopenharmony_ciSTAT_FN(lcl_hitm) 6468c2ecf20Sopenharmony_ciSTAT_FN(store) 6478c2ecf20Sopenharmony_ciSTAT_FN(st_l1hit) 6488c2ecf20Sopenharmony_ciSTAT_FN(st_l1miss) 6498c2ecf20Sopenharmony_ciSTAT_FN(ld_fbhit) 6508c2ecf20Sopenharmony_ciSTAT_FN(ld_l1hit) 6518c2ecf20Sopenharmony_ciSTAT_FN(ld_l2hit) 6528c2ecf20Sopenharmony_ciSTAT_FN(ld_llchit) 6538c2ecf20Sopenharmony_ciSTAT_FN(rmt_hit) 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_cistatic uint64_t total_records(struct c2c_stats *stats) 6568c2ecf20Sopenharmony_ci{ 6578c2ecf20Sopenharmony_ci uint64_t lclmiss, ldcnt, total; 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci lclmiss = stats->lcl_dram + 6608c2ecf20Sopenharmony_ci stats->rmt_dram + 6618c2ecf20Sopenharmony_ci stats->rmt_hitm + 6628c2ecf20Sopenharmony_ci stats->rmt_hit; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci ldcnt = lclmiss + 6658c2ecf20Sopenharmony_ci stats->ld_fbhit + 6668c2ecf20Sopenharmony_ci stats->ld_l1hit + 6678c2ecf20Sopenharmony_ci stats->ld_l2hit + 6688c2ecf20Sopenharmony_ci stats->ld_llchit + 6698c2ecf20Sopenharmony_ci stats->lcl_hitm; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci total = ldcnt + 6728c2ecf20Sopenharmony_ci stats->st_l1hit + 6738c2ecf20Sopenharmony_ci stats->st_l1miss; 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci return total; 6768c2ecf20Sopenharmony_ci} 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_cistatic int 6798c2ecf20Sopenharmony_citot_recs_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 6808c2ecf20Sopenharmony_ci struct hist_entry *he) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 6838c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 6848c2ecf20Sopenharmony_ci uint64_t tot_recs; 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 6878c2ecf20Sopenharmony_ci tot_recs = total_records(&c2c_he->stats); 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs); 6908c2ecf20Sopenharmony_ci} 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_cistatic int64_t 6938c2ecf20Sopenharmony_citot_recs_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 6948c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 6958c2ecf20Sopenharmony_ci{ 6968c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_left; 6978c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_right; 6988c2ecf20Sopenharmony_ci uint64_t tot_recs_left; 6998c2ecf20Sopenharmony_ci uint64_t tot_recs_right; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci c2c_left = container_of(left, struct c2c_hist_entry, he); 7028c2ecf20Sopenharmony_ci c2c_right = container_of(right, struct c2c_hist_entry, he); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci tot_recs_left = total_records(&c2c_left->stats); 7058c2ecf20Sopenharmony_ci tot_recs_right = total_records(&c2c_right->stats); 7068c2ecf20Sopenharmony_ci 7078c2ecf20Sopenharmony_ci return tot_recs_left - tot_recs_right; 7088c2ecf20Sopenharmony_ci} 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_cistatic uint64_t total_loads(struct c2c_stats *stats) 7118c2ecf20Sopenharmony_ci{ 7128c2ecf20Sopenharmony_ci uint64_t lclmiss, ldcnt; 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci lclmiss = stats->lcl_dram + 7158c2ecf20Sopenharmony_ci stats->rmt_dram + 7168c2ecf20Sopenharmony_ci stats->rmt_hitm + 7178c2ecf20Sopenharmony_ci stats->rmt_hit; 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci ldcnt = lclmiss + 7208c2ecf20Sopenharmony_ci stats->ld_fbhit + 7218c2ecf20Sopenharmony_ci stats->ld_l1hit + 7228c2ecf20Sopenharmony_ci stats->ld_l2hit + 7238c2ecf20Sopenharmony_ci stats->ld_llchit + 7248c2ecf20Sopenharmony_ci stats->lcl_hitm; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci return ldcnt; 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_cistatic int 7308c2ecf20Sopenharmony_citot_loads_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 7318c2ecf20Sopenharmony_ci struct hist_entry *he) 7328c2ecf20Sopenharmony_ci{ 7338c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 7348c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 7358c2ecf20Sopenharmony_ci uint64_t tot_recs; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 7388c2ecf20Sopenharmony_ci tot_recs = total_loads(&c2c_he->stats); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*" PRIu64, width, tot_recs); 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_cistatic int64_t 7448c2ecf20Sopenharmony_citot_loads_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 7458c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 7468c2ecf20Sopenharmony_ci{ 7478c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_left; 7488c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_right; 7498c2ecf20Sopenharmony_ci uint64_t tot_recs_left; 7508c2ecf20Sopenharmony_ci uint64_t tot_recs_right; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci c2c_left = container_of(left, struct c2c_hist_entry, he); 7538c2ecf20Sopenharmony_ci c2c_right = container_of(right, struct c2c_hist_entry, he); 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci tot_recs_left = total_loads(&c2c_left->stats); 7568c2ecf20Sopenharmony_ci tot_recs_right = total_loads(&c2c_right->stats); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci return tot_recs_left - tot_recs_right; 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_citypedef double (get_percent_cb)(struct c2c_hist_entry *); 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_cistatic int 7648c2ecf20Sopenharmony_cipercent_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 7658c2ecf20Sopenharmony_ci struct hist_entry *he, get_percent_cb get_percent) 7668c2ecf20Sopenharmony_ci{ 7678c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 7688c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 7698c2ecf20Sopenharmony_ci double per; 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 7728c2ecf20Sopenharmony_ci per = get_percent(c2c_he); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci#ifdef HAVE_SLANG_SUPPORT 7758c2ecf20Sopenharmony_ci if (use_browser) 7768c2ecf20Sopenharmony_ci return __hpp__slsmg_color_printf(hpp, "%*.2f%%", width - 1, per); 7778c2ecf20Sopenharmony_ci#endif 7788c2ecf20Sopenharmony_ci return hpp_color_scnprintf(hpp, "%*.2f%%", width - 1, per); 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic double percent_hitm(struct c2c_hist_entry *c2c_he) 7828c2ecf20Sopenharmony_ci{ 7838c2ecf20Sopenharmony_ci struct c2c_hists *hists; 7848c2ecf20Sopenharmony_ci struct c2c_stats *stats; 7858c2ecf20Sopenharmony_ci struct c2c_stats *total; 7868c2ecf20Sopenharmony_ci int tot = 0, st = 0; 7878c2ecf20Sopenharmony_ci double p; 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_ci hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); 7908c2ecf20Sopenharmony_ci stats = &c2c_he->stats; 7918c2ecf20Sopenharmony_ci total = &hists->stats; 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci switch (c2c.display) { 7948c2ecf20Sopenharmony_ci case DISPLAY_RMT: 7958c2ecf20Sopenharmony_ci st = stats->rmt_hitm; 7968c2ecf20Sopenharmony_ci tot = total->rmt_hitm; 7978c2ecf20Sopenharmony_ci break; 7988c2ecf20Sopenharmony_ci case DISPLAY_LCL: 7998c2ecf20Sopenharmony_ci st = stats->lcl_hitm; 8008c2ecf20Sopenharmony_ci tot = total->lcl_hitm; 8018c2ecf20Sopenharmony_ci break; 8028c2ecf20Sopenharmony_ci case DISPLAY_TOT: 8038c2ecf20Sopenharmony_ci st = stats->tot_hitm; 8048c2ecf20Sopenharmony_ci tot = total->tot_hitm; 8058c2ecf20Sopenharmony_ci default: 8068c2ecf20Sopenharmony_ci break; 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci p = tot ? (double) st / tot : 0; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return 100 * p; 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci#define PERC_STR(__s, __v) \ 8158c2ecf20Sopenharmony_ci({ \ 8168c2ecf20Sopenharmony_ci scnprintf(__s, sizeof(__s), "%.2F%%", __v); \ 8178c2ecf20Sopenharmony_ci __s; \ 8188c2ecf20Sopenharmony_ci}) 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_cistatic int 8218c2ecf20Sopenharmony_cipercent_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 8228c2ecf20Sopenharmony_ci struct hist_entry *he) 8238c2ecf20Sopenharmony_ci{ 8248c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 8258c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 8268c2ecf20Sopenharmony_ci char buf[10]; 8278c2ecf20Sopenharmony_ci double per; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 8308c2ecf20Sopenharmony_ci per = percent_hitm(c2c_he); 8318c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per)); 8328c2ecf20Sopenharmony_ci} 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_cistatic int 8358c2ecf20Sopenharmony_cipercent_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 8368c2ecf20Sopenharmony_ci struct hist_entry *he) 8378c2ecf20Sopenharmony_ci{ 8388c2ecf20Sopenharmony_ci return percent_color(fmt, hpp, he, percent_hitm); 8398c2ecf20Sopenharmony_ci} 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_cistatic int64_t 8428c2ecf20Sopenharmony_cipercent_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 8438c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 8448c2ecf20Sopenharmony_ci{ 8458c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_left; 8468c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_right; 8478c2ecf20Sopenharmony_ci double per_left; 8488c2ecf20Sopenharmony_ci double per_right; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci c2c_left = container_of(left, struct c2c_hist_entry, he); 8518c2ecf20Sopenharmony_ci c2c_right = container_of(right, struct c2c_hist_entry, he); 8528c2ecf20Sopenharmony_ci 8538c2ecf20Sopenharmony_ci per_left = percent_hitm(c2c_left); 8548c2ecf20Sopenharmony_ci per_right = percent_hitm(c2c_right); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci return per_left - per_right; 8578c2ecf20Sopenharmony_ci} 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_cistatic struct c2c_stats *he_stats(struct hist_entry *he) 8608c2ecf20Sopenharmony_ci{ 8618c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 8648c2ecf20Sopenharmony_ci return &c2c_he->stats; 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_cistatic struct c2c_stats *total_stats(struct hist_entry *he) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci struct c2c_hists *hists; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci hists = container_of(he->hists, struct c2c_hists, hists); 8728c2ecf20Sopenharmony_ci return &hists->stats; 8738c2ecf20Sopenharmony_ci} 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_cistatic double percent(int st, int tot) 8768c2ecf20Sopenharmony_ci{ 8778c2ecf20Sopenharmony_ci return tot ? 100. * (double) st / (double) tot : 0; 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci#define PERCENT(__h, __f) percent(he_stats(__h)->__f, total_stats(__h)->__f) 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci#define PERCENT_FN(__f) \ 8838c2ecf20Sopenharmony_cistatic double percent_ ## __f(struct c2c_hist_entry *c2c_he) \ 8848c2ecf20Sopenharmony_ci{ \ 8858c2ecf20Sopenharmony_ci struct c2c_hists *hists; \ 8868c2ecf20Sopenharmony_ci \ 8878c2ecf20Sopenharmony_ci hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); \ 8888c2ecf20Sopenharmony_ci return percent(c2c_he->stats.__f, hists->stats.__f); \ 8898c2ecf20Sopenharmony_ci} 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ciPERCENT_FN(rmt_hitm) 8928c2ecf20Sopenharmony_ciPERCENT_FN(lcl_hitm) 8938c2ecf20Sopenharmony_ciPERCENT_FN(st_l1hit) 8948c2ecf20Sopenharmony_ciPERCENT_FN(st_l1miss) 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic int 8978c2ecf20Sopenharmony_cipercent_rmt_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 8988c2ecf20Sopenharmony_ci struct hist_entry *he) 8998c2ecf20Sopenharmony_ci{ 9008c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 9018c2ecf20Sopenharmony_ci double per = PERCENT(he, rmt_hitm); 9028c2ecf20Sopenharmony_ci char buf[10]; 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per)); 9058c2ecf20Sopenharmony_ci} 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_cistatic int 9088c2ecf20Sopenharmony_cipercent_rmt_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 9098c2ecf20Sopenharmony_ci struct hist_entry *he) 9108c2ecf20Sopenharmony_ci{ 9118c2ecf20Sopenharmony_ci return percent_color(fmt, hpp, he, percent_rmt_hitm); 9128c2ecf20Sopenharmony_ci} 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_cistatic int64_t 9158c2ecf20Sopenharmony_cipercent_rmt_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 9168c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 9178c2ecf20Sopenharmony_ci{ 9188c2ecf20Sopenharmony_ci double per_left; 9198c2ecf20Sopenharmony_ci double per_right; 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci per_left = PERCENT(left, rmt_hitm); 9228c2ecf20Sopenharmony_ci per_right = PERCENT(right, rmt_hitm); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci return per_left - per_right; 9258c2ecf20Sopenharmony_ci} 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_cistatic int 9288c2ecf20Sopenharmony_cipercent_lcl_hitm_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 9298c2ecf20Sopenharmony_ci struct hist_entry *he) 9308c2ecf20Sopenharmony_ci{ 9318c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 9328c2ecf20Sopenharmony_ci double per = PERCENT(he, lcl_hitm); 9338c2ecf20Sopenharmony_ci char buf[10]; 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per)); 9368c2ecf20Sopenharmony_ci} 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_cistatic int 9398c2ecf20Sopenharmony_cipercent_lcl_hitm_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 9408c2ecf20Sopenharmony_ci struct hist_entry *he) 9418c2ecf20Sopenharmony_ci{ 9428c2ecf20Sopenharmony_ci return percent_color(fmt, hpp, he, percent_lcl_hitm); 9438c2ecf20Sopenharmony_ci} 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_cistatic int64_t 9468c2ecf20Sopenharmony_cipercent_lcl_hitm_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 9478c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 9488c2ecf20Sopenharmony_ci{ 9498c2ecf20Sopenharmony_ci double per_left; 9508c2ecf20Sopenharmony_ci double per_right; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci per_left = PERCENT(left, lcl_hitm); 9538c2ecf20Sopenharmony_ci per_right = PERCENT(right, lcl_hitm); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci return per_left - per_right; 9568c2ecf20Sopenharmony_ci} 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_cistatic int 9598c2ecf20Sopenharmony_cipercent_stores_l1hit_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 9608c2ecf20Sopenharmony_ci struct hist_entry *he) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 9638c2ecf20Sopenharmony_ci double per = PERCENT(he, st_l1hit); 9648c2ecf20Sopenharmony_ci char buf[10]; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per)); 9678c2ecf20Sopenharmony_ci} 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_cistatic int 9708c2ecf20Sopenharmony_cipercent_stores_l1hit_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 9718c2ecf20Sopenharmony_ci struct hist_entry *he) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci return percent_color(fmt, hpp, he, percent_st_l1hit); 9748c2ecf20Sopenharmony_ci} 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_cistatic int64_t 9778c2ecf20Sopenharmony_cipercent_stores_l1hit_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 9788c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 9798c2ecf20Sopenharmony_ci{ 9808c2ecf20Sopenharmony_ci double per_left; 9818c2ecf20Sopenharmony_ci double per_right; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci per_left = PERCENT(left, st_l1hit); 9848c2ecf20Sopenharmony_ci per_right = PERCENT(right, st_l1hit); 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci return per_left - per_right; 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_cistatic int 9908c2ecf20Sopenharmony_cipercent_stores_l1miss_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 9918c2ecf20Sopenharmony_ci struct hist_entry *he) 9928c2ecf20Sopenharmony_ci{ 9938c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 9948c2ecf20Sopenharmony_ci double per = PERCENT(he, st_l1miss); 9958c2ecf20Sopenharmony_ci char buf[10]; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, PERC_STR(buf, per)); 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic int 10018c2ecf20Sopenharmony_cipercent_stores_l1miss_color(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 10028c2ecf20Sopenharmony_ci struct hist_entry *he) 10038c2ecf20Sopenharmony_ci{ 10048c2ecf20Sopenharmony_ci return percent_color(fmt, hpp, he, percent_st_l1miss); 10058c2ecf20Sopenharmony_ci} 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_cistatic int64_t 10088c2ecf20Sopenharmony_cipercent_stores_l1miss_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 10098c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci double per_left; 10128c2ecf20Sopenharmony_ci double per_right; 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci per_left = PERCENT(left, st_l1miss); 10158c2ecf20Sopenharmony_ci per_right = PERCENT(right, st_l1miss); 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci return per_left - per_right; 10188c2ecf20Sopenharmony_ci} 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ciSTAT_FN(lcl_dram) 10218c2ecf20Sopenharmony_ciSTAT_FN(rmt_dram) 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_cistatic int 10248c2ecf20Sopenharmony_cipid_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 10258c2ecf20Sopenharmony_ci struct hist_entry *he) 10268c2ecf20Sopenharmony_ci{ 10278c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*d", width, he->thread->pid_); 10308c2ecf20Sopenharmony_ci} 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_cistatic int64_t 10338c2ecf20Sopenharmony_cipid_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 10348c2ecf20Sopenharmony_ci struct hist_entry *left, struct hist_entry *right) 10358c2ecf20Sopenharmony_ci{ 10368c2ecf20Sopenharmony_ci return left->thread->pid_ - right->thread->pid_; 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_cistatic int64_t 10408c2ecf20Sopenharmony_ciempty_cmp(struct perf_hpp_fmt *fmt __maybe_unused, 10418c2ecf20Sopenharmony_ci struct hist_entry *left __maybe_unused, 10428c2ecf20Sopenharmony_ci struct hist_entry *right __maybe_unused) 10438c2ecf20Sopenharmony_ci{ 10448c2ecf20Sopenharmony_ci return 0; 10458c2ecf20Sopenharmony_ci} 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_cistatic int 10488c2ecf20Sopenharmony_cinode_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, 10498c2ecf20Sopenharmony_ci struct hist_entry *he) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 10528c2ecf20Sopenharmony_ci bool first = true; 10538c2ecf20Sopenharmony_ci int node; 10548c2ecf20Sopenharmony_ci int ret = 0; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci for (node = 0; node < c2c.nodes_cnt; node++) { 10598c2ecf20Sopenharmony_ci DECLARE_BITMAP(set, c2c.cpus_cnt); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci bitmap_zero(set, c2c.cpus_cnt); 10628c2ecf20Sopenharmony_ci bitmap_and(set, c2c_he->cpuset, c2c.nodes[node], c2c.cpus_cnt); 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ci if (!bitmap_weight(set, c2c.cpus_cnt)) { 10658c2ecf20Sopenharmony_ci if (c2c.node_info == 1) { 10668c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%21s", " "); 10678c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 10688c2ecf20Sopenharmony_ci } 10698c2ecf20Sopenharmony_ci continue; 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci if (!first) { 10738c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, " "); 10748c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci switch (c2c.node_info) { 10788c2ecf20Sopenharmony_ci case 0: 10798c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%2d", node); 10808c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 10818c2ecf20Sopenharmony_ci break; 10828c2ecf20Sopenharmony_ci case 1: 10838c2ecf20Sopenharmony_ci { 10848c2ecf20Sopenharmony_ci int num = bitmap_weight(set, c2c.cpus_cnt); 10858c2ecf20Sopenharmony_ci struct c2c_stats *stats = &c2c_he->node_stats[node]; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%2d{%2d ", node, num); 10888c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci #define DISPLAY_HITM(__h) \ 10918c2ecf20Sopenharmony_ci if (c2c_he->stats.__h> 0) { \ 10928c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%5.1f%% ", \ 10938c2ecf20Sopenharmony_ci percent(stats->__h, c2c_he->stats.__h));\ 10948c2ecf20Sopenharmony_ci } else { \ 10958c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%6s ", "n/a"); \ 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_ci switch (c2c.display) { 10998c2ecf20Sopenharmony_ci case DISPLAY_RMT: 11008c2ecf20Sopenharmony_ci DISPLAY_HITM(rmt_hitm); 11018c2ecf20Sopenharmony_ci break; 11028c2ecf20Sopenharmony_ci case DISPLAY_LCL: 11038c2ecf20Sopenharmony_ci DISPLAY_HITM(lcl_hitm); 11048c2ecf20Sopenharmony_ci break; 11058c2ecf20Sopenharmony_ci case DISPLAY_TOT: 11068c2ecf20Sopenharmony_ci DISPLAY_HITM(tot_hitm); 11078c2ecf20Sopenharmony_ci default: 11088c2ecf20Sopenharmony_ci break; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci #undef DISPLAY_HITM 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci if (c2c_he->stats.store > 0) { 11168c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%5.1f%%}", 11178c2ecf20Sopenharmony_ci percent(stats->store, c2c_he->stats.store)); 11188c2ecf20Sopenharmony_ci } else { 11198c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%6s}", "n/a"); 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 11238c2ecf20Sopenharmony_ci break; 11248c2ecf20Sopenharmony_ci } 11258c2ecf20Sopenharmony_ci case 2: 11268c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "%2d{", node); 11278c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci ret = bitmap_scnprintf(set, c2c.cpus_cnt, hpp->buf, hpp->size); 11308c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci ret = scnprintf(hpp->buf, hpp->size, "}"); 11338c2ecf20Sopenharmony_ci advance_hpp(hpp, ret); 11348c2ecf20Sopenharmony_ci break; 11358c2ecf20Sopenharmony_ci default: 11368c2ecf20Sopenharmony_ci break; 11378c2ecf20Sopenharmony_ci } 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci first = false; 11408c2ecf20Sopenharmony_ci } 11418c2ecf20Sopenharmony_ci 11428c2ecf20Sopenharmony_ci return 0; 11438c2ecf20Sopenharmony_ci} 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_cistatic int 11468c2ecf20Sopenharmony_cimean_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 11478c2ecf20Sopenharmony_ci struct hist_entry *he, double mean) 11488c2ecf20Sopenharmony_ci{ 11498c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 11508c2ecf20Sopenharmony_ci char buf[10]; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci scnprintf(buf, 10, "%6.0f", mean); 11538c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, buf); 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci#define MEAN_ENTRY(__func, __val) \ 11578c2ecf20Sopenharmony_cistatic int \ 11588c2ecf20Sopenharmony_ci__func(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, struct hist_entry *he) \ 11598c2ecf20Sopenharmony_ci{ \ 11608c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; \ 11618c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); \ 11628c2ecf20Sopenharmony_ci return mean_entry(fmt, hpp, he, avg_stats(&c2c_he->cstats.__val)); \ 11638c2ecf20Sopenharmony_ci} 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ciMEAN_ENTRY(mean_rmt_entry, rmt_hitm); 11668c2ecf20Sopenharmony_ciMEAN_ENTRY(mean_lcl_entry, lcl_hitm); 11678c2ecf20Sopenharmony_ciMEAN_ENTRY(mean_load_entry, load); 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic int 11708c2ecf20Sopenharmony_cicpucnt_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 11718c2ecf20Sopenharmony_ci struct hist_entry *he) 11728c2ecf20Sopenharmony_ci{ 11738c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 11748c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 11758c2ecf20Sopenharmony_ci char buf[10]; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_ci scnprintf(buf, 10, "%d", bitmap_weight(c2c_he->cpuset, c2c.cpus_cnt)); 11808c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, buf); 11818c2ecf20Sopenharmony_ci} 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_cistatic int 11848c2ecf20Sopenharmony_cicl_idx_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 11858c2ecf20Sopenharmony_ci struct hist_entry *he) 11868c2ecf20Sopenharmony_ci{ 11878c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 11888c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 11898c2ecf20Sopenharmony_ci char buf[10]; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci scnprintf(buf, 10, "%u", c2c_he->cacheline_idx); 11948c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, buf); 11958c2ecf20Sopenharmony_ci} 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_cistatic int 11988c2ecf20Sopenharmony_cicl_idx_empty_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 11998c2ecf20Sopenharmony_ci struct hist_entry *he) 12008c2ecf20Sopenharmony_ci{ 12018c2ecf20Sopenharmony_ci int width = c2c_width(fmt, hpp, he->hists); 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci return scnprintf(hpp->buf, hpp->size, "%*s", width, ""); 12048c2ecf20Sopenharmony_ci} 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci#define HEADER_LOW(__h) \ 12078c2ecf20Sopenharmony_ci { \ 12088c2ecf20Sopenharmony_ci .line[1] = { \ 12098c2ecf20Sopenharmony_ci .text = __h, \ 12108c2ecf20Sopenharmony_ci }, \ 12118c2ecf20Sopenharmony_ci } 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci#define HEADER_BOTH(__h0, __h1) \ 12148c2ecf20Sopenharmony_ci { \ 12158c2ecf20Sopenharmony_ci .line[0] = { \ 12168c2ecf20Sopenharmony_ci .text = __h0, \ 12178c2ecf20Sopenharmony_ci }, \ 12188c2ecf20Sopenharmony_ci .line[1] = { \ 12198c2ecf20Sopenharmony_ci .text = __h1, \ 12208c2ecf20Sopenharmony_ci }, \ 12218c2ecf20Sopenharmony_ci } 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci#define HEADER_SPAN(__h0, __h1, __s) \ 12248c2ecf20Sopenharmony_ci { \ 12258c2ecf20Sopenharmony_ci .line[0] = { \ 12268c2ecf20Sopenharmony_ci .text = __h0, \ 12278c2ecf20Sopenharmony_ci .span = __s, \ 12288c2ecf20Sopenharmony_ci }, \ 12298c2ecf20Sopenharmony_ci .line[1] = { \ 12308c2ecf20Sopenharmony_ci .text = __h1, \ 12318c2ecf20Sopenharmony_ci }, \ 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci#define HEADER_SPAN_LOW(__h) \ 12358c2ecf20Sopenharmony_ci { \ 12368c2ecf20Sopenharmony_ci .line[1] = { \ 12378c2ecf20Sopenharmony_ci .text = __h, \ 12388c2ecf20Sopenharmony_ci }, \ 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dcacheline = { 12428c2ecf20Sopenharmony_ci .header = HEADER_SPAN("--- Cacheline ----", "Address", 2), 12438c2ecf20Sopenharmony_ci .name = "dcacheline", 12448c2ecf20Sopenharmony_ci .cmp = dcacheline_cmp, 12458c2ecf20Sopenharmony_ci .entry = dcacheline_entry, 12468c2ecf20Sopenharmony_ci .width = 18, 12478c2ecf20Sopenharmony_ci}; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dcacheline_node = { 12508c2ecf20Sopenharmony_ci .header = HEADER_LOW("Node"), 12518c2ecf20Sopenharmony_ci .name = "dcacheline_node", 12528c2ecf20Sopenharmony_ci .cmp = empty_cmp, 12538c2ecf20Sopenharmony_ci .entry = dcacheline_node_entry, 12548c2ecf20Sopenharmony_ci .width = 4, 12558c2ecf20Sopenharmony_ci}; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dcacheline_count = { 12588c2ecf20Sopenharmony_ci .header = HEADER_LOW("PA cnt"), 12598c2ecf20Sopenharmony_ci .name = "dcacheline_count", 12608c2ecf20Sopenharmony_ci .cmp = empty_cmp, 12618c2ecf20Sopenharmony_ci .entry = dcacheline_node_count, 12628c2ecf20Sopenharmony_ci .width = 6, 12638c2ecf20Sopenharmony_ci}; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_cistatic struct c2c_header header_offset_tui = HEADER_SPAN("-----", "Off", 2); 12668c2ecf20Sopenharmony_ci 12678c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_offset = { 12688c2ecf20Sopenharmony_ci .header = HEADER_SPAN("--- Data address -", "Offset", 2), 12698c2ecf20Sopenharmony_ci .name = "offset", 12708c2ecf20Sopenharmony_ci .cmp = offset_cmp, 12718c2ecf20Sopenharmony_ci .entry = offset_entry, 12728c2ecf20Sopenharmony_ci .width = 18, 12738c2ecf20Sopenharmony_ci}; 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_offset_node = { 12768c2ecf20Sopenharmony_ci .header = HEADER_LOW("Node"), 12778c2ecf20Sopenharmony_ci .name = "offset_node", 12788c2ecf20Sopenharmony_ci .cmp = empty_cmp, 12798c2ecf20Sopenharmony_ci .entry = dcacheline_node_entry, 12808c2ecf20Sopenharmony_ci .width = 4, 12818c2ecf20Sopenharmony_ci}; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_iaddr = { 12848c2ecf20Sopenharmony_ci .header = HEADER_LOW("Code address"), 12858c2ecf20Sopenharmony_ci .name = "iaddr", 12868c2ecf20Sopenharmony_ci .cmp = iaddr_cmp, 12878c2ecf20Sopenharmony_ci .entry = iaddr_entry, 12888c2ecf20Sopenharmony_ci .width = 18, 12898c2ecf20Sopenharmony_ci}; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_tot_hitm = { 12928c2ecf20Sopenharmony_ci .header = HEADER_SPAN("------- Load Hitm -------", "Total", 2), 12938c2ecf20Sopenharmony_ci .name = "tot_hitm", 12948c2ecf20Sopenharmony_ci .cmp = tot_hitm_cmp, 12958c2ecf20Sopenharmony_ci .entry = tot_hitm_entry, 12968c2ecf20Sopenharmony_ci .width = 7, 12978c2ecf20Sopenharmony_ci}; 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_lcl_hitm = { 13008c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("LclHitm"), 13018c2ecf20Sopenharmony_ci .name = "lcl_hitm", 13028c2ecf20Sopenharmony_ci .cmp = lcl_hitm_cmp, 13038c2ecf20Sopenharmony_ci .entry = lcl_hitm_entry, 13048c2ecf20Sopenharmony_ci .width = 7, 13058c2ecf20Sopenharmony_ci}; 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_rmt_hitm = { 13088c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("RmtHitm"), 13098c2ecf20Sopenharmony_ci .name = "rmt_hitm", 13108c2ecf20Sopenharmony_ci .cmp = rmt_hitm_cmp, 13118c2ecf20Sopenharmony_ci .entry = rmt_hitm_entry, 13128c2ecf20Sopenharmony_ci .width = 7, 13138c2ecf20Sopenharmony_ci}; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_cl_rmt_hitm = { 13168c2ecf20Sopenharmony_ci .header = HEADER_SPAN("----- HITM -----", "Rmt", 1), 13178c2ecf20Sopenharmony_ci .name = "cl_rmt_hitm", 13188c2ecf20Sopenharmony_ci .cmp = rmt_hitm_cmp, 13198c2ecf20Sopenharmony_ci .entry = rmt_hitm_entry, 13208c2ecf20Sopenharmony_ci .width = 7, 13218c2ecf20Sopenharmony_ci}; 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_cl_lcl_hitm = { 13248c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("Lcl"), 13258c2ecf20Sopenharmony_ci .name = "cl_lcl_hitm", 13268c2ecf20Sopenharmony_ci .cmp = lcl_hitm_cmp, 13278c2ecf20Sopenharmony_ci .entry = lcl_hitm_entry, 13288c2ecf20Sopenharmony_ci .width = 7, 13298c2ecf20Sopenharmony_ci}; 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_tot_stores = { 13328c2ecf20Sopenharmony_ci .header = HEADER_BOTH("Total", "Stores"), 13338c2ecf20Sopenharmony_ci .name = "tot_stores", 13348c2ecf20Sopenharmony_ci .cmp = store_cmp, 13358c2ecf20Sopenharmony_ci .entry = store_entry, 13368c2ecf20Sopenharmony_ci .width = 7, 13378c2ecf20Sopenharmony_ci}; 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_stores_l1hit = { 13408c2ecf20Sopenharmony_ci .header = HEADER_SPAN("---- Stores ----", "L1Hit", 1), 13418c2ecf20Sopenharmony_ci .name = "stores_l1hit", 13428c2ecf20Sopenharmony_ci .cmp = st_l1hit_cmp, 13438c2ecf20Sopenharmony_ci .entry = st_l1hit_entry, 13448c2ecf20Sopenharmony_ci .width = 7, 13458c2ecf20Sopenharmony_ci}; 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_stores_l1miss = { 13488c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("L1Miss"), 13498c2ecf20Sopenharmony_ci .name = "stores_l1miss", 13508c2ecf20Sopenharmony_ci .cmp = st_l1miss_cmp, 13518c2ecf20Sopenharmony_ci .entry = st_l1miss_entry, 13528c2ecf20Sopenharmony_ci .width = 7, 13538c2ecf20Sopenharmony_ci}; 13548c2ecf20Sopenharmony_ci 13558c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_cl_stores_l1hit = { 13568c2ecf20Sopenharmony_ci .header = HEADER_SPAN("-- Store Refs --", "L1 Hit", 1), 13578c2ecf20Sopenharmony_ci .name = "cl_stores_l1hit", 13588c2ecf20Sopenharmony_ci .cmp = st_l1hit_cmp, 13598c2ecf20Sopenharmony_ci .entry = st_l1hit_entry, 13608c2ecf20Sopenharmony_ci .width = 7, 13618c2ecf20Sopenharmony_ci}; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_cl_stores_l1miss = { 13648c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("L1 Miss"), 13658c2ecf20Sopenharmony_ci .name = "cl_stores_l1miss", 13668c2ecf20Sopenharmony_ci .cmp = st_l1miss_cmp, 13678c2ecf20Sopenharmony_ci .entry = st_l1miss_entry, 13688c2ecf20Sopenharmony_ci .width = 7, 13698c2ecf20Sopenharmony_ci}; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_ld_fbhit = { 13728c2ecf20Sopenharmony_ci .header = HEADER_SPAN("----- Core Load Hit -----", "FB", 2), 13738c2ecf20Sopenharmony_ci .name = "ld_fbhit", 13748c2ecf20Sopenharmony_ci .cmp = ld_fbhit_cmp, 13758c2ecf20Sopenharmony_ci .entry = ld_fbhit_entry, 13768c2ecf20Sopenharmony_ci .width = 7, 13778c2ecf20Sopenharmony_ci}; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_ld_l1hit = { 13808c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("L1"), 13818c2ecf20Sopenharmony_ci .name = "ld_l1hit", 13828c2ecf20Sopenharmony_ci .cmp = ld_l1hit_cmp, 13838c2ecf20Sopenharmony_ci .entry = ld_l1hit_entry, 13848c2ecf20Sopenharmony_ci .width = 7, 13858c2ecf20Sopenharmony_ci}; 13868c2ecf20Sopenharmony_ci 13878c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_ld_l2hit = { 13888c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("L2"), 13898c2ecf20Sopenharmony_ci .name = "ld_l2hit", 13908c2ecf20Sopenharmony_ci .cmp = ld_l2hit_cmp, 13918c2ecf20Sopenharmony_ci .entry = ld_l2hit_entry, 13928c2ecf20Sopenharmony_ci .width = 7, 13938c2ecf20Sopenharmony_ci}; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_ld_llchit = { 13968c2ecf20Sopenharmony_ci .header = HEADER_SPAN("- LLC Load Hit --", "LclHit", 1), 13978c2ecf20Sopenharmony_ci .name = "ld_lclhit", 13988c2ecf20Sopenharmony_ci .cmp = ld_llchit_cmp, 13998c2ecf20Sopenharmony_ci .entry = ld_llchit_entry, 14008c2ecf20Sopenharmony_ci .width = 8, 14018c2ecf20Sopenharmony_ci}; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_ld_rmthit = { 14048c2ecf20Sopenharmony_ci .header = HEADER_SPAN("- RMT Load Hit --", "RmtHit", 1), 14058c2ecf20Sopenharmony_ci .name = "ld_rmthit", 14068c2ecf20Sopenharmony_ci .cmp = rmt_hit_cmp, 14078c2ecf20Sopenharmony_ci .entry = rmt_hit_entry, 14088c2ecf20Sopenharmony_ci .width = 8, 14098c2ecf20Sopenharmony_ci}; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_tot_recs = { 14128c2ecf20Sopenharmony_ci .header = HEADER_BOTH("Total", "records"), 14138c2ecf20Sopenharmony_ci .name = "tot_recs", 14148c2ecf20Sopenharmony_ci .cmp = tot_recs_cmp, 14158c2ecf20Sopenharmony_ci .entry = tot_recs_entry, 14168c2ecf20Sopenharmony_ci .width = 7, 14178c2ecf20Sopenharmony_ci}; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_tot_loads = { 14208c2ecf20Sopenharmony_ci .header = HEADER_BOTH("Total", "Loads"), 14218c2ecf20Sopenharmony_ci .name = "tot_loads", 14228c2ecf20Sopenharmony_ci .cmp = tot_loads_cmp, 14238c2ecf20Sopenharmony_ci .entry = tot_loads_entry, 14248c2ecf20Sopenharmony_ci .width = 7, 14258c2ecf20Sopenharmony_ci}; 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_cistatic struct c2c_header percent_hitm_header[] = { 14288c2ecf20Sopenharmony_ci [DISPLAY_LCL] = HEADER_BOTH("Lcl", "Hitm"), 14298c2ecf20Sopenharmony_ci [DISPLAY_RMT] = HEADER_BOTH("Rmt", "Hitm"), 14308c2ecf20Sopenharmony_ci [DISPLAY_TOT] = HEADER_BOTH("Tot", "Hitm"), 14318c2ecf20Sopenharmony_ci}; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_percent_hitm = { 14348c2ecf20Sopenharmony_ci .name = "percent_hitm", 14358c2ecf20Sopenharmony_ci .cmp = percent_hitm_cmp, 14368c2ecf20Sopenharmony_ci .entry = percent_hitm_entry, 14378c2ecf20Sopenharmony_ci .color = percent_hitm_color, 14388c2ecf20Sopenharmony_ci .width = 7, 14398c2ecf20Sopenharmony_ci}; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_percent_rmt_hitm = { 14428c2ecf20Sopenharmony_ci .header = HEADER_SPAN("----- HITM -----", "RmtHitm", 1), 14438c2ecf20Sopenharmony_ci .name = "percent_rmt_hitm", 14448c2ecf20Sopenharmony_ci .cmp = percent_rmt_hitm_cmp, 14458c2ecf20Sopenharmony_ci .entry = percent_rmt_hitm_entry, 14468c2ecf20Sopenharmony_ci .color = percent_rmt_hitm_color, 14478c2ecf20Sopenharmony_ci .width = 7, 14488c2ecf20Sopenharmony_ci}; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_percent_lcl_hitm = { 14518c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("LclHitm"), 14528c2ecf20Sopenharmony_ci .name = "percent_lcl_hitm", 14538c2ecf20Sopenharmony_ci .cmp = percent_lcl_hitm_cmp, 14548c2ecf20Sopenharmony_ci .entry = percent_lcl_hitm_entry, 14558c2ecf20Sopenharmony_ci .color = percent_lcl_hitm_color, 14568c2ecf20Sopenharmony_ci .width = 7, 14578c2ecf20Sopenharmony_ci}; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_percent_stores_l1hit = { 14608c2ecf20Sopenharmony_ci .header = HEADER_SPAN("-- Store Refs --", "L1 Hit", 1), 14618c2ecf20Sopenharmony_ci .name = "percent_stores_l1hit", 14628c2ecf20Sopenharmony_ci .cmp = percent_stores_l1hit_cmp, 14638c2ecf20Sopenharmony_ci .entry = percent_stores_l1hit_entry, 14648c2ecf20Sopenharmony_ci .color = percent_stores_l1hit_color, 14658c2ecf20Sopenharmony_ci .width = 7, 14668c2ecf20Sopenharmony_ci}; 14678c2ecf20Sopenharmony_ci 14688c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_percent_stores_l1miss = { 14698c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("L1 Miss"), 14708c2ecf20Sopenharmony_ci .name = "percent_stores_l1miss", 14718c2ecf20Sopenharmony_ci .cmp = percent_stores_l1miss_cmp, 14728c2ecf20Sopenharmony_ci .entry = percent_stores_l1miss_entry, 14738c2ecf20Sopenharmony_ci .color = percent_stores_l1miss_color, 14748c2ecf20Sopenharmony_ci .width = 7, 14758c2ecf20Sopenharmony_ci}; 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dram_lcl = { 14788c2ecf20Sopenharmony_ci .header = HEADER_SPAN("--- Load Dram ----", "Lcl", 1), 14798c2ecf20Sopenharmony_ci .name = "dram_lcl", 14808c2ecf20Sopenharmony_ci .cmp = lcl_dram_cmp, 14818c2ecf20Sopenharmony_ci .entry = lcl_dram_entry, 14828c2ecf20Sopenharmony_ci .width = 8, 14838c2ecf20Sopenharmony_ci}; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dram_rmt = { 14868c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("Rmt"), 14878c2ecf20Sopenharmony_ci .name = "dram_rmt", 14888c2ecf20Sopenharmony_ci .cmp = rmt_dram_cmp, 14898c2ecf20Sopenharmony_ci .entry = rmt_dram_entry, 14908c2ecf20Sopenharmony_ci .width = 8, 14918c2ecf20Sopenharmony_ci}; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_pid = { 14948c2ecf20Sopenharmony_ci .header = HEADER_LOW("Pid"), 14958c2ecf20Sopenharmony_ci .name = "pid", 14968c2ecf20Sopenharmony_ci .cmp = pid_cmp, 14978c2ecf20Sopenharmony_ci .entry = pid_entry, 14988c2ecf20Sopenharmony_ci .width = 7, 14998c2ecf20Sopenharmony_ci}; 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_tid = { 15028c2ecf20Sopenharmony_ci .header = HEADER_LOW("Tid"), 15038c2ecf20Sopenharmony_ci .name = "tid", 15048c2ecf20Sopenharmony_ci .se = &sort_thread, 15058c2ecf20Sopenharmony_ci}; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_symbol = { 15088c2ecf20Sopenharmony_ci .name = "symbol", 15098c2ecf20Sopenharmony_ci .se = &sort_sym, 15108c2ecf20Sopenharmony_ci}; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dso = { 15138c2ecf20Sopenharmony_ci .header = HEADER_BOTH("Shared", "Object"), 15148c2ecf20Sopenharmony_ci .name = "dso", 15158c2ecf20Sopenharmony_ci .se = &sort_dso, 15168c2ecf20Sopenharmony_ci}; 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_cistatic struct c2c_header header_node[3] = { 15198c2ecf20Sopenharmony_ci HEADER_LOW("Node"), 15208c2ecf20Sopenharmony_ci HEADER_LOW("Node{cpus %hitms %stores}"), 15218c2ecf20Sopenharmony_ci HEADER_LOW("Node{cpu list}"), 15228c2ecf20Sopenharmony_ci}; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_node = { 15258c2ecf20Sopenharmony_ci .name = "node", 15268c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15278c2ecf20Sopenharmony_ci .entry = node_entry, 15288c2ecf20Sopenharmony_ci .width = 4, 15298c2ecf20Sopenharmony_ci}; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_mean_rmt = { 15328c2ecf20Sopenharmony_ci .header = HEADER_SPAN("---------- cycles ----------", "rmt hitm", 2), 15338c2ecf20Sopenharmony_ci .name = "mean_rmt", 15348c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15358c2ecf20Sopenharmony_ci .entry = mean_rmt_entry, 15368c2ecf20Sopenharmony_ci .width = 8, 15378c2ecf20Sopenharmony_ci}; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_mean_lcl = { 15408c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("lcl hitm"), 15418c2ecf20Sopenharmony_ci .name = "mean_lcl", 15428c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15438c2ecf20Sopenharmony_ci .entry = mean_lcl_entry, 15448c2ecf20Sopenharmony_ci .width = 8, 15458c2ecf20Sopenharmony_ci}; 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_mean_load = { 15488c2ecf20Sopenharmony_ci .header = HEADER_SPAN_LOW("load"), 15498c2ecf20Sopenharmony_ci .name = "mean_load", 15508c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15518c2ecf20Sopenharmony_ci .entry = mean_load_entry, 15528c2ecf20Sopenharmony_ci .width = 8, 15538c2ecf20Sopenharmony_ci}; 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_cpucnt = { 15568c2ecf20Sopenharmony_ci .header = HEADER_BOTH("cpu", "cnt"), 15578c2ecf20Sopenharmony_ci .name = "cpucnt", 15588c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15598c2ecf20Sopenharmony_ci .entry = cpucnt_entry, 15608c2ecf20Sopenharmony_ci .width = 8, 15618c2ecf20Sopenharmony_ci}; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_srcline = { 15648c2ecf20Sopenharmony_ci .name = "cl_srcline", 15658c2ecf20Sopenharmony_ci .se = &sort_srcline, 15668c2ecf20Sopenharmony_ci}; 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dcacheline_idx = { 15698c2ecf20Sopenharmony_ci .header = HEADER_LOW("Index"), 15708c2ecf20Sopenharmony_ci .name = "cl_idx", 15718c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15728c2ecf20Sopenharmony_ci .entry = cl_idx_entry, 15738c2ecf20Sopenharmony_ci .width = 5, 15748c2ecf20Sopenharmony_ci}; 15758c2ecf20Sopenharmony_ci 15768c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dcacheline_num = { 15778c2ecf20Sopenharmony_ci .header = HEADER_LOW("Num"), 15788c2ecf20Sopenharmony_ci .name = "cl_num", 15798c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15808c2ecf20Sopenharmony_ci .entry = cl_idx_entry, 15818c2ecf20Sopenharmony_ci .width = 5, 15828c2ecf20Sopenharmony_ci}; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_cistatic struct c2c_dimension dim_dcacheline_num_empty = { 15858c2ecf20Sopenharmony_ci .header = HEADER_LOW("Num"), 15868c2ecf20Sopenharmony_ci .name = "cl_num_empty", 15878c2ecf20Sopenharmony_ci .cmp = empty_cmp, 15888c2ecf20Sopenharmony_ci .entry = cl_idx_empty_entry, 15898c2ecf20Sopenharmony_ci .width = 5, 15908c2ecf20Sopenharmony_ci}; 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_cistatic struct c2c_dimension *dimensions[] = { 15938c2ecf20Sopenharmony_ci &dim_dcacheline, 15948c2ecf20Sopenharmony_ci &dim_dcacheline_node, 15958c2ecf20Sopenharmony_ci &dim_dcacheline_count, 15968c2ecf20Sopenharmony_ci &dim_offset, 15978c2ecf20Sopenharmony_ci &dim_offset_node, 15988c2ecf20Sopenharmony_ci &dim_iaddr, 15998c2ecf20Sopenharmony_ci &dim_tot_hitm, 16008c2ecf20Sopenharmony_ci &dim_lcl_hitm, 16018c2ecf20Sopenharmony_ci &dim_rmt_hitm, 16028c2ecf20Sopenharmony_ci &dim_cl_lcl_hitm, 16038c2ecf20Sopenharmony_ci &dim_cl_rmt_hitm, 16048c2ecf20Sopenharmony_ci &dim_tot_stores, 16058c2ecf20Sopenharmony_ci &dim_stores_l1hit, 16068c2ecf20Sopenharmony_ci &dim_stores_l1miss, 16078c2ecf20Sopenharmony_ci &dim_cl_stores_l1hit, 16088c2ecf20Sopenharmony_ci &dim_cl_stores_l1miss, 16098c2ecf20Sopenharmony_ci &dim_ld_fbhit, 16108c2ecf20Sopenharmony_ci &dim_ld_l1hit, 16118c2ecf20Sopenharmony_ci &dim_ld_l2hit, 16128c2ecf20Sopenharmony_ci &dim_ld_llchit, 16138c2ecf20Sopenharmony_ci &dim_ld_rmthit, 16148c2ecf20Sopenharmony_ci &dim_tot_recs, 16158c2ecf20Sopenharmony_ci &dim_tot_loads, 16168c2ecf20Sopenharmony_ci &dim_percent_hitm, 16178c2ecf20Sopenharmony_ci &dim_percent_rmt_hitm, 16188c2ecf20Sopenharmony_ci &dim_percent_lcl_hitm, 16198c2ecf20Sopenharmony_ci &dim_percent_stores_l1hit, 16208c2ecf20Sopenharmony_ci &dim_percent_stores_l1miss, 16218c2ecf20Sopenharmony_ci &dim_dram_lcl, 16228c2ecf20Sopenharmony_ci &dim_dram_rmt, 16238c2ecf20Sopenharmony_ci &dim_pid, 16248c2ecf20Sopenharmony_ci &dim_tid, 16258c2ecf20Sopenharmony_ci &dim_symbol, 16268c2ecf20Sopenharmony_ci &dim_dso, 16278c2ecf20Sopenharmony_ci &dim_node, 16288c2ecf20Sopenharmony_ci &dim_mean_rmt, 16298c2ecf20Sopenharmony_ci &dim_mean_lcl, 16308c2ecf20Sopenharmony_ci &dim_mean_load, 16318c2ecf20Sopenharmony_ci &dim_cpucnt, 16328c2ecf20Sopenharmony_ci &dim_srcline, 16338c2ecf20Sopenharmony_ci &dim_dcacheline_idx, 16348c2ecf20Sopenharmony_ci &dim_dcacheline_num, 16358c2ecf20Sopenharmony_ci &dim_dcacheline_num_empty, 16368c2ecf20Sopenharmony_ci NULL, 16378c2ecf20Sopenharmony_ci}; 16388c2ecf20Sopenharmony_ci 16398c2ecf20Sopenharmony_cistatic void fmt_free(struct perf_hpp_fmt *fmt) 16408c2ecf20Sopenharmony_ci{ 16418c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt; 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci c2c_fmt = container_of(fmt, struct c2c_fmt, fmt); 16448c2ecf20Sopenharmony_ci free(c2c_fmt); 16458c2ecf20Sopenharmony_ci} 16468c2ecf20Sopenharmony_ci 16478c2ecf20Sopenharmony_cistatic bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b) 16488c2ecf20Sopenharmony_ci{ 16498c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_a = container_of(a, struct c2c_fmt, fmt); 16508c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_b = container_of(b, struct c2c_fmt, fmt); 16518c2ecf20Sopenharmony_ci 16528c2ecf20Sopenharmony_ci return c2c_a->dim == c2c_b->dim; 16538c2ecf20Sopenharmony_ci} 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_cistatic struct c2c_dimension *get_dimension(const char *name) 16568c2ecf20Sopenharmony_ci{ 16578c2ecf20Sopenharmony_ci unsigned int i; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci for (i = 0; dimensions[i]; i++) { 16608c2ecf20Sopenharmony_ci struct c2c_dimension *dim = dimensions[i]; 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci if (!strcmp(dim->name, name)) 16638c2ecf20Sopenharmony_ci return dim; 16648c2ecf20Sopenharmony_ci } 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci return NULL; 16678c2ecf20Sopenharmony_ci} 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_cistatic int c2c_se_entry(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 16708c2ecf20Sopenharmony_ci struct hist_entry *he) 16718c2ecf20Sopenharmony_ci{ 16728c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt); 16738c2ecf20Sopenharmony_ci struct c2c_dimension *dim = c2c_fmt->dim; 16748c2ecf20Sopenharmony_ci size_t len = fmt->user_len; 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_ci if (!len) { 16778c2ecf20Sopenharmony_ci len = hists__col_len(he->hists, dim->se->se_width_idx); 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci if (dim == &dim_symbol || dim == &dim_srcline) 16808c2ecf20Sopenharmony_ci len = symbol_width(he->hists, dim->se); 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci return dim->se->se_snprintf(he, hpp->buf, hpp->size, len); 16848c2ecf20Sopenharmony_ci} 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_cistatic int64_t c2c_se_cmp(struct perf_hpp_fmt *fmt, 16878c2ecf20Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) 16888c2ecf20Sopenharmony_ci{ 16898c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt); 16908c2ecf20Sopenharmony_ci struct c2c_dimension *dim = c2c_fmt->dim; 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci return dim->se->se_cmp(a, b); 16938c2ecf20Sopenharmony_ci} 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_cistatic int64_t c2c_se_collapse(struct perf_hpp_fmt *fmt, 16968c2ecf20Sopenharmony_ci struct hist_entry *a, struct hist_entry *b) 16978c2ecf20Sopenharmony_ci{ 16988c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt = container_of(fmt, struct c2c_fmt, fmt); 16998c2ecf20Sopenharmony_ci struct c2c_dimension *dim = c2c_fmt->dim; 17008c2ecf20Sopenharmony_ci int64_t (*collapse_fn)(struct hist_entry *, struct hist_entry *); 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci collapse_fn = dim->se->se_collapse ?: dim->se->se_cmp; 17038c2ecf20Sopenharmony_ci return collapse_fn(a, b); 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_cistatic struct c2c_fmt *get_format(const char *name) 17078c2ecf20Sopenharmony_ci{ 17088c2ecf20Sopenharmony_ci struct c2c_dimension *dim = get_dimension(name); 17098c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt; 17108c2ecf20Sopenharmony_ci struct perf_hpp_fmt *fmt; 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci if (!dim) 17138c2ecf20Sopenharmony_ci return NULL; 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci c2c_fmt = zalloc(sizeof(*c2c_fmt)); 17168c2ecf20Sopenharmony_ci if (!c2c_fmt) 17178c2ecf20Sopenharmony_ci return NULL; 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_ci c2c_fmt->dim = dim; 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci fmt = &c2c_fmt->fmt; 17228c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fmt->list); 17238c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&fmt->sort_list); 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci fmt->cmp = dim->se ? c2c_se_cmp : dim->cmp; 17268c2ecf20Sopenharmony_ci fmt->sort = dim->se ? c2c_se_cmp : dim->cmp; 17278c2ecf20Sopenharmony_ci fmt->color = dim->se ? NULL : dim->color; 17288c2ecf20Sopenharmony_ci fmt->entry = dim->se ? c2c_se_entry : dim->entry; 17298c2ecf20Sopenharmony_ci fmt->header = c2c_header; 17308c2ecf20Sopenharmony_ci fmt->width = c2c_width; 17318c2ecf20Sopenharmony_ci fmt->collapse = dim->se ? c2c_se_collapse : dim->cmp; 17328c2ecf20Sopenharmony_ci fmt->equal = fmt_equal; 17338c2ecf20Sopenharmony_ci fmt->free = fmt_free; 17348c2ecf20Sopenharmony_ci 17358c2ecf20Sopenharmony_ci return c2c_fmt; 17368c2ecf20Sopenharmony_ci} 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_cistatic int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name) 17398c2ecf20Sopenharmony_ci{ 17408c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt = get_format(name); 17418c2ecf20Sopenharmony_ci 17428c2ecf20Sopenharmony_ci if (!c2c_fmt) { 17438c2ecf20Sopenharmony_ci reset_dimensions(); 17448c2ecf20Sopenharmony_ci return output_field_add(hpp_list, name); 17458c2ecf20Sopenharmony_ci } 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci perf_hpp_list__column_register(hpp_list, &c2c_fmt->fmt); 17488c2ecf20Sopenharmony_ci return 0; 17498c2ecf20Sopenharmony_ci} 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_cistatic int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name) 17528c2ecf20Sopenharmony_ci{ 17538c2ecf20Sopenharmony_ci struct c2c_fmt *c2c_fmt = get_format(name); 17548c2ecf20Sopenharmony_ci struct c2c_dimension *dim; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci if (!c2c_fmt) { 17578c2ecf20Sopenharmony_ci reset_dimensions(); 17588c2ecf20Sopenharmony_ci return sort_dimension__add(hpp_list, name, NULL, 0); 17598c2ecf20Sopenharmony_ci } 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci dim = c2c_fmt->dim; 17628c2ecf20Sopenharmony_ci if (dim == &dim_dso) 17638c2ecf20Sopenharmony_ci hpp_list->dso = 1; 17648c2ecf20Sopenharmony_ci 17658c2ecf20Sopenharmony_ci perf_hpp_list__register_sort_field(hpp_list, &c2c_fmt->fmt); 17668c2ecf20Sopenharmony_ci return 0; 17678c2ecf20Sopenharmony_ci} 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci#define PARSE_LIST(_list, _fn) \ 17708c2ecf20Sopenharmony_ci do { \ 17718c2ecf20Sopenharmony_ci char *tmp, *tok; \ 17728c2ecf20Sopenharmony_ci ret = 0; \ 17738c2ecf20Sopenharmony_ci \ 17748c2ecf20Sopenharmony_ci if (!_list) \ 17758c2ecf20Sopenharmony_ci break; \ 17768c2ecf20Sopenharmony_ci \ 17778c2ecf20Sopenharmony_ci for (tok = strtok_r((char *)_list, ", ", &tmp); \ 17788c2ecf20Sopenharmony_ci tok; tok = strtok_r(NULL, ", ", &tmp)) { \ 17798c2ecf20Sopenharmony_ci ret = _fn(hpp_list, tok); \ 17808c2ecf20Sopenharmony_ci if (ret == -EINVAL) { \ 17818c2ecf20Sopenharmony_ci pr_err("Invalid --fields key: `%s'", tok); \ 17828c2ecf20Sopenharmony_ci break; \ 17838c2ecf20Sopenharmony_ci } else if (ret == -ESRCH) { \ 17848c2ecf20Sopenharmony_ci pr_err("Unknown --fields key: `%s'", tok); \ 17858c2ecf20Sopenharmony_ci break; \ 17868c2ecf20Sopenharmony_ci } \ 17878c2ecf20Sopenharmony_ci } \ 17888c2ecf20Sopenharmony_ci } while (0) 17898c2ecf20Sopenharmony_ci 17908c2ecf20Sopenharmony_cistatic int hpp_list__parse(struct perf_hpp_list *hpp_list, 17918c2ecf20Sopenharmony_ci const char *output_, 17928c2ecf20Sopenharmony_ci const char *sort_) 17938c2ecf20Sopenharmony_ci{ 17948c2ecf20Sopenharmony_ci char *output = output_ ? strdup(output_) : NULL; 17958c2ecf20Sopenharmony_ci char *sort = sort_ ? strdup(sort_) : NULL; 17968c2ecf20Sopenharmony_ci int ret; 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci PARSE_LIST(output, c2c_hists__init_output); 17998c2ecf20Sopenharmony_ci PARSE_LIST(sort, c2c_hists__init_sort); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci /* copy sort keys to output fields */ 18028c2ecf20Sopenharmony_ci perf_hpp__setup_output_field(hpp_list); 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci /* 18058c2ecf20Sopenharmony_ci * We dont need other sorting keys other than those 18068c2ecf20Sopenharmony_ci * we already specified. It also really slows down 18078c2ecf20Sopenharmony_ci * the processing a lot with big number of output 18088c2ecf20Sopenharmony_ci * fields, so switching this off for c2c. 18098c2ecf20Sopenharmony_ci */ 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci#if 0 18128c2ecf20Sopenharmony_ci /* and then copy output fields to sort keys */ 18138c2ecf20Sopenharmony_ci perf_hpp__append_sort_keys(&hists->list); 18148c2ecf20Sopenharmony_ci#endif 18158c2ecf20Sopenharmony_ci 18168c2ecf20Sopenharmony_ci free(output); 18178c2ecf20Sopenharmony_ci free(sort); 18188c2ecf20Sopenharmony_ci return ret; 18198c2ecf20Sopenharmony_ci} 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_cistatic int c2c_hists__init(struct c2c_hists *hists, 18228c2ecf20Sopenharmony_ci const char *sort, 18238c2ecf20Sopenharmony_ci int nr_header_lines) 18248c2ecf20Sopenharmony_ci{ 18258c2ecf20Sopenharmony_ci __hists__init(&hists->hists, &hists->list); 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci /* 18288c2ecf20Sopenharmony_ci * Initialize only with sort fields, we need to resort 18298c2ecf20Sopenharmony_ci * later anyway, and that's where we add output fields 18308c2ecf20Sopenharmony_ci * as well. 18318c2ecf20Sopenharmony_ci */ 18328c2ecf20Sopenharmony_ci perf_hpp_list__init(&hists->list); 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci /* Overload number of header lines.*/ 18358c2ecf20Sopenharmony_ci hists->list.nr_header_lines = nr_header_lines; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci return hpp_list__parse(&hists->list, NULL, sort); 18388c2ecf20Sopenharmony_ci} 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_cistatic int c2c_hists__reinit(struct c2c_hists *c2c_hists, 18418c2ecf20Sopenharmony_ci const char *output, 18428c2ecf20Sopenharmony_ci const char *sort) 18438c2ecf20Sopenharmony_ci{ 18448c2ecf20Sopenharmony_ci perf_hpp__reset_output_field(&c2c_hists->list); 18458c2ecf20Sopenharmony_ci return hpp_list__parse(&c2c_hists->list, output, sort); 18468c2ecf20Sopenharmony_ci} 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci#define DISPLAY_LINE_LIMIT 0.001 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_cistatic bool he__display(struct hist_entry *he, struct c2c_stats *stats) 18518c2ecf20Sopenharmony_ci{ 18528c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 18538c2ecf20Sopenharmony_ci double ld_dist; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci if (c2c.show_all) 18568c2ecf20Sopenharmony_ci return true; 18578c2ecf20Sopenharmony_ci 18588c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci#define FILTER_HITM(__h) \ 18618c2ecf20Sopenharmony_ci if (stats->__h) { \ 18628c2ecf20Sopenharmony_ci ld_dist = ((double)c2c_he->stats.__h / stats->__h); \ 18638c2ecf20Sopenharmony_ci if (ld_dist < DISPLAY_LINE_LIMIT) \ 18648c2ecf20Sopenharmony_ci he->filtered = HIST_FILTER__C2C; \ 18658c2ecf20Sopenharmony_ci } else { \ 18668c2ecf20Sopenharmony_ci he->filtered = HIST_FILTER__C2C; \ 18678c2ecf20Sopenharmony_ci } 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci switch (c2c.display) { 18708c2ecf20Sopenharmony_ci case DISPLAY_LCL: 18718c2ecf20Sopenharmony_ci FILTER_HITM(lcl_hitm); 18728c2ecf20Sopenharmony_ci break; 18738c2ecf20Sopenharmony_ci case DISPLAY_RMT: 18748c2ecf20Sopenharmony_ci FILTER_HITM(rmt_hitm); 18758c2ecf20Sopenharmony_ci break; 18768c2ecf20Sopenharmony_ci case DISPLAY_TOT: 18778c2ecf20Sopenharmony_ci FILTER_HITM(tot_hitm); 18788c2ecf20Sopenharmony_ci default: 18798c2ecf20Sopenharmony_ci break; 18808c2ecf20Sopenharmony_ci } 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci#undef FILTER_HITM 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci return he->filtered == 0; 18858c2ecf20Sopenharmony_ci} 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_cistatic inline int valid_hitm_or_store(struct hist_entry *he) 18888c2ecf20Sopenharmony_ci{ 18898c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 18908c2ecf20Sopenharmony_ci bool has_hitm; 18918c2ecf20Sopenharmony_ci 18928c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 18938c2ecf20Sopenharmony_ci has_hitm = c2c.display == DISPLAY_TOT ? c2c_he->stats.tot_hitm : 18948c2ecf20Sopenharmony_ci c2c.display == DISPLAY_LCL ? c2c_he->stats.lcl_hitm : 18958c2ecf20Sopenharmony_ci c2c_he->stats.rmt_hitm; 18968c2ecf20Sopenharmony_ci return has_hitm || c2c_he->stats.store; 18978c2ecf20Sopenharmony_ci} 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_cistatic void set_node_width(struct c2c_hist_entry *c2c_he, int len) 19008c2ecf20Sopenharmony_ci{ 19018c2ecf20Sopenharmony_ci struct c2c_dimension *dim; 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ci dim = &c2c.hists == c2c_he->hists ? 19048c2ecf20Sopenharmony_ci &dim_dcacheline_node : &dim_offset_node; 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci if (len > dim->width) 19078c2ecf20Sopenharmony_ci dim->width = len; 19088c2ecf20Sopenharmony_ci} 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_cistatic int set_nodestr(struct c2c_hist_entry *c2c_he) 19118c2ecf20Sopenharmony_ci{ 19128c2ecf20Sopenharmony_ci char buf[30]; 19138c2ecf20Sopenharmony_ci int len; 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci if (c2c_he->nodestr) 19168c2ecf20Sopenharmony_ci return 0; 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_ci if (bitmap_weight(c2c_he->nodeset, c2c.nodes_cnt)) { 19198c2ecf20Sopenharmony_ci len = bitmap_scnprintf(c2c_he->nodeset, c2c.nodes_cnt, 19208c2ecf20Sopenharmony_ci buf, sizeof(buf)); 19218c2ecf20Sopenharmony_ci } else { 19228c2ecf20Sopenharmony_ci len = scnprintf(buf, sizeof(buf), "N/A"); 19238c2ecf20Sopenharmony_ci } 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci set_node_width(c2c_he, len); 19268c2ecf20Sopenharmony_ci c2c_he->nodestr = strdup(buf); 19278c2ecf20Sopenharmony_ci return c2c_he->nodestr ? 0 : -ENOMEM; 19288c2ecf20Sopenharmony_ci} 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_cistatic void calc_width(struct c2c_hist_entry *c2c_he) 19318c2ecf20Sopenharmony_ci{ 19328c2ecf20Sopenharmony_ci struct c2c_hists *c2c_hists; 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci c2c_hists = container_of(c2c_he->he.hists, struct c2c_hists, hists); 19358c2ecf20Sopenharmony_ci hists__calc_col_len(&c2c_hists->hists, &c2c_he->he); 19368c2ecf20Sopenharmony_ci set_nodestr(c2c_he); 19378c2ecf20Sopenharmony_ci} 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_cistatic int filter_cb(struct hist_entry *he, void *arg __maybe_unused) 19408c2ecf20Sopenharmony_ci{ 19418c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci if (c2c.show_src && !he->srcline) 19468c2ecf20Sopenharmony_ci he->srcline = hist_entry__srcline(he); 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci calc_width(c2c_he); 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci if (!valid_hitm_or_store(he)) 19518c2ecf20Sopenharmony_ci he->filtered = HIST_FILTER__C2C; 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_ci return 0; 19548c2ecf20Sopenharmony_ci} 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_cistatic int resort_cl_cb(struct hist_entry *he, void *arg __maybe_unused) 19578c2ecf20Sopenharmony_ci{ 19588c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 19598c2ecf20Sopenharmony_ci struct c2c_hists *c2c_hists; 19608c2ecf20Sopenharmony_ci bool display = he__display(he, &c2c.hitm_stats); 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 19638c2ecf20Sopenharmony_ci c2c_hists = c2c_he->hists; 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci if (display && c2c_hists) { 19668c2ecf20Sopenharmony_ci static unsigned int idx; 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci c2c_he->cacheline_idx = idx++; 19698c2ecf20Sopenharmony_ci calc_width(c2c_he); 19708c2ecf20Sopenharmony_ci 19718c2ecf20Sopenharmony_ci c2c_hists__reinit(c2c_hists, c2c.cl_output, c2c.cl_resort); 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci hists__collapse_resort(&c2c_hists->hists, NULL); 19748c2ecf20Sopenharmony_ci hists__output_resort_cb(&c2c_hists->hists, NULL, filter_cb); 19758c2ecf20Sopenharmony_ci } 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci return 0; 19788c2ecf20Sopenharmony_ci} 19798c2ecf20Sopenharmony_ci 19808c2ecf20Sopenharmony_cistatic void setup_nodes_header(void) 19818c2ecf20Sopenharmony_ci{ 19828c2ecf20Sopenharmony_ci dim_node.header = header_node[c2c.node_info]; 19838c2ecf20Sopenharmony_ci} 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_cistatic int setup_nodes(struct perf_session *session) 19868c2ecf20Sopenharmony_ci{ 19878c2ecf20Sopenharmony_ci struct numa_node *n; 19888c2ecf20Sopenharmony_ci unsigned long **nodes; 19898c2ecf20Sopenharmony_ci int node, cpu; 19908c2ecf20Sopenharmony_ci int *cpu2node; 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_ci if (c2c.node_info > 2) 19938c2ecf20Sopenharmony_ci c2c.node_info = 2; 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci c2c.nodes_cnt = session->header.env.nr_numa_nodes; 19968c2ecf20Sopenharmony_ci c2c.cpus_cnt = session->header.env.nr_cpus_avail; 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci n = session->header.env.numa_nodes; 19998c2ecf20Sopenharmony_ci if (!n) 20008c2ecf20Sopenharmony_ci return -EINVAL; 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci nodes = zalloc(sizeof(unsigned long *) * c2c.nodes_cnt); 20038c2ecf20Sopenharmony_ci if (!nodes) 20048c2ecf20Sopenharmony_ci return -ENOMEM; 20058c2ecf20Sopenharmony_ci 20068c2ecf20Sopenharmony_ci c2c.nodes = nodes; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci cpu2node = zalloc(sizeof(int) * c2c.cpus_cnt); 20098c2ecf20Sopenharmony_ci if (!cpu2node) 20108c2ecf20Sopenharmony_ci return -ENOMEM; 20118c2ecf20Sopenharmony_ci 20128c2ecf20Sopenharmony_ci for (cpu = 0; cpu < c2c.cpus_cnt; cpu++) 20138c2ecf20Sopenharmony_ci cpu2node[cpu] = -1; 20148c2ecf20Sopenharmony_ci 20158c2ecf20Sopenharmony_ci c2c.cpu2node = cpu2node; 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci for (node = 0; node < c2c.nodes_cnt; node++) { 20188c2ecf20Sopenharmony_ci struct perf_cpu_map *map = n[node].map; 20198c2ecf20Sopenharmony_ci unsigned long *set; 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci set = bitmap_alloc(c2c.cpus_cnt); 20228c2ecf20Sopenharmony_ci if (!set) 20238c2ecf20Sopenharmony_ci return -ENOMEM; 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci nodes[node] = set; 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci /* empty node, skip */ 20288c2ecf20Sopenharmony_ci if (perf_cpu_map__empty(map)) 20298c2ecf20Sopenharmony_ci continue; 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci for (cpu = 0; cpu < map->nr; cpu++) { 20328c2ecf20Sopenharmony_ci set_bit(map->map[cpu], set); 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci if (WARN_ONCE(cpu2node[map->map[cpu]] != -1, "node/cpu topology bug")) 20358c2ecf20Sopenharmony_ci return -EINVAL; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci cpu2node[map->map[cpu]] = node; 20388c2ecf20Sopenharmony_ci } 20398c2ecf20Sopenharmony_ci } 20408c2ecf20Sopenharmony_ci 20418c2ecf20Sopenharmony_ci setup_nodes_header(); 20428c2ecf20Sopenharmony_ci return 0; 20438c2ecf20Sopenharmony_ci} 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci#define HAS_HITMS(__h) ((__h)->stats.lcl_hitm || (__h)->stats.rmt_hitm) 20468c2ecf20Sopenharmony_ci 20478c2ecf20Sopenharmony_cistatic int resort_hitm_cb(struct hist_entry *he, void *arg __maybe_unused) 20488c2ecf20Sopenharmony_ci{ 20498c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 20508c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 20518c2ecf20Sopenharmony_ci 20528c2ecf20Sopenharmony_ci if (HAS_HITMS(c2c_he)) { 20538c2ecf20Sopenharmony_ci c2c.shared_clines++; 20548c2ecf20Sopenharmony_ci c2c_add_stats(&c2c.hitm_stats, &c2c_he->stats); 20558c2ecf20Sopenharmony_ci } 20568c2ecf20Sopenharmony_ci 20578c2ecf20Sopenharmony_ci return 0; 20588c2ecf20Sopenharmony_ci} 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_cistatic int hists__iterate_cb(struct hists *hists, hists__resort_cb_t cb) 20618c2ecf20Sopenharmony_ci{ 20628c2ecf20Sopenharmony_ci struct rb_node *next = rb_first_cached(&hists->entries); 20638c2ecf20Sopenharmony_ci int ret = 0; 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci while (next) { 20668c2ecf20Sopenharmony_ci struct hist_entry *he; 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci he = rb_entry(next, struct hist_entry, rb_node); 20698c2ecf20Sopenharmony_ci ret = cb(he, NULL); 20708c2ecf20Sopenharmony_ci if (ret) 20718c2ecf20Sopenharmony_ci break; 20728c2ecf20Sopenharmony_ci next = rb_next(&he->rb_node); 20738c2ecf20Sopenharmony_ci } 20748c2ecf20Sopenharmony_ci 20758c2ecf20Sopenharmony_ci return ret; 20768c2ecf20Sopenharmony_ci} 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_cistatic void print_c2c__display_stats(FILE *out) 20798c2ecf20Sopenharmony_ci{ 20808c2ecf20Sopenharmony_ci int llc_misses; 20818c2ecf20Sopenharmony_ci struct c2c_stats *stats = &c2c.hists.stats; 20828c2ecf20Sopenharmony_ci 20838c2ecf20Sopenharmony_ci llc_misses = stats->lcl_dram + 20848c2ecf20Sopenharmony_ci stats->rmt_dram + 20858c2ecf20Sopenharmony_ci stats->rmt_hit + 20868c2ecf20Sopenharmony_ci stats->rmt_hitm; 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 20898c2ecf20Sopenharmony_ci fprintf(out, " Trace Event Information \n"); 20908c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 20918c2ecf20Sopenharmony_ci fprintf(out, " Total records : %10d\n", stats->nr_entries); 20928c2ecf20Sopenharmony_ci fprintf(out, " Locked Load/Store Operations : %10d\n", stats->locks); 20938c2ecf20Sopenharmony_ci fprintf(out, " Load Operations : %10d\n", stats->load); 20948c2ecf20Sopenharmony_ci fprintf(out, " Loads - uncacheable : %10d\n", stats->ld_uncache); 20958c2ecf20Sopenharmony_ci fprintf(out, " Loads - IO : %10d\n", stats->ld_io); 20968c2ecf20Sopenharmony_ci fprintf(out, " Loads - Miss : %10d\n", stats->ld_miss); 20978c2ecf20Sopenharmony_ci fprintf(out, " Loads - no mapping : %10d\n", stats->ld_noadrs); 20988c2ecf20Sopenharmony_ci fprintf(out, " Load Fill Buffer Hit : %10d\n", stats->ld_fbhit); 20998c2ecf20Sopenharmony_ci fprintf(out, " Load L1D hit : %10d\n", stats->ld_l1hit); 21008c2ecf20Sopenharmony_ci fprintf(out, " Load L2D hit : %10d\n", stats->ld_l2hit); 21018c2ecf20Sopenharmony_ci fprintf(out, " Load LLC hit : %10d\n", stats->ld_llchit + stats->lcl_hitm); 21028c2ecf20Sopenharmony_ci fprintf(out, " Load Local HITM : %10d\n", stats->lcl_hitm); 21038c2ecf20Sopenharmony_ci fprintf(out, " Load Remote HITM : %10d\n", stats->rmt_hitm); 21048c2ecf20Sopenharmony_ci fprintf(out, " Load Remote HIT : %10d\n", stats->rmt_hit); 21058c2ecf20Sopenharmony_ci fprintf(out, " Load Local DRAM : %10d\n", stats->lcl_dram); 21068c2ecf20Sopenharmony_ci fprintf(out, " Load Remote DRAM : %10d\n", stats->rmt_dram); 21078c2ecf20Sopenharmony_ci fprintf(out, " Load MESI State Exclusive : %10d\n", stats->ld_excl); 21088c2ecf20Sopenharmony_ci fprintf(out, " Load MESI State Shared : %10d\n", stats->ld_shared); 21098c2ecf20Sopenharmony_ci fprintf(out, " Load LLC Misses : %10d\n", llc_misses); 21108c2ecf20Sopenharmony_ci fprintf(out, " LLC Misses to Local DRAM : %10.1f%%\n", ((double)stats->lcl_dram/(double)llc_misses) * 100.); 21118c2ecf20Sopenharmony_ci fprintf(out, " LLC Misses to Remote DRAM : %10.1f%%\n", ((double)stats->rmt_dram/(double)llc_misses) * 100.); 21128c2ecf20Sopenharmony_ci fprintf(out, " LLC Misses to Remote cache (HIT) : %10.1f%%\n", ((double)stats->rmt_hit /(double)llc_misses) * 100.); 21138c2ecf20Sopenharmony_ci fprintf(out, " LLC Misses to Remote cache (HITM) : %10.1f%%\n", ((double)stats->rmt_hitm/(double)llc_misses) * 100.); 21148c2ecf20Sopenharmony_ci fprintf(out, " Store Operations : %10d\n", stats->store); 21158c2ecf20Sopenharmony_ci fprintf(out, " Store - uncacheable : %10d\n", stats->st_uncache); 21168c2ecf20Sopenharmony_ci fprintf(out, " Store - no mapping : %10d\n", stats->st_noadrs); 21178c2ecf20Sopenharmony_ci fprintf(out, " Store L1D Hit : %10d\n", stats->st_l1hit); 21188c2ecf20Sopenharmony_ci fprintf(out, " Store L1D Miss : %10d\n", stats->st_l1miss); 21198c2ecf20Sopenharmony_ci fprintf(out, " No Page Map Rejects : %10d\n", stats->nomap); 21208c2ecf20Sopenharmony_ci fprintf(out, " Unable to parse data source : %10d\n", stats->noparse); 21218c2ecf20Sopenharmony_ci} 21228c2ecf20Sopenharmony_ci 21238c2ecf20Sopenharmony_cistatic void print_shared_cacheline_info(FILE *out) 21248c2ecf20Sopenharmony_ci{ 21258c2ecf20Sopenharmony_ci struct c2c_stats *stats = &c2c.hitm_stats; 21268c2ecf20Sopenharmony_ci int hitm_cnt = stats->lcl_hitm + stats->rmt_hitm; 21278c2ecf20Sopenharmony_ci 21288c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 21298c2ecf20Sopenharmony_ci fprintf(out, " Global Shared Cache Line Event Information \n"); 21308c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 21318c2ecf20Sopenharmony_ci fprintf(out, " Total Shared Cache Lines : %10d\n", c2c.shared_clines); 21328c2ecf20Sopenharmony_ci fprintf(out, " Load HITs on shared lines : %10d\n", stats->load); 21338c2ecf20Sopenharmony_ci fprintf(out, " Fill Buffer Hits on shared lines : %10d\n", stats->ld_fbhit); 21348c2ecf20Sopenharmony_ci fprintf(out, " L1D hits on shared lines : %10d\n", stats->ld_l1hit); 21358c2ecf20Sopenharmony_ci fprintf(out, " L2D hits on shared lines : %10d\n", stats->ld_l2hit); 21368c2ecf20Sopenharmony_ci fprintf(out, " LLC hits on shared lines : %10d\n", stats->ld_llchit + stats->lcl_hitm); 21378c2ecf20Sopenharmony_ci fprintf(out, " Locked Access on shared lines : %10d\n", stats->locks); 21388c2ecf20Sopenharmony_ci fprintf(out, " Store HITs on shared lines : %10d\n", stats->store); 21398c2ecf20Sopenharmony_ci fprintf(out, " Store L1D hits on shared lines : %10d\n", stats->st_l1hit); 21408c2ecf20Sopenharmony_ci fprintf(out, " Total Merged records : %10d\n", hitm_cnt + stats->store); 21418c2ecf20Sopenharmony_ci} 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_cistatic void print_cacheline(struct c2c_hists *c2c_hists, 21448c2ecf20Sopenharmony_ci struct hist_entry *he_cl, 21458c2ecf20Sopenharmony_ci struct perf_hpp_list *hpp_list, 21468c2ecf20Sopenharmony_ci FILE *out) 21478c2ecf20Sopenharmony_ci{ 21488c2ecf20Sopenharmony_ci char bf[1000]; 21498c2ecf20Sopenharmony_ci struct perf_hpp hpp = { 21508c2ecf20Sopenharmony_ci .buf = bf, 21518c2ecf20Sopenharmony_ci .size = 1000, 21528c2ecf20Sopenharmony_ci }; 21538c2ecf20Sopenharmony_ci static bool once; 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci if (!once) { 21568c2ecf20Sopenharmony_ci hists__fprintf_headers(&c2c_hists->hists, out); 21578c2ecf20Sopenharmony_ci once = true; 21588c2ecf20Sopenharmony_ci } else { 21598c2ecf20Sopenharmony_ci fprintf(out, "\n"); 21608c2ecf20Sopenharmony_ci } 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci fprintf(out, " -------------------------------------------------------------\n"); 21638c2ecf20Sopenharmony_ci __hist_entry__snprintf(he_cl, &hpp, hpp_list); 21648c2ecf20Sopenharmony_ci fprintf(out, "%s\n", bf); 21658c2ecf20Sopenharmony_ci fprintf(out, " -------------------------------------------------------------\n"); 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci hists__fprintf(&c2c_hists->hists, false, 0, 0, 0, out, false); 21688c2ecf20Sopenharmony_ci} 21698c2ecf20Sopenharmony_ci 21708c2ecf20Sopenharmony_cistatic void print_pareto(FILE *out) 21718c2ecf20Sopenharmony_ci{ 21728c2ecf20Sopenharmony_ci struct perf_hpp_list hpp_list; 21738c2ecf20Sopenharmony_ci struct rb_node *nd; 21748c2ecf20Sopenharmony_ci int ret; 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci perf_hpp_list__init(&hpp_list); 21778c2ecf20Sopenharmony_ci ret = hpp_list__parse(&hpp_list, 21788c2ecf20Sopenharmony_ci "cl_num," 21798c2ecf20Sopenharmony_ci "cl_rmt_hitm," 21808c2ecf20Sopenharmony_ci "cl_lcl_hitm," 21818c2ecf20Sopenharmony_ci "cl_stores_l1hit," 21828c2ecf20Sopenharmony_ci "cl_stores_l1miss," 21838c2ecf20Sopenharmony_ci "dcacheline", 21848c2ecf20Sopenharmony_ci NULL); 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci if (WARN_ONCE(ret, "failed to setup sort entries\n")) 21878c2ecf20Sopenharmony_ci return; 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci nd = rb_first_cached(&c2c.hists.hists.entries); 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci for (; nd; nd = rb_next(nd)) { 21928c2ecf20Sopenharmony_ci struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); 21938c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci if (he->filtered) 21968c2ecf20Sopenharmony_ci continue; 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 21998c2ecf20Sopenharmony_ci print_cacheline(c2c_he->hists, he, &hpp_list, out); 22008c2ecf20Sopenharmony_ci } 22018c2ecf20Sopenharmony_ci} 22028c2ecf20Sopenharmony_ci 22038c2ecf20Sopenharmony_cistatic void print_c2c_info(FILE *out, struct perf_session *session) 22048c2ecf20Sopenharmony_ci{ 22058c2ecf20Sopenharmony_ci struct evlist *evlist = session->evlist; 22068c2ecf20Sopenharmony_ci struct evsel *evsel; 22078c2ecf20Sopenharmony_ci bool first = true; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 22108c2ecf20Sopenharmony_ci fprintf(out, " c2c details \n"); 22118c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci evlist__for_each_entry(evlist, evsel) { 22148c2ecf20Sopenharmony_ci fprintf(out, "%-36s: %s\n", first ? " Events" : "", evsel__name(evsel)); 22158c2ecf20Sopenharmony_ci first = false; 22168c2ecf20Sopenharmony_ci } 22178c2ecf20Sopenharmony_ci fprintf(out, " Cachelines sort on : %s HITMs\n", 22188c2ecf20Sopenharmony_ci display_str[c2c.display]); 22198c2ecf20Sopenharmony_ci fprintf(out, " Cacheline data grouping : %s\n", c2c.cl_sort); 22208c2ecf20Sopenharmony_ci} 22218c2ecf20Sopenharmony_ci 22228c2ecf20Sopenharmony_cistatic void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session) 22238c2ecf20Sopenharmony_ci{ 22248c2ecf20Sopenharmony_ci setup_pager(); 22258c2ecf20Sopenharmony_ci 22268c2ecf20Sopenharmony_ci print_c2c__display_stats(out); 22278c2ecf20Sopenharmony_ci fprintf(out, "\n"); 22288c2ecf20Sopenharmony_ci print_shared_cacheline_info(out); 22298c2ecf20Sopenharmony_ci fprintf(out, "\n"); 22308c2ecf20Sopenharmony_ci print_c2c_info(out, session); 22318c2ecf20Sopenharmony_ci 22328c2ecf20Sopenharmony_ci if (c2c.stats_only) 22338c2ecf20Sopenharmony_ci return; 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci fprintf(out, "\n"); 22368c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 22378c2ecf20Sopenharmony_ci fprintf(out, " Shared Data Cache Line Table \n"); 22388c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 22398c2ecf20Sopenharmony_ci fprintf(out, "#\n"); 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci hists__fprintf(&c2c.hists.hists, true, 0, 0, 0, stdout, true); 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci fprintf(out, "\n"); 22448c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 22458c2ecf20Sopenharmony_ci fprintf(out, " Shared Cache Line Distribution Pareto \n"); 22468c2ecf20Sopenharmony_ci fprintf(out, "=================================================\n"); 22478c2ecf20Sopenharmony_ci fprintf(out, "#\n"); 22488c2ecf20Sopenharmony_ci 22498c2ecf20Sopenharmony_ci print_pareto(out); 22508c2ecf20Sopenharmony_ci} 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci#ifdef HAVE_SLANG_SUPPORT 22538c2ecf20Sopenharmony_cistatic void c2c_browser__update_nr_entries(struct hist_browser *hb) 22548c2ecf20Sopenharmony_ci{ 22558c2ecf20Sopenharmony_ci u64 nr_entries = 0; 22568c2ecf20Sopenharmony_ci struct rb_node *nd = rb_first_cached(&hb->hists->entries); 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_ci while (nd) { 22598c2ecf20Sopenharmony_ci struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node); 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci if (!he->filtered) 22628c2ecf20Sopenharmony_ci nr_entries++; 22638c2ecf20Sopenharmony_ci 22648c2ecf20Sopenharmony_ci nd = rb_next(nd); 22658c2ecf20Sopenharmony_ci } 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci hb->nr_non_filtered_entries = nr_entries; 22688c2ecf20Sopenharmony_ci} 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_cistruct c2c_cacheline_browser { 22718c2ecf20Sopenharmony_ci struct hist_browser hb; 22728c2ecf20Sopenharmony_ci struct hist_entry *he; 22738c2ecf20Sopenharmony_ci}; 22748c2ecf20Sopenharmony_ci 22758c2ecf20Sopenharmony_cistatic int 22768c2ecf20Sopenharmony_ciperf_c2c_cacheline_browser__title(struct hist_browser *browser, 22778c2ecf20Sopenharmony_ci char *bf, size_t size) 22788c2ecf20Sopenharmony_ci{ 22798c2ecf20Sopenharmony_ci struct c2c_cacheline_browser *cl_browser; 22808c2ecf20Sopenharmony_ci struct hist_entry *he; 22818c2ecf20Sopenharmony_ci uint64_t addr = 0; 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci cl_browser = container_of(browser, struct c2c_cacheline_browser, hb); 22848c2ecf20Sopenharmony_ci he = cl_browser->he; 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci if (he->mem_info) 22878c2ecf20Sopenharmony_ci addr = cl_address(he->mem_info->daddr.addr); 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci scnprintf(bf, size, "Cacheline 0x%lx", addr); 22908c2ecf20Sopenharmony_ci return 0; 22918c2ecf20Sopenharmony_ci} 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_cistatic struct c2c_cacheline_browser* 22948c2ecf20Sopenharmony_cic2c_cacheline_browser__new(struct hists *hists, struct hist_entry *he) 22958c2ecf20Sopenharmony_ci{ 22968c2ecf20Sopenharmony_ci struct c2c_cacheline_browser *browser; 22978c2ecf20Sopenharmony_ci 22988c2ecf20Sopenharmony_ci browser = zalloc(sizeof(*browser)); 22998c2ecf20Sopenharmony_ci if (browser) { 23008c2ecf20Sopenharmony_ci hist_browser__init(&browser->hb, hists); 23018c2ecf20Sopenharmony_ci browser->hb.c2c_filter = true; 23028c2ecf20Sopenharmony_ci browser->hb.title = perf_c2c_cacheline_browser__title; 23038c2ecf20Sopenharmony_ci browser->he = he; 23048c2ecf20Sopenharmony_ci } 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ci return browser; 23078c2ecf20Sopenharmony_ci} 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_cistatic int perf_c2c__browse_cacheline(struct hist_entry *he) 23108c2ecf20Sopenharmony_ci{ 23118c2ecf20Sopenharmony_ci struct c2c_hist_entry *c2c_he; 23128c2ecf20Sopenharmony_ci struct c2c_hists *c2c_hists; 23138c2ecf20Sopenharmony_ci struct c2c_cacheline_browser *cl_browser; 23148c2ecf20Sopenharmony_ci struct hist_browser *browser; 23158c2ecf20Sopenharmony_ci int key = -1; 23168c2ecf20Sopenharmony_ci static const char help[] = 23178c2ecf20Sopenharmony_ci " ENTER Toggle callchains (if present) \n" 23188c2ecf20Sopenharmony_ci " n Toggle Node details info \n" 23198c2ecf20Sopenharmony_ci " s Toggle full length of symbol and source line columns \n" 23208c2ecf20Sopenharmony_ci " q Return back to cacheline list \n"; 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci if (!he) 23238c2ecf20Sopenharmony_ci return 0; 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci /* Display compact version first. */ 23268c2ecf20Sopenharmony_ci c2c.symbol_full = false; 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci c2c_he = container_of(he, struct c2c_hist_entry, he); 23298c2ecf20Sopenharmony_ci c2c_hists = c2c_he->hists; 23308c2ecf20Sopenharmony_ci 23318c2ecf20Sopenharmony_ci cl_browser = c2c_cacheline_browser__new(&c2c_hists->hists, he); 23328c2ecf20Sopenharmony_ci if (cl_browser == NULL) 23338c2ecf20Sopenharmony_ci return -1; 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_ci browser = &cl_browser->hb; 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_ci /* reset abort key so that it can get Ctrl-C as a key */ 23388c2ecf20Sopenharmony_ci SLang_reset_tty(); 23398c2ecf20Sopenharmony_ci SLang_init_tty(0, 0, 0); 23408c2ecf20Sopenharmony_ci 23418c2ecf20Sopenharmony_ci c2c_browser__update_nr_entries(browser); 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci while (1) { 23448c2ecf20Sopenharmony_ci key = hist_browser__run(browser, "? - help", true, 0); 23458c2ecf20Sopenharmony_ci 23468c2ecf20Sopenharmony_ci switch (key) { 23478c2ecf20Sopenharmony_ci case 's': 23488c2ecf20Sopenharmony_ci c2c.symbol_full = !c2c.symbol_full; 23498c2ecf20Sopenharmony_ci break; 23508c2ecf20Sopenharmony_ci case 'n': 23518c2ecf20Sopenharmony_ci c2c.node_info = (c2c.node_info + 1) % 3; 23528c2ecf20Sopenharmony_ci setup_nodes_header(); 23538c2ecf20Sopenharmony_ci break; 23548c2ecf20Sopenharmony_ci case 'q': 23558c2ecf20Sopenharmony_ci goto out; 23568c2ecf20Sopenharmony_ci case '?': 23578c2ecf20Sopenharmony_ci ui_browser__help_window(&browser->b, help); 23588c2ecf20Sopenharmony_ci break; 23598c2ecf20Sopenharmony_ci default: 23608c2ecf20Sopenharmony_ci break; 23618c2ecf20Sopenharmony_ci } 23628c2ecf20Sopenharmony_ci } 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ciout: 23658c2ecf20Sopenharmony_ci free(cl_browser); 23668c2ecf20Sopenharmony_ci return 0; 23678c2ecf20Sopenharmony_ci} 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_cistatic int perf_c2c_browser__title(struct hist_browser *browser, 23708c2ecf20Sopenharmony_ci char *bf, size_t size) 23718c2ecf20Sopenharmony_ci{ 23728c2ecf20Sopenharmony_ci scnprintf(bf, size, 23738c2ecf20Sopenharmony_ci "Shared Data Cache Line Table " 23748c2ecf20Sopenharmony_ci "(%lu entries, sorted on %s HITMs)", 23758c2ecf20Sopenharmony_ci browser->nr_non_filtered_entries, 23768c2ecf20Sopenharmony_ci display_str[c2c.display]); 23778c2ecf20Sopenharmony_ci return 0; 23788c2ecf20Sopenharmony_ci} 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_cistatic struct hist_browser* 23818c2ecf20Sopenharmony_ciperf_c2c_browser__new(struct hists *hists) 23828c2ecf20Sopenharmony_ci{ 23838c2ecf20Sopenharmony_ci struct hist_browser *browser = hist_browser__new(hists); 23848c2ecf20Sopenharmony_ci 23858c2ecf20Sopenharmony_ci if (browser) { 23868c2ecf20Sopenharmony_ci browser->title = perf_c2c_browser__title; 23878c2ecf20Sopenharmony_ci browser->c2c_filter = true; 23888c2ecf20Sopenharmony_ci } 23898c2ecf20Sopenharmony_ci 23908c2ecf20Sopenharmony_ci return browser; 23918c2ecf20Sopenharmony_ci} 23928c2ecf20Sopenharmony_ci 23938c2ecf20Sopenharmony_cistatic int perf_c2c__hists_browse(struct hists *hists) 23948c2ecf20Sopenharmony_ci{ 23958c2ecf20Sopenharmony_ci struct hist_browser *browser; 23968c2ecf20Sopenharmony_ci int key = -1; 23978c2ecf20Sopenharmony_ci static const char help[] = 23988c2ecf20Sopenharmony_ci " d Display cacheline details \n" 23998c2ecf20Sopenharmony_ci " ENTER Toggle callchains (if present) \n" 24008c2ecf20Sopenharmony_ci " q Quit \n"; 24018c2ecf20Sopenharmony_ci 24028c2ecf20Sopenharmony_ci browser = perf_c2c_browser__new(hists); 24038c2ecf20Sopenharmony_ci if (browser == NULL) 24048c2ecf20Sopenharmony_ci return -1; 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci /* reset abort key so that it can get Ctrl-C as a key */ 24078c2ecf20Sopenharmony_ci SLang_reset_tty(); 24088c2ecf20Sopenharmony_ci SLang_init_tty(0, 0, 0); 24098c2ecf20Sopenharmony_ci 24108c2ecf20Sopenharmony_ci c2c_browser__update_nr_entries(browser); 24118c2ecf20Sopenharmony_ci 24128c2ecf20Sopenharmony_ci while (1) { 24138c2ecf20Sopenharmony_ci key = hist_browser__run(browser, "? - help", true, 0); 24148c2ecf20Sopenharmony_ci 24158c2ecf20Sopenharmony_ci switch (key) { 24168c2ecf20Sopenharmony_ci case 'q': 24178c2ecf20Sopenharmony_ci goto out; 24188c2ecf20Sopenharmony_ci case 'd': 24198c2ecf20Sopenharmony_ci perf_c2c__browse_cacheline(browser->he_selection); 24208c2ecf20Sopenharmony_ci break; 24218c2ecf20Sopenharmony_ci case '?': 24228c2ecf20Sopenharmony_ci ui_browser__help_window(&browser->b, help); 24238c2ecf20Sopenharmony_ci break; 24248c2ecf20Sopenharmony_ci default: 24258c2ecf20Sopenharmony_ci break; 24268c2ecf20Sopenharmony_ci } 24278c2ecf20Sopenharmony_ci } 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ciout: 24308c2ecf20Sopenharmony_ci hist_browser__delete(browser); 24318c2ecf20Sopenharmony_ci return 0; 24328c2ecf20Sopenharmony_ci} 24338c2ecf20Sopenharmony_ci 24348c2ecf20Sopenharmony_cistatic void perf_c2c_display(struct perf_session *session) 24358c2ecf20Sopenharmony_ci{ 24368c2ecf20Sopenharmony_ci if (use_browser == 0) 24378c2ecf20Sopenharmony_ci perf_c2c__hists_fprintf(stdout, session); 24388c2ecf20Sopenharmony_ci else 24398c2ecf20Sopenharmony_ci perf_c2c__hists_browse(&c2c.hists.hists); 24408c2ecf20Sopenharmony_ci} 24418c2ecf20Sopenharmony_ci#else 24428c2ecf20Sopenharmony_cistatic void perf_c2c_display(struct perf_session *session) 24438c2ecf20Sopenharmony_ci{ 24448c2ecf20Sopenharmony_ci use_browser = 0; 24458c2ecf20Sopenharmony_ci perf_c2c__hists_fprintf(stdout, session); 24468c2ecf20Sopenharmony_ci} 24478c2ecf20Sopenharmony_ci#endif /* HAVE_SLANG_SUPPORT */ 24488c2ecf20Sopenharmony_ci 24498c2ecf20Sopenharmony_cistatic char *fill_line(const char *orig, int len) 24508c2ecf20Sopenharmony_ci{ 24518c2ecf20Sopenharmony_ci int i, j, olen = strlen(orig); 24528c2ecf20Sopenharmony_ci char *buf; 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_ci buf = zalloc(len + 1); 24558c2ecf20Sopenharmony_ci if (!buf) 24568c2ecf20Sopenharmony_ci return NULL; 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci j = len / 2 - olen / 2; 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci for (i = 0; i < j - 1; i++) 24618c2ecf20Sopenharmony_ci buf[i] = '-'; 24628c2ecf20Sopenharmony_ci 24638c2ecf20Sopenharmony_ci buf[i++] = ' '; 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci strcpy(buf + i, orig); 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci i += olen; 24688c2ecf20Sopenharmony_ci 24698c2ecf20Sopenharmony_ci buf[i++] = ' '; 24708c2ecf20Sopenharmony_ci 24718c2ecf20Sopenharmony_ci for (; i < len; i++) 24728c2ecf20Sopenharmony_ci buf[i] = '-'; 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci return buf; 24758c2ecf20Sopenharmony_ci} 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_cistatic int ui_quirks(void) 24788c2ecf20Sopenharmony_ci{ 24798c2ecf20Sopenharmony_ci const char *nodestr = "Data address"; 24808c2ecf20Sopenharmony_ci char *buf; 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_ci if (!c2c.use_stdio) { 24838c2ecf20Sopenharmony_ci dim_offset.width = 5; 24848c2ecf20Sopenharmony_ci dim_offset.header = header_offset_tui; 24858c2ecf20Sopenharmony_ci nodestr = "CL"; 24868c2ecf20Sopenharmony_ci } 24878c2ecf20Sopenharmony_ci 24888c2ecf20Sopenharmony_ci dim_percent_hitm.header = percent_hitm_header[c2c.display]; 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_ci /* Fix the zero line for dcacheline column. */ 24918c2ecf20Sopenharmony_ci buf = fill_line("Cacheline", dim_dcacheline.width + 24928c2ecf20Sopenharmony_ci dim_dcacheline_node.width + 24938c2ecf20Sopenharmony_ci dim_dcacheline_count.width + 4); 24948c2ecf20Sopenharmony_ci if (!buf) 24958c2ecf20Sopenharmony_ci return -ENOMEM; 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci dim_dcacheline.header.line[0].text = buf; 24988c2ecf20Sopenharmony_ci 24998c2ecf20Sopenharmony_ci /* Fix the zero line for offset column. */ 25008c2ecf20Sopenharmony_ci buf = fill_line(nodestr, dim_offset.width + 25018c2ecf20Sopenharmony_ci dim_offset_node.width + 25028c2ecf20Sopenharmony_ci dim_dcacheline_count.width + 4); 25038c2ecf20Sopenharmony_ci if (!buf) 25048c2ecf20Sopenharmony_ci return -ENOMEM; 25058c2ecf20Sopenharmony_ci 25068c2ecf20Sopenharmony_ci dim_offset.header.line[0].text = buf; 25078c2ecf20Sopenharmony_ci 25088c2ecf20Sopenharmony_ci return 0; 25098c2ecf20Sopenharmony_ci} 25108c2ecf20Sopenharmony_ci 25118c2ecf20Sopenharmony_ci#define CALLCHAIN_DEFAULT_OPT "graph,0.5,caller,function,percent" 25128c2ecf20Sopenharmony_ci 25138c2ecf20Sopenharmony_ciconst char callchain_help[] = "Display call graph (stack chain/backtrace):\n\n" 25148c2ecf20Sopenharmony_ci CALLCHAIN_REPORT_HELP 25158c2ecf20Sopenharmony_ci "\n\t\t\t\tDefault: " CALLCHAIN_DEFAULT_OPT; 25168c2ecf20Sopenharmony_ci 25178c2ecf20Sopenharmony_cistatic int 25188c2ecf20Sopenharmony_ciparse_callchain_opt(const struct option *opt, const char *arg, int unset) 25198c2ecf20Sopenharmony_ci{ 25208c2ecf20Sopenharmony_ci struct callchain_param *callchain = opt->value; 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_ci callchain->enabled = !unset; 25238c2ecf20Sopenharmony_ci /* 25248c2ecf20Sopenharmony_ci * --no-call-graph 25258c2ecf20Sopenharmony_ci */ 25268c2ecf20Sopenharmony_ci if (unset) { 25278c2ecf20Sopenharmony_ci symbol_conf.use_callchain = false; 25288c2ecf20Sopenharmony_ci callchain->mode = CHAIN_NONE; 25298c2ecf20Sopenharmony_ci return 0; 25308c2ecf20Sopenharmony_ci } 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci return parse_callchain_report_opt(arg); 25338c2ecf20Sopenharmony_ci} 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_cistatic int setup_callchain(struct evlist *evlist) 25368c2ecf20Sopenharmony_ci{ 25378c2ecf20Sopenharmony_ci u64 sample_type = evlist__combined_sample_type(evlist); 25388c2ecf20Sopenharmony_ci enum perf_call_graph_mode mode = CALLCHAIN_NONE; 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci if ((sample_type & PERF_SAMPLE_REGS_USER) && 25418c2ecf20Sopenharmony_ci (sample_type & PERF_SAMPLE_STACK_USER)) { 25428c2ecf20Sopenharmony_ci mode = CALLCHAIN_DWARF; 25438c2ecf20Sopenharmony_ci dwarf_callchain_users = true; 25448c2ecf20Sopenharmony_ci } else if (sample_type & PERF_SAMPLE_BRANCH_STACK) 25458c2ecf20Sopenharmony_ci mode = CALLCHAIN_LBR; 25468c2ecf20Sopenharmony_ci else if (sample_type & PERF_SAMPLE_CALLCHAIN) 25478c2ecf20Sopenharmony_ci mode = CALLCHAIN_FP; 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci if (!callchain_param.enabled && 25508c2ecf20Sopenharmony_ci callchain_param.mode != CHAIN_NONE && 25518c2ecf20Sopenharmony_ci mode != CALLCHAIN_NONE) { 25528c2ecf20Sopenharmony_ci symbol_conf.use_callchain = true; 25538c2ecf20Sopenharmony_ci if (callchain_register_param(&callchain_param) < 0) { 25548c2ecf20Sopenharmony_ci ui__error("Can't register callchain params.\n"); 25558c2ecf20Sopenharmony_ci return -EINVAL; 25568c2ecf20Sopenharmony_ci } 25578c2ecf20Sopenharmony_ci } 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci if (c2c.stitch_lbr && (mode != CALLCHAIN_LBR)) { 25608c2ecf20Sopenharmony_ci ui__warning("Can't find LBR callchain. Switch off --stitch-lbr.\n" 25618c2ecf20Sopenharmony_ci "Please apply --call-graph lbr when recording.\n"); 25628c2ecf20Sopenharmony_ci c2c.stitch_lbr = false; 25638c2ecf20Sopenharmony_ci } 25648c2ecf20Sopenharmony_ci 25658c2ecf20Sopenharmony_ci callchain_param.record_mode = mode; 25668c2ecf20Sopenharmony_ci callchain_param.min_percent = 0; 25678c2ecf20Sopenharmony_ci return 0; 25688c2ecf20Sopenharmony_ci} 25698c2ecf20Sopenharmony_ci 25708c2ecf20Sopenharmony_cistatic int setup_display(const char *str) 25718c2ecf20Sopenharmony_ci{ 25728c2ecf20Sopenharmony_ci const char *display = str ?: "tot"; 25738c2ecf20Sopenharmony_ci 25748c2ecf20Sopenharmony_ci if (!strcmp(display, "tot")) 25758c2ecf20Sopenharmony_ci c2c.display = DISPLAY_TOT; 25768c2ecf20Sopenharmony_ci else if (!strcmp(display, "rmt")) 25778c2ecf20Sopenharmony_ci c2c.display = DISPLAY_RMT; 25788c2ecf20Sopenharmony_ci else if (!strcmp(display, "lcl")) 25798c2ecf20Sopenharmony_ci c2c.display = DISPLAY_LCL; 25808c2ecf20Sopenharmony_ci else { 25818c2ecf20Sopenharmony_ci pr_err("failed: unknown display type: %s\n", str); 25828c2ecf20Sopenharmony_ci return -1; 25838c2ecf20Sopenharmony_ci } 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci return 0; 25868c2ecf20Sopenharmony_ci} 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci#define for_each_token(__tok, __buf, __sep, __tmp) \ 25898c2ecf20Sopenharmony_ci for (__tok = strtok_r(__buf, __sep, &__tmp); __tok; \ 25908c2ecf20Sopenharmony_ci __tok = strtok_r(NULL, __sep, &__tmp)) 25918c2ecf20Sopenharmony_ci 25928c2ecf20Sopenharmony_cistatic int build_cl_output(char *cl_sort, bool no_source) 25938c2ecf20Sopenharmony_ci{ 25948c2ecf20Sopenharmony_ci char *tok, *tmp, *buf = strdup(cl_sort); 25958c2ecf20Sopenharmony_ci bool add_pid = false; 25968c2ecf20Sopenharmony_ci bool add_tid = false; 25978c2ecf20Sopenharmony_ci bool add_iaddr = false; 25988c2ecf20Sopenharmony_ci bool add_sym = false; 25998c2ecf20Sopenharmony_ci bool add_dso = false; 26008c2ecf20Sopenharmony_ci bool add_src = false; 26018c2ecf20Sopenharmony_ci int ret = 0; 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_ci if (!buf) 26048c2ecf20Sopenharmony_ci return -ENOMEM; 26058c2ecf20Sopenharmony_ci 26068c2ecf20Sopenharmony_ci for_each_token(tok, buf, ",", tmp) { 26078c2ecf20Sopenharmony_ci if (!strcmp(tok, "tid")) { 26088c2ecf20Sopenharmony_ci add_tid = true; 26098c2ecf20Sopenharmony_ci } else if (!strcmp(tok, "pid")) { 26108c2ecf20Sopenharmony_ci add_pid = true; 26118c2ecf20Sopenharmony_ci } else if (!strcmp(tok, "iaddr")) { 26128c2ecf20Sopenharmony_ci add_iaddr = true; 26138c2ecf20Sopenharmony_ci add_sym = true; 26148c2ecf20Sopenharmony_ci add_dso = true; 26158c2ecf20Sopenharmony_ci add_src = no_source ? false : true; 26168c2ecf20Sopenharmony_ci } else if (!strcmp(tok, "dso")) { 26178c2ecf20Sopenharmony_ci add_dso = true; 26188c2ecf20Sopenharmony_ci } else if (strcmp(tok, "offset")) { 26198c2ecf20Sopenharmony_ci pr_err("unrecognized sort token: %s\n", tok); 26208c2ecf20Sopenharmony_ci ret = -EINVAL; 26218c2ecf20Sopenharmony_ci goto err; 26228c2ecf20Sopenharmony_ci } 26238c2ecf20Sopenharmony_ci } 26248c2ecf20Sopenharmony_ci 26258c2ecf20Sopenharmony_ci if (asprintf(&c2c.cl_output, 26268c2ecf20Sopenharmony_ci "%s%s%s%s%s%s%s%s%s%s", 26278c2ecf20Sopenharmony_ci c2c.use_stdio ? "cl_num_empty," : "", 26288c2ecf20Sopenharmony_ci "percent_rmt_hitm," 26298c2ecf20Sopenharmony_ci "percent_lcl_hitm," 26308c2ecf20Sopenharmony_ci "percent_stores_l1hit," 26318c2ecf20Sopenharmony_ci "percent_stores_l1miss," 26328c2ecf20Sopenharmony_ci "offset,offset_node,dcacheline_count,", 26338c2ecf20Sopenharmony_ci add_pid ? "pid," : "", 26348c2ecf20Sopenharmony_ci add_tid ? "tid," : "", 26358c2ecf20Sopenharmony_ci add_iaddr ? "iaddr," : "", 26368c2ecf20Sopenharmony_ci "mean_rmt," 26378c2ecf20Sopenharmony_ci "mean_lcl," 26388c2ecf20Sopenharmony_ci "mean_load," 26398c2ecf20Sopenharmony_ci "tot_recs," 26408c2ecf20Sopenharmony_ci "cpucnt,", 26418c2ecf20Sopenharmony_ci add_sym ? "symbol," : "", 26428c2ecf20Sopenharmony_ci add_dso ? "dso," : "", 26438c2ecf20Sopenharmony_ci add_src ? "cl_srcline," : "", 26448c2ecf20Sopenharmony_ci "node") < 0) { 26458c2ecf20Sopenharmony_ci ret = -ENOMEM; 26468c2ecf20Sopenharmony_ci goto err; 26478c2ecf20Sopenharmony_ci } 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci c2c.show_src = add_src; 26508c2ecf20Sopenharmony_cierr: 26518c2ecf20Sopenharmony_ci free(buf); 26528c2ecf20Sopenharmony_ci return ret; 26538c2ecf20Sopenharmony_ci} 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_cistatic int setup_coalesce(const char *coalesce, bool no_source) 26568c2ecf20Sopenharmony_ci{ 26578c2ecf20Sopenharmony_ci const char *c = coalesce ?: coalesce_default; 26588c2ecf20Sopenharmony_ci 26598c2ecf20Sopenharmony_ci if (asprintf(&c2c.cl_sort, "offset,%s", c) < 0) 26608c2ecf20Sopenharmony_ci return -ENOMEM; 26618c2ecf20Sopenharmony_ci 26628c2ecf20Sopenharmony_ci if (build_cl_output(c2c.cl_sort, no_source)) 26638c2ecf20Sopenharmony_ci return -1; 26648c2ecf20Sopenharmony_ci 26658c2ecf20Sopenharmony_ci if (asprintf(&c2c.cl_resort, "offset,%s", 26668c2ecf20Sopenharmony_ci c2c.display == DISPLAY_TOT ? 26678c2ecf20Sopenharmony_ci "tot_hitm" : 26688c2ecf20Sopenharmony_ci c2c.display == DISPLAY_RMT ? 26698c2ecf20Sopenharmony_ci "rmt_hitm,lcl_hitm" : 26708c2ecf20Sopenharmony_ci "lcl_hitm,rmt_hitm") < 0) 26718c2ecf20Sopenharmony_ci return -ENOMEM; 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci pr_debug("coalesce sort fields: %s\n", c2c.cl_sort); 26748c2ecf20Sopenharmony_ci pr_debug("coalesce resort fields: %s\n", c2c.cl_resort); 26758c2ecf20Sopenharmony_ci pr_debug("coalesce output fields: %s\n", c2c.cl_output); 26768c2ecf20Sopenharmony_ci return 0; 26778c2ecf20Sopenharmony_ci} 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_cistatic int perf_c2c__report(int argc, const char **argv) 26808c2ecf20Sopenharmony_ci{ 26818c2ecf20Sopenharmony_ci struct perf_session *session; 26828c2ecf20Sopenharmony_ci struct ui_progress prog; 26838c2ecf20Sopenharmony_ci struct perf_data data = { 26848c2ecf20Sopenharmony_ci .mode = PERF_DATA_MODE_READ, 26858c2ecf20Sopenharmony_ci }; 26868c2ecf20Sopenharmony_ci char callchain_default_opt[] = CALLCHAIN_DEFAULT_OPT; 26878c2ecf20Sopenharmony_ci const char *display = NULL; 26888c2ecf20Sopenharmony_ci const char *coalesce = NULL; 26898c2ecf20Sopenharmony_ci bool no_source = false; 26908c2ecf20Sopenharmony_ci const struct option options[] = { 26918c2ecf20Sopenharmony_ci OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 26928c2ecf20Sopenharmony_ci "file", "vmlinux pathname"), 26938c2ecf20Sopenharmony_ci OPT_STRING('i', "input", &input_name, "file", 26948c2ecf20Sopenharmony_ci "the input file to process"), 26958c2ecf20Sopenharmony_ci OPT_INCR('N', "node-info", &c2c.node_info, 26968c2ecf20Sopenharmony_ci "show extra node info in report (repeat for more info)"), 26978c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "stdio", &c2c.use_stdio, "Use the stdio interface"), 26988c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "stats", &c2c.stats_only, 26998c2ecf20Sopenharmony_ci "Display only statistic tables (implies --stdio)"), 27008c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "full-symbols", &c2c.symbol_full, 27018c2ecf20Sopenharmony_ci "Display full length of symbols"), 27028c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "no-source", &no_source, 27038c2ecf20Sopenharmony_ci "Do not display Source Line column"), 27048c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "show-all", &c2c.show_all, 27058c2ecf20Sopenharmony_ci "Show all captured HITM lines."), 27068c2ecf20Sopenharmony_ci OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param, 27078c2ecf20Sopenharmony_ci "print_type,threshold[,print_limit],order,sort_key[,branch],value", 27088c2ecf20Sopenharmony_ci callchain_help, &parse_callchain_opt, 27098c2ecf20Sopenharmony_ci callchain_default_opt), 27108c2ecf20Sopenharmony_ci OPT_STRING('d', "display", &display, "Switch HITM output type", "lcl,rmt"), 27118c2ecf20Sopenharmony_ci OPT_STRING('c', "coalesce", &coalesce, "coalesce fields", 27128c2ecf20Sopenharmony_ci "coalesce fields: pid,tid,iaddr,dso"), 27138c2ecf20Sopenharmony_ci OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), 27148c2ecf20Sopenharmony_ci OPT_BOOLEAN(0, "stitch-lbr", &c2c.stitch_lbr, 27158c2ecf20Sopenharmony_ci "Enable LBR callgraph stitching approach"), 27168c2ecf20Sopenharmony_ci OPT_PARENT(c2c_options), 27178c2ecf20Sopenharmony_ci OPT_END() 27188c2ecf20Sopenharmony_ci }; 27198c2ecf20Sopenharmony_ci int err = 0; 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci argc = parse_options(argc, argv, options, report_c2c_usage, 27228c2ecf20Sopenharmony_ci PARSE_OPT_STOP_AT_NON_OPTION); 27238c2ecf20Sopenharmony_ci if (argc) 27248c2ecf20Sopenharmony_ci usage_with_options(report_c2c_usage, options); 27258c2ecf20Sopenharmony_ci 27268c2ecf20Sopenharmony_ci#ifndef HAVE_SLANG_SUPPORT 27278c2ecf20Sopenharmony_ci c2c.use_stdio = true; 27288c2ecf20Sopenharmony_ci#endif 27298c2ecf20Sopenharmony_ci 27308c2ecf20Sopenharmony_ci if (c2c.stats_only) 27318c2ecf20Sopenharmony_ci c2c.use_stdio = true; 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci if (!input_name || !strlen(input_name)) 27348c2ecf20Sopenharmony_ci input_name = "perf.data"; 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci data.path = input_name; 27378c2ecf20Sopenharmony_ci data.force = symbol_conf.force; 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci err = setup_display(display); 27408c2ecf20Sopenharmony_ci if (err) 27418c2ecf20Sopenharmony_ci goto out; 27428c2ecf20Sopenharmony_ci 27438c2ecf20Sopenharmony_ci err = setup_coalesce(coalesce, no_source); 27448c2ecf20Sopenharmony_ci if (err) { 27458c2ecf20Sopenharmony_ci pr_debug("Failed to initialize hists\n"); 27468c2ecf20Sopenharmony_ci goto out; 27478c2ecf20Sopenharmony_ci } 27488c2ecf20Sopenharmony_ci 27498c2ecf20Sopenharmony_ci err = c2c_hists__init(&c2c.hists, "dcacheline", 2); 27508c2ecf20Sopenharmony_ci if (err) { 27518c2ecf20Sopenharmony_ci pr_debug("Failed to initialize hists\n"); 27528c2ecf20Sopenharmony_ci goto out; 27538c2ecf20Sopenharmony_ci } 27548c2ecf20Sopenharmony_ci 27558c2ecf20Sopenharmony_ci session = perf_session__new(&data, 0, &c2c.tool); 27568c2ecf20Sopenharmony_ci if (IS_ERR(session)) { 27578c2ecf20Sopenharmony_ci err = PTR_ERR(session); 27588c2ecf20Sopenharmony_ci pr_debug("Error creating perf session\n"); 27598c2ecf20Sopenharmony_ci goto out; 27608c2ecf20Sopenharmony_ci } 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci err = setup_nodes(session); 27638c2ecf20Sopenharmony_ci if (err) { 27648c2ecf20Sopenharmony_ci pr_err("Failed setup nodes\n"); 27658c2ecf20Sopenharmony_ci goto out; 27668c2ecf20Sopenharmony_ci } 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci err = mem2node__init(&c2c.mem2node, &session->header.env); 27698c2ecf20Sopenharmony_ci if (err) 27708c2ecf20Sopenharmony_ci goto out_session; 27718c2ecf20Sopenharmony_ci 27728c2ecf20Sopenharmony_ci err = setup_callchain(session->evlist); 27738c2ecf20Sopenharmony_ci if (err) 27748c2ecf20Sopenharmony_ci goto out_mem2node; 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci if (symbol__init(&session->header.env) < 0) 27778c2ecf20Sopenharmony_ci goto out_mem2node; 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci /* No pipe support at the moment. */ 27808c2ecf20Sopenharmony_ci if (perf_data__is_pipe(session->data)) { 27818c2ecf20Sopenharmony_ci pr_debug("No pipe support at the moment.\n"); 27828c2ecf20Sopenharmony_ci goto out_mem2node; 27838c2ecf20Sopenharmony_ci } 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci if (c2c.use_stdio) 27868c2ecf20Sopenharmony_ci use_browser = 0; 27878c2ecf20Sopenharmony_ci else 27888c2ecf20Sopenharmony_ci use_browser = 1; 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci setup_browser(false); 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci err = perf_session__process_events(session); 27938c2ecf20Sopenharmony_ci if (err) { 27948c2ecf20Sopenharmony_ci pr_err("failed to process sample\n"); 27958c2ecf20Sopenharmony_ci goto out_mem2node; 27968c2ecf20Sopenharmony_ci } 27978c2ecf20Sopenharmony_ci 27988c2ecf20Sopenharmony_ci c2c_hists__reinit(&c2c.hists, 27998c2ecf20Sopenharmony_ci "cl_idx," 28008c2ecf20Sopenharmony_ci "dcacheline," 28018c2ecf20Sopenharmony_ci "dcacheline_node," 28028c2ecf20Sopenharmony_ci "dcacheline_count," 28038c2ecf20Sopenharmony_ci "percent_hitm," 28048c2ecf20Sopenharmony_ci "tot_hitm,lcl_hitm,rmt_hitm," 28058c2ecf20Sopenharmony_ci "tot_recs," 28068c2ecf20Sopenharmony_ci "tot_loads," 28078c2ecf20Sopenharmony_ci "tot_stores," 28088c2ecf20Sopenharmony_ci "stores_l1hit,stores_l1miss," 28098c2ecf20Sopenharmony_ci "ld_fbhit,ld_l1hit,ld_l2hit," 28108c2ecf20Sopenharmony_ci "ld_lclhit,lcl_hitm," 28118c2ecf20Sopenharmony_ci "ld_rmthit,rmt_hitm," 28128c2ecf20Sopenharmony_ci "dram_lcl,dram_rmt", 28138c2ecf20Sopenharmony_ci c2c.display == DISPLAY_TOT ? "tot_hitm" : 28148c2ecf20Sopenharmony_ci c2c.display == DISPLAY_LCL ? "lcl_hitm" : "rmt_hitm" 28158c2ecf20Sopenharmony_ci ); 28168c2ecf20Sopenharmony_ci 28178c2ecf20Sopenharmony_ci ui_progress__init(&prog, c2c.hists.hists.nr_entries, "Sorting..."); 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci hists__collapse_resort(&c2c.hists.hists, NULL); 28208c2ecf20Sopenharmony_ci hists__output_resort_cb(&c2c.hists.hists, &prog, resort_hitm_cb); 28218c2ecf20Sopenharmony_ci hists__iterate_cb(&c2c.hists.hists, resort_cl_cb); 28228c2ecf20Sopenharmony_ci 28238c2ecf20Sopenharmony_ci ui_progress__finish(); 28248c2ecf20Sopenharmony_ci 28258c2ecf20Sopenharmony_ci if (ui_quirks()) { 28268c2ecf20Sopenharmony_ci pr_err("failed to setup UI\n"); 28278c2ecf20Sopenharmony_ci goto out_mem2node; 28288c2ecf20Sopenharmony_ci } 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci perf_c2c_display(session); 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ciout_mem2node: 28338c2ecf20Sopenharmony_ci mem2node__exit(&c2c.mem2node); 28348c2ecf20Sopenharmony_ciout_session: 28358c2ecf20Sopenharmony_ci perf_session__delete(session); 28368c2ecf20Sopenharmony_ciout: 28378c2ecf20Sopenharmony_ci return err; 28388c2ecf20Sopenharmony_ci} 28398c2ecf20Sopenharmony_ci 28408c2ecf20Sopenharmony_cistatic int parse_record_events(const struct option *opt, 28418c2ecf20Sopenharmony_ci const char *str, int unset __maybe_unused) 28428c2ecf20Sopenharmony_ci{ 28438c2ecf20Sopenharmony_ci bool *event_set = (bool *) opt->value; 28448c2ecf20Sopenharmony_ci 28458c2ecf20Sopenharmony_ci if (!strcmp(str, "list")) { 28468c2ecf20Sopenharmony_ci perf_mem_events__list(); 28478c2ecf20Sopenharmony_ci exit(0); 28488c2ecf20Sopenharmony_ci } 28498c2ecf20Sopenharmony_ci if (perf_mem_events__parse(str)) 28508c2ecf20Sopenharmony_ci exit(-1); 28518c2ecf20Sopenharmony_ci 28528c2ecf20Sopenharmony_ci *event_set = true; 28538c2ecf20Sopenharmony_ci return 0; 28548c2ecf20Sopenharmony_ci} 28558c2ecf20Sopenharmony_ci 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_cistatic const char * const __usage_record[] = { 28588c2ecf20Sopenharmony_ci "perf c2c record [<options>] [<command>]", 28598c2ecf20Sopenharmony_ci "perf c2c record [<options>] -- <command> [<options>]", 28608c2ecf20Sopenharmony_ci NULL 28618c2ecf20Sopenharmony_ci}; 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_cistatic const char * const *record_mem_usage = __usage_record; 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_cistatic int perf_c2c__record(int argc, const char **argv) 28668c2ecf20Sopenharmony_ci{ 28678c2ecf20Sopenharmony_ci int rec_argc, i = 0, j; 28688c2ecf20Sopenharmony_ci const char **rec_argv; 28698c2ecf20Sopenharmony_ci int ret; 28708c2ecf20Sopenharmony_ci bool all_user = false, all_kernel = false; 28718c2ecf20Sopenharmony_ci bool event_set = false; 28728c2ecf20Sopenharmony_ci struct option options[] = { 28738c2ecf20Sopenharmony_ci OPT_CALLBACK('e', "event", &event_set, "event", 28748c2ecf20Sopenharmony_ci "event selector. Use 'perf c2c record -e list' to list available events", 28758c2ecf20Sopenharmony_ci parse_record_events), 28768c2ecf20Sopenharmony_ci OPT_BOOLEAN('u', "all-user", &all_user, "collect only user level data"), 28778c2ecf20Sopenharmony_ci OPT_BOOLEAN('k', "all-kernel", &all_kernel, "collect only kernel level data"), 28788c2ecf20Sopenharmony_ci OPT_UINTEGER('l', "ldlat", &perf_mem_events__loads_ldlat, "setup mem-loads latency"), 28798c2ecf20Sopenharmony_ci OPT_PARENT(c2c_options), 28808c2ecf20Sopenharmony_ci OPT_END() 28818c2ecf20Sopenharmony_ci }; 28828c2ecf20Sopenharmony_ci 28838c2ecf20Sopenharmony_ci if (perf_mem_events__init()) { 28848c2ecf20Sopenharmony_ci pr_err("failed: memory events not supported\n"); 28858c2ecf20Sopenharmony_ci return -1; 28868c2ecf20Sopenharmony_ci } 28878c2ecf20Sopenharmony_ci 28888c2ecf20Sopenharmony_ci argc = parse_options(argc, argv, options, record_mem_usage, 28898c2ecf20Sopenharmony_ci PARSE_OPT_KEEP_UNKNOWN); 28908c2ecf20Sopenharmony_ci 28918c2ecf20Sopenharmony_ci rec_argc = argc + 11; /* max number of arguments */ 28928c2ecf20Sopenharmony_ci rec_argv = calloc(rec_argc + 1, sizeof(char *)); 28938c2ecf20Sopenharmony_ci if (!rec_argv) 28948c2ecf20Sopenharmony_ci return -1; 28958c2ecf20Sopenharmony_ci 28968c2ecf20Sopenharmony_ci rec_argv[i++] = "record"; 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_ci if (!event_set) { 28998c2ecf20Sopenharmony_ci perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; 29008c2ecf20Sopenharmony_ci perf_mem_events[PERF_MEM_EVENTS__STORE].record = true; 29018c2ecf20Sopenharmony_ci } 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_ci if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) 29048c2ecf20Sopenharmony_ci rec_argv[i++] = "-W"; 29058c2ecf20Sopenharmony_ci 29068c2ecf20Sopenharmony_ci rec_argv[i++] = "-d"; 29078c2ecf20Sopenharmony_ci rec_argv[i++] = "--phys-data"; 29088c2ecf20Sopenharmony_ci rec_argv[i++] = "--sample-cpu"; 29098c2ecf20Sopenharmony_ci 29108c2ecf20Sopenharmony_ci for (j = 0; j < PERF_MEM_EVENTS__MAX; j++) { 29118c2ecf20Sopenharmony_ci if (!perf_mem_events[j].record) 29128c2ecf20Sopenharmony_ci continue; 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci if (!perf_mem_events[j].supported) { 29158c2ecf20Sopenharmony_ci pr_err("failed: event '%s' not supported\n", 29168c2ecf20Sopenharmony_ci perf_mem_events[j].name); 29178c2ecf20Sopenharmony_ci free(rec_argv); 29188c2ecf20Sopenharmony_ci return -1; 29198c2ecf20Sopenharmony_ci } 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci rec_argv[i++] = "-e"; 29228c2ecf20Sopenharmony_ci rec_argv[i++] = perf_mem_events__name(j); 29238c2ecf20Sopenharmony_ci } 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci if (all_user) 29268c2ecf20Sopenharmony_ci rec_argv[i++] = "--all-user"; 29278c2ecf20Sopenharmony_ci 29288c2ecf20Sopenharmony_ci if (all_kernel) 29298c2ecf20Sopenharmony_ci rec_argv[i++] = "--all-kernel"; 29308c2ecf20Sopenharmony_ci 29318c2ecf20Sopenharmony_ci for (j = 0; j < argc; j++, i++) 29328c2ecf20Sopenharmony_ci rec_argv[i] = argv[j]; 29338c2ecf20Sopenharmony_ci 29348c2ecf20Sopenharmony_ci if (verbose > 0) { 29358c2ecf20Sopenharmony_ci pr_debug("calling: "); 29368c2ecf20Sopenharmony_ci 29378c2ecf20Sopenharmony_ci j = 0; 29388c2ecf20Sopenharmony_ci 29398c2ecf20Sopenharmony_ci while (rec_argv[j]) { 29408c2ecf20Sopenharmony_ci pr_debug("%s ", rec_argv[j]); 29418c2ecf20Sopenharmony_ci j++; 29428c2ecf20Sopenharmony_ci } 29438c2ecf20Sopenharmony_ci pr_debug("\n"); 29448c2ecf20Sopenharmony_ci } 29458c2ecf20Sopenharmony_ci 29468c2ecf20Sopenharmony_ci ret = cmd_record(i, rec_argv); 29478c2ecf20Sopenharmony_ci free(rec_argv); 29488c2ecf20Sopenharmony_ci return ret; 29498c2ecf20Sopenharmony_ci} 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_ciint cmd_c2c(int argc, const char **argv) 29528c2ecf20Sopenharmony_ci{ 29538c2ecf20Sopenharmony_ci argc = parse_options(argc, argv, c2c_options, c2c_usage, 29548c2ecf20Sopenharmony_ci PARSE_OPT_STOP_AT_NON_OPTION); 29558c2ecf20Sopenharmony_ci 29568c2ecf20Sopenharmony_ci if (!argc) 29578c2ecf20Sopenharmony_ci usage_with_options(c2c_usage, c2c_options); 29588c2ecf20Sopenharmony_ci 29598c2ecf20Sopenharmony_ci if (!strncmp(argv[0], "rec", 3)) { 29608c2ecf20Sopenharmony_ci return perf_c2c__record(argc, argv); 29618c2ecf20Sopenharmony_ci } else if (!strncmp(argv[0], "rep", 3)) { 29628c2ecf20Sopenharmony_ci return perf_c2c__report(argc, argv); 29638c2ecf20Sopenharmony_ci } else { 29648c2ecf20Sopenharmony_ci usage_with_options(c2c_usage, c2c_options); 29658c2ecf20Sopenharmony_ci } 29668c2ecf20Sopenharmony_ci 29678c2ecf20Sopenharmony_ci return 0; 29688c2ecf20Sopenharmony_ci} 2969