Check for being stuck in a loop. That can happen if a decoder error results in the decoder erroneously setting the ip to an address that is itself in an infinite loop that consumes no packets. The only way to be in a loop that consumes no packets is if it consists of unconditional branches. So the check for being stuck is if we see a repeating cycle of consecutive unconditional branches.
Signed-off-by: Adrian Hunter <[email protected]> --- .../perf/util/intel-pt-decoder/intel-pt-decoder.c | 42 ++++++++++++++++++++++ .../perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 + 2 files changed, 43 insertions(+) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 748a7a078313..e8ff6573ecec 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -37,6 +37,9 @@ #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 + struct intel_pt_blk { struct intel_pt_blk *prev; uint64_t ip[INTEL_PT_BLK_SIZE]; @@ -114,6 +117,10 @@ struct intel_pt_decoder { unsigned int fup_tx_flags; unsigned int tx_flags; uint64_t timestamp_insn_cnt; + uint64_t stuck_ip; + int no_progress; + int stuck_ip_prd; + int stuck_ip_cnt; const unsigned char *next_buf; size_t next_len; unsigned char temp_buf[INTEL_PT_PKT_MAX_SZ]; @@ -263,6 +270,8 @@ static int intel_pt_ext_err(int code) return INTEL_PT_ERR_OVR; case -ENOSPC: return INTEL_PT_ERR_LOST; + case -ELOOP: + return INTEL_PT_ERR_NELOOP; default: return INTEL_PT_ERR_UNK; } @@ -278,6 +287,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", }; int intel_pt__strerror(int code, char *buf, size_t buflen) @@ -550,6 +560,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, decoder->period_insn_cnt += insn_cnt; if (err) { + decoder->no_progress = 0; decoder->pkt_state = INTEL_PT_STATE_ERR2; intel_pt_log_at("ERROR: Failed to get instruction", decoder->ip); @@ -589,13 +600,44 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder, } if (intel_pt_insn->branch == INTEL_PT_BR_UNCONDITIONAL) { + int cnt = decoder->no_progress++; + decoder->state.from_ip = decoder->ip; decoder->ip += intel_pt_insn->length + intel_pt_insn->rel; decoder->state.to_ip = decoder->ip; err = INTEL_PT_RETURN; + + /* + * Check for being stuck in a loop. This can happen if a + * decoder error results in the decoder erroneously setting the + * ip to an address that is itself in an infinite loop that + * consumes no packets. When that happens, there must be an + * unconditional branch. + */ + if (cnt) { + if (cnt == 1) { + decoder->stuck_ip = decoder->state.to_ip; + decoder->stuck_ip_prd = 1; + decoder->stuck_ip_cnt = 1; + } else if (cnt > INTEL_PT_MAX_LOOPS || + decoder->state.to_ip == decoder->stuck_ip) { + intel_pt_log_at("ERROR: Never-ending loop", + decoder->state.to_ip); + decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; + err = -ELOOP; + goto out; + } else if (!--decoder->stuck_ip_cnt) { + decoder->stuck_ip_prd += 1; + decoder->stuck_ip_cnt = decoder->stuck_ip_prd; + decoder->stuck_ip = decoder->state.to_ip; + } + } + goto out_no_progress; } out: + decoder->no_progress = 0; +out_no_progress: decoder->state.insn_op = intel_pt_insn->op; decoder->state.insn_len = intel_pt_insn->length; diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h index 955263adfd8d..706c6bccc57e 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h @@ -48,6 +48,7 @@ enum { INTEL_PT_ERR_OVR, INTEL_PT_ERR_LOST, INTEL_PT_ERR_UNK, + INTEL_PT_ERR_NELOOP, INTEL_PT_ERR_MAX, }; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

