diff options
Diffstat (limited to 'tools/perf/util/intel-pt-decoder/intel-pt-decoder.c')
-rw-r--r-- | tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | 30 |
1 files changed, 30 insertions, 0 deletions
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 8ff6c6a61291..7591a0c37473 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c | |||
@@ -80,6 +80,7 @@ struct intel_pt_decoder { | |||
80 | int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, | 80 | int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, |
81 | uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, | 81 | uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, |
82 | uint64_t max_insn_cnt, void *data); | 82 | uint64_t max_insn_cnt, void *data); |
83 | bool (*pgd_ip)(uint64_t ip, void *data); | ||
83 | void *data; | 84 | void *data; |
84 | struct intel_pt_state state; | 85 | struct intel_pt_state state; |
85 | const unsigned char *buf; | 86 | const unsigned char *buf; |
@@ -186,6 +187,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params) | |||
186 | 187 | ||
187 | decoder->get_trace = params->get_trace; | 188 | decoder->get_trace = params->get_trace; |
188 | decoder->walk_insn = params->walk_insn; | 189 | decoder->walk_insn = params->walk_insn; |
190 | decoder->pgd_ip = params->pgd_ip; | ||
189 | decoder->data = params->data; | 191 | decoder->data = params->data; |
190 | decoder->return_compression = params->return_compression; | 192 | decoder->return_compression = params->return_compression; |
191 | 193 | ||
@@ -1008,6 +1010,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder) | |||
1008 | int err; | 1010 | int err; |
1009 | 1011 | ||
1010 | err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0); | 1012 | err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0); |
1013 | if (err == INTEL_PT_RETURN && | ||
1014 | decoder->pgd_ip && | ||
1015 | decoder->pkt_state == INTEL_PT_STATE_TIP_PGD && | ||
1016 | (decoder->state.type & INTEL_PT_BRANCH) && | ||
1017 | decoder->pgd_ip(decoder->state.to_ip, decoder->data)) { | ||
1018 | /* Unconditional branch leaving filter region */ | ||
1019 | decoder->no_progress = 0; | ||
1020 | decoder->pge = false; | ||
1021 | decoder->continuous_period = false; | ||
1022 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; | ||
1023 | decoder->state.to_ip = 0; | ||
1024 | return 0; | ||
1025 | } | ||
1011 | if (err == INTEL_PT_RETURN) | 1026 | if (err == INTEL_PT_RETURN) |
1012 | return 0; | 1027 | return 0; |
1013 | if (err) | 1028 | if (err) |
@@ -1036,6 +1051,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder) | |||
1036 | } | 1051 | } |
1037 | 1052 | ||
1038 | if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { | 1053 | if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { |
1054 | uint64_t to_ip = decoder->ip + intel_pt_insn.length + | ||
1055 | intel_pt_insn.rel; | ||
1056 | |||
1057 | if (decoder->pgd_ip && | ||
1058 | decoder->pkt_state == INTEL_PT_STATE_TIP_PGD && | ||
1059 | decoder->pgd_ip(to_ip, decoder->data)) { | ||
1060 | /* Conditional branch leaving filter region */ | ||
1061 | decoder->pge = false; | ||
1062 | decoder->continuous_period = false; | ||
1063 | decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; | ||
1064 | decoder->ip = to_ip; | ||
1065 | decoder->state.from_ip = decoder->ip; | ||
1066 | decoder->state.to_ip = 0; | ||
1067 | return 0; | ||
1068 | } | ||
1039 | intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", | 1069 | intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", |
1040 | decoder->ip); | 1070 | decoder->ip); |
1041 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; | 1071 | decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; |