From: Adrian Hunter <adrian.hunter@intel.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>,
linux-kernel@vger.kernel.org, Jiri Olsa <jolsa@redhat.com>
Subject: [PATCH V8 20/25] perf tools: Add Intel PT support for decoding MTC packets
Date: Fri, 17 Jul 2015 19:33:55 +0300 [thread overview]
Message-ID: <1437150840-31811-21-git-send-email-adrian.hunter@intel.com> (raw)
In-Reply-To: <1437150840-31811-1-git-send-email-adrian.hunter@intel.com>
MTC packets provide finer grain timestamp information
than TSC packets. MTC packets record time using the
hardware crystal clock (CTC) which is related to TSC
packets using a TMA packet.
This patch just adds decoder support.
Support for a default value and validation of values
is provided by a later patch. Also documentation is
updated in a separate patch.
For details refer to the June 2015 or later Intel 64 and
IA-32 Architectures SDM Chapter 36 Intel Processor Trace.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
.../perf/util/intel-pt-decoder/intel-pt-decoder.c | 162 ++++++++++++++++++++-
.../perf/util/intel-pt-decoder/intel-pt-decoder.h | 1 +
2 files changed, 159 insertions(+), 4 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 4a0e9fb1d173..f7119a11a4b6 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -85,7 +85,9 @@ struct intel_pt_decoder {
const unsigned char *buf;
size_t len;
bool return_compression;
+ bool mtc_insn;
bool pge;
+ bool have_tma;
uint64_t pos;
uint64_t last_ip;
uint64_t ip;
@@ -94,6 +96,15 @@ struct intel_pt_decoder {
uint64_t tsc_timestamp;
uint64_t ref_timestamp;
uint64_t ret_addr;
+ uint64_t ctc_timestamp;
+ uint64_t ctc_delta;
+ 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;
enum intel_pt_pkt_state pkt_state;
struct intel_pt_pkt packet;
@@ -149,6 +160,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 *decoder;
@@ -175,6 +193,39 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
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;
}
@@ -368,6 +419,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)
{
intel_pt_clear_tx_flags(decoder);
+ decoder->have_tma = false;
decoder->pkt_len = 1;
decoder->pkt_step = 1;
intel_pt_decoder_log_packet(decoder);
@@ -400,6 +452,7 @@ static int intel_pt_get_data(struct intel_pt_decoder *decoder)
decoder->pkt_state = INTEL_PT_STATE_NO_PSB;
decoder->ref_timestamp = buffer.ref_timestamp;
decoder->timestamp = 0;
+ decoder->have_tma = false;
decoder->state.trace_nr = buffer.trace_nr;
intel_pt_log("Reference timestamp 0x%" PRIx64 "\n",
decoder->ref_timestamp);
@@ -523,6 +576,7 @@ static uint64_t intel_pt_next_sample(struct intel_pt_decoder *decoder)
case INTEL_PT_PERIOD_TICKS:
return intel_pt_next_period(decoder);
case INTEL_PT_PERIOD_NONE:
+ case INTEL_PT_PERIOD_MTC:
default:
return 0;
}
@@ -542,6 +596,7 @@ static void intel_pt_sample_insn(struct intel_pt_decoder *decoder)
decoder->last_masked_timestamp = masked_timestamp;
break;
case INTEL_PT_PERIOD_NONE:
+ case INTEL_PT_PERIOD_MTC:
default:
break;
}
@@ -555,6 +610,9 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
uint64_t max_insn_cnt, insn_cnt = 0;
int err;
+ if (!decoder->mtc_insn)
+ decoder->mtc_insn = true;
+
max_insn_cnt = intel_pt_next_sample(decoder);
err = decoder->walk_insn(intel_pt_insn, &insn_cnt, &decoder->ip, ip,
@@ -861,6 +919,8 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
{
uint64_t timestamp;
+ decoder->have_tma = false;
+
if (decoder->ref_timestamp) {
timestamp = decoder->packet.payload |
(decoder->ref_timestamp & (0xffULL << 56));
@@ -878,17 +938,18 @@ static void intel_pt_calc_tsc_timestamp(struct intel_pt_decoder *decoder)
} else if (decoder->timestamp) {
timestamp = decoder->packet.payload |
(decoder->timestamp & (0xffULL << 56));
+ decoder->tsc_timestamp = 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 = decoder->timestamp;
}
while (timestamp < decoder->timestamp) {
intel_pt_log_to("Wraparound timestamp", timestamp);
timestamp += (1ULL << 56);
+ decoder->tsc_timestamp = timestamp;
}
- decoder->tsc_timestamp = timestamp;
decoder->timestamp = timestamp;
decoder->timestamp_insn_cnt = 0;
}
@@ -900,11 +961,73 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
{
intel_pt_log("ERROR: Buffer overflow\n");
intel_pt_clear_tx_flags(decoder);
+ decoder->have_tma = false;
decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
decoder->overflow = true;
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;
+}
+
/* Walk PSB+ packets when already in sync. */
static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
{
@@ -926,6 +1049,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
case INTEL_PT_TRACESTOP:
case INTEL_PT_BAD:
case INTEL_PT_PSB:
+ decoder->have_tma = false;
intel_pt_log("ERROR: Unexpected packet\n");
return -EAGAIN;
@@ -937,6 +1061,7 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
break;
case INTEL_PT_TMA:
+ intel_pt_calc_tma(decoder);
break;
case INTEL_PT_CBR:
@@ -961,6 +1086,9 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
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:
@@ -1048,6 +1176,9 @@ static int intel_pt_walk_fup_tip(struct intel_pt_decoder *decoder)
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:
@@ -1159,13 +1290,31 @@ next:
break;
case INTEL_PT_MTC:
- break;
+ 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:
intel_pt_calc_tsc_timestamp(decoder);
break;
case INTEL_PT_TMA:
+ intel_pt_calc_tma(decoder);
break;
case INTEL_PT_CYC:
@@ -1237,6 +1386,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
break;
case INTEL_PT_MTC:
+ intel_pt_calc_mtc_timestamp(decoder);
break;
case INTEL_PT_TSC:
@@ -1244,6 +1394,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
break;
case INTEL_PT_TMA:
+ intel_pt_calc_tma(decoder);
break;
case INTEL_PT_CYC:
@@ -1267,6 +1418,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
case INTEL_PT_TRACESTOP:
case INTEL_PT_TNT:
+ decoder->have_tma = false;
intel_pt_log("ERROR: Unexpected packet\n");
if (decoder->ip)
decoder->pkt_state = INTEL_PT_STATE_ERR4;
@@ -1329,6 +1481,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
break;
case INTEL_PT_MTC:
+ intel_pt_calc_mtc_timestamp(decoder);
break;
case INTEL_PT_TSC:
@@ -1336,6 +1489,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
break;
case INTEL_PT_TMA:
+ intel_pt_calc_tma(decoder);
break;
case INTEL_PT_CYC:
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 56cc47baca11..02c38fec1c37 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -36,6 +36,7 @@ enum intel_pt_period_type {
INTEL_PT_PERIOD_NONE,
INTEL_PT_PERIOD_INSTRUCTIONS,
INTEL_PT_PERIOD_TICKS,
+ INTEL_PT_PERIOD_MTC,
};
enum {
--
1.9.1
next prev parent reply other threads:[~2015-07-17 16:41 UTC|newest]
Thread overview: 77+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-17 16:33 [PATCH V8 00/25] perf tools: Introduce an abstraction for AUX Area and Instruction Tracing Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 01/25] perf auxtrace: Add Intel PT as an AUX area tracing type Adrian Hunter
2015-08-20 9:57 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 02/25] perf tools: Add Intel PT packet decoder Adrian Hunter
2015-08-20 9:57 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 03/25] perf tools: Add Intel PT instruction decoder Adrian Hunter
2015-08-12 20:55 ` Arnaldo Carvalho de Melo
2015-08-13 6:48 ` Adrian Hunter
2015-08-13 7:14 ` [PATCH V9 " Adrian Hunter
2015-08-13 12:37 ` Arnaldo Carvalho de Melo
2015-08-20 9:57 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 04/25] perf tools: Add Intel PT log Adrian Hunter
2015-08-20 9:58 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 05/25] perf tools: Add Intel PT decoder Adrian Hunter
2015-08-20 9:58 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 06/25] perf tools: Add Intel PT support Adrian Hunter
2015-08-20 9:59 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 07/25] perf tools: Take Intel PT into use Adrian Hunter
2015-08-20 9:59 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 08/25] perf tools: Add Intel BTS support Adrian Hunter
2015-08-17 15:52 ` Arnaldo Carvalho de Melo
2015-08-17 17:43 ` Adrian Hunter
2015-08-17 17:58 ` Arnaldo Carvalho de Melo
2015-08-17 19:09 ` Adrian Hunter
2015-08-17 19:58 ` Arnaldo Carvalho de Melo
2015-08-18 6:39 ` Adrian Hunter
2015-08-18 9:09 ` Adrian Hunter
2015-08-18 16:10 ` Arnaldo Carvalho de Melo
2015-08-20 8:53 ` Adrian Hunter
2015-08-21 14:18 ` Arnaldo Carvalho de Melo
2015-08-22 6:52 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 09/25] perf tools: Put itrace options into an asciidoc include Adrian Hunter
2015-08-22 6:53 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 10/25] perf tools: Add example call-graph script Adrian Hunter
2015-08-21 15:00 ` Arnaldo Carvalho de Melo
2015-08-21 15:11 ` Arnaldo Carvalho de Melo
2015-08-21 15:21 ` Arnaldo Carvalho de Melo
2015-08-21 15:28 ` Arnaldo Carvalho de Melo
2015-08-21 15:32 ` Arnaldo Carvalho de Melo
2015-08-24 7:00 ` Adrian Hunter
2015-08-24 20:20 ` Arnaldo Carvalho de Melo
2015-08-22 6:53 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 11/25] perf auxtrace: Fix period type 'i' not working Adrian Hunter
2015-08-06 19:50 ` Arnaldo Carvalho de Melo
2015-08-07 7:22 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 12/25] perf tools: Fix perf-with-kcore handling of arguments containing spaces Adrian Hunter
2015-08-06 19:50 ` Arnaldo Carvalho de Melo
2015-08-07 7:22 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 13/25] perf tools: Fix Intel PT 'instructions' sample period Adrian Hunter
2015-08-28 6:37 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 14/25] perf tools: Add perf_pmu__format_bits() Adrian Hunter
2015-08-06 19:50 ` Arnaldo Carvalho de Melo
2015-08-07 7:23 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 15/25] perf tools: Validate config term maximum value Adrian Hunter
2015-08-06 19:50 ` Arnaldo Carvalho de Melo
2015-08-07 7:23 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 16/25] perf tools: Extend the event parser maximum error index Adrian Hunter
2015-08-06 19:50 ` Arnaldo Carvalho de Melo
2015-08-07 7:23 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 17/25] perf tools: Add Intel PT support for PSB periods Adrian Hunter
2015-08-28 6:38 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 18/25] perf tools: Add new Intel PT packet definitions Adrian Hunter
2015-08-28 6:38 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 19/25] perf tools: Pass Intel PT information for decoding MTC and CYC Adrian Hunter
2015-08-28 6:38 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` Adrian Hunter [this message]
2015-08-28 6:39 ` [tip:perf/core] perf tools: Add Intel PT support for decoding MTC packets tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 21/25] perf tools: Add Intel PT support for using " Adrian Hunter
2015-08-28 6:39 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 22/25] perf tools: Add Intel PT support for decoding CYC packets Adrian Hunter
2015-08-28 6:39 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 23/25] perf tools: Add Intel PT support for using " Adrian Hunter
2015-08-28 6:40 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:33 ` [PATCH V8 24/25] perf tools: Add Intel PT support for decoding TRACESTOP packets Adrian Hunter
2015-08-28 6:40 ` [tip:perf/core] " tip-bot for Adrian Hunter
2015-07-17 16:34 ` [PATCH V8 25/25] perf tools: Update Intel PT documentation Adrian Hunter
2015-08-28 6:40 ` [tip:perf/core] " tip-bot for Adrian Hunter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1437150840-31811-21-git-send-email-adrian.hunter@intel.com \
--to=adrian.hunter@intel.com \
--cc=acme@kernel.org \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome