perf intel-pt: Fix improved sample timestamp
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 10 May 2019 12:41:42 +0000 (15:41 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 May 2019 16:26:50 +0000 (18:26 +0200)
commit 61b6e08dc8e3ea80b7485c9b3f875ddd45c8466b upstream.

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.

The intel_pt_sample_time() function decides which is which, but was not
handling TNT packets exactly correctly.

In the case of TNT, the timestamp applies to the first branch, so the
decoder must first walk to that branch.

That means intel_pt_sample_time() should return true for TNT, and this
patch makes that change. However, if the first branch is a non-taken
branch (i.e. a 'N'), then intel_pt_sample_time() needs to return false
for subsequent taken branches in the same TNT packet.

To handle that, introduce a new state INTEL_PT_STATE_TNT_CONT to
distinguish the cases.

Note that commit 3f04d98e972b5 ("perf intel-pt: Improve sample
timestamp") was also a stable fix and appears, for example, in v4.4
stable tree as commit a4ebb58fd124 ("perf intel-pt: Improve sample
timestamp").

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: stable@vger.kernel.org # v4.4+
Fixes: 3f04d98e972b5 ("perf intel-pt: Improve sample timestamp")
Link: http://lkml.kernel.org/r/20190510124143.27054-3-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c

index 562fc4bf86d42878013d58459e3a6797060ba70c..6e8eb4a397937b9ee63b868008e37499ff06c3f1 100644 (file)
@@ -58,6 +58,7 @@ enum intel_pt_pkt_state {
        INTEL_PT_STATE_NO_IP,
        INTEL_PT_STATE_ERR_RESYNC,
        INTEL_PT_STATE_IN_SYNC,
+       INTEL_PT_STATE_TNT_CONT,
        INTEL_PT_STATE_TNT,
        INTEL_PT_STATE_TIP,
        INTEL_PT_STATE_TIP_PGD,
@@ -72,8 +73,9 @@ static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state)
        case INTEL_PT_STATE_NO_IP:
        case INTEL_PT_STATE_ERR_RESYNC:
        case INTEL_PT_STATE_IN_SYNC:
-       case INTEL_PT_STATE_TNT:
+       case INTEL_PT_STATE_TNT_CONT:
                return true;
+       case INTEL_PT_STATE_TNT:
        case INTEL_PT_STATE_TIP:
        case INTEL_PT_STATE_TIP_PGD:
        case INTEL_PT_STATE_FUP:
@@ -1178,7 +1180,9 @@ static int intel_pt_walk_tnt(struct intel_pt_decoder *decoder)
                                return -ENOENT;
                        }
                        decoder->tnt.count -= 1;
-                       if (!decoder->tnt.count)
+                       if (decoder->tnt.count)
+                               decoder->pkt_state = INTEL_PT_STATE_TNT_CONT;
+                       else
                                decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
                        decoder->tnt.payload <<= 1;
                        decoder->state.from_ip = decoder->ip;
@@ -1209,7 +1213,9 @@ static int intel_pt_walk_tnt(struct intel_pt_decoder *decoder)
 
                if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
                        decoder->tnt.count -= 1;
-                       if (!decoder->tnt.count)
+                       if (decoder->tnt.count)
+                               decoder->pkt_state = INTEL_PT_STATE_TNT_CONT;
+                       else
                                decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
                        if (decoder->tnt.payload & BIT63) {
                                decoder->tnt.payload <<= 1;
@@ -2153,6 +2159,7 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
                        err = intel_pt_walk_trace(decoder);
                        break;
                case INTEL_PT_STATE_TNT:
+               case INTEL_PT_STATE_TNT_CONT:
                        err = intel_pt_walk_tnt(decoder);
                        if (err == -EAGAIN)
                                err = intel_pt_walk_trace(decoder);