OSDN Git Service

perf intel-pt: Fix state setting when receiving overflow (OVF) packet
authorAdrian Hunter <adrian.hunter@intel.com>
Fri, 10 Dec 2021 16:23:00 +0000 (18:23 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Sat, 11 Dec 2021 11:19:47 +0000 (08:19 -0300)
An overflow (OVF packet) is treated as an error because it represents a
loss of trace data, but there is no loss of synchronization, so the packet
state should be INTEL_PT_STATE_IN_SYNC not INTEL_PT_STATE_ERR_RESYNC.

To support that, some additional variables must be reset, and the FUP
packet that may follow OVF is treated as an FUP event.

Fixes: f4aa081949e7b6 ("perf tools: Add Intel PT decoder")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: stable@vger.kernel.org # v5.15+
Link: https://lore.kernel.org/r/20211210162303.2288710-5-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c

index 16fbbf0..845b0ca 100644 (file)
@@ -1249,6 +1249,20 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
                decoder->state.type |= INTEL_PT_BLK_ITEMS;
                ret = true;
        }
+       if (decoder->overflow) {
+               decoder->overflow = false;
+               if (!ret && !decoder->pge) {
+                       if (decoder->hop) {
+                               decoder->state.type = 0;
+                               decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
+                       }
+                       decoder->pge = true;
+                       decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN;
+                       decoder->state.from_ip = 0;
+                       decoder->state.to_ip = decoder->ip;
+                       return true;
+               }
+       }
        if (ret) {
                decoder->state.from_ip = decoder->ip;
                decoder->state.to_ip = 0;
@@ -1602,7 +1616,16 @@ static int intel_pt_overflow(struct intel_pt_decoder *decoder)
        intel_pt_clear_tx_flags(decoder);
        intel_pt_set_nr(decoder);
        decoder->timestamp_insn_cnt = 0;
-       decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
+       decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
+       decoder->state.from_ip = decoder->ip;
+       decoder->ip = 0;
+       decoder->pge = false;
+       decoder->set_fup_tx_flags = false;
+       decoder->set_fup_ptw = false;
+       decoder->set_fup_mwait = false;
+       decoder->set_fup_pwre = false;
+       decoder->set_fup_exstop = false;
+       decoder->set_fup_bep = false;
        decoder->overflow = true;
        return -EOVERFLOW;
 }
@@ -2957,6 +2980,7 @@ next:
 
                case INTEL_PT_TIP_PGE: {
                        decoder->pge = true;
+                       decoder->overflow = false;
                        intel_pt_mtc_cyc_cnt_pge(decoder);
                        intel_pt_set_nr(decoder);
                        if (decoder->packet.count == 0) {
@@ -3462,10 +3486,10 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
        decoder->set_fup_pwre = false;
        decoder->set_fup_exstop = false;
        decoder->set_fup_bep = false;
+       decoder->overflow = false;
 
        if (!decoder->branch_enable) {
                decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
-               decoder->overflow = false;
                decoder->state.type = 0; /* Do not have a sample */
                return 0;
        }
@@ -3480,7 +3504,6 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
                decoder->pkt_state = INTEL_PT_STATE_RESAMPLE;
        else
                decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
-       decoder->overflow = false;
 
        decoder->state.from_ip = 0;
        decoder->state.to_ip = decoder->ip;
@@ -3699,7 +3722,8 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
 
        if (err) {
                decoder->state.err = intel_pt_ext_err(err);
-               decoder->state.from_ip = decoder->ip;
+               if (err != -EOVERFLOW)
+                       decoder->state.from_ip = decoder->ip;
                intel_pt_update_sample_time(decoder);
                decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt;
                intel_pt_set_nr(decoder);