|
@@ -64,6 +64,25 @@ enum intel_pt_pkt_state {
|
|
INTEL_PT_STATE_FUP_NO_TIP,
|
|
INTEL_PT_STATE_FUP_NO_TIP,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state)
|
|
|
|
+{
|
|
|
|
+ switch (pkt_state) {
|
|
|
|
+ case INTEL_PT_STATE_NO_PSB:
|
|
|
|
+ case INTEL_PT_STATE_NO_IP:
|
|
|
|
+ case INTEL_PT_STATE_ERR_RESYNC:
|
|
|
|
+ case INTEL_PT_STATE_IN_SYNC:
|
|
|
|
+ case INTEL_PT_STATE_TNT:
|
|
|
|
+ return true;
|
|
|
|
+ case INTEL_PT_STATE_TIP:
|
|
|
|
+ case INTEL_PT_STATE_TIP_PGD:
|
|
|
|
+ case INTEL_PT_STATE_FUP:
|
|
|
|
+ case INTEL_PT_STATE_FUP_NO_TIP:
|
|
|
|
+ return false;
|
|
|
|
+ default:
|
|
|
|
+ return true;
|
|
|
|
+ };
|
|
|
|
+}
|
|
|
|
+
|
|
#ifdef INTEL_PT_STRICT
|
|
#ifdef INTEL_PT_STRICT
|
|
#define INTEL_PT_STATE_ERR1 INTEL_PT_STATE_NO_PSB
|
|
#define INTEL_PT_STATE_ERR1 INTEL_PT_STATE_NO_PSB
|
|
#define INTEL_PT_STATE_ERR2 INTEL_PT_STATE_NO_PSB
|
|
#define INTEL_PT_STATE_ERR2 INTEL_PT_STATE_NO_PSB
|
|
@@ -87,11 +106,13 @@ struct intel_pt_decoder {
|
|
const unsigned char *buf;
|
|
const unsigned char *buf;
|
|
size_t len;
|
|
size_t len;
|
|
bool return_compression;
|
|
bool return_compression;
|
|
|
|
+ bool branch_enable;
|
|
bool mtc_insn;
|
|
bool mtc_insn;
|
|
bool pge;
|
|
bool pge;
|
|
bool have_tma;
|
|
bool have_tma;
|
|
bool have_cyc;
|
|
bool have_cyc;
|
|
bool fixup_last_mtc;
|
|
bool fixup_last_mtc;
|
|
|
|
+ bool have_last_ip;
|
|
uint64_t pos;
|
|
uint64_t pos;
|
|
uint64_t last_ip;
|
|
uint64_t last_ip;
|
|
uint64_t ip;
|
|
uint64_t ip;
|
|
@@ -99,6 +120,7 @@ struct intel_pt_decoder {
|
|
uint64_t timestamp;
|
|
uint64_t timestamp;
|
|
uint64_t tsc_timestamp;
|
|
uint64_t tsc_timestamp;
|
|
uint64_t ref_timestamp;
|
|
uint64_t ref_timestamp;
|
|
|
|
+ uint64_t sample_timestamp;
|
|
uint64_t ret_addr;
|
|
uint64_t ret_addr;
|
|
uint64_t ctc_timestamp;
|
|
uint64_t ctc_timestamp;
|
|
uint64_t ctc_delta;
|
|
uint64_t ctc_delta;
|
|
@@ -119,6 +141,7 @@ struct intel_pt_decoder {
|
|
int pkt_len;
|
|
int pkt_len;
|
|
int last_packet_type;
|
|
int last_packet_type;
|
|
unsigned int cbr;
|
|
unsigned int cbr;
|
|
|
|
+ unsigned int cbr_seen;
|
|
unsigned int max_non_turbo_ratio;
|
|
unsigned int max_non_turbo_ratio;
|
|
double max_non_turbo_ratio_fp;
|
|
double max_non_turbo_ratio_fp;
|
|
double cbr_cyc_to_tsc;
|
|
double cbr_cyc_to_tsc;
|
|
@@ -136,9 +159,18 @@ struct intel_pt_decoder {
|
|
bool continuous_period;
|
|
bool continuous_period;
|
|
bool overflow;
|
|
bool overflow;
|
|
bool set_fup_tx_flags;
|
|
bool set_fup_tx_flags;
|
|
|
|
+ bool set_fup_ptw;
|
|
|
|
+ bool set_fup_mwait;
|
|
|
|
+ bool set_fup_pwre;
|
|
|
|
+ bool set_fup_exstop;
|
|
unsigned int fup_tx_flags;
|
|
unsigned int fup_tx_flags;
|
|
unsigned int tx_flags;
|
|
unsigned int tx_flags;
|
|
|
|
+ uint64_t fup_ptw_payload;
|
|
|
|
+ uint64_t fup_mwait_payload;
|
|
|
|
+ uint64_t fup_pwre_payload;
|
|
|
|
+ uint64_t cbr_payload;
|
|
uint64_t timestamp_insn_cnt;
|
|
uint64_t timestamp_insn_cnt;
|
|
|
|
+ uint64_t sample_insn_cnt;
|
|
uint64_t stuck_ip;
|
|
uint64_t stuck_ip;
|
|
int no_progress;
|
|
int no_progress;
|
|
int stuck_ip_prd;
|
|
int stuck_ip_prd;
|
|
@@ -192,6 +224,7 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
|
|
decoder->pgd_ip = params->pgd_ip;
|
|
decoder->pgd_ip = params->pgd_ip;
|
|
decoder->data = params->data;
|
|
decoder->data = params->data;
|
|
decoder->return_compression = params->return_compression;
|
|
decoder->return_compression = params->return_compression;
|
|
|
|
+ decoder->branch_enable = params->branch_enable;
|
|
|
|
|
|
decoder->period = params->period;
|
|
decoder->period = params->period;
|
|
decoder->period_type = params->period_type;
|
|
decoder->period_type = params->period_type;
|
|
@@ -398,6 +431,7 @@ static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
|
|
static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
|
|
static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
|
|
decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
|
|
|
|
+ decoder->have_last_ip = true;
|
|
}
|
|
}
|
|
|
|
|
|
static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
|
|
static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
|
|
@@ -635,6 +669,8 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_VMCS:
|
|
case INTEL_PT_VMCS:
|
|
case INTEL_PT_MNT:
|
|
case INTEL_PT_MNT:
|
|
|
|
+ case INTEL_PT_PTWRITE:
|
|
|
|
+ case INTEL_PT_PTWRITE_IP:
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
case INTEL_PT_MTC:
|
|
case INTEL_PT_MTC:
|
|
@@ -733,6 +769,11 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
|
|
|
|
|
|
case INTEL_PT_TIP_PGD:
|
|
case INTEL_PT_TIP_PGD:
|
|
case INTEL_PT_TRACESTOP:
|
|
case INTEL_PT_TRACESTOP:
|
|
|
|
+ case INTEL_PT_EXSTOP:
|
|
|
|
+ case INTEL_PT_EXSTOP_IP:
|
|
|
|
+ case INTEL_PT_MWAIT:
|
|
|
|
+ case INTEL_PT_PWRE:
|
|
|
|
+ case INTEL_PT_PWRX:
|
|
case INTEL_PT_OVF:
|
|
case INTEL_PT_OVF:
|
|
case INTEL_PT_BAD: /* Does not happen */
|
|
case INTEL_PT_BAD: /* Does not happen */
|
|
default:
|
|
default:
|
|
@@ -898,6 +939,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
|
|
|
|
|
|
decoder->tot_insn_cnt += insn_cnt;
|
|
decoder->tot_insn_cnt += insn_cnt;
|
|
decoder->timestamp_insn_cnt += insn_cnt;
|
|
decoder->timestamp_insn_cnt += insn_cnt;
|
|
|
|
+ decoder->sample_insn_cnt += insn_cnt;
|
|
decoder->period_insn_cnt += insn_cnt;
|
|
decoder->period_insn_cnt += insn_cnt;
|
|
|
|
|
|
if (err) {
|
|
if (err) {
|
|
@@ -990,6 +1032,57 @@ out_no_progress:
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
|
|
|
|
+{
|
|
|
|
+ bool ret = false;
|
|
|
|
+
|
|
|
|
+ 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.from_ip = decoder->ip;
|
|
|
|
+ decoder->state.to_ip = 0;
|
|
|
|
+ decoder->state.flags = decoder->fup_tx_flags;
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ if (decoder->set_fup_ptw) {
|
|
|
|
+ decoder->set_fup_ptw = false;
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+ 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.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;
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
|
|
static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
struct intel_pt_insn intel_pt_insn;
|
|
struct intel_pt_insn intel_pt_insn;
|
|
@@ -1003,15 +1096,8 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
|
|
if (err == INTEL_PT_RETURN)
|
|
if (err == INTEL_PT_RETURN)
|
|
return 0;
|
|
return 0;
|
|
if (err == -EAGAIN) {
|
|
if (err == -EAGAIN) {
|
|
- 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.from_ip = decoder->ip;
|
|
|
|
- decoder->state.to_ip = 0;
|
|
|
|
- decoder->state.flags = decoder->fup_tx_flags;
|
|
|
|
|
|
+ if (intel_pt_fup_event(decoder))
|
|
return 0;
|
|
return 0;
|
|
- }
|
|
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
decoder->set_fup_tx_flags = false;
|
|
decoder->set_fup_tx_flags = false;
|
|
@@ -1360,7 +1446,9 @@ static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder)
|
|
static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
- unsigned int cbr = decoder->packet.payload;
|
|
|
|
|
|
+ unsigned int cbr = decoder->packet.payload & 0xff;
|
|
|
|
+
|
|
|
|
+ decoder->cbr_payload = decoder->packet.payload;
|
|
|
|
|
|
if (decoder->cbr == cbr)
|
|
if (decoder->cbr == cbr)
|
|
return;
|
|
return;
|
|
@@ -1417,6 +1505,13 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
case INTEL_PT_TRACESTOP:
|
|
case INTEL_PT_TRACESTOP:
|
|
case INTEL_PT_BAD:
|
|
case INTEL_PT_BAD:
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
|
|
+ case INTEL_PT_PTWRITE:
|
|
|
|
+ case INTEL_PT_PTWRITE_IP:
|
|
|
|
+ case INTEL_PT_EXSTOP:
|
|
|
|
+ case INTEL_PT_EXSTOP_IP:
|
|
|
|
+ case INTEL_PT_MWAIT:
|
|
|
|
+ case INTEL_PT_PWRE:
|
|
|
|
+ case INTEL_PT_PWRX:
|
|
decoder->have_tma = false;
|
|
decoder->have_tma = false;
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
@@ -1446,7 +1541,8 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
case INTEL_PT_FUP:
|
|
case INTEL_PT_FUP:
|
|
decoder->pge = true;
|
|
decoder->pge = true;
|
|
- intel_pt_set_last_ip(decoder);
|
|
|
|
|
|
+ if (decoder->packet.count)
|
|
|
|
+ intel_pt_set_last_ip(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MODE_TSX:
|
|
case INTEL_PT_MODE_TSX:
|
|
@@ -1497,6 +1593,13 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
|
|
case INTEL_PT_MODE_TSX:
|
|
case INTEL_PT_MODE_TSX:
|
|
case INTEL_PT_BAD:
|
|
case INTEL_PT_BAD:
|
|
case INTEL_PT_PSBEND:
|
|
case INTEL_PT_PSBEND:
|
|
|
|
+ case INTEL_PT_PTWRITE:
|
|
|
|
+ case INTEL_PT_PTWRITE_IP:
|
|
|
|
+ case INTEL_PT_EXSTOP:
|
|
|
|
+ case INTEL_PT_EXSTOP_IP:
|
|
|
|
+ case INTEL_PT_MWAIT:
|
|
|
|
+ case INTEL_PT_PWRE:
|
|
|
|
+ case INTEL_PT_PWRX:
|
|
intel_pt_log("ERROR: Missing TIP after FUP\n");
|
|
intel_pt_log("ERROR: Missing TIP after FUP\n");
|
|
decoder->pkt_state = INTEL_PT_STATE_ERR3;
|
|
decoder->pkt_state = INTEL_PT_STATE_ERR3;
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
@@ -1625,6 +1728,15 @@ next:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
intel_pt_set_last_ip(decoder);
|
|
intel_pt_set_last_ip(decoder);
|
|
|
|
+ if (!decoder->branch_enable) {
|
|
|
|
+ decoder->ip = decoder->last_ip;
|
|
|
|
+ if (intel_pt_fup_event(decoder))
|
|
|
|
+ return 0;
|
|
|
|
+ no_tip = false;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if (decoder->set_fup_mwait)
|
|
|
|
+ no_tip = true;
|
|
err = intel_pt_walk_fup(decoder);
|
|
err = intel_pt_walk_fup(decoder);
|
|
if (err != -EAGAIN) {
|
|
if (err != -EAGAIN) {
|
|
if (err)
|
|
if (err)
|
|
@@ -1650,6 +1762,8 @@ next:
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
|
|
+ decoder->last_ip = 0;
|
|
|
|
+ decoder->have_last_ip = true;
|
|
intel_pt_clear_stack(&decoder->stack);
|
|
intel_pt_clear_stack(&decoder->stack);
|
|
err = intel_pt_walk_psbend(decoder);
|
|
err = intel_pt_walk_psbend(decoder);
|
|
if (err == -EAGAIN)
|
|
if (err == -EAGAIN)
|
|
@@ -1696,6 +1810,16 @@ next:
|
|
|
|
|
|
case INTEL_PT_CBR:
|
|
case INTEL_PT_CBR:
|
|
intel_pt_calc_cbr(decoder);
|
|
intel_pt_calc_cbr(decoder);
|
|
|
|
+ if (!decoder->branch_enable &&
|
|
|
|
+ decoder->cbr != decoder->cbr_seen) {
|
|
|
|
+ decoder->cbr_seen = decoder->cbr;
|
|
|
|
+ decoder->state.type = INTEL_PT_CBR_CHG;
|
|
|
|
+ decoder->state.from_ip = decoder->ip;
|
|
|
|
+ decoder->state.to_ip = 0;
|
|
|
|
+ decoder->state.cbr_payload =
|
|
|
|
+ decoder->packet.payload;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MODE_EXEC:
|
|
case INTEL_PT_MODE_EXEC:
|
|
@@ -1722,6 +1846,71 @@ next:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_PTWRITE_IP:
|
|
|
|
+ decoder->fup_ptw_payload = decoder->packet.payload;
|
|
|
|
+ err = intel_pt_get_next_packet(decoder);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+ if (decoder->packet.type == INTEL_PT_FUP) {
|
|
|
|
+ decoder->set_fup_ptw = true;
|
|
|
|
+ no_tip = true;
|
|
|
|
+ } else {
|
|
|
|
+ intel_pt_log_at("ERROR: Missing FUP after PTWRITE",
|
|
|
|
+ decoder->pos);
|
|
|
|
+ }
|
|
|
|
+ goto next;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_PTWRITE:
|
|
|
|
+ decoder->state.type = INTEL_PT_PTW;
|
|
|
|
+ decoder->state.from_ip = decoder->ip;
|
|
|
|
+ decoder->state.to_ip = 0;
|
|
|
|
+ decoder->state.ptw_payload = decoder->packet.payload;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_MWAIT:
|
|
|
|
+ decoder->fup_mwait_payload = decoder->packet.payload;
|
|
|
|
+ decoder->set_fup_mwait = true;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_PWRE:
|
|
|
|
+ if (decoder->set_fup_mwait) {
|
|
|
|
+ decoder->fup_pwre_payload =
|
|
|
|
+ decoder->packet.payload;
|
|
|
|
+ decoder->set_fup_pwre = true;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ decoder->state.type = INTEL_PT_PWR_ENTRY;
|
|
|
|
+ decoder->state.from_ip = decoder->ip;
|
|
|
|
+ decoder->state.to_ip = 0;
|
|
|
|
+ decoder->state.pwrx_payload = decoder->packet.payload;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_EXSTOP_IP:
|
|
|
|
+ err = intel_pt_get_next_packet(decoder);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+ if (decoder->packet.type == INTEL_PT_FUP) {
|
|
|
|
+ decoder->set_fup_exstop = true;
|
|
|
|
+ no_tip = true;
|
|
|
|
+ } else {
|
|
|
|
+ intel_pt_log_at("ERROR: Missing FUP after EXSTOP",
|
|
|
|
+ decoder->pos);
|
|
|
|
+ }
|
|
|
|
+ goto next;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_EXSTOP:
|
|
|
|
+ decoder->state.type = INTEL_PT_EX_STOP;
|
|
|
|
+ decoder->state.from_ip = decoder->ip;
|
|
|
|
+ decoder->state.to_ip = 0;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_PWRX:
|
|
|
|
+ decoder->state.type = INTEL_PT_PWR_EXIT;
|
|
|
|
+ decoder->state.from_ip = decoder->ip;
|
|
|
|
+ decoder->state.to_ip = 0;
|
|
|
|
+ decoder->state.pwrx_payload = decoder->packet.payload;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
default:
|
|
default:
|
|
return intel_pt_bug(decoder);
|
|
return intel_pt_bug(decoder);
|
|
}
|
|
}
|
|
@@ -1730,8 +1919,9 @@ next:
|
|
|
|
|
|
static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
|
|
static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
- return decoder->last_ip || decoder->packet.count == 0 ||
|
|
|
|
- decoder->packet.count == 3 || decoder->packet.count == 6;
|
|
|
|
|
|
+ return decoder->packet.count &&
|
|
|
|
+ (decoder->have_last_ip || decoder->packet.count == 3 ||
|
|
|
|
+ decoder->packet.count == 6);
|
|
}
|
|
}
|
|
|
|
|
|
/* Walk PSB+ packets to get in sync. */
|
|
/* Walk PSB+ packets to get in sync. */
|
|
@@ -1750,6 +1940,13 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
|
|
__fallthrough;
|
|
__fallthrough;
|
|
case INTEL_PT_TIP_PGE:
|
|
case INTEL_PT_TIP_PGE:
|
|
case INTEL_PT_TIP:
|
|
case INTEL_PT_TIP:
|
|
|
|
+ case INTEL_PT_PTWRITE:
|
|
|
|
+ case INTEL_PT_PTWRITE_IP:
|
|
|
|
+ case INTEL_PT_EXSTOP:
|
|
|
|
+ case INTEL_PT_EXSTOP_IP:
|
|
|
|
+ case INTEL_PT_MWAIT:
|
|
|
|
+ case INTEL_PT_PWRE:
|
|
|
|
+ case INTEL_PT_PWRX:
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
return -ENOENT;
|
|
return -ENOENT;
|
|
|
|
|
|
@@ -1854,14 +2051,10 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_FUP:
|
|
case INTEL_PT_FUP:
|
|
- if (decoder->overflow) {
|
|
|
|
- if (intel_pt_have_ip(decoder))
|
|
|
|
- intel_pt_set_ip(decoder);
|
|
|
|
- if (decoder->ip)
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
- if (decoder->packet.count)
|
|
|
|
- intel_pt_set_last_ip(decoder);
|
|
|
|
|
|
+ if (intel_pt_have_ip(decoder))
|
|
|
|
+ intel_pt_set_ip(decoder);
|
|
|
|
+ if (decoder->ip)
|
|
|
|
+ return 0;
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MTC:
|
|
case INTEL_PT_MTC:
|
|
@@ -1910,6 +2103,9 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
|
|
+ decoder->last_ip = 0;
|
|
|
|
+ decoder->have_last_ip = true;
|
|
|
|
+ intel_pt_clear_stack(&decoder->stack);
|
|
err = intel_pt_walk_psb(decoder);
|
|
err = intel_pt_walk_psb(decoder);
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
@@ -1925,6 +2121,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
case INTEL_PT_VMCS:
|
|
case INTEL_PT_VMCS:
|
|
case INTEL_PT_MNT:
|
|
case INTEL_PT_MNT:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
|
|
+ case INTEL_PT_PTWRITE:
|
|
|
|
+ case INTEL_PT_PTWRITE_IP:
|
|
|
|
+ case INTEL_PT_EXSTOP:
|
|
|
|
+ case INTEL_PT_EXSTOP_IP:
|
|
|
|
+ case INTEL_PT_MWAIT:
|
|
|
|
+ case INTEL_PT_PWRE:
|
|
|
|
+ case INTEL_PT_PWRX:
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -1935,6 +2138,19 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
|
+ 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;
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
intel_pt_log("Scanning for full IP\n");
|
|
intel_pt_log("Scanning for full IP\n");
|
|
err = intel_pt_walk_to_ip(decoder);
|
|
err = intel_pt_walk_to_ip(decoder);
|
|
if (err)
|
|
if (err)
|
|
@@ -2043,6 +2259,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
decoder->pge = false;
|
|
decoder->pge = false;
|
|
decoder->continuous_period = false;
|
|
decoder->continuous_period = false;
|
|
|
|
+ decoder->have_last_ip = false;
|
|
decoder->last_ip = 0;
|
|
decoder->last_ip = 0;
|
|
decoder->ip = 0;
|
|
decoder->ip = 0;
|
|
intel_pt_clear_stack(&decoder->stack);
|
|
intel_pt_clear_stack(&decoder->stack);
|
|
@@ -2051,6 +2268,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
|
|
if (err)
|
|
if (err)
|
|
return err;
|
|
return err;
|
|
|
|
|
|
|
|
+ decoder->have_last_ip = true;
|
|
decoder->pkt_state = INTEL_PT_STATE_NO_IP;
|
|
decoder->pkt_state = INTEL_PT_STATE_NO_IP;
|
|
|
|
|
|
err = intel_pt_walk_psb(decoder);
|
|
err = intel_pt_walk_psb(decoder);
|
|
@@ -2069,7 +2287,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
|
|
static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
- uint64_t est = decoder->timestamp_insn_cnt << 1;
|
|
|
|
|
|
+ uint64_t est = decoder->sample_insn_cnt << 1;
|
|
|
|
|
|
if (!decoder->cbr || !decoder->max_non_turbo_ratio)
|
|
if (!decoder->cbr || !decoder->max_non_turbo_ratio)
|
|
goto out;
|
|
goto out;
|
|
@@ -2077,7 +2295,7 @@ static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
|
|
est *= decoder->max_non_turbo_ratio;
|
|
est *= decoder->max_non_turbo_ratio;
|
|
est /= decoder->cbr;
|
|
est /= decoder->cbr;
|
|
out:
|
|
out:
|
|
- return decoder->timestamp + est;
|
|
|
|
|
|
+ return decoder->sample_timestamp + est;
|
|
}
|
|
}
|
|
|
|
|
|
const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
|
|
const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
|
|
@@ -2093,8 +2311,10 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
|
|
err = intel_pt_sync(decoder);
|
|
err = intel_pt_sync(decoder);
|
|
break;
|
|
break;
|
|
case INTEL_PT_STATE_NO_IP:
|
|
case INTEL_PT_STATE_NO_IP:
|
|
|
|
+ decoder->have_last_ip = false;
|
|
decoder->last_ip = 0;
|
|
decoder->last_ip = 0;
|
|
- /* Fall through */
|
|
|
|
|
|
+ decoder->ip = 0;
|
|
|
|
+ __fallthrough;
|
|
case INTEL_PT_STATE_ERR_RESYNC:
|
|
case INTEL_PT_STATE_ERR_RESYNC:
|
|
err = intel_pt_sync_ip(decoder);
|
|
err = intel_pt_sync_ip(decoder);
|
|
break;
|
|
break;
|
|
@@ -2130,15 +2350,29 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
|
|
}
|
|
}
|
|
} while (err == -ENOLINK);
|
|
} while (err == -ENOLINK);
|
|
|
|
|
|
- decoder->state.err = err ? intel_pt_ext_err(err) : 0;
|
|
|
|
- decoder->state.timestamp = decoder->timestamp;
|
|
|
|
|
|
+ if (err) {
|
|
|
|
+ decoder->state.err = intel_pt_ext_err(err);
|
|
|
|
+ decoder->state.from_ip = decoder->ip;
|
|
|
|
+ decoder->sample_timestamp = decoder->timestamp;
|
|
|
|
+ decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
|
|
|
|
+ } else {
|
|
|
|
+ decoder->state.err = 0;
|
|
|
|
+ if (decoder->cbr != decoder->cbr_seen && decoder->state.type) {
|
|
|
|
+ decoder->cbr_seen = decoder->cbr;
|
|
|
|
+ decoder->state.type |= INTEL_PT_CBR_CHG;
|
|
|
|
+ decoder->state.cbr_payload = decoder->cbr_payload;
|
|
|
|
+ }
|
|
|
|
+ if (intel_pt_sample_time(decoder->pkt_state)) {
|
|
|
|
+ decoder->sample_timestamp = decoder->timestamp;
|
|
|
|
+ decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ decoder->state.timestamp = decoder->sample_timestamp;
|
|
decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
|
|
decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
|
|
decoder->state.cr3 = decoder->cr3;
|
|
decoder->state.cr3 = decoder->cr3;
|
|
decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
|
|
decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
|
|
|
|
|
|
- if (err)
|
|
|
|
- decoder->state.from_ip = decoder->ip;
|
|
|
|
-
|
|
|
|
return &decoder->state;
|
|
return &decoder->state;
|
|
}
|
|
}
|
|
|
|
|