|
@@ -85,7 +85,10 @@ 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 mtc_insn;
|
|
bool pge;
|
|
bool pge;
|
|
|
|
+ bool have_tma;
|
|
|
|
+ bool have_cyc;
|
|
uint64_t pos;
|
|
uint64_t pos;
|
|
uint64_t last_ip;
|
|
uint64_t last_ip;
|
|
uint64_t ip;
|
|
uint64_t ip;
|
|
@@ -94,20 +97,37 @@ struct intel_pt_decoder {
|
|
uint64_t tsc_timestamp;
|
|
uint64_t tsc_timestamp;
|
|
uint64_t ref_timestamp;
|
|
uint64_t ref_timestamp;
|
|
uint64_t ret_addr;
|
|
uint64_t ret_addr;
|
|
|
|
+ uint64_t ctc_timestamp;
|
|
|
|
+ uint64_t ctc_delta;
|
|
|
|
+ uint64_t cycle_cnt;
|
|
|
|
+ uint64_t cyc_ref_timestamp;
|
|
|
|
+ uint32_t last_mtc;
|
|
|
|
+ uint32_t tsc_ctc_ratio_n;
|
|
|
|
+ uint32_t tsc_ctc_ratio_d;
|
|
|
|
+ uint32_t tsc_ctc_mult;
|
|
|
|
+ uint32_t tsc_slip;
|
|
|
|
+ uint32_t ctc_rem_mask;
|
|
|
|
+ int mtc_shift;
|
|
struct intel_pt_stack stack;
|
|
struct intel_pt_stack stack;
|
|
enum intel_pt_pkt_state pkt_state;
|
|
enum intel_pt_pkt_state pkt_state;
|
|
struct intel_pt_pkt packet;
|
|
struct intel_pt_pkt packet;
|
|
struct intel_pt_pkt tnt;
|
|
struct intel_pt_pkt tnt;
|
|
int pkt_step;
|
|
int pkt_step;
|
|
int pkt_len;
|
|
int pkt_len;
|
|
|
|
+ int last_packet_type;
|
|
unsigned int cbr;
|
|
unsigned int cbr;
|
|
unsigned int max_non_turbo_ratio;
|
|
unsigned int max_non_turbo_ratio;
|
|
|
|
+ double max_non_turbo_ratio_fp;
|
|
|
|
+ double cbr_cyc_to_tsc;
|
|
|
|
+ double calc_cyc_to_tsc;
|
|
|
|
+ bool have_calc_cyc_to_tsc;
|
|
int exec_mode;
|
|
int exec_mode;
|
|
unsigned int insn_bytes;
|
|
unsigned int insn_bytes;
|
|
uint64_t sign_bit;
|
|
uint64_t sign_bit;
|
|
uint64_t sign_bits;
|
|
uint64_t sign_bits;
|
|
uint64_t period;
|
|
uint64_t period;
|
|
enum intel_pt_period_type period_type;
|
|
enum intel_pt_period_type period_type;
|
|
|
|
+ uint64_t tot_insn_cnt;
|
|
uint64_t period_insn_cnt;
|
|
uint64_t period_insn_cnt;
|
|
uint64_t period_mask;
|
|
uint64_t period_mask;
|
|
uint64_t period_ticks;
|
|
uint64_t period_ticks;
|
|
@@ -148,6 +168,13 @@ static void intel_pt_setup_period(struct intel_pt_decoder *decoder)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static uint64_t multdiv(uint64_t t, uint32_t n, uint32_t d)
|
|
|
|
+{
|
|
|
|
+ if (!d)
|
|
|
|
+ return 0;
|
|
|
|
+ return (t / d) * n + ((t % d) * n) / d;
|
|
|
|
+}
|
|
|
|
+
|
|
struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
|
|
struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
|
|
{
|
|
{
|
|
struct intel_pt_decoder *decoder;
|
|
struct intel_pt_decoder *decoder;
|
|
@@ -170,10 +197,44 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
|
|
decoder->period = params->period;
|
|
decoder->period = params->period;
|
|
decoder->period_type = params->period_type;
|
|
decoder->period_type = params->period_type;
|
|
|
|
|
|
- decoder->max_non_turbo_ratio = params->max_non_turbo_ratio;
|
|
|
|
|
|
+ decoder->max_non_turbo_ratio = params->max_non_turbo_ratio;
|
|
|
|
+ decoder->max_non_turbo_ratio_fp = params->max_non_turbo_ratio;
|
|
|
|
|
|
intel_pt_setup_period(decoder);
|
|
intel_pt_setup_period(decoder);
|
|
|
|
|
|
|
|
+ decoder->mtc_shift = params->mtc_period;
|
|
|
|
+ decoder->ctc_rem_mask = (1 << decoder->mtc_shift) - 1;
|
|
|
|
+
|
|
|
|
+ decoder->tsc_ctc_ratio_n = params->tsc_ctc_ratio_n;
|
|
|
|
+ decoder->tsc_ctc_ratio_d = params->tsc_ctc_ratio_d;
|
|
|
|
+
|
|
|
|
+ if (!decoder->tsc_ctc_ratio_n)
|
|
|
|
+ decoder->tsc_ctc_ratio_d = 0;
|
|
|
|
+
|
|
|
|
+ if (decoder->tsc_ctc_ratio_d) {
|
|
|
|
+ if (!(decoder->tsc_ctc_ratio_n % decoder->tsc_ctc_ratio_d))
|
|
|
|
+ decoder->tsc_ctc_mult = decoder->tsc_ctc_ratio_n /
|
|
|
|
+ decoder->tsc_ctc_ratio_d;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * Allow for timestamps appearing to backwards because a TSC
|
|
|
|
+ * packet has slipped past a MTC packet, so allow 2 MTC ticks
|
|
|
|
+ * or ...
|
|
|
|
+ */
|
|
|
|
+ decoder->tsc_slip = multdiv(2 << decoder->mtc_shift,
|
|
|
|
+ decoder->tsc_ctc_ratio_n,
|
|
|
|
+ decoder->tsc_ctc_ratio_d);
|
|
|
|
+ }
|
|
|
|
+ /* ... or 0x100 paranoia */
|
|
|
|
+ if (decoder->tsc_slip < 0x100)
|
|
|
|
+ decoder->tsc_slip = 0x100;
|
|
|
|
+
|
|
|
|
+ intel_pt_log("timestamp: mtc_shift %u\n", decoder->mtc_shift);
|
|
|
|
+ intel_pt_log("timestamp: tsc_ctc_ratio_n %u\n", decoder->tsc_ctc_ratio_n);
|
|
|
|
+ intel_pt_log("timestamp: tsc_ctc_ratio_d %u\n", decoder->tsc_ctc_ratio_d);
|
|
|
|
+ intel_pt_log("timestamp: tsc_ctc_mult %u\n", decoder->tsc_ctc_mult);
|
|
|
|
+ intel_pt_log("timestamp: tsc_slip %#x\n", decoder->tsc_slip);
|
|
|
|
+
|
|
return decoder;
|
|
return decoder;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -367,6 +428,7 @@ static inline void intel_pt_update_in_tx(struct intel_pt_decoder *decoder)
|
|
static int intel_pt_bad_packet(struct intel_pt_decoder *decoder)
|
|
static int intel_pt_bad_packet(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
intel_pt_clear_tx_flags(decoder);
|
|
intel_pt_clear_tx_flags(decoder);
|
|
|
|
+ decoder->have_tma = false;
|
|
decoder->pkt_len = 1;
|
|
decoder->pkt_len = 1;
|
|
decoder->pkt_step = 1;
|
|
decoder->pkt_step = 1;
|
|
intel_pt_decoder_log_packet(decoder);
|
|
intel_pt_decoder_log_packet(decoder);
|
|
@@ -399,6 +461,7 @@ static int intel_pt_get_data(struct intel_pt_decoder *decoder)
|
|
decoder->pkt_state = INTEL_PT_STATE_NO_PSB;
|
|
decoder->pkt_state = INTEL_PT_STATE_NO_PSB;
|
|
decoder->ref_timestamp = buffer.ref_timestamp;
|
|
decoder->ref_timestamp = buffer.ref_timestamp;
|
|
decoder->timestamp = 0;
|
|
decoder->timestamp = 0;
|
|
|
|
+ decoder->have_tma = false;
|
|
decoder->state.trace_nr = buffer.trace_nr;
|
|
decoder->state.trace_nr = buffer.trace_nr;
|
|
intel_pt_log("Reference timestamp 0x%" PRIx64 "\n",
|
|
intel_pt_log("Reference timestamp 0x%" PRIx64 "\n",
|
|
decoder->ref_timestamp);
|
|
decoder->ref_timestamp);
|
|
@@ -460,10 +523,247 @@ static int intel_pt_get_split_packet(struct intel_pt_decoder *decoder)
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct intel_pt_pkt_info {
|
|
|
|
+ struct intel_pt_decoder *decoder;
|
|
|
|
+ struct intel_pt_pkt packet;
|
|
|
|
+ uint64_t pos;
|
|
|
|
+ int pkt_len;
|
|
|
|
+ int last_packet_type;
|
|
|
|
+ void *data;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+typedef int (*intel_pt_pkt_cb_t)(struct intel_pt_pkt_info *pkt_info);
|
|
|
|
+
|
|
|
|
+/* Lookahead packets in current buffer */
|
|
|
|
+static int intel_pt_pkt_lookahead(struct intel_pt_decoder *decoder,
|
|
|
|
+ intel_pt_pkt_cb_t cb, void *data)
|
|
|
|
+{
|
|
|
|
+ struct intel_pt_pkt_info pkt_info;
|
|
|
|
+ const unsigned char *buf = decoder->buf;
|
|
|
|
+ size_t len = decoder->len;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ pkt_info.decoder = decoder;
|
|
|
|
+ pkt_info.pos = decoder->pos;
|
|
|
|
+ pkt_info.pkt_len = decoder->pkt_step;
|
|
|
|
+ pkt_info.last_packet_type = decoder->last_packet_type;
|
|
|
|
+ pkt_info.data = data;
|
|
|
|
+
|
|
|
|
+ while (1) {
|
|
|
|
+ do {
|
|
|
|
+ pkt_info.pos += pkt_info.pkt_len;
|
|
|
|
+ buf += pkt_info.pkt_len;
|
|
|
|
+ len -= pkt_info.pkt_len;
|
|
|
|
+
|
|
|
|
+ if (!len)
|
|
|
|
+ return INTEL_PT_NEED_MORE_BYTES;
|
|
|
|
+
|
|
|
|
+ ret = intel_pt_get_packet(buf, len, &pkt_info.packet);
|
|
|
|
+ if (!ret)
|
|
|
|
+ return INTEL_PT_NEED_MORE_BYTES;
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+ pkt_info.pkt_len = ret;
|
|
|
|
+ } while (pkt_info.packet.type == INTEL_PT_PAD);
|
|
|
|
+
|
|
|
|
+ ret = cb(&pkt_info);
|
|
|
|
+ if (ret)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ pkt_info.last_packet_type = pkt_info.packet.type;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+struct intel_pt_calc_cyc_to_tsc_info {
|
|
|
|
+ uint64_t cycle_cnt;
|
|
|
|
+ unsigned int cbr;
|
|
|
|
+ uint32_t last_mtc;
|
|
|
|
+ uint64_t ctc_timestamp;
|
|
|
|
+ uint64_t ctc_delta;
|
|
|
|
+ uint64_t tsc_timestamp;
|
|
|
|
+ uint64_t timestamp;
|
|
|
|
+ bool have_tma;
|
|
|
|
+ bool from_mtc;
|
|
|
|
+ double cbr_cyc_to_tsc;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
|
|
|
|
+{
|
|
|
|
+ struct intel_pt_decoder *decoder = pkt_info->decoder;
|
|
|
|
+ struct intel_pt_calc_cyc_to_tsc_info *data = pkt_info->data;
|
|
|
|
+ uint64_t timestamp;
|
|
|
|
+ double cyc_to_tsc;
|
|
|
|
+ unsigned int cbr;
|
|
|
|
+ uint32_t mtc, mtc_delta, ctc, fc, ctc_rem;
|
|
|
|
+
|
|
|
|
+ switch (pkt_info->packet.type) {
|
|
|
|
+ case INTEL_PT_TNT:
|
|
|
|
+ case INTEL_PT_TIP_PGE:
|
|
|
|
+ case INTEL_PT_TIP:
|
|
|
|
+ case INTEL_PT_FUP:
|
|
|
|
+ case INTEL_PT_PSB:
|
|
|
|
+ case INTEL_PT_PIP:
|
|
|
|
+ case INTEL_PT_MODE_EXEC:
|
|
|
|
+ case INTEL_PT_MODE_TSX:
|
|
|
|
+ case INTEL_PT_PSBEND:
|
|
|
|
+ case INTEL_PT_PAD:
|
|
|
|
+ case INTEL_PT_VMCS:
|
|
|
|
+ case INTEL_PT_MNT:
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_MTC:
|
|
|
|
+ if (!data->have_tma)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ mtc = pkt_info->packet.payload;
|
|
|
|
+ if (mtc > data->last_mtc)
|
|
|
|
+ mtc_delta = mtc - data->last_mtc;
|
|
|
|
+ else
|
|
|
|
+ mtc_delta = mtc + 256 - data->last_mtc;
|
|
|
|
+ data->ctc_delta += mtc_delta << decoder->mtc_shift;
|
|
|
|
+ data->last_mtc = mtc;
|
|
|
|
+
|
|
|
|
+ if (decoder->tsc_ctc_mult) {
|
|
|
|
+ timestamp = data->ctc_timestamp +
|
|
|
|
+ data->ctc_delta * decoder->tsc_ctc_mult;
|
|
|
|
+ } else {
|
|
|
|
+ timestamp = data->ctc_timestamp +
|
|
|
|
+ multdiv(data->ctc_delta,
|
|
|
|
+ decoder->tsc_ctc_ratio_n,
|
|
|
|
+ decoder->tsc_ctc_ratio_d);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (timestamp < data->timestamp)
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ if (pkt_info->last_packet_type != INTEL_PT_CYC) {
|
|
|
|
+ data->timestamp = timestamp;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_TSC:
|
|
|
|
+ timestamp = pkt_info->packet.payload |
|
|
|
|
+ (data->timestamp & (0xffULL << 56));
|
|
|
|
+ if (data->from_mtc && timestamp < data->timestamp &&
|
|
|
|
+ data->timestamp - timestamp < decoder->tsc_slip)
|
|
|
|
+ return 1;
|
|
|
|
+ while (timestamp < data->timestamp)
|
|
|
|
+ timestamp += (1ULL << 56);
|
|
|
|
+ if (pkt_info->last_packet_type != INTEL_PT_CYC) {
|
|
|
|
+ if (data->from_mtc)
|
|
|
|
+ return 1;
|
|
|
|
+ data->tsc_timestamp = timestamp;
|
|
|
|
+ data->timestamp = timestamp;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_TMA:
|
|
|
|
+ if (data->from_mtc)
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ if (!decoder->tsc_ctc_ratio_d)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ ctc = pkt_info->packet.payload;
|
|
|
|
+ fc = pkt_info->packet.count;
|
|
|
|
+ ctc_rem = ctc & decoder->ctc_rem_mask;
|
|
|
|
+
|
|
|
|
+ data->last_mtc = (ctc >> decoder->mtc_shift) & 0xff;
|
|
|
|
+
|
|
|
|
+ data->ctc_timestamp = data->tsc_timestamp - fc;
|
|
|
|
+ if (decoder->tsc_ctc_mult) {
|
|
|
|
+ data->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult;
|
|
|
|
+ } else {
|
|
|
|
+ data->ctc_timestamp -=
|
|
|
|
+ multdiv(ctc_rem, decoder->tsc_ctc_ratio_n,
|
|
|
|
+ decoder->tsc_ctc_ratio_d);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ data->ctc_delta = 0;
|
|
|
|
+ data->have_tma = true;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_CYC:
|
|
|
|
+ data->cycle_cnt += pkt_info->packet.payload;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_CBR:
|
|
|
|
+ cbr = pkt_info->packet.payload;
|
|
|
|
+ if (data->cbr && data->cbr != cbr)
|
|
|
|
+ return 1;
|
|
|
|
+ data->cbr = cbr;
|
|
|
|
+ data->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_TIP_PGD:
|
|
|
|
+ case INTEL_PT_TRACESTOP:
|
|
|
|
+ case INTEL_PT_OVF:
|
|
|
|
+ case INTEL_PT_BAD: /* Does not happen */
|
|
|
|
+ default:
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!data->cbr && decoder->cbr) {
|
|
|
|
+ data->cbr = decoder->cbr;
|
|
|
|
+ data->cbr_cyc_to_tsc = decoder->cbr_cyc_to_tsc;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!data->cycle_cnt)
|
|
|
|
+ return 1;
|
|
|
|
+
|
|
|
|
+ cyc_to_tsc = (double)(timestamp - decoder->timestamp) / data->cycle_cnt;
|
|
|
|
+
|
|
|
|
+ if (data->cbr && cyc_to_tsc > data->cbr_cyc_to_tsc &&
|
|
|
|
+ cyc_to_tsc / data->cbr_cyc_to_tsc > 1.25) {
|
|
|
|
+ intel_pt_log("Timestamp: calculated %g TSC ticks per cycle too big (c.f. CBR-based value %g), pos " x64_fmt "\n",
|
|
|
|
+ cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos);
|
|
|
|
+ return 1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ decoder->calc_cyc_to_tsc = cyc_to_tsc;
|
|
|
|
+ decoder->have_calc_cyc_to_tsc = true;
|
|
|
|
+
|
|
|
|
+ if (data->cbr) {
|
|
|
|
+ intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. CBR-based value %g, pos " x64_fmt "\n",
|
|
|
|
+ cyc_to_tsc, data->cbr_cyc_to_tsc, pkt_info->pos);
|
|
|
|
+ } else {
|
|
|
|
+ intel_pt_log("Timestamp: calculated %g TSC ticks per cycle c.f. unknown CBR-based value, pos " x64_fmt "\n",
|
|
|
|
+ cyc_to_tsc, pkt_info->pos);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder *decoder,
|
|
|
|
+ bool from_mtc)
|
|
|
|
+{
|
|
|
|
+ struct intel_pt_calc_cyc_to_tsc_info data = {
|
|
|
|
+ .cycle_cnt = 0,
|
|
|
|
+ .cbr = 0,
|
|
|
|
+ .last_mtc = decoder->last_mtc,
|
|
|
|
+ .ctc_timestamp = decoder->ctc_timestamp,
|
|
|
|
+ .ctc_delta = decoder->ctc_delta,
|
|
|
|
+ .tsc_timestamp = decoder->tsc_timestamp,
|
|
|
|
+ .timestamp = decoder->timestamp,
|
|
|
|
+ .have_tma = decoder->have_tma,
|
|
|
|
+ .from_mtc = from_mtc,
|
|
|
|
+ .cbr_cyc_to_tsc = 0,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ intel_pt_pkt_lookahead(decoder, intel_pt_calc_cyc_cb, &data);
|
|
|
|
+}
|
|
|
|
+
|
|
static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
|
|
static int intel_pt_get_next_packet(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
|
|
+ decoder->last_packet_type = decoder->packet.type;
|
|
|
|
+
|
|
do {
|
|
do {
|
|
decoder->pos += decoder->pkt_step;
|
|
decoder->pos += decoder->pkt_step;
|
|
decoder->buf += decoder->pkt_step;
|
|
decoder->buf += decoder->pkt_step;
|
|
@@ -522,6 +822,7 @@ static uint64_t intel_pt_next_sample(struct intel_pt_decoder *decoder)
|
|
case INTEL_PT_PERIOD_TICKS:
|
|
case INTEL_PT_PERIOD_TICKS:
|
|
return intel_pt_next_period(decoder);
|
|
return intel_pt_next_period(decoder);
|
|
case INTEL_PT_PERIOD_NONE:
|
|
case INTEL_PT_PERIOD_NONE:
|
|
|
|
+ case INTEL_PT_PERIOD_MTC:
|
|
default:
|
|
default:
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -541,6 +842,7 @@ static void intel_pt_sample_insn(struct intel_pt_decoder *decoder)
|
|
decoder->last_masked_timestamp = masked_timestamp;
|
|
decoder->last_masked_timestamp = masked_timestamp;
|
|
break;
|
|
break;
|
|
case INTEL_PT_PERIOD_NONE:
|
|
case INTEL_PT_PERIOD_NONE:
|
|
|
|
+ case INTEL_PT_PERIOD_MTC:
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -554,11 +856,15 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
|
|
uint64_t max_insn_cnt, insn_cnt = 0;
|
|
uint64_t max_insn_cnt, insn_cnt = 0;
|
|
int err;
|
|
int err;
|
|
|
|
|
|
|
|
+ if (!decoder->mtc_insn)
|
|
|
|
+ decoder->mtc_insn = true;
|
|
|
|
+
|
|
max_insn_cnt = intel_pt_next_sample(decoder);
|
|
max_insn_cnt = intel_pt_next_sample(decoder);
|
|
|
|
|
|
err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip,
|
|
err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip,
|
|
max_insn_cnt, decoder->data);
|
|
max_insn_cnt, decoder->data);
|
|
|
|
|
|
|
|
+ decoder->tot_insn_cnt += insn_cnt;
|
|
decoder->timestamp_insn_cnt += insn_cnt;
|
|
decoder->timestamp_insn_cnt += insn_cnt;
|
|
decoder->period_insn_cnt += insn_cnt;
|
|
decoder->period_insn_cnt += insn_cnt;
|
|
|
|
|
|
@@ -859,6 +1165,8 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
uint64_t timestamp;
|
|
uint64_t timestamp;
|
|
|
|
|
|
|
|
+ decoder->have_tma = false;
|
|
|
|
+
|
|
if (decoder->ref_timestamp) {
|
|
if (decoder->ref_timestamp) {
|
|
timestamp = decoder->packet.payload |
|
|
timestamp = decoder->packet.payload |
|
|
(decoder->ref_timestamp & (0xffULL << 56));
|
|
(decoder->ref_timestamp & (0xffULL << 56));
|
|
@@ -876,21 +1184,29 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
|
|
} else if (decoder->timestamp) {
|
|
} else if (decoder->timestamp) {
|
|
timestamp = decoder->packet.payload |
|
|
timestamp = decoder->packet.payload |
|
|
(decoder->timestamp & (0xffULL << 56));
|
|
(decoder->timestamp & (0xffULL << 56));
|
|
|
|
+ decoder->tsc_timestamp = timestamp;
|
|
if (timestamp < decoder->timestamp &&
|
|
if (timestamp < decoder->timestamp &&
|
|
- decoder->timestamp - timestamp < 0x100) {
|
|
|
|
- intel_pt_log_to("ERROR: Suppressing backwards timestamp",
|
|
|
|
|
|
+ decoder->timestamp - timestamp < decoder->tsc_slip) {
|
|
|
|
+ intel_pt_log_to("Suppressing backwards timestamp",
|
|
timestamp);
|
|
timestamp);
|
|
timestamp = decoder->timestamp;
|
|
timestamp = decoder->timestamp;
|
|
}
|
|
}
|
|
while (timestamp < decoder->timestamp) {
|
|
while (timestamp < decoder->timestamp) {
|
|
intel_pt_log_to("Wraparound timestamp", timestamp);
|
|
intel_pt_log_to("Wraparound timestamp", timestamp);
|
|
timestamp += (1ULL << 56);
|
|
timestamp += (1ULL << 56);
|
|
|
|
+ decoder->tsc_timestamp = timestamp;
|
|
}
|
|
}
|
|
- decoder->tsc_timestamp = timestamp;
|
|
|
|
decoder->timestamp = timestamp;
|
|
decoder->timestamp = timestamp;
|
|
decoder->timestamp_insn_cnt = 0;
|
|
decoder->timestamp_insn_cnt = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (decoder->last_packet_type == INTEL_PT_CYC) {
|
|
|
|
+ decoder->cyc_ref_timestamp = decoder->timestamp;
|
|
|
|
+ decoder->cycle_cnt = 0;
|
|
|
|
+ decoder->have_calc_cyc_to_tsc = false;
|
|
|
|
+ intel_pt_calc_cyc_to_tsc(decoder, false);
|
|
|
|
+ }
|
|
|
|
+
|
|
intel_pt_log_to("Setting timestamp", decoder->timestamp);
|
|
intel_pt_log_to("Setting timestamp", decoder->timestamp);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -898,11 +1214,117 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
intel_pt_log("ERROR: Buffer overflow\n");
|
|
intel_pt_log("ERROR: Buffer overflow\n");
|
|
intel_pt_clear_tx_flags(decoder);
|
|
intel_pt_clear_tx_flags(decoder);
|
|
|
|
+ decoder->have_tma = false;
|
|
|
|
+ decoder->cbr = 0;
|
|
decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
|
|
decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
|
|
decoder->overflow = true;
|
|
decoder->overflow = true;
|
|
return -EOVERFLOW;
|
|
return -EOVERFLOW;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void intel_pt_calc_tma(struct intel_pt_decoder *decoder)
|
|
|
|
+{
|
|
|
|
+ uint32_t ctc = decoder->packet.payload;
|
|
|
|
+ uint32_t fc = decoder->packet.count;
|
|
|
|
+ uint32_t ctc_rem = ctc & decoder->ctc_rem_mask;
|
|
|
|
+
|
|
|
|
+ if (!decoder->tsc_ctc_ratio_d)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ decoder->last_mtc = (ctc >> decoder->mtc_shift) & 0xff;
|
|
|
|
+ decoder->ctc_timestamp = decoder->tsc_timestamp - fc;
|
|
|
|
+ if (decoder->tsc_ctc_mult) {
|
|
|
|
+ decoder->ctc_timestamp -= ctc_rem * decoder->tsc_ctc_mult;
|
|
|
|
+ } else {
|
|
|
|
+ decoder->ctc_timestamp -= multdiv(ctc_rem,
|
|
|
|
+ decoder->tsc_ctc_ratio_n,
|
|
|
|
+ decoder->tsc_ctc_ratio_d);
|
|
|
|
+ }
|
|
|
|
+ decoder->ctc_delta = 0;
|
|
|
|
+ decoder->have_tma = true;
|
|
|
|
+ intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x CTC rem %#x\n",
|
|
|
|
+ decoder->ctc_timestamp, decoder->last_mtc, ctc_rem);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder)
|
|
|
|
+{
|
|
|
|
+ uint64_t timestamp;
|
|
|
|
+ uint32_t mtc, mtc_delta;
|
|
|
|
+
|
|
|
|
+ if (!decoder->have_tma)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ mtc = decoder->packet.payload;
|
|
|
|
+
|
|
|
|
+ if (mtc > decoder->last_mtc)
|
|
|
|
+ mtc_delta = mtc - decoder->last_mtc;
|
|
|
|
+ else
|
|
|
|
+ mtc_delta = mtc + 256 - decoder->last_mtc;
|
|
|
|
+
|
|
|
|
+ decoder->ctc_delta += mtc_delta << decoder->mtc_shift;
|
|
|
|
+
|
|
|
|
+ if (decoder->tsc_ctc_mult) {
|
|
|
|
+ timestamp = decoder->ctc_timestamp +
|
|
|
|
+ decoder->ctc_delta * decoder->tsc_ctc_mult;
|
|
|
|
+ } else {
|
|
|
|
+ timestamp = decoder->ctc_timestamp +
|
|
|
|
+ multdiv(decoder->ctc_delta,
|
|
|
|
+ decoder->tsc_ctc_ratio_n,
|
|
|
|
+ decoder->tsc_ctc_ratio_d);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (timestamp < decoder->timestamp)
|
|
|
|
+ intel_pt_log("Suppressing MTC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n",
|
|
|
|
+ timestamp, decoder->timestamp);
|
|
|
|
+ else
|
|
|
|
+ decoder->timestamp = timestamp;
|
|
|
|
+
|
|
|
|
+ decoder->timestamp_insn_cnt = 0;
|
|
|
|
+ decoder->last_mtc = mtc;
|
|
|
|
+
|
|
|
|
+ if (decoder->last_packet_type == INTEL_PT_CYC) {
|
|
|
|
+ decoder->cyc_ref_timestamp = decoder->timestamp;
|
|
|
|
+ decoder->cycle_cnt = 0;
|
|
|
|
+ decoder->have_calc_cyc_to_tsc = false;
|
|
|
|
+ intel_pt_calc_cyc_to_tsc(decoder, true);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void intel_pt_calc_cbr(struct intel_pt_decoder *decoder)
|
|
|
|
+{
|
|
|
|
+ unsigned int cbr = decoder->packet.payload;
|
|
|
|
+
|
|
|
|
+ if (decoder->cbr == cbr)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ decoder->cbr = cbr;
|
|
|
|
+ decoder->cbr_cyc_to_tsc = decoder->max_non_turbo_ratio_fp / cbr;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder)
|
|
|
|
+{
|
|
|
|
+ uint64_t timestamp = decoder->cyc_ref_timestamp;
|
|
|
|
+
|
|
|
|
+ decoder->have_cyc = true;
|
|
|
|
+
|
|
|
|
+ decoder->cycle_cnt += decoder->packet.payload;
|
|
|
|
+
|
|
|
|
+ if (!decoder->cyc_ref_timestamp)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (decoder->have_calc_cyc_to_tsc)
|
|
|
|
+ timestamp += decoder->cycle_cnt * decoder->calc_cyc_to_tsc;
|
|
|
|
+ else if (decoder->cbr)
|
|
|
|
+ timestamp += decoder->cycle_cnt * decoder->cbr_cyc_to_tsc;
|
|
|
|
+ else
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (timestamp < decoder->timestamp)
|
|
|
|
+ intel_pt_log("Suppressing CYC timestamp " x64_fmt " less than current timestamp " x64_fmt "\n",
|
|
|
|
+ timestamp, decoder->timestamp);
|
|
|
|
+ else
|
|
|
|
+ decoder->timestamp = timestamp;
|
|
|
|
+}
|
|
|
|
+
|
|
/* Walk PSB+ packets when already in sync. */
|
|
/* Walk PSB+ packets when already in sync. */
|
|
static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
{
|
|
{
|
|
@@ -921,8 +1343,10 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
case INTEL_PT_TIP_PGE:
|
|
case INTEL_PT_TIP_PGE:
|
|
case INTEL_PT_TIP:
|
|
case INTEL_PT_TIP:
|
|
case INTEL_PT_TNT:
|
|
case INTEL_PT_TNT:
|
|
|
|
+ case INTEL_PT_TRACESTOP:
|
|
case INTEL_PT_BAD:
|
|
case INTEL_PT_BAD:
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
|
|
+ decoder->have_tma = false;
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
return -EAGAIN;
|
|
return -EAGAIN;
|
|
|
|
|
|
@@ -933,8 +1357,12 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_TMA:
|
|
|
|
+ intel_pt_calc_tma(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_CBR:
|
|
case INTEL_PT_CBR:
|
|
- decoder->cbr = decoder->packet.payload;
|
|
|
|
|
|
+ intel_pt_calc_cbr(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MODE_EXEC:
|
|
case INTEL_PT_MODE_EXEC:
|
|
@@ -942,7 +1370,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_PIP:
|
|
case INTEL_PT_PIP:
|
|
- decoder->cr3 = decoder->packet.payload;
|
|
|
|
|
|
+ decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_FUP:
|
|
case INTEL_PT_FUP:
|
|
@@ -954,6 +1382,15 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
|
|
intel_pt_update_in_tx(decoder);
|
|
intel_pt_update_in_tx(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_MTC:
|
|
|
|
+ intel_pt_calc_mtc_timestamp(decoder);
|
|
|
|
+ if (decoder->period_type == INTEL_PT_PERIOD_MTC)
|
|
|
|
+ decoder->state.type |= INTEL_PT_INSTRUCTION;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_CYC:
|
|
|
|
+ case INTEL_PT_VMCS:
|
|
|
|
+ case INTEL_PT_MNT:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
@@ -981,8 +1418,10 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
|
|
switch (decoder->packet.type) {
|
|
switch (decoder->packet.type) {
|
|
case INTEL_PT_TNT:
|
|
case INTEL_PT_TNT:
|
|
case INTEL_PT_FUP:
|
|
case INTEL_PT_FUP:
|
|
|
|
+ case INTEL_PT_TRACESTOP:
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_TSC:
|
|
case INTEL_PT_TSC:
|
|
|
|
+ case INTEL_PT_TMA:
|
|
case INTEL_PT_CBR:
|
|
case INTEL_PT_CBR:
|
|
case INTEL_PT_MODE_TSX:
|
|
case INTEL_PT_MODE_TSX:
|
|
case INTEL_PT_BAD:
|
|
case INTEL_PT_BAD:
|
|
@@ -1030,13 +1469,25 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
case INTEL_PT_PIP:
|
|
case INTEL_PT_PIP:
|
|
- decoder->cr3 = decoder->packet.payload;
|
|
|
|
|
|
+ decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_MTC:
|
|
|
|
+ intel_pt_calc_mtc_timestamp(decoder);
|
|
|
|
+ if (decoder->period_type == INTEL_PT_PERIOD_MTC)
|
|
|
|
+ decoder->state.type |= INTEL_PT_INSTRUCTION;
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_CYC:
|
|
|
|
+ intel_pt_calc_cyc_timestamp(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MODE_EXEC:
|
|
case INTEL_PT_MODE_EXEC:
|
|
decoder->exec_mode = decoder->packet.payload;
|
|
decoder->exec_mode = decoder->packet.payload;
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_VMCS:
|
|
|
|
+ case INTEL_PT_MNT:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -1120,6 +1571,13 @@ next:
|
|
}
|
|
}
|
|
return intel_pt_walk_fup_tip(decoder);
|
|
return intel_pt_walk_fup_tip(decoder);
|
|
|
|
|
|
|
|
+ case INTEL_PT_TRACESTOP:
|
|
|
|
+ decoder->pge = false;
|
|
|
|
+ decoder->continuous_period = false;
|
|
|
|
+ intel_pt_clear_tx_flags(decoder);
|
|
|
|
+ decoder->have_tma = false;
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
intel_pt_clear_stack(&decoder->stack);
|
|
intel_pt_clear_stack(&decoder->stack);
|
|
err = intel_pt_walk_psbend(decoder);
|
|
err = intel_pt_walk_psbend(decoder);
|
|
@@ -1130,15 +1588,43 @@ next:
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_PIP:
|
|
case INTEL_PT_PIP:
|
|
- decoder->cr3 = decoder->packet.payload;
|
|
|
|
|
|
+ decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_MTC:
|
|
|
|
+ intel_pt_calc_mtc_timestamp(decoder);
|
|
|
|
+ if (decoder->period_type != INTEL_PT_PERIOD_MTC)
|
|
|
|
+ break;
|
|
|
|
+ /*
|
|
|
|
+ * Ensure that there has been an instruction since the
|
|
|
|
+ * last MTC.
|
|
|
|
+ */
|
|
|
|
+ if (!decoder->mtc_insn)
|
|
|
|
+ break;
|
|
|
|
+ decoder->mtc_insn = false;
|
|
|
|
+ /* Ensure that there is a timestamp */
|
|
|
|
+ if (!decoder->timestamp)
|
|
|
|
+ break;
|
|
|
|
+ decoder->state.type = INTEL_PT_INSTRUCTION;
|
|
|
|
+ decoder->state.from_ip = decoder->ip;
|
|
|
|
+ decoder->state.to_ip = 0;
|
|
|
|
+ decoder->mtc_insn = false;
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
case INTEL_PT_TSC:
|
|
case INTEL_PT_TSC:
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_TMA:
|
|
|
|
+ intel_pt_calc_tma(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_CYC:
|
|
|
|
+ intel_pt_calc_cyc_timestamp(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_CBR:
|
|
case INTEL_PT_CBR:
|
|
- decoder->cbr = decoder->packet.payload;
|
|
|
|
|
|
+ intel_pt_calc_cbr(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MODE_EXEC:
|
|
case INTEL_PT_MODE_EXEC:
|
|
@@ -1160,6 +1646,8 @@ next:
|
|
return intel_pt_bug(decoder);
|
|
return intel_pt_bug(decoder);
|
|
|
|
|
|
case INTEL_PT_PSBEND:
|
|
case INTEL_PT_PSBEND:
|
|
|
|
+ case INTEL_PT_VMCS:
|
|
|
|
+ case INTEL_PT_MNT:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
break;
|
|
break;
|
|
|
|
|
|
@@ -1200,16 +1688,28 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_MTC:
|
|
|
|
+ intel_pt_calc_mtc_timestamp(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_TSC:
|
|
case INTEL_PT_TSC:
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_TMA:
|
|
|
|
+ intel_pt_calc_tma(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_CYC:
|
|
|
|
+ intel_pt_calc_cyc_timestamp(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_CBR:
|
|
case INTEL_PT_CBR:
|
|
- decoder->cbr = decoder->packet.payload;
|
|
|
|
|
|
+ intel_pt_calc_cbr(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_PIP:
|
|
case INTEL_PT_PIP:
|
|
- decoder->cr3 = decoder->packet.payload;
|
|
|
|
|
|
+ decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MODE_EXEC:
|
|
case INTEL_PT_MODE_EXEC:
|
|
@@ -1220,7 +1720,12 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
|
|
intel_pt_update_in_tx(decoder);
|
|
intel_pt_update_in_tx(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_TRACESTOP:
|
|
|
|
+ decoder->pge = false;
|
|
|
|
+ decoder->continuous_period = false;
|
|
|
|
+ intel_pt_clear_tx_flags(decoder);
|
|
case INTEL_PT_TNT:
|
|
case INTEL_PT_TNT:
|
|
|
|
+ decoder->have_tma = false;
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
intel_pt_log("ERROR: Unexpected packet\n");
|
|
if (decoder->ip)
|
|
if (decoder->ip)
|
|
decoder->pkt_state = INTEL_PT_STATE_ERR4;
|
|
decoder->pkt_state = INTEL_PT_STATE_ERR4;
|
|
@@ -1238,6 +1743,8 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
|
|
+ case INTEL_PT_VMCS:
|
|
|
|
+ case INTEL_PT_MNT:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
@@ -1280,16 +1787,28 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
intel_pt_set_last_ip(decoder);
|
|
intel_pt_set_last_ip(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_MTC:
|
|
|
|
+ intel_pt_calc_mtc_timestamp(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_TSC:
|
|
case INTEL_PT_TSC:
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
intel_pt_calc_tsc_timestamp(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
|
|
+ case INTEL_PT_TMA:
|
|
|
|
+ intel_pt_calc_tma(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case INTEL_PT_CYC:
|
|
|
|
+ intel_pt_calc_cyc_timestamp(decoder);
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_CBR:
|
|
case INTEL_PT_CBR:
|
|
- decoder->cbr = decoder->packet.payload;
|
|
|
|
|
|
+ intel_pt_calc_cbr(decoder);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_PIP:
|
|
case INTEL_PT_PIP:
|
|
- decoder->cr3 = decoder->packet.payload;
|
|
|
|
|
|
+ decoder->cr3 = decoder->packet.payload & (BIT63 - 1);
|
|
break;
|
|
break;
|
|
|
|
|
|
case INTEL_PT_MODE_EXEC:
|
|
case INTEL_PT_MODE_EXEC:
|
|
@@ -1306,6 +1825,13 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
case INTEL_PT_BAD: /* Does not happen */
|
|
case INTEL_PT_BAD: /* Does not happen */
|
|
return intel_pt_bug(decoder);
|
|
return intel_pt_bug(decoder);
|
|
|
|
|
|
|
|
+ case INTEL_PT_TRACESTOP:
|
|
|
|
+ decoder->pge = false;
|
|
|
|
+ decoder->continuous_period = false;
|
|
|
|
+ intel_pt_clear_tx_flags(decoder);
|
|
|
|
+ decoder->have_tma = false;
|
|
|
|
+ break;
|
|
|
|
+
|
|
case INTEL_PT_PSB:
|
|
case INTEL_PT_PSB:
|
|
err = intel_pt_walk_psb(decoder);
|
|
err = intel_pt_walk_psb(decoder);
|
|
if (err)
|
|
if (err)
|
|
@@ -1319,6 +1845,8 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
|
|
|
|
|
|
case INTEL_PT_TNT:
|
|
case INTEL_PT_TNT:
|
|
case INTEL_PT_PSBEND:
|
|
case INTEL_PT_PSBEND:
|
|
|
|
+ case INTEL_PT_VMCS:
|
|
|
|
+ case INTEL_PT_MNT:
|
|
case INTEL_PT_PAD:
|
|
case INTEL_PT_PAD:
|
|
default:
|
|
default:
|
|
break;
|
|
break;
|
|
@@ -1529,6 +2057,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
|
|
decoder->state.timestamp = decoder->timestamp;
|
|
decoder->state.timestamp = decoder->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;
|
|
|
|
|
|
if (err)
|
|
if (err)
|
|
decoder->state.from_ip = decoder->ip;
|
|
decoder->state.from_ip = decoder->ip;
|