Commit d1c9f7d1 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo-5.7-20200317' of...

Merge tag 'perf-core-for-mingo-5.7-20200317' 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 record:

  Alexey Budankov:

  - Fix binding of AIO user space buffers to nodes

maps:

  Dominik b. Czarnota:

  - Fix off by one in strncpy() size argument.

  Arnaldo Carvalho de Melo:

  - Use strstarts() to look for Android libraries.

  Ian Rogers:

  - Give synthetic mmap events an inode generation.

man pages:

  Ian Rogers:

  - Set man page date to last git commit.

perf test:

  Ian Rogers:

  - Print if shell directory isn't present.

perf report:

  Jin Yao:

  - Fix no branch type statistics report issue.

perf expr:

  Jiri Olsa:

  - Fix copy/paste mistake

vendor events:

  Kan Liang:

  - Support metric constraints.

vendor events intel:

  Kan Liang:

  - Add NO_NMI_WATCHDOG metric constraint.

vendor events s390:

  Thomas Richter:

 - Add new deflate counters for IBM z15.

ARM cs-etm:

  Leo Yan:

  - Last branch improvements.

intel-pt:

  Adrian Hunter:

  - Update intel-pt.txt file with new location of the documentation.

  - Add Intel PT man page references.

  - Rename intel-pt.txt and put it in man page format.

perl scripting:

  Michael Petlan:

 - Add common_callchain to fix argument order.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>

Conflicts:
	tools/perf/util/map.c
parents 409e1a31 59a08b4b
......@@ -295,7 +295,10 @@ $(OUTPUT)%.1 $(OUTPUT)%.5 $(OUTPUT)%.7 : $(OUTPUT)%.xml
$(OUTPUT)%.xml : %.txt
$(QUIET_ASCIIDOC)$(RM) $@+ $@ && \
$(ASCIIDOC) -b docbook -d manpage \
$(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) -o $@+ $< && \
$(ASCIIDOC_EXTRA) -aperf_version=$(PERF_VERSION) \
-aperf_date=$(shell git log -1 --pretty="format:%cd" \
--date=short $<) \
-o $@+ $< && \
mv $@+ $@
XSLT = docbook.xsl
......
This diff is collapsed.
......@@ -66,4 +66,5 @@ include::itrace.txt[]
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1],
linkperf:perf-intel-pt[1]
This diff is collapsed.
......@@ -589,4 +589,4 @@ appended unit character - B/K/M/G
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-list[1]
linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-intel-pt[1]
......@@ -546,4 +546,5 @@ include::callchain-overhead-calculation.txt[]
SEE ALSO
--------
linkperf:perf-stat[1], linkperf:perf-annotate[1], linkperf:perf-record[1]
linkperf:perf-stat[1], linkperf:perf-annotate[1], linkperf:perf-record[1],
linkperf:perf-intel-pt[1]
......@@ -429,4 +429,4 @@ include::itrace.txt[]
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script-perl[1],
linkperf:perf-script-python[1]
linkperf:perf-script-python[1], linkperf:perf-intel-pt[1]
......@@ -186,24 +186,23 @@ static int hist_iter__branch_callback(struct hist_entry_iter *iter,
{
struct hist_entry *he = iter->he;
struct report *rep = arg;
struct branch_info *bi;
struct branch_info *bi = he->branch_info;
struct perf_sample *sample = iter->sample;
struct evsel *evsel = iter->evsel;
int err;
branch_type_count(&rep->brtype_stat, &bi->flags,
bi->from.addr, bi->to.addr);
if (!ui__has_annotation() && !rep->symbol_ipc)
return 0;
bi = he->branch_info;
err = addr_map_symbol__inc_samples(&bi->from, sample, evsel);
if (err)
goto out;
err = addr_map_symbol__inc_samples(&bi->to, sample, evsel);
branch_type_count(&rep->brtype_stat, &bi->flags,
bi->from.addr, bi->to.addr);
out:
return err;
}
......
......@@ -4,27 +4,27 @@
"EventCode": "80",
"EventName": "ECC_FUNCTION_COUNT",
"BriefDescription": "ECC Function Count",
"PublicDescription": "Long ECC function Count"
"PublicDescription": "This counter counts the total number of the elliptic-curve cryptography (ECC) functions issued by the CPU."
},
{
"Unit": "CPU-M-CF",
"EventCode": "81",
"EventName": "ECC_CYCLES_COUNT",
"BriefDescription": "ECC Cycles Count",
"PublicDescription": "Long ECC Function cycles count"
"PublicDescription": "This counter counts the total number of CPU cycles when the ECC coprocessor is busy performing the elliptic-curve cryptography (ECC) functions issued by the CPU."
},
{
"Unit": "CPU-M-CF",
"EventCode": "82",
"EventName": "ECC_BLOCKED_FUNCTION_COUNT",
"BriefDescription": "Ecc Blocked Function Count",
"PublicDescription": "Long ECC blocked function count"
"PublicDescription": "This counter counts the total number of the elliptic-curve cryptography (ECC) functions that are issued by the CPU and are blocked because the ECC coprocessor is busy performing a function issued by another CPU."
},
{
"Unit": "CPU-M-CF",
"EventCode": "83",
"EventName": "ECC_BLOCKED_CYCLES_COUNT",
"BriefDescription": "ECC Blocked Cycles Count",
"PublicDescription": "Long ECC blocked cycles count"
"PublicDescription": "This counter counts the total number of CPU cycles blocked for the elliptic-curve cryptography (ECC) functions issued by the CPU because the ECC coprocessor is busy performing a function issued by another CPU."
},
]
......@@ -25,7 +25,7 @@
"EventCode": "131",
"EventName": "DTLB2_HPAGE_WRITES",
"BriefDescription": "DTLB2 One-Megabyte Page Writes",
"PublicDescription": "A translation entry was written into the Combined Region and Segment Table Entry array in the Level-2 TLB for a one-megabyte page or a Last Host Translation was done"
"PublicDescription": "A translation entry was written into the Combined Region and Segment Table Entry array in the Level-2 TLB for a one-megabyte page"
},
{
"Unit": "CPU-M-CF",
......@@ -356,6 +356,34 @@
"BriefDescription": "Aborted transactions in constrained TX mode using special completion logic",
"PublicDescription": "A transaction abort has occurred in a constrained transactional-execution mode and the CPU is using special logic to allow the transaction to complete"
},
{
"Unit": "CPU-M-CF",
"EventCode": "247",
"EventName": "DFLT_ACCESS",
"BriefDescription": "Cycles CPU spent obtaining access to Deflate unit",
"PublicDescription": "Cycles CPU spent obtaining access to Deflate unit"
},
{
"Unit": "CPU-M-CF",
"EventCode": "252",
"EventName": "DFLT_CYCLES",
"BriefDescription": "Cycles CPU is using Deflate unit",
"PublicDescription": "Cycles CPU is using Deflate unit"
},
{
"Unit": "CPU-M-CF",
"EventCode": "264",
"EventName": "DFLT_CC",
"BriefDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed",
"PublicDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed"
},
{
"Unit": "CPU-M-CF",
"EventCode": "265",
"EventName": "DFLT_CCERROR",
"BriefDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2",
"PublicDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2"
},
{
"Unit": "CPU-M-CF",
"EventCode": "448",
......
......@@ -215,7 +215,8 @@
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
"MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * cycles )",
"MetricGroup": "TLB",
"MetricName": "Page_Walks_Utilization"
"MetricName": "Page_Walks_Utilization",
"MetricConstraint": "NO_NMI_WATCHDOG"
},
{
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
......
......@@ -215,7 +215,8 @@
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
"MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * cycles )",
"MetricGroup": "TLB",
"MetricName": "Page_Walks_Utilization"
"MetricName": "Page_Walks_Utilization",
"MetricConstraint": "NO_NMI_WATCHDOG"
},
{
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
......
......@@ -215,7 +215,8 @@
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
"MetricExpr": "( ITLB_MISSES.WALK_PENDING + DTLB_LOAD_MISSES.WALK_PENDING + DTLB_STORE_MISSES.WALK_PENDING + EPT.WALK_PENDING ) / ( 2 * cycles )",
"MetricGroup": "TLB",
"MetricName": "Page_Walks_Utilization"
"MetricName": "Page_Walks_Utilization",
"MetricConstraint": "NO_NMI_WATCHDOG"
},
{
"BriefDescription": "Utilization of the core's Page Walker(s) serving STLB misses triggered by instruction/Load/Store accesses",
......
......@@ -323,7 +323,7 @@ static int print_events_table_entry(void *data, char *name, char *event,
char *pmu, char *unit, char *perpkg,
char *metric_expr,
char *metric_name, char *metric_group,
char *deprecated)
char *deprecated, char *metric_constraint)
{
struct perf_entry_data *pd = data;
FILE *outfp = pd->outfp;
......@@ -357,6 +357,8 @@ static int print_events_table_entry(void *data, char *name, char *event,
fprintf(outfp, "\t.metric_group = \"%s\",\n", metric_group);
if (deprecated)
fprintf(outfp, "\t.deprecated = \"%s\",\n", deprecated);
if (metric_constraint)
fprintf(outfp, "\t.metric_constraint = \"%s\",\n", metric_constraint);
fprintf(outfp, "},\n");
return 0;
......@@ -375,6 +377,7 @@ struct event_struct {
char *metric_name;
char *metric_group;
char *deprecated;
char *metric_constraint;
};
#define ADD_EVENT_FIELD(field) do { if (field) { \
......@@ -422,7 +425,7 @@ static int save_arch_std_events(void *data, char *name, char *event,
char *desc, char *long_desc, char *pmu,
char *unit, char *perpkg, char *metric_expr,
char *metric_name, char *metric_group,
char *deprecated)
char *deprecated, char *metric_constraint)
{
struct event_struct *es;
......@@ -486,7 +489,7 @@ try_fixup(const char *fn, char *arch_std, char **event, char **desc,
char **name, char **long_desc, char **pmu, char **filter,
char **perpkg, char **unit, char **metric_expr, char **metric_name,
char **metric_group, unsigned long long eventcode,
char **deprecated)
char **deprecated, char **metric_constraint)
{
/* try to find matching event from arch standard values */
struct event_struct *es;
......@@ -515,7 +518,7 @@ int json_events(const char *fn,
char *pmu, char *unit, char *perpkg,
char *metric_expr,
char *metric_name, char *metric_group,
char *deprecated),
char *deprecated, char *metric_constraint),
void *data)
{
int err;
......@@ -545,6 +548,7 @@ int json_events(const char *fn,
char *metric_name = NULL;
char *metric_group = NULL;
char *deprecated = NULL;
char *metric_constraint = NULL;
char *arch_std = NULL;
unsigned long long eventcode = 0;
struct msrmap *msr = NULL;
......@@ -629,6 +633,8 @@ int json_events(const char *fn,
addfield(map, &metric_name, "", "", val);
} else if (json_streq(map, field, "MetricGroup")) {
addfield(map, &metric_group, "", "", val);
} else if (json_streq(map, field, "MetricConstraint")) {
addfield(map, &metric_constraint, "", "", val);
} else if (json_streq(map, field, "MetricExpr")) {
addfield(map, &metric_expr, "", "", val);
for (s = metric_expr; *s; s++)
......@@ -670,13 +676,13 @@ int json_events(const char *fn,
&long_desc, &pmu, &filter, &perpkg,
&unit, &metric_expr, &metric_name,
&metric_group, eventcode,
&deprecated);
&deprecated, &metric_constraint);
if (err)
goto free_strings;
}
err = func(data, name, real_event(name, event), desc, long_desc,
pmu, unit, perpkg, metric_expr, metric_name,
metric_group, deprecated);
metric_group, deprecated, metric_constraint);
free_strings:
free(event);
free(desc);
......@@ -691,6 +697,7 @@ int json_events(const char *fn,
free(metric_expr);
free(metric_name);
free(metric_group);
free(metric_constraint);
free(arch_std);
if (err)
......
......@@ -8,7 +8,7 @@ int json_events(const char *fn,
char *pmu,
char *unit, char *perpkg, char *metric_expr,
char *metric_name, char *metric_group,
char *deprecated),
char *deprecated, char *metric_constraint),
void *data);
char *get_cpu_str(void);
......
......@@ -18,6 +18,7 @@ struct pmu_event {
const char *metric_name;
const char *metric_group;
const char *deprecated;
const char *metric_constraint;
};
/*
......
......@@ -28,7 +28,7 @@ sub trace_end
sub irq::softirq_entry
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$vec) = @_;
print_header($event_name, $common_cpu, $common_secs, $common_nsecs,
......@@ -43,7 +43,7 @@ sub irq::softirq_entry
sub kmem::kmalloc
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$call_site, $ptr, $bytes_req, $bytes_alloc,
$gfp_flags) = @_;
......@@ -92,7 +92,7 @@ sub print_unhandled
sub trace_unhandled
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm) = @_;
$common_pid, $common_comm, $common_callchain) = @_;
$unhandled{$event_name}++;
}
......
......@@ -18,7 +18,7 @@ my %failed_syscalls;
sub raw_syscalls::sys_exit
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$id, $ret) = @_;
if ($ret < 0) {
......
......@@ -28,7 +28,7 @@ my %writes;
sub syscalls::sys_enter_read
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm, $nr, $fd, $buf, $count) = @_;
$common_pid, $common_comm, $common_callchain, $nr, $fd, $buf, $count) = @_;
if ($common_comm eq $for_comm) {
$reads{$fd}{bytes_requested} += $count;
......@@ -39,7 +39,7 @@ sub syscalls::sys_enter_read
sub syscalls::sys_enter_write
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm, $nr, $fd, $buf, $count) = @_;
$common_pid, $common_comm, $common_callchain, $nr, $fd, $buf, $count) = @_;
if ($common_comm eq $for_comm) {
$writes{$fd}{bytes_written} += $count;
......@@ -98,7 +98,7 @@ sub print_unhandled
sub trace_unhandled
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm) = @_;
$common_pid, $common_comm, $common_callchain) = @_;
$unhandled{$event_name}++;
}
......
......@@ -24,7 +24,7 @@ my %writes;
sub syscalls::sys_exit_read
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $ret) = @_;
if ($ret > 0) {
......@@ -40,7 +40,7 @@ sub syscalls::sys_exit_read
sub syscalls::sys_enter_read
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $fd, $buf, $count) = @_;
$reads{$common_pid}{bytes_requested} += $count;
......@@ -51,7 +51,7 @@ sub syscalls::sys_enter_read
sub syscalls::sys_exit_write
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $ret) = @_;
if ($ret <= 0) {
......@@ -62,7 +62,7 @@ sub syscalls::sys_exit_write
sub syscalls::sys_enter_write
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $fd, $buf, $count) = @_;
$writes{$common_pid}{bytes_written} += $count;
......@@ -178,7 +178,7 @@ sub print_unhandled
sub trace_unhandled
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm) = @_;
$common_pid, $common_comm, $common_callchain) = @_;
$unhandled{$event_name}++;
}
......@@ -35,7 +35,7 @@ if (!$interval) {
sub syscalls::sys_exit_read
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $ret) = @_;
print_check();
......@@ -53,7 +53,7 @@ sub syscalls::sys_exit_read
sub syscalls::sys_enter_read
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $fd, $buf, $count) = @_;
print_check();
......@@ -66,7 +66,7 @@ sub syscalls::sys_enter_read
sub syscalls::sys_exit_write
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $ret) = @_;
print_check();
......@@ -79,7 +79,7 @@ sub syscalls::sys_exit_write
sub syscalls::sys_enter_write
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$nr, $fd, $buf, $count) = @_;
print_check();
......@@ -197,7 +197,7 @@ sub print_unhandled
sub trace_unhandled
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm) = @_;
$common_pid, $common_comm, $common_callchain) = @_;
$unhandled{$event_name}++;
}
......@@ -28,7 +28,7 @@ my $total_wakeups = 0;
sub sched::sched_switch
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$prev_comm, $prev_pid, $prev_prio, $prev_state, $next_comm, $next_pid,
$next_prio) = @_;
......@@ -51,7 +51,7 @@ sub sched::sched_switch
sub sched::sched_wakeup
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm,
$common_pid, $common_comm, $common_callchain,
$comm, $pid, $prio, $success, $target_cpu) = @_;
$last_wakeup{$target_cpu}{ts} = nsecs($common_secs, $common_nsecs);
......@@ -101,7 +101,7 @@ sub print_unhandled
sub trace_unhandled
{
my ($event_name, $context, $common_cpu, $common_secs, $common_nsecs,
$common_pid, $common_comm) = @_;
$common_pid, $common_comm, $common_callchain) = @_;
$unhandled{$event_name}++;
}
......@@ -543,8 +543,11 @@ static int run_shell_tests(int argc, const char *argv[], int i, int width)
return -1;
dir = opendir(st.dir);
if (!dir)
if (!dir) {
pr_err("failed to open shell test directory: %s\n",
st.dir);
return -1;
}
for_each_shell_test(dir, st.dir, ent) {
int curr = i++;
......
......@@ -363,6 +363,23 @@ struct cs_etm_packet_queue
return NULL;
}
static void cs_etm__packet_swap(struct cs_etm_auxtrace *etm,
struct cs_etm_traceid_queue *tidq)
{
struct cs_etm_packet *tmp;
if (etm->sample_branches || etm->synth_opts.last_branch ||
etm->sample_instructions) {
/*
* Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
* the next incoming packet.
*/
tmp = tidq->packet;
tidq->packet = tidq->prev_packet;
tidq->prev_packet = tmp;
}
}
static void cs_etm__packet_dump(const char *pkt_string)
{
const char *color = PERF_COLOR_BLUE;
......@@ -945,7 +962,7 @@ static inline u64 cs_etm__instr_addr(struct cs_etm_queue *etmq,
if (packet->isa == CS_ETM_ISA_T32) {
u64 addr = packet->start_addr;
while (offset > 0) {
while (offset) {
addr += cs_etm__t32_instr_size(etmq,
trace_chan_id, addr);
offset--;
......@@ -1134,10 +1151,8 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
cs_etm__copy_insn(etmq, tidq->trace_chan_id, tidq->packet, &sample);
if (etm->synth_opts.last_branch) {
cs_etm__copy_last_branch_rb(etmq, tidq);
if (etm->synth_opts.last_branch)
sample.branch_stack = tidq->last_branch;
}
if (etm->synth_opts.inject) {
ret = cs_etm__inject_event(event, &sample,
......@@ -1153,9 +1168,6 @@ static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
"CS ETM Trace: failed to deliver instruction event, error %d\n",
ret);
if (etm->synth_opts.last_branch)
cs_etm__reset_last_branch_rb(tidq);
return ret;
}
......@@ -1342,12 +1354,14 @@ static int cs_etm__sample(struct cs_etm_queue *etmq,
struct cs_etm_traceid_queue *tidq)
{
struct cs_etm_auxtrace *etm = etmq->etm;
struct cs_etm_packet *tmp;
int ret;
u8 trace_chan_id = tidq->trace_chan_id;
u64 instrs_executed = tidq->packet->instr_count;
u64 instrs_prev;
/* Get instructions remainder from previous packet */
instrs_prev = tidq->period_instructions;
tidq->period_instructions += instrs_executed;
tidq->period_instructions += tidq->packet->instr_count;
/*
* Record a branch when the last instruction in
......@@ -1365,26 +1379,80 @@ static int cs_etm__sample(struct cs_etm_queue *etmq,
* TODO: allow period to be defined in cycles and clock time
*/
/* Get number of instructions executed after the sample point */
u64 instrs_over = tidq->period_instructions -
etm->instructions_sample_period;
/*
* Below diagram demonstrates the instruction samples
* generation flows:
*
* Instrs Instrs Instrs Instrs
* Sample(n) Sample(n+1) Sample(n+2) Sample(n+3)
* | | | |
* V V V V
* --------------------------------------------------
* ^ ^
* | |
* Period Period
* instructions(Pi) instructions(Pi')
*
* | |
* \---------------- -----------------/
* V
* tidq->packet->instr_count
*
* Instrs Sample(n...) are the synthesised samples occurring
* every etm->instructions_sample_period instructions - as
* defined on the perf command line. Sample(n) is being the
* last sample before the current etm packet, n+1 to n+3
* samples are generated from the current etm packet.
*
* tidq->packet->instr_count represents the number of
* instructions in the current etm packet.
*
* Period instructions (Pi) contains the the number of
* instructions executed after the sample point(n) from the
* previous etm packet. This will always be less than
* etm->instructions_sample_period.
*
* When generate new samples, it combines with two parts
* instructions, one is the tail of the old packet and another
* is the head of the new coming packet, to generate
* sample(n+1); sample(n+2) and sample(n+3) consume the
* instructions with sample period. After sample(n+3), the rest
* instructions will be used by later packet and it is assigned
* to tidq->period_instructions for next round calculation.
*/
/*
* Calculate the address of the sampled instruction (-1 as
* sample is reported as though instruction has just been
* executed, but PC has not advanced to next instruction)
* Get the initial offset into the current packet instructions;
* entry conditions ensure that instrs_prev is less than
* etm->instructions_sample_period.
*/
u64 offset = (instrs_executed - instrs_over - 1);
u64 addr = cs_etm__instr_addr(etmq, trace_chan_id,
tidq->packet, offset);
u64 offset = etm->instructions_sample_period - instrs_prev;
u64 addr;
ret = cs_etm__synth_instruction_sample(
etmq, tidq, addr, etm->instructions_sample_period);
if (ret)
return ret;
/* Prepare last branches for instruction sample */
if (etm->synth_opts.last_branch)
cs_etm__copy_last_branch_rb(etmq, tidq);
/* Carry remaining instructions into next sample period */
tidq->period_instructions = instrs_over;
while (tidq->period_instructions >=
etm->instructions_sample_period) {
/*
* Calculate the address of the sampled instruction (-1
* as sample is reported as though instruction has just
* been executed, but PC has not advanced to next
* instruction)
*/
addr = cs_etm__instr_addr(etmq, trace_chan_id,
tidq->packet, offset - 1);
ret = cs_etm__synth_instruction_sample(
etmq, tidq, addr,
etm->instructions_sample_period);
if (ret)
return ret;
offset += etm->instructions_sample_period;
tidq->period_instructions -=
etm->instructions_sample_period;
}
}
if (etm->sample_branches) {
......@@ -1406,15 +1474,7 @@ static int cs_etm__sample(struct cs_etm_queue *etmq,
}
}
if (etm->sample_branches || etm->synth_opts.last_branch) {
/*
* Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
* the next incoming packet.
*/
tmp = tidq->packet;
tidq->packet = tidq->prev_packet;
tidq->prev_packet = tmp;
}
cs_etm__packet_swap(etm, tidq);
return 0;
}
......@@ -1443,7 +1503,6 @@ static int cs_etm__flush(struct cs_etm_queue *etmq,
{
int err = 0;
struct cs_etm_auxtrace *etm = etmq->etm;
struct cs_etm_packet *tmp;
/* Handle start tracing packet */
if (tidq->prev_packet->sample_type == CS_ETM_EMPTY)
......@@ -1451,6 +1510,11 @@ static int cs_etm__flush(struct cs_etm_queue *etmq,
if (etmq->etm->synth_opts.last_branch &&
tidq->prev_packet->sample_type == CS_ETM_RANGE) {
u64 addr;
/* Prepare last branches for instruction sample */
cs_etm__copy_last_branch_rb(etmq, tidq);
/*
* Generate a last branch event for the branches left in the
* circular buffer at the end of the trace.
......@@ -1458,7 +1522,7 @@ static int cs_etm__flush(struct cs_etm_queue *etmq,
* Use the address of the end of the last reported execution
* range
*/
u64 addr = cs_etm__last_executed_instr(tidq->prev_packet);
addr = cs_etm__last_executed_instr(tidq->prev_packet);
err = cs_etm__synth_instruction_sample(
etmq, tidq, addr,
......@@ -1478,15 +1542,11 @@ static int cs_etm__flush(struct cs_etm_queue *etmq,
}
swap_packet:
if (etm->sample_branches || etm->synth_opts.last_branch) {
/*
* Swap PACKET with PREV_PACKET: PACKET becomes PREV_PACKET for
* the next incoming packet.
*/
tmp = tidq->packet;
tidq->packet = tidq->prev_packet;
tidq->prev_packet = tmp;
}
cs_etm__packet_swap(etm, tidq);
/* Reset last branches after flush the trace */
if (etm->synth_opts.last_branch)
cs_etm__reset_last_branch_rb(tidq);
return err;
}
......@@ -1507,11 +1567,16 @@ static int cs_etm__end_block(struct cs_etm_queue *etmq,
*/
if (etmq->etm->synth_opts.last_branch &&
tidq->prev_packet->sample_type == CS_ETM_RANGE) {
u64 addr;
/* Prepare last branches for instruction sample */
cs_etm__copy_last_branch_rb(etmq, tidq);
/*
* Use the address of the end of the last reported execution
* range.
*/
u64 addr = cs_etm__last_executed_instr(tidq->prev_packet);
addr = cs_etm__last_executed_instr(tidq->prev_packet);
err = cs_etm__synth_instruction_sample(
etmq, tidq, addr,
......
......@@ -79,10 +79,10 @@ symbol {spec}*{sym}*{spec}*{sym}*
{
int start_token;
start_token = parse_events_get_extra(yyscanner);
start_token = expr_get_extra(yyscanner);
if (start_token) {
parse_events_set_extra(NULL, yyscanner);
expr_set_extra(NULL, yyscanner);
return start_token;
}
}
......
......@@ -44,8 +44,8 @@ static inline int is_no_dso_memory(const char *filename)
static inline int is_android_lib(const char *filename)
{
return !strncmp(filename, "/data/app-lib", 13) ||
!strncmp(filename, "/system/lib", 11);
return strstarts(filename, "/data/app-lib/") ||
strstarts(filename, "/system/lib/");
}
static inline bool replace_android_lib(const char *filename, char *newfilename)
......@@ -65,7 +65,7 @@ static inline bool replace_android_lib(const char *filename, char *newfilename)
app_abi_length = strlen(app_abi);
if (!strncmp(filename, "/data/app-lib", 13)) {
if (strstarts(filename, "/data/app-lib/")) {
char *apk_path;
if (!app_abi_length)
......@@ -89,7 +89,7 @@ static inline bool replace_android_lib(const char *filename, char *newfilename)
return true;
}
if (!strncmp(filename, "/system/lib/", 12)) {
if (strstarts(filename, "/system/lib/")) {
char *ndk, *app;
const char *arch;
size_t ndk_length;
......
......@@ -22,6 +22,8 @@
#include <linux/string.h>
#include <linux/zalloc.h>
#include <subcmd/parse-options.h>
#include <api/fs/fs.h>
#include "util.h"
struct metric_event *metricgroup__lookup(struct rblist *metric_events,
struct evsel *evsel,
......@@ -399,13 +401,85 @@ void metricgroup__print(bool metrics, bool metricgroups, char *filter,
strlist__delete(metriclist);
}
static void metricgroup__add_metric_weak_group(struct strbuf *events,
const char **ids,
int idnum)
{
bool no_group = false;
int i;
for (i = 0; i < idnum; i++) {
pr_debug("found event %s\n", ids[i]);
/*
* Duration time maps to a software event and can make
* groups not count. Always use it outside a
* group.
*/
if (!strcmp(ids[i], "duration_time")) {
if (i > 0)
strbuf_addf(events, "}:W,");
strbuf_addf(events, "duration_time");
no_group = true;
continue;
}
strbuf_addf(events, "%s%s",
i == 0 || no_group ? "{" : ",",
ids[i]);
no_group = false;
}
if (!no_group)
strbuf_addf(events, "}:W");
}
static void metricgroup__add_metric_non_group(struct strbuf *events,
const char **ids,
int idnum)
{
int i;
for (i = 0; i < idnum; i++)
strbuf_addf(events, ",%s", ids[i]);
}
static void metricgroup___watchdog_constraint_hint(const char *name, bool foot)
{
static bool violate_nmi_constraint;
if (!foot) {
pr_warning("Splitting metric group %s into standalone metrics.\n", name);
violate_nmi_constraint = true;
return;
}
if (!violate_nmi_constraint)
return;
pr_warning("Try disabling the NMI watchdog to comply NO_NMI_WATCHDOG metric constraint:\n"
" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
" perf stat ...\n"
" echo 1 > /proc/sys/kernel/nmi_watchdog\n");
}
static bool metricgroup__has_constraint(struct pmu_event *pe)
{
if (!pe->metric_constraint)
return false;
if (!strcmp(pe->metric_constraint, "NO_NMI_WATCHDOG") &&
sysctl__nmi_watchdog_enabled()) {
metricgroup___watchdog_constraint_hint(pe->metric_name, false);
return true;
}
return false;
}
static int metricgroup__add_metric(const char *metric, struct strbuf *events,
struct list_head *group_list)
{
struct pmu_events_map *map = perf_pmu__find_map(NULL);
struct pmu_event *pe;
int ret = -EINVAL;
int i, j;
int i, ret = -EINVAL;
if (!map)
return 0;
......@@ -422,7 +496,6 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
const char **ids;
int idnum;
struct egroup *eg;
bool no_group = false;
pr_debug("metric expr %s for %s\n", pe->metric_expr, pe->metric_name);
......@@ -431,27 +504,11 @@ static int metricgroup__add_metric(const char *metric, struct strbuf *events,
continue;
if (events->len > 0)
strbuf_addf(events, ",");
for (j = 0; j < idnum; 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",
j == 0 || no_group ? "{" : ",",
ids[j]);
no_group = false;
}
if (!no_group)
strbuf_addf(events, "}:W");
if (metricgroup__has_constraint(pe))
metricgroup__add_metric_non_group(events, ids, idnum);
else
metricgroup__add_metric_weak_group(events, ids, idnum);
eg = malloc(sizeof(struct egroup));
if (!eg) {
......@@ -493,6 +550,10 @@ static int metricgroup__add_metric_list(const char *list, struct strbuf *events,
}
}
free(nlist);
if (!ret)
metricgroup___watchdog_constraint_hint(NULL, true);
return ret;
}
......
......@@ -98,20 +98,29 @@ static int perf_mmap__aio_bind(struct mmap *map, int idx, int cpu, int affinity)
{
void *data;
size_t mmap_len;
unsigned long node_mask;
unsigned long *node_mask;
unsigned long node_index;
int err = 0;
if (affinity != PERF_AFFINITY_SYS && cpu__max_node() > 1) {
data = map->aio.data[idx];
mmap_len = mmap__mmap_len(map);
node_mask = 1UL << cpu__get_node(cpu);
if (mbind(data, mmap_len, MPOL_BIND, &node_mask, 1, 0)) {
pr_err("Failed to bind [%p-%p] AIO buffer to node %d: error %m\n",
data, data + mmap_len, cpu__get_node(cpu));
node_index = cpu__get_node(cpu);
node_mask = bitmap_alloc(node_index + 1);
if (!node_mask) {
pr_err("Failed to allocate node mask for mbind: error %m\n");
return -1;
}
set_bit(node_index, node_mask);
if (mbind(data, mmap_len, MPOL_BIND, node_mask, node_index + 1 + 1, 0)) {
pr_err("Failed to bind [%p-%p] AIO buffer to node %lu: error %m\n",
data, data + mmap_len, node_index);
err = -1;
}
bitmap_free(node_mask);
}
return 0;
return err;
}
#else /* !HAVE_LIBNUMA_SUPPORT */
static int perf_mmap__aio_alloc(struct mmap *map, int idx)
......
......@@ -16,6 +16,7 @@
#include <linux/ctype.h>
#include "cgroup.h"
#include <api/fs/fs.h>
#include "util.h"
#define CNTR_NOT_SUPPORTED "<not supported>"
#define CNTR_NOT_COUNTED "<not counted>"
......@@ -1097,7 +1098,6 @@ static void print_footer(struct perf_stat_config *config)
{
double avg = avg_stats(config->walltime_nsecs_stats) / NSEC_PER_SEC;
FILE *output = config->output;
int n;
if (!config->null_run)
fprintf(output, "\n");
......@@ -1131,9 +1131,7 @@ static void print_footer(struct perf_stat_config *config)
}
fprintf(output, "\n\n");
if (config->print_free_counters_hint &&
sysctl__read_int("kernel/nmi_watchdog", &n) >= 0 &&
n > 0)
if (config->print_free_counters_hint && sysctl__nmi_watchdog_enabled())
fprintf(output,
"Some events weren't counted. Try disabling the NMI watchdog:\n"
" echo 0 > /proc/sys/kernel/nmi_watchdog\n"
......
......@@ -345,6 +345,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
continue;
event->mmap2.ino = (u64)ino;
event->mmap2.ino_generation = 0;
/*
* Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
......
......@@ -55,6 +55,24 @@ int sysctl__max_stack(void)
return sysctl_perf_event_max_stack;
}
bool sysctl__nmi_watchdog_enabled(void)
{
static bool cached;
static bool nmi_watchdog;
int value;
if (cached)
return nmi_watchdog;
if (sysctl__read_int("kernel/nmi_watchdog", &value) < 0)
return false;
nmi_watchdog = (value > 0) ? true : false;
cached = true;
return nmi_watchdog;
}
bool test_attr__enabled;
bool perf_host = true;
......
......@@ -29,6 +29,8 @@ size_t hex_width(u64 v);
int sysctl__max_stack(void);
bool sysctl__nmi_watchdog_enabled(void);
int fetch_kernel_version(unsigned int *puint,
char *str, size_t str_sz);
#define KVER_VERSION(x) (((x) >> 16) & 0xff)
......
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