From: Arnaldo Carvalho de Melo <a...@redhat.com> >From the c2c prototype:
[root@sandy ~]# perf c2c -r report | head -7 T Status Pid Tid CPU Inst Adrs Virt Data Adrs Phys Data Adrs Cycles Source Decoded Source ObJect:Symbol -------------------------------------------------------------------------------------------------------------------------------------------- raw input 779 779 7 0xffffffff810865dd 0xffff8803f4d75ec8 0 370 0x68080882 [LOAD,LCL_LLC,MISS,SNP NA] [kernel.kallsyms]:try_to_wake_up raw input 779 779 7 0xffffffff8107acb3 0xffff8802a5b73158 0 297 0x6a100142 [LOAD,L1,HIT,SNP NONE,LOCKED] [kernel.kallsyms]:up_read raw input 779 779 7 0x3b7e009814 0x7fff87429ea0 0 925 0x68100142 [LOAD,L1,HIT,SNP NONE] ???:??? raw input 0 0 1 0xffffffff8108bf81 0xffff8803eafebf50 0 172 0x68800842 [LOAD,LCL_LLC,HIT,SNP HITM] [kernel.kallsyms]:update_stats_wait_end raw input 779 779 7 0x3b7e0097cc 0x7fac94b69068 0 228 0x68100242 [LOAD,LFB,HIT,SNP NONE] ???:??? [root@sandy ~]# The "Phys Data Adrs" column is not available at this point. Cc: David Ahern <dsah...@gmail.com> Cc: Don Zickus <dzic...@redhat.com> Cc: Frederic Weisbecker <fweis...@gmail.com> Cc: Joe Mario <jma...@redhat.com> Cc: Mike Galbraith <efa...@gmx.de> Cc: Paul Mackerras <pau...@samba.org> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Richard Fowles <rfow...@redhat.com> Cc: Stephane Eranian <eran...@google.com> Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com> --- tools/perf/builtin-c2c.c | 148 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 125 insertions(+), 23 deletions(-) diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c index 2935484..7082913 100644 --- a/tools/perf/builtin-c2c.c +++ b/tools/perf/builtin-c2c.c @@ -11,51 +11,148 @@ struct perf_c2c { struct perf_tool tool; + bool raw_records; }; -static int perf_sample__fprintf(struct perf_sample *sample, - struct perf_evsel *evsel, - struct addr_location *al, FILE *fp) +enum { OP, LVL, SNP, LCK, TLB }; + +static int perf_c2c__scnprintf_data_src(char *bf, size_t size, uint64_t val) { - return fprintf(fp, "%25.25s: %5d %5d 0x%016" PRIx64 " 0x016%" PRIx64 " %5" PRIu64 " 0x%06" PRIx64 " %s:%s\n", - perf_evsel__name(evsel), - sample->pid, sample->tid, sample->ip, sample->addr, - sample->weight, sample->data_src, - al->map ? (al->map->dso ? al->map->dso->long_name : "???") : "???", - al->sym ? al->sym->name : "???"); +#define PREFIX "[" +#define SUFFIX "]" +#define ELLIPSIS "..." + static const struct { + uint64_t bit; + int64_t field; + const char *name; + } decode_bits[] = { + { PERF_MEM_OP_LOAD, OP, "LOAD" }, + { PERF_MEM_OP_STORE, OP, "STORE" }, + { PERF_MEM_OP_NA, OP, "OP_NA" }, + { PERF_MEM_LVL_LFB, LVL, "LFB" }, + { PERF_MEM_LVL_L1, LVL, "L1" }, + { PERF_MEM_LVL_L2, LVL, "L2" }, + { PERF_MEM_LVL_L3, LVL, "LCL_LLC" }, + { PERF_MEM_LVL_LOC_RAM, LVL, "LCL_RAM" }, + { PERF_MEM_LVL_REM_RAM1, LVL, "RMT_RAM" }, + { PERF_MEM_LVL_REM_RAM2, LVL, "RMT_RAM" }, + { PERF_MEM_LVL_REM_CCE1, LVL, "RMT_LLC" }, + { PERF_MEM_LVL_REM_CCE2, LVL, "RMT_LLC" }, + { PERF_MEM_LVL_IO, LVL, "I/O" }, + { PERF_MEM_LVL_UNC, LVL, "UNCACHED" }, + { PERF_MEM_LVL_NA, LVL, "N" }, + { PERF_MEM_LVL_HIT, LVL, "HIT" }, + { PERF_MEM_LVL_MISS, LVL, "MISS" }, + { PERF_MEM_SNOOP_NONE, SNP, "SNP NONE" }, + { PERF_MEM_SNOOP_HIT, SNP, "SNP HIT" }, + { PERF_MEM_SNOOP_MISS, SNP, "SNP MISS" }, + { PERF_MEM_SNOOP_HITM, SNP, "SNP HITM" }, + { PERF_MEM_SNOOP_NA, SNP, "SNP NA" }, + { PERF_MEM_LOCK_LOCKED, LCK, "LOCKED" }, + { PERF_MEM_LOCK_NA, LCK, "LOCK_NA" }, + }; + union perf_mem_data_src dsrc = { .val = val, }; + int printed = scnprintf(bf, size, PREFIX); + size_t i; + bool first_present = true; + + for (i = 0; i < ARRAY_SIZE(decode_bits); i++) { + int bitval; + + switch (decode_bits[i].field) { + case OP: bitval = decode_bits[i].bit & dsrc.mem_op; break; + case LVL: bitval = decode_bits[i].bit & dsrc.mem_lvl; break; + case SNP: bitval = decode_bits[i].bit & dsrc.mem_snoop; break; + case LCK: bitval = decode_bits[i].bit & dsrc.mem_lock; break; + case TLB: bitval = decode_bits[i].bit & dsrc.mem_dtlb; break; + default: bitval = 0; break; + } + + if (!bitval) + continue; + + if (strlen(decode_bits[i].name) + !!i > size - printed - sizeof(SUFFIX)) { + sprintf(bf + size - sizeof(SUFFIX) - sizeof(ELLIPSIS) + 1, ELLIPSIS); + printed = size - sizeof(SUFFIX); + break; + } + + printed += scnprintf(bf + printed, size - printed, "%s%s", + first_present ? "" : ",", decode_bits[i].name); + first_present = false; + } + + printed += scnprintf(bf + printed, size - printed, SUFFIX); + return printed; } -static int perf_c2c__process_load(struct perf_evsel *evsel, - struct perf_sample *sample, - struct addr_location *al) +static int perf_c2c__fprintf_header(FILE *fp) { - perf_sample__fprintf(sample, evsel, al, stdout); - return 0; + int printed = fprintf(fp, "%c %-16s %6s %6s %4s %18s %18s %18s %6s %-10s %-60s %s\n", + 'T', + "Status", + "Pid", + "Tid", + "CPU", + "Inst Adrs", + "Virt Data Adrs", + "Phys Data Adrs", + "Cycles", + "Source", + " Decoded Source", + "ObJect:Symbol"); + return printed + fprintf(fp, "%-*.*s\n", printed, printed, graph_dotted_line); +} + +static int perf_sample__fprintf(struct perf_sample *sample, char tag, + const char *reason, struct addr_location *al, FILE *fp) +{ + char data_src[61]; + + perf_c2c__scnprintf_data_src(data_src, sizeof(data_src), sample->data_src); + + return fprintf(fp, "%c %-16s %6d %6d %4d %#18" PRIx64 " %#18" PRIx64 " %#18" PRIx64 " %6" PRIu64 " %#10" PRIx64 " %-60.60s %s:%s\n", + tag, + reason ?: "valid record", + sample->pid, + sample->tid, + sample->cpu, + sample->ip, + sample->addr, + 0UL, + sample->weight, + sample->data_src, + data_src, + al->map ? (al->map->dso ? al->map->dso->long_name : "???") : "???", + al->sym ? al->sym->name : "???"); } -static int perf_c2c__process_store(struct perf_evsel *evsel, - struct perf_sample *sample, - struct addr_location *al) +static int perf_c2c__process_load_store(struct perf_c2c *c2c, + struct perf_sample *sample, + struct addr_location *al) { - perf_sample__fprintf(sample, evsel, al, stdout); + if (c2c->raw_records) + perf_sample__fprintf(sample, ' ', "raw input", al, stdout); + return 0; } static const struct perf_evsel_str_handler handlers[] = { - { "cpu/mem-loads,ldlat=30/pp", perf_c2c__process_load, }, - { "cpu/mem-stores/pp", perf_c2c__process_store, }, + { "cpu/mem-loads,ldlat=30/pp", perf_c2c__process_load_store, }, + { "cpu/mem-stores/pp", perf_c2c__process_load_store, }, }; -typedef int (*sample_handler)(struct perf_evsel *evsel, +typedef int (*sample_handler)(struct perf_c2c *c2c, struct perf_sample *sample, struct addr_location *al); -static int perf_c2c__process_sample(struct perf_tool *tool __maybe_unused, +static int perf_c2c__process_sample(struct perf_tool *tool, union perf_event *event, struct perf_sample *sample, struct perf_evsel *evsel, struct machine *machine) { + struct perf_c2c *c2c = container_of(tool, struct perf_c2c, tool); struct addr_location al; int err = 0; @@ -67,7 +164,7 @@ static int perf_c2c__process_sample(struct perf_tool *tool __maybe_unused, if (evsel->handler != NULL) { sample_handler f = evsel->handler; - err = f(evsel, sample, &al); + err = f(c2c, sample, &al); } return err; @@ -111,6 +208,10 @@ out: static int perf_c2c__report(struct perf_c2c *c2c) { setup_pager(); + + if (c2c->raw_records) + perf_c2c__fprintf_header(stdout); + return perf_c2c__read_events(c2c); } @@ -161,6 +262,7 @@ int cmd_c2c(int argc, const char **argv, const char *prefix __maybe_unused) }, }; const struct option c2c_options[] = { + OPT_BOOLEAN('r', "raw_records", &c2c.raw_records, "dump raw events"), OPT_END() }; const char * const c2c_usage[] = { -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/