diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 8b7c1fd3538069b8a95564fd66764fac1516ca40..f7a961e55a92b9abac902f4ae609e99c916a5784 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -118,6 +118,7 @@ enum { DISPLAY_LCL_HITM, DISPLAY_RMT_HITM, DISPLAY_TOT_HITM, + DISPLAY_SNP_PEER, DISPLAY_MAX, }; @@ -125,6 +126,7 @@ static const char *display_str[DISPLAY_MAX] = { [DISPLAY_LCL_HITM] = "Local HITMs", [DISPLAY_RMT_HITM] = "Remote HITMs", [DISPLAY_TOT_HITM] = "Total HITMs", + [DISPLAY_SNP_PEER] = "Peer Snoop", }; static const struct option c2c_options[] = { @@ -822,6 +824,11 @@ static double percent_costly_snoop(struct c2c_hist_entry *c2c_he) case DISPLAY_TOT_HITM: st = stats->tot_hitm; tot = total->tot_hitm; + break; + case DISPLAY_SNP_PEER: + st = stats->tot_peer; + tot = total->tot_peer; + break; default: break; } @@ -1229,6 +1236,10 @@ node_entry(struct perf_hpp_fmt *fmt __maybe_unused, struct perf_hpp *hpp, ret = display_metrics(hpp, stats->tot_hitm, c2c_he->stats.tot_hitm); break; + case DISPLAY_SNP_PEER: + ret = display_metrics(hpp, stats->tot_peer, + c2c_he->stats.tot_peer); + break; default: break; } @@ -1609,6 +1620,7 @@ static struct c2c_header percent_costly_snoop_header[] = { [DISPLAY_LCL_HITM] = HEADER_BOTH("Lcl", "Hitm"), [DISPLAY_RMT_HITM] = HEADER_BOTH("Rmt", "Hitm"), [DISPLAY_TOT_HITM] = HEADER_BOTH("Tot", "Hitm"), + [DISPLAY_SNP_PEER] = HEADER_BOTH("Peer", "Snoop"), }; static struct c2c_dimension dim_percent_costly_snoop = { @@ -2107,6 +2119,10 @@ static bool he__display(struct hist_entry *he, struct c2c_stats *stats) he->filtered = filter_display(c2c_he->stats.tot_hitm, stats->tot_hitm); break; + case DISPLAY_SNP_PEER: + he->filtered = filter_display(c2c_he->stats.tot_peer, + stats->tot_peer); + break; default: break; } @@ -2135,6 +2151,8 @@ static inline bool is_valid_hist_entry(struct hist_entry *he) case DISPLAY_TOT_HITM: has_record = !!c2c_he->stats.tot_hitm; break; + case DISPLAY_SNP_PEER: + has_record = !!c2c_he->stats.tot_peer; default: break; } @@ -2224,7 +2242,10 @@ static int resort_cl_cb(struct hist_entry *he, void *arg __maybe_unused) } static struct c2c_header header_node_0 = HEADER_LOW("Node"); -static struct c2c_header header_node_1 = HEADER_LOW("Node{cpus %hitms %stores}"); +static struct c2c_header header_node_1_hitms_stores = + HEADER_LOW("Node{cpus %hitms %stores}"); +static struct c2c_header header_node_1_peers_stores = + HEADER_LOW("Node{cpus %peers %stores}"); static struct c2c_header header_node_2 = HEADER_LOW("Node{cpu list}"); static void setup_nodes_header(void) @@ -2234,7 +2255,10 @@ static void setup_nodes_header(void) dim_node.header = header_node_0; break; case 1: - dim_node.header = header_node_1; + if (c2c.display == DISPLAY_SNP_PEER) + dim_node.header = header_node_1_peers_stores; + else + dim_node.header = header_node_1_hitms_stores; break; case 2: dim_node.header = header_node_2; @@ -2308,13 +2332,14 @@ static int setup_nodes(struct perf_session *session) } #define HAS_HITMS(__h) ((__h)->stats.lcl_hitm || (__h)->stats.rmt_hitm) +#define HAS_PEER(__h) ((__h)->stats.lcl_peer || (__h)->stats.rmt_peer) static int resort_shared_cl_cb(struct hist_entry *he, void *arg __maybe_unused) { struct c2c_hist_entry *c2c_he; c2c_he = container_of(he, struct c2c_hist_entry, he); - if (HAS_HITMS(c2c_he)) { + if (HAS_HITMS(c2c_he) || HAS_PEER(c2c_he)) { c2c.shared_clines++; c2c_add_stats(&c2c.shared_clines_stats, &c2c_he->stats); } @@ -2447,13 +2472,22 @@ static void print_pareto(FILE *out) int ret; const char *cl_output; - cl_output = "cl_num," - "cl_rmt_hitm," - "cl_lcl_hitm," - "cl_stores_l1hit," - "cl_stores_l1miss," - "cl_stores_na," - "dcacheline"; + if (c2c.display != DISPLAY_SNP_PEER) + cl_output = "cl_num," + "cl_rmt_hitm," + "cl_lcl_hitm," + "cl_stores_l1hit," + "cl_stores_l1miss," + "cl_stores_na," + "dcacheline"; + else + cl_output = "cl_num," + "cl_rmt_peer," + "cl_lcl_peer," + "cl_stores_l1hit," + "cl_stores_l1miss," + "cl_stores_na," + "dcacheline"; perf_hpp_list__init(&hpp_list); ret = hpp_list__parse(&hpp_list, cl_output, NULL); @@ -2852,6 +2886,8 @@ static int setup_display(const char *str) c2c.display = DISPLAY_RMT_HITM; else if (!strcmp(display, "lcl")) c2c.display = DISPLAY_LCL_HITM; + else if (!strcmp(display, "peer")) + c2c.display = DISPLAY_SNP_PEER; else { pr_err("failed: unknown display type: %s\n", str); return -1; @@ -2898,10 +2934,12 @@ static int build_cl_output(char *cl_sort, bool no_source) } if (asprintf(&c2c.cl_output, - "%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s", c2c.use_stdio ? "cl_num_empty," : "", - "percent_rmt_hitm," - "percent_lcl_hitm," + c2c.display == DISPLAY_SNP_PEER ? "percent_rmt_peer," + "percent_lcl_peer," : + "percent_rmt_hitm," + "percent_lcl_hitm,", "percent_stores_l1hit," "percent_stores_l1miss," "percent_stores_na," @@ -2909,8 +2947,10 @@ static int build_cl_output(char *cl_sort, bool no_source) add_pid ? "pid," : "", add_tid ? "tid," : "", add_iaddr ? "iaddr," : "", - "mean_rmt," - "mean_lcl," + c2c.display == DISPLAY_SNP_PEER ? "mean_rmt_peer," + "mean_lcl_peer," : + "mean_rmt," + "mean_lcl,", "mean_load," "tot_recs," "cpucnt,", @@ -2931,6 +2971,7 @@ static int build_cl_output(char *cl_sort, bool no_source) static int setup_coalesce(const char *coalesce, bool no_source) { const char *c = coalesce ?: coalesce_default; + const char *sort_str = NULL; if (asprintf(&c2c.cl_sort, "offset,%s", c) < 0) return -ENOMEM; @@ -2938,12 +2979,16 @@ static int setup_coalesce(const char *coalesce, bool no_source) if (build_cl_output(c2c.cl_sort, no_source)) return -1; - if (asprintf(&c2c.cl_resort, "offset,%s", - c2c.display == DISPLAY_TOT_HITM ? - "tot_hitm" : - c2c.display == DISPLAY_RMT_HITM ? - "rmt_hitm,lcl_hitm" : - "lcl_hitm,rmt_hitm") < 0) + if (c2c.display == DISPLAY_TOT_HITM) + sort_str = "tot_hitm"; + else if (c2c.display == DISPLAY_RMT_HITM) + sort_str = "rmt_hitm,lcl_hitm"; + else if (c2c.display == DISPLAY_LCL_HITM) + sort_str = "lcl_hitm,rmt_hitm"; + else if (c2c.display == DISPLAY_SNP_PEER) + sort_str = "tot_peer"; + + if (asprintf(&c2c.cl_resort, "offset,%s", sort_str) < 0) return -ENOMEM; pr_debug("coalesce sort fields: %s\n", c2c.cl_sort); @@ -2989,7 +3034,7 @@ static int perf_c2c__report(int argc, const char **argv) "print_type,threshold[,print_limit],order,sort_key[,branch],value", callchain_help, &parse_callchain_opt, callchain_default_opt), - OPT_STRING('d', "display", &display, "Switch HITM output type", "lcl,rmt"), + OPT_STRING('d', "display", &display, "Switch HITM output type", "tot,lcl,rmt,peer"), OPT_STRING('c', "coalesce", &coalesce, "coalesce fields", "coalesce fields: pid,tid,iaddr,dso"), OPT_BOOLEAN('f', "force", &symbol_conf.force, "don't complain, do it"), @@ -3084,20 +3129,36 @@ static int perf_c2c__report(int argc, const char **argv) goto out_mem2node; } - output_str = "cl_idx," - "dcacheline," - "dcacheline_node," - "dcacheline_count," - "percent_costly_snoop," - "tot_hitm,lcl_hitm,rmt_hitm," - "tot_recs," - "tot_loads," - "tot_stores," - "stores_l1hit,stores_l1miss,stores_na," - "ld_fbhit,ld_l1hit,ld_l2hit," - "ld_lclhit,lcl_hitm," - "ld_rmthit,rmt_hitm," - "dram_lcl,dram_rmt"; + if (c2c.display != DISPLAY_SNP_PEER) + output_str = "cl_idx," + "dcacheline," + "dcacheline_node," + "dcacheline_count," + "percent_costly_snoop," + "tot_hitm,lcl_hitm,rmt_hitm," + "tot_recs," + "tot_loads," + "tot_stores," + "stores_l1hit,stores_l1miss,stores_na," + "ld_fbhit,ld_l1hit,ld_l2hit," + "ld_lclhit,lcl_hitm," + "ld_rmthit,rmt_hitm," + "dram_lcl,dram_rmt"; + else + output_str = "cl_idx," + "dcacheline," + "dcacheline_node," + "dcacheline_count," + "percent_costly_snoop," + "tot_peer,lcl_peer,rmt_peer," + "tot_recs," + "tot_loads," + "tot_stores," + "stores_l1hit,stores_l1miss,stores_na," + "ld_fbhit,ld_l1hit,ld_l2hit," + "ld_lclhit,lcl_hitm," + "ld_rmthit,rmt_hitm," + "dram_lcl,dram_rmt"; if (c2c.display == DISPLAY_TOT_HITM) sort_str = "tot_hitm"; @@ -3105,6 +3166,8 @@ static int perf_c2c__report(int argc, const char **argv) sort_str = "rmt_hitm"; else if (c2c.display == DISPLAY_LCL_HITM) sort_str = "lcl_hitm"; + else if (c2c.display == DISPLAY_SNP_PEER) + sort_str = "tot_peer"; c2c_hists__reinit(&c2c.hists, output_str, sort_str);