| From 61b6e08dc8e3ea80b7485c9b3f875ddd45c8466b Mon Sep 17 00:00:00 2001 |
| From: Adrian Hunter <adrian.hunter@intel.com> |
| Date: Fri, 10 May 2019 15:41:42 +0300 |
| Subject: perf intel-pt: Fix improved sample timestamp |
| |
| From: Adrian Hunter <adrian.hunter@intel.com> |
| |
| 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 | 13 ++++++++++--- |
| 1 file changed, 10 insertions(+), 3 deletions(-) |
| |
| --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c |
| +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c |
| @@ -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( |
| 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 inte |
| 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 inte |
| |
| 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_de |
| 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); |