|
|
|
@@ -1205,61 +1205,69 @@ out_no_progress:
|
|
|
|
|
|
|
|
|
|
static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
|
|
|
|
|
{
|
|
|
|
|
enum intel_pt_sample_type type = decoder->state.type;
|
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
|
|
decoder->state.type &= ~INTEL_PT_BRANCH;
|
|
|
|
|
|
|
|
|
|
if (decoder->set_fup_tx_flags) {
|
|
|
|
|
decoder->set_fup_tx_flags = false;
|
|
|
|
|
decoder->tx_flags = decoder->fup_tx_flags;
|
|
|
|
|
decoder->state.type = INTEL_PT_TRANSACTION;
|
|
|
|
|
decoder->state.type |= INTEL_PT_TRANSACTION;
|
|
|
|
|
if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX)
|
|
|
|
|
decoder->state.type |= INTEL_PT_BRANCH;
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->state.to_ip = 0;
|
|
|
|
|
decoder->state.flags = decoder->fup_tx_flags;
|
|
|
|
|
return true;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
if (decoder->set_fup_ptw) {
|
|
|
|
|
decoder->set_fup_ptw = false;
|
|
|
|
|
decoder->state.type = INTEL_PT_PTW;
|
|
|
|
|
decoder->state.type |= INTEL_PT_PTW;
|
|
|
|
|
decoder->state.flags |= INTEL_PT_FUP_IP;
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->state.to_ip = 0;
|
|
|
|
|
decoder->state.ptw_payload = decoder->fup_ptw_payload;
|
|
|
|
|
return true;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
if (decoder->set_fup_mwait) {
|
|
|
|
|
decoder->set_fup_mwait = false;
|
|
|
|
|
decoder->state.type = INTEL_PT_MWAIT_OP;
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->state.to_ip = 0;
|
|
|
|
|
decoder->state.type |= INTEL_PT_MWAIT_OP;
|
|
|
|
|
decoder->state.mwait_payload = decoder->fup_mwait_payload;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
if (decoder->set_fup_pwre) {
|
|
|
|
|
decoder->set_fup_pwre = false;
|
|
|
|
|
decoder->state.type |= INTEL_PT_PWR_ENTRY;
|
|
|
|
|
decoder->state.type &= ~INTEL_PT_BRANCH;
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->state.to_ip = 0;
|
|
|
|
|
decoder->state.pwre_payload = decoder->fup_pwre_payload;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
if (decoder->set_fup_exstop) {
|
|
|
|
|
decoder->set_fup_exstop = false;
|
|
|
|
|
decoder->state.type |= INTEL_PT_EX_STOP;
|
|
|
|
|
decoder->state.type &= ~INTEL_PT_BRANCH;
|
|
|
|
|
decoder->state.flags |= INTEL_PT_FUP_IP;
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->state.to_ip = 0;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
if (decoder->set_fup_bep) {
|
|
|
|
|
decoder->set_fup_bep = false;
|
|
|
|
|
decoder->state.type |= INTEL_PT_BLK_ITEMS;
|
|
|
|
|
decoder->state.type &= ~INTEL_PT_BRANCH;
|
|
|
|
|
ret = true;
|
|
|
|
|
}
|
|
|
|
|
if (decoder->overflow) {
|
|
|
|
|
decoder->overflow = false;
|
|
|
|
|
if (!ret && !decoder->pge) {
|
|
|
|
|
if (decoder->hop) {
|
|
|
|
|
decoder->state.type = 0;
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
|
|
|
|
|
}
|
|
|
|
|
decoder->pge = true;
|
|
|
|
|
decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN;
|
|
|
|
|
decoder->state.from_ip = 0;
|
|
|
|
|
decoder->state.to_ip = decoder->ip;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ret) {
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->state.to_ip = 0;
|
|
|
|
|
ret = true;
|
|
|
|
|
} else {
|
|
|
|
|
decoder->state.type = type;
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
@@ -1608,7 +1616,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
|
|
|
|
|
intel_pt_clear_tx_flags(decoder);
|
|
|
|
|
intel_pt_set_nr(decoder);
|
|
|
|
|
decoder->timestamp_insn_cnt = 0;
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->ip = 0;
|
|
|
|
|
decoder->pge = false;
|
|
|
|
|
decoder->set_fup_tx_flags = false;
|
|
|
|
|
decoder->set_fup_ptw = false;
|
|
|
|
|
decoder->set_fup_mwait = false;
|
|
|
|
|
decoder->set_fup_pwre = false;
|
|
|
|
|
decoder->set_fup_exstop = false;
|
|
|
|
|
decoder->set_fup_bep = false;
|
|
|
|
|
decoder->overflow = true;
|
|
|
|
|
return -EOVERFLOW;
|
|
|
|
|
}
|
|
|
|
@@ -2666,6 +2683,8 @@ static int intel_pt_scan_for_psb(struct intel_pt_decoder *decoder);
|
|
|
|
|
/* Hop mode: Ignore TNT, do not walk code, but get ip from FUPs and TIPs */
|
|
|
|
|
static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, int *err)
|
|
|
|
|
{
|
|
|
|
|
*err = 0;
|
|
|
|
|
|
|
|
|
|
/* Leap from PSB to PSB, getting ip from FUP within PSB+ */
|
|
|
|
|
if (decoder->leap && !decoder->in_psb && decoder->packet.type != INTEL_PT_PSB) {
|
|
|
|
|
*err = intel_pt_scan_for_psb(decoder);
|
|
|
|
@@ -2678,6 +2697,7 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in
|
|
|
|
|
return HOP_IGNORE;
|
|
|
|
|
|
|
|
|
|
case INTEL_PT_TIP_PGD:
|
|
|
|
|
decoder->pge = false;
|
|
|
|
|
if (!decoder->packet.count) {
|
|
|
|
|
intel_pt_set_nr(decoder);
|
|
|
|
|
return HOP_IGNORE;
|
|
|
|
@@ -2705,18 +2725,21 @@ static int intel_pt_hop_trace(struct intel_pt_decoder *decoder, bool *no_tip, in
|
|
|
|
|
if (!decoder->packet.count)
|
|
|
|
|
return HOP_IGNORE;
|
|
|
|
|
intel_pt_set_ip(decoder);
|
|
|
|
|
if (intel_pt_fup_event(decoder))
|
|
|
|
|
return HOP_RETURN;
|
|
|
|
|
if (!decoder->branch_enable)
|
|
|
|
|
if (decoder->set_fup_mwait || decoder->set_fup_pwre)
|
|
|
|
|
*no_tip = true;
|
|
|
|
|
if (!decoder->branch_enable || !decoder->pge)
|
|
|
|
|
*no_tip = true;
|
|
|
|
|
if (*no_tip) {
|
|
|
|
|
decoder->state.type = INTEL_PT_INSTRUCTION;
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
decoder->state.to_ip = 0;
|
|
|
|
|
intel_pt_fup_event(decoder);
|
|
|
|
|
return HOP_RETURN;
|
|
|
|
|
}
|
|
|
|
|
intel_pt_fup_event(decoder);
|
|
|
|
|
decoder->state.type |= INTEL_PT_INSTRUCTION | INTEL_PT_BRANCH;
|
|
|
|
|
*err = intel_pt_walk_fup_tip(decoder);
|
|
|
|
|
if (!*err)
|
|
|
|
|
if (!*err && decoder->state.to_ip)
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
|
|
|
|
|
return HOP_RETURN;
|
|
|
|
|
|
|
|
|
@@ -2897,7 +2920,7 @@ static bool intel_pt_psb_with_fup(struct intel_pt_decoder *decoder, int *err)
|
|
|
|
|
{
|
|
|
|
|
struct intel_pt_psb_info data = { .fup = false };
|
|
|
|
|
|
|
|
|
|
if (!decoder->branch_enable || !decoder->pge)
|
|
|
|
|
if (!decoder->branch_enable)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
intel_pt_pkt_lookahead(decoder, intel_pt_psb_lookahead_cb, &data);
|
|
|
|
@@ -2924,6 +2947,7 @@ static int intel_pt_walk_trace(struct intel_pt_decoder *decoder)
|
|
|
|
|
if (err)
|
|
|
|
|
return err;
|
|
|
|
|
next:
|
|
|
|
|
err = 0;
|
|
|
|
|
if (decoder->cyc_threshold) {
|
|
|
|
|
if (decoder->sample_cyc && last_packet_type != INTEL_PT_CYC)
|
|
|
|
|
decoder->sample_cyc = false;
|
|
|
|
@@ -2962,6 +2986,7 @@ next:
|
|
|
|
|
|
|
|
|
|
case INTEL_PT_TIP_PGE: {
|
|
|
|
|
decoder->pge = true;
|
|
|
|
|
decoder->overflow = false;
|
|
|
|
|
intel_pt_mtc_cyc_cnt_pge(decoder);
|
|
|
|
|
intel_pt_set_nr(decoder);
|
|
|
|
|
if (decoder->packet.count == 0) {
|
|
|
|
@@ -2999,7 +3024,7 @@ next:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
intel_pt_set_last_ip(decoder);
|
|
|
|
|
if (!decoder->branch_enable) {
|
|
|
|
|
if (!decoder->branch_enable || !decoder->pge) {
|
|
|
|
|
decoder->ip = decoder->last_ip;
|
|
|
|
|
if (intel_pt_fup_event(decoder))
|
|
|
|
|
return 0;
|
|
|
|
@@ -3467,10 +3492,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
|
|
|
|
|
decoder->set_fup_pwre = false;
|
|
|
|
|
decoder->set_fup_exstop = false;
|
|
|
|
|
decoder->set_fup_bep = false;
|
|
|
|
|
decoder->overflow = false;
|
|
|
|
|
|
|
|
|
|
if (!decoder->branch_enable) {
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
|
|
|
|
|
decoder->overflow = false;
|
|
|
|
|
decoder->state.type = 0; /* Do not have a sample */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@@ -3485,7 +3510,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
|
|
|
|
|
else
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
|
|
|
|
|
decoder->overflow = false;
|
|
|
|
|
|
|
|
|
|
decoder->state.from_ip = 0;
|
|
|
|
|
decoder->state.to_ip = decoder->ip;
|
|
|
|
@@ -3607,7 +3631,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decoder->have_last_ip = true;
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_NO_IP;
|
|
|
|
|
decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
|
|
|
|
|
|
|
|
|
|
err = intel_pt_walk_psb(decoder);
|
|
|
|
|
if (err)
|
|
|
|
@@ -3704,7 +3728,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
|
decoder->state.err = intel_pt_ext_err(err);
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
if (err != -EOVERFLOW)
|
|
|
|
|
decoder->state.from_ip = decoder->ip;
|
|
|
|
|
intel_pt_update_sample_time(decoder);
|
|
|
|
|
decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt;
|
|
|
|
|
intel_pt_set_nr(decoder);
|
|
|
|
|