|
@@ -113,6 +113,7 @@ struct intel_pt_decoder {
|
|
|
bool have_cyc;
|
|
|
bool fixup_last_mtc;
|
|
|
bool have_last_ip;
|
|
|
+ enum intel_pt_param_flags flags;
|
|
|
uint64_t pos;
|
|
|
uint64_t last_ip;
|
|
|
uint64_t ip;
|
|
@@ -226,6 +227,8 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
|
|
|
decoder->return_compression = params->return_compression;
|
|
|
decoder->branch_enable = params->branch_enable;
|
|
|
|
|
|
+ decoder->flags = params->flags;
|
|
|
+
|
|
|
decoder->period = params->period;
|
|
|
decoder->period_type = params->period_type;
|
|
|
|
|
@@ -1097,6 +1100,15 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static inline bool intel_pt_fup_with_nlip(struct intel_pt_decoder *decoder,
|
|
|
+ struct intel_pt_insn *intel_pt_insn,
|
|
|
+ uint64_t ip, int err)
|
|
|
+{
|
|
|
+ return decoder->flags & INTEL_PT_FUP_WITH_NLIP && !err &&
|
|
|
+ intel_pt_insn->branch == INTEL_PT_BR_INDIRECT &&
|
|
|
+ ip == decoder->ip + intel_pt_insn->length;
|
|
|
+}
|
|
|
+
|
|
|
static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
|
|
|
{
|
|
|
struct intel_pt_insn intel_pt_insn;
|
|
@@ -1109,10 +1121,11 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
|
|
|
err = intel_pt_walk_insn(decoder, &intel_pt_insn, ip);
|
|
|
if (err == INTEL_PT_RETURN)
|
|
|
return 0;
|
|
|
- if (err == -EAGAIN) {
|
|
|
+ if (err == -EAGAIN ||
|
|
|
+ intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) {
|
|
|
if (intel_pt_fup_event(decoder))
|
|
|
return 0;
|
|
|
- return err;
|
|
|
+ return -EAGAIN;
|
|
|
}
|
|
|
decoder->set_fup_tx_flags = false;
|
|
|
if (err)
|