Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf intel-pt: Fix state setting when receiving overflow (OVF) packet

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>

authored by

Adrian Hunter and committed by
Arnaldo Carvalho de Melo
c79ee2b2 4c761d80

+28 -4
+28 -4
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
··· 1249 1249 decoder->state.type |= INTEL_PT_BLK_ITEMS; 1250 1250 ret = true; 1251 1251 } 1252 + if (decoder->overflow) { 1253 + decoder->overflow = false; 1254 + if (!ret && !decoder->pge) { 1255 + if (decoder->hop) { 1256 + decoder->state.type = 0; 1257 + decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; 1258 + } 1259 + decoder->pge = true; 1260 + decoder->state.type |= INTEL_PT_BRANCH | INTEL_PT_TRACE_BEGIN; 1261 + decoder->state.from_ip = 0; 1262 + decoder->state.to_ip = decoder->ip; 1263 + return true; 1264 + } 1265 + } 1252 1266 if (ret) { 1253 1267 decoder->state.from_ip = decoder->ip; 1254 1268 decoder->state.to_ip = 0; ··· 1616 1602 intel_pt_clear_tx_flags(decoder); 1617 1603 intel_pt_set_nr(decoder); 1618 1604 decoder->timestamp_insn_cnt = 0; 1619 - decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1605 + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 1606 + decoder->state.from_ip = decoder->ip; 1607 + decoder->ip = 0; 1608 + decoder->pge = false; 1609 + decoder->set_fup_tx_flags = false; 1610 + decoder->set_fup_ptw = false; 1611 + decoder->set_fup_mwait = false; 1612 + decoder->set_fup_pwre = false; 1613 + decoder->set_fup_exstop = false; 1614 + decoder->set_fup_bep = false; 1620 1615 decoder->overflow = true; 1621 1616 return -EOVERFLOW; 1622 1617 } ··· 2980 2957 2981 2958 case INTEL_PT_TIP_PGE: { 2982 2959 decoder->pge = true; 2960 + decoder->overflow = false; 2983 2961 intel_pt_mtc_cyc_cnt_pge(decoder); 2984 2962 intel_pt_set_nr(decoder); 2985 2963 if (decoder->packet.count == 0) { ··· 3486 3462 decoder->set_fup_pwre = false; 3487 3463 decoder->set_fup_exstop = false; 3488 3464 decoder->set_fup_bep = false; 3465 + decoder->overflow = false; 3489 3466 3490 3467 if (!decoder->branch_enable) { 3491 3468 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 3492 - decoder->overflow = false; 3493 3469 decoder->state.type = 0; /* Do not have a sample */ 3494 3470 return 0; 3495 3471 } ··· 3504 3480 decoder->pkt_state = INTEL_PT_STATE_RESAMPLE; 3505 3481 else 3506 3482 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; 3507 - decoder->overflow = false; 3508 3483 3509 3484 decoder->state.from_ip = 0; 3510 3485 decoder->state.to_ip = decoder->ip; ··· 3722 3699 3723 3700 if (err) { 3724 3701 decoder->state.err = intel_pt_ext_err(err); 3725 - decoder->state.from_ip = decoder->ip; 3702 + if (err != -EOVERFLOW) 3703 + decoder->state.from_ip = decoder->ip; 3726 3704 intel_pt_update_sample_time(decoder); 3727 3705 decoder->sample_tot_cyc_cnt = decoder->tot_cyc_cnt; 3728 3706 intel_pt_set_nr(decoder);