The decoder uses its current timestamp in samples. Usually that is a
timestamp that has already passed, but in some cases it is a timestamp for
a branch that the decoder is walking towards, and consequently hasn't
reached. Improve that situation by using the pkt_state to determine when
to use the current or previous timestamp.

Signed-off-by: Adrian Hunter <adrian.hun...@intel.com>
---
 .../perf/util/intel-pt-decoder/intel-pt-decoder.c  | 42 ++++++++++++++++++----
 1 file changed, 35 insertions(+), 7 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 a6f41a0e1ae8..aa1593ce551d 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -64,6 +64,25 @@ enum intel_pt_pkt_state {
        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
 #define INTEL_PT_STATE_ERR1    INTEL_PT_STATE_NO_PSB
 #define INTEL_PT_STATE_ERR2    INTEL_PT_STATE_NO_PSB
@@ -101,6 +120,7 @@ struct intel_pt_decoder {
        uint64_t timestamp;
        uint64_t tsc_timestamp;
        uint64_t ref_timestamp;
+       uint64_t sample_timestamp;
        uint64_t ret_addr;
        uint64_t ctc_timestamp;
        uint64_t ctc_delta;
@@ -150,6 +170,7 @@ struct intel_pt_decoder {
        uint64_t fup_pwre_payload;
        uint64_t cbr_payload;
        uint64_t timestamp_insn_cnt;
+       uint64_t sample_insn_cnt;
        uint64_t stuck_ip;
        int no_progress;
        int stuck_ip_prd;
@@ -932,6 +953,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder 
*decoder,
 
        decoder->tot_insn_cnt += insn_cnt;
        decoder->timestamp_insn_cnt += insn_cnt;
+       decoder->sample_insn_cnt += insn_cnt;
        decoder->period_insn_cnt += insn_cnt;
 
        if (err) {
@@ -2279,7 +2301,7 @@ static int intel_pt_sync(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)
                goto out;
@@ -2287,7 +2309,7 @@ static uint64_t intel_pt_est_timestamp(struct 
intel_pt_decoder *decoder)
        est *= decoder->max_non_turbo_ratio;
        est /= decoder->cbr;
 out:
-       return decoder->timestamp + est;
+       return decoder->sample_timestamp + est;
 }
 
 const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
@@ -2342,14 +2364,11 @@ const struct intel_pt_state *intel_pt_decode(struct 
intel_pt_decoder *decoder)
                }
        } while (err == -ENOLINK);
 
-       decoder->state.timestamp = decoder->timestamp;
-       decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
-       decoder->state.cr3 = decoder->cr3;
-       decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
-
        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) {
@@ -2357,8 +2376,17 @@ const struct intel_pt_state *intel_pt_decode(struct 
intel_pt_decoder *decoder)
                        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.cr3 = decoder->cr3;
+       decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
+
        return &decoder->state;
 }
 
-- 
1.9.1

Reply via email to