Commit a328a259 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-5.3-20190703' of...

Merge tag 'perf-core-for-mingo-5.3-20190703' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

perf metrics:

  Andi Kleen:

  - Fixes for SkylakeX and CascadeLakeX Intel vendor events.

  - Avoid extra ':' for --raw metrics.

  - Don't include duration_time in group.

perf script:

  Arnaldo Carvalho de Melo/Jiri Olsa:

  - Fix processing guest samples.

perf diff:

  Jin Yao:

  - Do diffs by basic blocks.

objtool:

  Jiri Olsa:

  - Fix build by linking against tools/lib/ctype.o sources.

perf pmu:

  John Garry:

  - Support more complex PMU event aliasing.

  - Add support for Hisi hip08 DDRC, HHA and L3C PMU aliasing.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents a041ede0 15a108af
...@@ -9,6 +9,7 @@ objtool-y += special.o ...@@ -9,6 +9,7 @@ objtool-y += special.o
objtool-y += objtool.o objtool-y += objtool.o
objtool-y += libstring.o objtool-y += libstring.o
objtool-y += libctype.o
objtool-y += str_error_r.o objtool-y += str_error_r.o
CFLAGS += -I$(srctree)/tools/lib CFLAGS += -I$(srctree)/tools/lib
...@@ -17,6 +18,10 @@ $(OUTPUT)libstring.o: ../lib/string.c FORCE ...@@ -17,6 +18,10 @@ $(OUTPUT)libstring.o: ../lib/string.c FORCE
$(call rule_mkdir) $(call rule_mkdir)
$(call if_changed_dep,cc_o_c) $(call if_changed_dep,cc_o_c)
$(OUTPUT)libctype.o: ../lib/ctype.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_o_c)
$(OUTPUT)str_error_r.o: ../lib/str_error_r.c FORCE $(OUTPUT)str_error_r.o: ../lib/str_error_r.c FORCE
$(call rule_mkdir) $(call rule_mkdir)
$(call if_changed_dep,cc_o_c) $(call if_changed_dep,cc_o_c)
...@@ -90,9 +90,10 @@ OPTIONS ...@@ -90,9 +90,10 @@ OPTIONS
-c:: -c::
--compute:: --compute::
Differential computation selection - delta, ratio, wdiff, delta-abs Differential computation selection - delta, ratio, wdiff, cycles,
(default is delta-abs). Default can be changed using diff.compute delta-abs (default is delta-abs). Default can be changed using
config option. See COMPARISON METHODS section for more info. diff.compute config option. See COMPARISON METHODS section for
more info.
-p:: -p::
--period:: --period::
...@@ -280,6 +281,16 @@ If specified the 'Weighted diff' column is displayed with value 'd' computed as: ...@@ -280,6 +281,16 @@ If specified the 'Weighted diff' column is displayed with value 'd' computed as:
- WEIGHT-A being the weight of the data file - WEIGHT-A being the weight of the data file
- WEIGHT-B being the weight of the baseline data file - WEIGHT-B being the weight of the baseline data file
cycles
~~~~~~
If specified the '[Program Block Range] Cycles Diff' column is displayed.
It displays the cycles difference of same program basic block amongst
two perf.data. The program basic block is the code between two branches.
'[Program Block Range]' indicates the range of a program basic block.
Source line is reported if it can be found otherwise uses symbol+offset
instead.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-report[1] linkperf:perf-record[1], linkperf:perf-report[1]
...@@ -89,7 +89,7 @@ OPTIONS ...@@ -89,7 +89,7 @@ OPTIONS
- socket: processor socket number the task ran at the time of sample - socket: processor socket number the task ran at the time of sample
- srcline: filename and line number executed at the time of sample. The - srcline: filename and line number executed at the time of sample. The
DWARF debugging info must be provided. DWARF debugging info must be provided.
- srcfile: file name of the source file of the same. Requires dwarf - srcfile: file name of the source file of the samples. Requires dwarf
information. information.
- weight: Event specific weight, e.g. memory latency or transaction - weight: Event specific weight, e.g. memory latency or transaction
abort cost. This is the global weight. abort cost. This is the global weight.
......
...@@ -38,6 +38,6 @@ To report cacheline events from previous recording: perf c2c report ...@@ -38,6 +38,6 @@ To report cacheline events from previous recording: perf c2c report
To browse sample contexts use perf report --sample 10 and select in context menu To browse sample contexts use perf report --sample 10 and select in context menu
To separate samples by time use perf report --sort time,overhead,sym To separate samples by time use perf report --sort time,overhead,sym
To set sample time separation other than 100ms with --sort time use --time-quantum To set sample time separation other than 100ms with --sort time use --time-quantum
Add -I to perf report to sample register values visible in perf report context. Add -I to perf record to sample register values, which will be visible in perf report sample context.
To show IPC for sampling periods use perf record -e '{cycles,instructions}:S' and then browse context To show IPC for sampling periods use perf record -e '{cycles,instructions}:S' and then browse context
To show context switches in perf report sample context add --switch-events to perf record. To show context switches in perf report sample context add --switch-events to perf record.
This diff is collapsed.
...@@ -3522,6 +3522,15 @@ int cmd_script(int argc, const char **argv) ...@@ -3522,6 +3522,15 @@ int cmd_script(int argc, const char **argv)
"Time span of interest (start,stop)"), "Time span of interest (start,stop)"),
OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name, OPT_BOOLEAN(0, "inline", &symbol_conf.inline_name,
"Show inline function"), "Show inline function"),
OPT_STRING(0, "guestmount", &symbol_conf.guestmount, "directory",
"guest mount directory under which every guest os"
" instance has a subdir"),
OPT_STRING(0, "guestvmlinux", &symbol_conf.default_guest_vmlinux_name,
"file", "file saving guest os vmlinux"),
OPT_STRING(0, "guestkallsyms", &symbol_conf.default_guest_kallsyms,
"file", "file saving guest os /proc/kallsyms"),
OPT_STRING(0, "guestmodules", &symbol_conf.default_guest_modules,
"file", "file saving guest os /proc/modules"),
OPT_END() OPT_END()
}; };
const char * const script_subcommands[] = { "record", "report", NULL }; const char * const script_subcommands[] = { "record", "report", NULL };
...@@ -3541,6 +3550,16 @@ int cmd_script(int argc, const char **argv) ...@@ -3541,6 +3550,16 @@ int cmd_script(int argc, const char **argv)
argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage, argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
PARSE_OPT_STOP_AT_NON_OPTION); PARSE_OPT_STOP_AT_NON_OPTION);
if (symbol_conf.guestmount ||
symbol_conf.default_guest_vmlinux_name ||
symbol_conf.default_guest_kallsyms ||
symbol_conf.default_guest_modules) {
/*
* Enable guest sample processing.
*/
perf_guest = true;
}
data.path = input_name; data.path = input_name;
data.force = symbol_conf.force; data.force = symbol_conf.force;
......
[
{
"EventCode": "0x02",
"EventName": "uncore_hisi_ddrc.flux_wcmd",
"BriefDescription": "DDRC write commands",
"PublicDescription": "DDRC write commands",
"Unit": "hisi_sccl,ddrc",
},
{
"EventCode": "0x03",
"EventName": "uncore_hisi_ddrc.flux_rcmd",
"BriefDescription": "DDRC read commands",
"PublicDescription": "DDRC read commands",
"Unit": "hisi_sccl,ddrc",
},
{
"EventCode": "0x04",
"EventName": "uncore_hisi_ddrc.flux_wr",
"BriefDescription": "DDRC precharge commands",
"PublicDescription": "DDRC precharge commands",
"Unit": "hisi_sccl,ddrc",
},
{
"EventCode": "0x05",
"EventName": "uncore_hisi_ddrc.act_cmd",
"BriefDescription": "DDRC active commands",
"PublicDescription": "DDRC active commands",
"Unit": "hisi_sccl,ddrc",
},
{
"EventCode": "0x06",
"EventName": "uncore_hisi_ddrc.rnk_chg",
"BriefDescription": "DDRC rank commands",
"PublicDescription": "DDRC rank commands",
"Unit": "hisi_sccl,ddrc",
},
{
"EventCode": "0x07",
"EventName": "uncore_hisi_ddrc.rw_chg",
"BriefDescription": "DDRC read and write changes",
"PublicDescription": "DDRC read and write changes",
"Unit": "hisi_sccl,ddrc",
},
]
[
{
"EventCode": "0x00",
"EventName": "uncore_hisi_hha.rx_ops_num",
"BriefDescription": "The number of all operations received by the HHA",
"PublicDescription": "The number of all operations received by the HHA",
"Unit": "hisi_sccl,hha",
},
{
"EventCode": "0x01",
"EventName": "uncore_hisi_hha.rx_outer",
"BriefDescription": "The number of all operations received by the HHA from another socket",
"PublicDescription": "The number of all operations received by the HHA from another socket",
"Unit": "hisi_sccl,hha",
},
{
"EventCode": "0x02",
"EventName": "uncore_hisi_hha.rx_sccl",
"BriefDescription": "The number of all operations received by the HHA from another SCCL in this socket",
"PublicDescription": "The number of all operations received by the HHA from another SCCL in this socket",
"Unit": "hisi_sccl,hha",
},
{
"EventCode": "0x1c",
"EventName": "uncore_hisi_hha.rd_ddr_64b",
"BriefDescription": "The number of read operations sent by HHA to DDRC which size is 64 bytes",
"PublicDescription": "The number of read operations sent by HHA to DDRC which size is 64bytes",
"Unit": "hisi_sccl,hha",
},
{
"EventCode": "0x1d",
"EventName": "uncore_hisi_hha.wr_dr_64b",
"BriefDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes",
"PublicDescription": "The number of write operations sent by HHA to DDRC which size is 64 bytes",
"Unit": "hisi_sccl,hha",
},
{
"EventCode": "0x1e",
"EventName": "uncore_hisi_hha.rd_ddr_128b",
"BriefDescription": "The number of read operations sent by HHA to DDRC which size is 128 bytes",
"PublicDescription": "The number of read operations sent by HHA to DDRC which size is 128 bytes",
"Unit": "hisi_sccl,hha",
},
{
"EventCode": "0x1f",
"EventName": "uncore_hisi_hha.wr_ddr_128b",
"BriefDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes",
"PublicDescription": "The number of write operations sent by HHA to DDRC which size is 128 bytes",
"Unit": "hisi_sccl,hha",
},
]
[
{
"EventCode": "0x00",
"EventName": "uncore_hisi_l3c.rd_cpipe",
"BriefDescription": "Total read accesses",
"PublicDescription": "Total read accesses",
"Unit": "hisi_sccl,l3c",
},
{
"EventCode": "0x01",
"EventName": "uncore_hisi_l3c.wr_cpipe",
"BriefDescription": "Total write accesses",
"PublicDescription": "Total write accesses",
"Unit": "hisi_sccl,l3c",
},
{
"EventCode": "0x02",
"EventName": "uncore_hisi_l3c.rd_hit_cpipe",
"BriefDescription": "Total read hits",
"PublicDescription": "Total read hits",
"Unit": "hisi_sccl,l3c",
},
{
"EventCode": "0x03",
"EventName": "uncore_hisi_l3c.wr_hit_cpipe",
"BriefDescription": "Total write hits",
"PublicDescription": "Total write hits",
"Unit": "hisi_sccl,l3c",
},
{
"EventCode": "0x04",
"EventName": "uncore_hisi_l3c.victim_num",
"BriefDescription": "l3c precharge commands",
"PublicDescription": "l3c precharge commands",
"Unit": "hisi_sccl,l3c",
},
]
...@@ -314,13 +314,13 @@ ...@@ -314,13 +314,13 @@
"MetricName": "DRAM_BW_Use" "MetricName": "DRAM_BW_Use"
}, },
{ {
"MetricExpr": "1000000000 * ( cha@event\\=0x36\\\\\\,umask\\=0x21@ / cha@event\\=0x35\\\\\\,umask\\=0x21@ ) / ( cha_0@event\\=0x0@ / duration_time )", "MetricExpr": "1000000000 * ( cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,config\\=0x40433@ / cha@event\\=0x35\\\\\\,umask\\=0x21\\\\\\,config\\=0x40433@ ) / ( cha_0@event\\=0x0@ / duration_time )",
"BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches", "BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches",
"MetricGroup": "Memory_Lat", "MetricGroup": "Memory_Lat",
"MetricName": "DRAM_Read_Latency" "MetricName": "DRAM_Read_Latency"
}, },
{ {
"MetricExpr": "cha@event\\=0x36\\\\\\,umask\\=0x21@ / cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,thresh\\=1@", "MetricExpr": "cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,config\\=0x40433@ / cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,thresh\\=1\\\\\\,config\\=0x40433@",
"BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches", "BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches",
"MetricGroup": "Memory_BW", "MetricGroup": "Memory_BW",
"MetricName": "DRAM_Parallel_Reads" "MetricName": "DRAM_Parallel_Reads"
......
...@@ -314,35 +314,17 @@ ...@@ -314,35 +314,17 @@
"MetricName": "DRAM_BW_Use" "MetricName": "DRAM_BW_Use"
}, },
{ {
"MetricExpr": "1000000000 * ( cha@event\\=0x36\\\\\\,umask\\=0x21@ / cha@event\\=0x35\\\\\\,umask\\=0x21@ ) / ( cha_0@event\\=0x0@ / duration_time )", "MetricExpr": "1000000000 * ( cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,config\\=0x40433@ / cha@event\\=0x35\\\\\\,umask\\=0x21\\\\\\,config\\=0x40433@ ) / ( cha_0@event\\=0x0@ / duration_time )",
"BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches", "BriefDescription": "Average latency of data read request to external memory (in nanoseconds). Accounts for demand loads and L1/L2 prefetches",
"MetricGroup": "Memory_Lat", "MetricGroup": "Memory_Lat",
"MetricName": "DRAM_Read_Latency" "MetricName": "DRAM_Read_Latency"
}, },
{ {
"MetricExpr": "cha@event\\=0x36\\\\\\,umask\\=0x21@ / cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,thresh\\=1@", "MetricExpr": "cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,config\\=0x40433@ / cha@event\\=0x36\\\\\\,umask\\=0x21\\\\\\,thresh\\=1\\\\\\,config\\=0x40433@",
"BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches", "BriefDescription": "Average number of parallel data read requests to external memory. Accounts for demand loads and L1/L2 prefetches",
"MetricGroup": "Memory_BW", "MetricGroup": "Memory_BW",
"MetricName": "DRAM_Parallel_Reads" "MetricName": "DRAM_Parallel_Reads"
}, },
{
"MetricExpr": "( 1000000000 * ( imc@event\\=0xe0\\\\\\,umask\\=0x1@ / imc@event\\=0xe3@ ) / imc_0@event\\=0x0@ ) if 1 if 0 == 1 else 0 else 0",
"BriefDescription": "Average latency of data read request to external 3D X-Point memory [in nanoseconds]. Accounts for demand loads and L1/L2 data-read prefetches",
"MetricGroup": "Memory_Lat",
"MetricName": "MEM_PMM_Read_Latency"
},
{
"MetricExpr": "( ( 64 * imc@event\\=0xe3@ / 1000000000 ) / duration_time ) if 1 if 0 == 1 else 0 else 0",
"BriefDescription": "Average 3DXP Memory Bandwidth Use for reads [GB / sec]",
"MetricGroup": "Memory_BW",
"MetricName": "PMM_Read_BW"
},
{
"MetricExpr": "( ( 64 * imc@event\\=0xe7@ / 1000000000 ) / duration_time ) if 1 if 0 == 1 else 0 else 0",
"BriefDescription": "Average 3DXP Memory Bandwidth Use for Writes [GB / sec]",
"MetricGroup": "Memory_BW",
"MetricName": "PMM_Write_BW"
},
{ {
"MetricExpr": "cha_0@event\\=0x0@", "MetricExpr": "cha_0@event\\=0x0@",
"BriefDescription": "Socket actual clocks when any core is active on that socket", "BriefDescription": "Socket actual clocks when any core is active on that socket",
......
...@@ -236,6 +236,9 @@ static struct map { ...@@ -236,6 +236,9 @@ static struct map {
{ "CPU-M-CF", "cpum_cf" }, { "CPU-M-CF", "cpum_cf" },
{ "CPU-M-SF", "cpum_sf" }, { "CPU-M-SF", "cpum_sf" },
{ "UPI LL", "uncore_upi" }, { "UPI LL", "uncore_upi" },
{ "hisi_sccl,ddrc", "hisi_sccl,ddrc" },
{ "hisi_sccl,hha", "hisi_sccl,hha" },
{ "hisi_sccl,l3c", "hisi_sccl,l3c" },
{} {}
}; };
......
...@@ -531,6 +531,30 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he, ...@@ -531,6 +531,30 @@ static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
return printed; return printed;
} }
static int hist_entry__block_fprintf(struct hist_entry *he,
char *bf, size_t size,
FILE *fp)
{
struct block_hist *bh = container_of(he, struct block_hist, he);
int ret = 0;
for (unsigned int i = 0; i < bh->block_hists.nr_entries; i++) {
struct perf_hpp hpp = {
.buf = bf,
.size = size,
.skip = false,
};
bh->block_idx = i;
hist_entry__snprintf(he, &hpp);
if (!hpp.skip)
ret += fprintf(fp, "%s\n", bf);
}
return ret;
}
static int hist_entry__fprintf(struct hist_entry *he, size_t size, static int hist_entry__fprintf(struct hist_entry *he, size_t size,
char *bf, size_t bfsz, FILE *fp, char *bf, size_t bfsz, FILE *fp,
bool ignore_callchains) bool ignore_callchains)
...@@ -550,6 +574,9 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, ...@@ -550,6 +574,9 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
if (symbol_conf.report_hierarchy) if (symbol_conf.report_hierarchy)
return hist_entry__hierarchy_fprintf(he, &hpp, hists, fp); return hist_entry__hierarchy_fprintf(he, &hpp, hists, fp);
if (symbol_conf.report_block)
return hist_entry__block_fprintf(he, bf, size, fp);
hist_entry__snprintf(he, &hpp); hist_entry__snprintf(he, &hpp);
ret = fprintf(fp, "%s\n", bf); ret = fprintf(fp, "%s\n", bf);
......
...@@ -376,6 +376,24 @@ void hists__delete_entries(struct hists *hists) ...@@ -376,6 +376,24 @@ void hists__delete_entries(struct hists *hists)
} }
} }
struct hist_entry *hists__get_entry(struct hists *hists, int idx)
{
struct rb_node *next = rb_first_cached(&hists->entries);
struct hist_entry *n;
int i = 0;
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
if (i == idx)
return n;
next = rb_next(&n->rb_node);
i++;
}
return NULL;
}
/* /*
* histogram, sorted on item, collects periods * histogram, sorted on item, collects periods
*/ */
...@@ -574,6 +592,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists, ...@@ -574,6 +592,8 @@ static struct hist_entry *hists__findnew_entry(struct hists *hists,
*/ */
mem_info__zput(entry->mem_info); mem_info__zput(entry->mem_info);
block_info__zput(entry->block_info);
/* If the map of an existing hist_entry has /* If the map of an existing hist_entry has
* become out-of-date due to an exec() or * become out-of-date due to an exec() or
* similar, update it. Otherwise we will * similar, update it. Otherwise we will
...@@ -645,6 +665,7 @@ __hists__add_entry(struct hists *hists, ...@@ -645,6 +665,7 @@ __hists__add_entry(struct hists *hists,
struct symbol *sym_parent, struct symbol *sym_parent,
struct branch_info *bi, struct branch_info *bi,
struct mem_info *mi, struct mem_info *mi,
struct block_info *block_info,
struct perf_sample *sample, struct perf_sample *sample,
bool sample_self, bool sample_self,
struct hist_entry_ops *ops) struct hist_entry_ops *ops)
...@@ -677,6 +698,7 @@ __hists__add_entry(struct hists *hists, ...@@ -677,6 +698,7 @@ __hists__add_entry(struct hists *hists,
.hists = hists, .hists = hists,
.branch_info = bi, .branch_info = bi,
.mem_info = mi, .mem_info = mi,
.block_info = block_info,
.transaction = sample->transaction, .transaction = sample->transaction,
.raw_data = sample->raw_data, .raw_data = sample->raw_data,
.raw_size = sample->raw_size, .raw_size = sample->raw_size,
...@@ -699,7 +721,7 @@ struct hist_entry *hists__add_entry(struct hists *hists, ...@@ -699,7 +721,7 @@ struct hist_entry *hists__add_entry(struct hists *hists,
struct perf_sample *sample, struct perf_sample *sample,
bool sample_self) bool sample_self)
{ {
return __hists__add_entry(hists, al, sym_parent, bi, mi, return __hists__add_entry(hists, al, sym_parent, bi, mi, NULL,
sample, sample_self, NULL); sample, sample_self, NULL);
} }
...@@ -712,10 +734,22 @@ struct hist_entry *hists__add_entry_ops(struct hists *hists, ...@@ -712,10 +734,22 @@ struct hist_entry *hists__add_entry_ops(struct hists *hists,
struct perf_sample *sample, struct perf_sample *sample,
bool sample_self) bool sample_self)
{ {
return __hists__add_entry(hists, al, sym_parent, bi, mi, return __hists__add_entry(hists, al, sym_parent, bi, mi, NULL,
sample, sample_self, ops); sample, sample_self, ops);
} }
struct hist_entry *hists__add_entry_block(struct hists *hists,
struct addr_location *al,
struct block_info *block_info)
{
struct hist_entry entry = {
.block_info = block_info,
.hists = hists,
}, *he = hists__findnew_entry(hists, &entry, al, false);
return he;
}
static int static int
iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused, iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused,
struct addr_location *al __maybe_unused) struct addr_location *al __maybe_unused)
...@@ -1213,6 +1247,9 @@ void hist_entry__delete(struct hist_entry *he) ...@@ -1213,6 +1247,9 @@ void hist_entry__delete(struct hist_entry *he)
mem_info__zput(he->mem_info); mem_info__zput(he->mem_info);
} }
if (he->block_info)
block_info__zput(he->block_info);
zfree(&he->res_samples); zfree(&he->res_samples);
zfree(&he->stat_acc); zfree(&he->stat_acc);
free_srcline(he->srcline); free_srcline(he->srcline);
......
...@@ -16,6 +16,7 @@ struct addr_location; ...@@ -16,6 +16,7 @@ struct addr_location;
struct map_symbol; struct map_symbol;
struct mem_info; struct mem_info;
struct branch_info; struct branch_info;
struct block_info;
struct symbol; struct symbol;
enum hist_filter { enum hist_filter {
...@@ -149,6 +150,10 @@ struct hist_entry *hists__add_entry_ops(struct hists *hists, ...@@ -149,6 +150,10 @@ struct hist_entry *hists__add_entry_ops(struct hists *hists,
struct perf_sample *sample, struct perf_sample *sample,
bool sample_self); bool sample_self);
struct hist_entry *hists__add_entry_block(struct hists *hists,
struct addr_location *al,
struct block_info *bi);
int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
int max_stack_depth, void *arg); int max_stack_depth, void *arg);
...@@ -178,6 +183,8 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); ...@@ -178,6 +183,8 @@ void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
void hists__delete_entries(struct hists *hists); void hists__delete_entries(struct hists *hists);
void hists__output_recalc_col_len(struct hists *hists, int max_rows); void hists__output_recalc_col_len(struct hists *hists, int max_rows);
struct hist_entry *hists__get_entry(struct hists *hists, int idx);
u64 hists__total_period(struct hists *hists); u64 hists__total_period(struct hists *hists);
void hists__reset_stats(struct hists *hists); void hists__reset_stats(struct hists *hists);
void hists__inc_stats(struct hists *hists, struct hist_entry *h); void hists__inc_stats(struct hists *hists, struct hist_entry *h);
...@@ -243,6 +250,7 @@ struct perf_hpp { ...@@ -243,6 +250,7 @@ struct perf_hpp {
size_t size; size_t size;
const char *sep; const char *sep;
void *ptr; void *ptr;
bool skip;
}; };
struct perf_hpp_fmt { struct perf_hpp_fmt {
......
...@@ -375,7 +375,7 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter, ...@@ -375,7 +375,7 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
struct mep *me = container_of(node, struct mep, nd); struct mep *me = container_of(node, struct mep, nd);
if (metricgroups) if (metricgroups)
printf("%s%s%s", me->name, metrics ? ":" : "", raw ? " " : "\n"); printf("%s%s%s", me->name, metrics && !raw ? ":" : "", raw ? " " : "\n");
if (metrics) if (metrics)
metricgroup__print_strlist(me->metrics, raw); metricgroup__print_strlist(me->metrics, raw);
next = rb_next(node); next = rb_next(node);
...@@ -409,6 +409,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, ...@@ -409,6 +409,7 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
const char **ids; const char **ids;
int idnum; int idnum;
struct egroup *eg; struct egroup *eg;
bool no_group = false;
pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name); pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
...@@ -419,11 +420,25 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events, ...@@ -419,11 +420,25 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
strbuf_addf(events, ","); strbuf_addf(events, ",");
for (j = 0; j < idnum; j++) { for (j = 0; j < idnum; j++) {
pr_debug("found event %s\n", ids[j]); pr_debug("found event %s\n", ids[j]);
/*
* Duration time maps to a software event and can make
* groups not count. Always use it outside a
* group.
*/
if (!strcmp(ids[j], "duration_time")) {
if (j > 0)
strbuf_addf(events, "}:W,");
strbuf_addf(events, "duration_time");
no_group = true;
continue;
}
strbuf_addf(events, "%s%s", strbuf_addf(events, "%s%s",
j == 0 ? "{" : ",", j == 0 || no_group ? "{" : ",",
ids[j]); ids[j]);
no_group = false;
} }
strbuf_addf(events, "}:W"); if (!no_group)
strbuf_addf(events, "}:W");
eg = malloc(sizeof(struct egroup)); eg = malloc(sizeof(struct egroup));
if (!eg) { if (!eg) {
......
...@@ -701,6 +701,46 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu) ...@@ -701,6 +701,46 @@ struct pmu_events_map *perf_pmu__find_map(struct perf_pmu *pmu)
return map; return map;
} }
static bool pmu_uncore_alias_match(const char *pmu_name, const char *name)
{
char *tmp = NULL, *tok, *str;
bool res;
str = strdup(pmu_name);
if (!str)
return false;
/*
* uncore alias may be from different PMU with common prefix
*/
tok = strtok_r(str, ",", &tmp);
if (strncmp(pmu_name, tok, strlen(tok))) {
res = false;
goto out;
}
/*
* Match more complex aliases where the alias name is a comma-delimited
* list of tokens, orderly contained in the matching PMU name.
*
* Example: For alias "socket,pmuname" and PMU "socketX_pmunameY", we
* match "socket" in "socketX_pmunameY" and then "pmuname" in
* "pmunameY".
*/
for (; tok; name += strlen(tok), tok = strtok_r(NULL, ",", &tmp)) {
name = strstr(name, tok);
if (!name) {
res = false;
goto out;
}
}
res = true;
out:
free(str);
return res;
}
/* /*
* From the pmu_events_map, find the table of PMU events that corresponds * From the pmu_events_map, find the table of PMU events that corresponds
* to the current running CPU. Then, add all PMU events from that table * to the current running CPU. Then, add all PMU events from that table
...@@ -731,12 +771,8 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu) ...@@ -731,12 +771,8 @@ static void pmu_add_cpu_aliases(struct list_head *head, struct perf_pmu *pmu)
break; break;
} }
/*
* uncore alias may be from different PMU
* with common prefix
*/
if (pmu_is_uncore(name) && if (pmu_is_uncore(name) &&
!strncmp(pname, name, strlen(pname))) pmu_uncore_alias_match(pname, name))
goto new_alias; goto new_alias;
if (strcmp(pname, name)) if (strcmp(pname, name))
......
...@@ -79,6 +79,9 @@ struct hist_entry_diff { ...@@ -79,6 +79,9 @@ struct hist_entry_diff {
/* HISTC_WEIGHTED_DIFF */ /* HISTC_WEIGHTED_DIFF */
s64 wdiff; s64 wdiff;
/* PERF_HPP_DIFF__CYCLES */
s64 cycles;
}; };
}; };
...@@ -144,6 +147,7 @@ struct hist_entry { ...@@ -144,6 +147,7 @@ struct hist_entry {
long time; long time;
struct hists *hists; struct hists *hists;
struct mem_info *mem_info; struct mem_info *mem_info;
struct block_info *block_info;
void *raw_data; void *raw_data;
u32 raw_size; u32 raw_size;
int num_res; int num_res;
...@@ -285,6 +289,15 @@ struct sort_entry { ...@@ -285,6 +289,15 @@ struct sort_entry {
u8 se_width_idx; u8 se_width_idx;
}; };
struct block_hist {
struct hists block_hists;
struct perf_hpp_list block_list;
struct perf_hpp_fmt block_fmt;
int block_idx;
bool valid;
struct hist_entry he;
};
extern struct sort_entry sort_thread; extern struct sort_entry sort_thread;
extern struct list_head hist_entry__sort_list; extern struct list_head hist_entry__sort_list;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "util/util.h" #include "util/util.h"
#include "util/debug.h" #include "util/debug.h"
#include "util/callchain.h" #include "util/callchain.h"
#include "util/symbol_conf.h"
#include "srcline.h" #include "srcline.h"
#include "string2.h" #include "string2.h"
#include "symbol.h" #include "symbol.h"
...@@ -288,7 +289,8 @@ static int addr2line(const char *dso_name, u64 addr, ...@@ -288,7 +289,8 @@ static int addr2line(const char *dso_name, u64 addr,
} }
if (a2l == NULL) { if (a2l == NULL) {
pr_warning("addr2line_init failed for %s\n", dso_name); if (!symbol_conf.disable_add2line_warn)
pr_warning("addr2line_init failed for %s\n", dso_name);
return 0; return 0;
} }
......
...@@ -2351,3 +2351,25 @@ struct mem_info *mem_info__new(void) ...@@ -2351,3 +2351,25 @@ struct mem_info *mem_info__new(void)
refcount_set(&mi->refcnt, 1); refcount_set(&mi->refcnt, 1);
return mi; return mi;
} }
struct block_info *block_info__get(struct block_info *bi)
{
if (bi)
refcount_inc(&bi->refcnt);
return bi;
}
void block_info__put(struct block_info *bi)
{
if (bi && refcount_dec_and_test(&bi->refcnt))
free(bi);
}
struct block_info *block_info__new(void)
{
struct block_info *bi = zalloc(sizeof(*bi));
if (bi)
refcount_set(&bi->refcnt, 1);
return bi;
}
...@@ -131,6 +131,17 @@ struct mem_info { ...@@ -131,6 +131,17 @@ struct mem_info {
refcount_t refcnt; refcount_t refcnt;
}; };
struct block_info {
struct symbol *sym;
u64 start;
u64 end;
u64 cycles;
u64 cycles_aggr;
int num;
int num_aggr;
refcount_t refcnt;
};
struct addr_location { struct addr_location {
struct machine *machine; struct machine *machine;
struct thread *thread; struct thread *thread;
...@@ -332,4 +343,16 @@ static inline void __mem_info__zput(struct mem_info **mi) ...@@ -332,4 +343,16 @@ static inline void __mem_info__zput(struct mem_info **mi)
#define mem_info__zput(mi) __mem_info__zput(&mi) #define mem_info__zput(mi) __mem_info__zput(&mi)
struct block_info *block_info__new(void);
struct block_info *block_info__get(struct block_info *bi);
void block_info__put(struct block_info *bi);
static inline void __block_info__zput(struct block_info **bi)
{
block_info__put(*bi);
*bi = NULL;
}
#define block_info__zput(bi) __block_info__zput(&bi)
#endif /* __PERF_SYMBOL */ #endif /* __PERF_SYMBOL */
...@@ -39,7 +39,9 @@ struct symbol_conf { ...@@ -39,7 +39,9 @@ struct symbol_conf {
hide_unresolved, hide_unresolved,
raw_trace, raw_trace,
report_hierarchy, report_hierarchy,
inline_name; report_block,
inline_name,
disable_add2line_warn;
const char *vmlinux_name, const char *vmlinux_name,
*kallsyms_name, *kallsyms_name,
*source_prefix, *source_prefix,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment