Skip to content

Commit

Permalink
perf intel-pt: Add a config for max loops without consuming a packet
Browse files Browse the repository at this point in the history
The Intel PT decoder limits the number of unconditional branches (e.g.
jmps) decoded without consuming any trace packets. Generally, a loop
needs a conditional branch which generates a TNT packet, whereas a "ret"
instruction will generate a TIP or TNT packet. So exceeding the limit is
assumed to be a never-ending loop, which can happen if there has been a
decoding error putting the decoder at the wrong place in the code.

Up until now, the limit of 10000 has been enough but some analytic
purposes have been reported to exceed that.

Increase the limit to 100000, and make it configurable via perf config
intel-pt.max-loops. Also amend the "Never-ending loop" message to
mention the configuration entry.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Link: http://lore.kernel.org/lkml/20210701175132.3977-1-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
  • Loading branch information
Adrian Hunter authored and Arnaldo Carvalho de Melo committed Jul 7, 2021
1 parent 493be70 commit b4b046f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 4 deletions.
6 changes: 6 additions & 0 deletions tools/perf/Documentation/perf-config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,12 @@ intel-pt.*::
If set, Intel PT decoder will set the mispred flag on all
branches.

intel-pt.max-loops::
If set and non-zero, the maximum number of unconditional
branches decoded without consuming any trace packets. If
the maximum is exceeded there will be a "Never-ending loop"
error. The default is 100000.

auxtrace.*::

auxtrace.dumpdir::
Expand Down
13 changes: 9 additions & 4 deletions tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@

#define INTEL_PT_RETURN 1

/* Maximum number of loops with no packets consumed i.e. stuck in a loop */
#define INTEL_PT_MAX_LOOPS 10000
/*
* Default maximum number of loops with no packets consumed i.e. stuck in a
* loop.
*/
#define INTEL_PT_MAX_LOOPS 100000

struct intel_pt_blk {
struct intel_pt_blk *prev;
Expand Down Expand Up @@ -220,6 +223,7 @@ struct intel_pt_decoder {
uint64_t timestamp_insn_cnt;
uint64_t sample_insn_cnt;
uint64_t stuck_ip;
int max_loops;
int no_progress;
int stuck_ip_prd;
int stuck_ip_cnt;
Expand Down Expand Up @@ -315,6 +319,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
decoder->vm_tm_corr_dry_run = params->vm_tm_corr_dry_run;
decoder->first_timestamp = params->first_timestamp;
decoder->last_reliable_timestamp = params->first_timestamp;
decoder->max_loops = params->max_loops ? params->max_loops : INTEL_PT_MAX_LOOPS;

decoder->flags = params->flags;

Expand Down Expand Up @@ -483,7 +488,7 @@ static const char *intel_pt_err_msgs[] = {
[INTEL_PT_ERR_OVR] = "Overflow packet",
[INTEL_PT_ERR_LOST] = "Lost trace data",
[INTEL_PT_ERR_UNK] = "Unknown error!",
[INTEL_PT_ERR_NELOOP] = "Never-ending loop",
[INTEL_PT_ERR_NELOOP] = "Never-ending loop (refer perf config intel-pt.max-loops)",
};

int intel_pt__strerror(int code, char *buf, size_t buflen)
Expand Down Expand Up @@ -1168,7 +1173,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
decoder->stuck_ip = decoder->state.to_ip;
decoder->stuck_ip_prd = 1;
decoder->stuck_ip_cnt = 1;
} else if (cnt > INTEL_PT_MAX_LOOPS ||
} else if (cnt > decoder->max_loops ||
decoder->state.to_ip == decoder->stuck_ip) {
intel_pt_log_at("ERROR: Never-ending loop",
decoder->state.to_ip);
Expand Down
1 change: 1 addition & 0 deletions tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ struct intel_pt_params {
uint32_t tsc_ctc_ratio_d;
enum intel_pt_param_flags flags;
unsigned int quick;
int max_loops;
};

struct intel_pt_decoder;
Expand Down
5 changes: 5 additions & 0 deletions tools/perf/util/intel-pt.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct intel_pt {
u64 noretcomp_bit;
unsigned max_non_turbo_ratio;
unsigned cbr2khz;
int max_loops;

unsigned long num_events;

Expand Down Expand Up @@ -1200,6 +1201,7 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
params.vm_time_correlation = pt->synth_opts.vm_time_correlation;
params.vm_tm_corr_dry_run = pt->synth_opts.vm_tm_corr_dry_run;
params.first_timestamp = pt->first_timestamp;
params.max_loops = pt->max_loops;

if (pt->filts.cnt > 0)
params.pgd_ip = intel_pt_pgd_ip;
Expand Down Expand Up @@ -3431,6 +3433,9 @@ static int intel_pt_perf_config(const char *var, const char *value, void *data)
if (!strcmp(var, "intel-pt.mispred-all"))
pt->mispred_all = perf_config_bool(var, value);

if (!strcmp(var, "intel-pt.max-loops"))
perf_config_int(&pt->max_loops, var, value);

return 0;
}

Expand Down

0 comments on commit b4b046f

Please sign in to comment.