1*f6aab3d8Srobert //===-- TraceIntelPTMultiCpuDecoder.h ---------------------------*- C++ -*-===// 2*f6aab3d8Srobert // 3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information. 5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*f6aab3d8Srobert // 7*f6aab3d8Srobert //===----------------------------------------------------------------------===// 8*f6aab3d8Srobert 9*f6aab3d8Srobert #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H 10*f6aab3d8Srobert #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H 11*f6aab3d8Srobert 12*f6aab3d8Srobert #include "LibiptDecoder.h" 13*f6aab3d8Srobert #include "PerfContextSwitchDecoder.h" 14*f6aab3d8Srobert #include "ThreadDecoder.h" 15*f6aab3d8Srobert #include "forward-declarations.h" 16*f6aab3d8Srobert #include <optional> 17*f6aab3d8Srobert 18*f6aab3d8Srobert namespace lldb_private { 19*f6aab3d8Srobert namespace trace_intel_pt { 20*f6aab3d8Srobert 21*f6aab3d8Srobert /// Class used to decode a multi-cpu Intel PT trace. It assumes that each 22*f6aab3d8Srobert /// thread could have potentially been executed on different cpu cores. It uses 23*f6aab3d8Srobert /// a context switch trace per CPU with timestamps to identify which thread owns 24*f6aab3d8Srobert /// each Intel PT decoded instruction and in which order. It also assumes that 25*f6aab3d8Srobert /// the Intel PT data and context switches might have gaps in their traces due 26*f6aab3d8Srobert /// to contention or race conditions. Finally, it assumes that a tid is not 27*f6aab3d8Srobert /// repeated twice for two different threads because of the shortness of the 28*f6aab3d8Srobert /// intel pt trace. 29*f6aab3d8Srobert /// 30*f6aab3d8Srobert /// This object should be recreated after every stop in the case of live 31*f6aab3d8Srobert /// processes. 32*f6aab3d8Srobert class TraceIntelPTMultiCpuDecoder { 33*f6aab3d8Srobert public: 34*f6aab3d8Srobert /// \param[in] TraceIntelPT 35*f6aab3d8Srobert /// The trace object to be decoded 36*f6aab3d8Srobert TraceIntelPTMultiCpuDecoder(TraceIntelPTSP trace_sp); 37*f6aab3d8Srobert 38*f6aab3d8Srobert /// \return 39*f6aab3d8Srobert /// A \a DecodedThread for the \p thread by decoding its instructions on all 40*f6aab3d8Srobert /// CPUs, sorted by TSCs. An \a llvm::Error is returned if the decoder 41*f6aab3d8Srobert /// couldn't be properly set up. 42*f6aab3d8Srobert llvm::Expected<DecodedThreadSP> Decode(Thread &thread); 43*f6aab3d8Srobert 44*f6aab3d8Srobert /// \return 45*f6aab3d8Srobert /// \b true if the given \p tid is managed by this decoder, regardless of 46*f6aab3d8Srobert /// whether there's tracing data associated to it or not. 47*f6aab3d8Srobert bool TracesThread(lldb::tid_t tid) const; 48*f6aab3d8Srobert 49*f6aab3d8Srobert /// \return 50*f6aab3d8Srobert /// The number of continuous executions found for the given \p tid. 51*f6aab3d8Srobert size_t GetNumContinuousExecutionsForThread(lldb::tid_t tid) const; 52*f6aab3d8Srobert 53*f6aab3d8Srobert /// \return 54*f6aab3d8Srobert /// The number of PSB blocks for a given thread in all cores. 55*f6aab3d8Srobert size_t GePSBBlocksCountForThread(lldb::tid_t tid) const; 56*f6aab3d8Srobert 57*f6aab3d8Srobert /// \return 58*f6aab3d8Srobert /// The total number of continuous executions found across CPUs. 59*f6aab3d8Srobert size_t GetTotalContinuousExecutionsCount() const; 60*f6aab3d8Srobert 61*f6aab3d8Srobert /// \return 62*f6aab3d8Srobert /// The number of psb blocks in all cores that couldn't be matched with a 63*f6aab3d8Srobert /// thread execution coming from context switch traces. 64*f6aab3d8Srobert size_t GetUnattributedPSBBlocksCount() const; 65*f6aab3d8Srobert 66*f6aab3d8Srobert /// \return 67*f6aab3d8Srobert /// The total number of PSB blocks in all cores. 68*f6aab3d8Srobert size_t GetTotalPSBBlocksCount() const; 69*f6aab3d8Srobert 70*f6aab3d8Srobert /// \return 71*f6aab3d8Srobert /// The lowest TSC value in this trace if available, \a std::nullopt if 72*f6aab3d8Srobert /// the trace is empty or the trace contains no timing information, or an 73*f6aab3d8Srobert /// \a llvm::Error if it was not possible to set up the decoder. 74*f6aab3d8Srobert llvm::Expected<std::optional<uint64_t>> FindLowestTSC(); 75*f6aab3d8Srobert 76*f6aab3d8Srobert private: 77*f6aab3d8Srobert /// Traverse the context switch traces and the basic intel pt continuous 78*f6aab3d8Srobert /// subtraces and produce a list of continuous executions for each process and 79*f6aab3d8Srobert /// thread. 80*f6aab3d8Srobert /// 81*f6aab3d8Srobert /// See \a DoCorrelateContextSwitchesAndIntelPtTraces. 82*f6aab3d8Srobert /// 83*f6aab3d8Srobert /// Any errors are stored in \a m_setup_error. 84*f6aab3d8Srobert llvm::Error CorrelateContextSwitchesAndIntelPtTraces(); 85*f6aab3d8Srobert 86*f6aab3d8Srobert /// Produce a mapping from thread ids to the list of continuos executions with 87*f6aab3d8Srobert /// their associated intel pt subtraces. 88*f6aab3d8Srobert llvm::Expected< 89*f6aab3d8Srobert llvm::DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>> 90*f6aab3d8Srobert DoCorrelateContextSwitchesAndIntelPtTraces(); 91*f6aab3d8Srobert 92*f6aab3d8Srobert TraceIntelPTSP GetTrace(); 93*f6aab3d8Srobert 94*f6aab3d8Srobert std::weak_ptr<TraceIntelPT> m_trace_wp; 95*f6aab3d8Srobert std::set<lldb::tid_t> m_tids; 96*f6aab3d8Srobert std::optional< 97*f6aab3d8Srobert llvm::DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>> 98*f6aab3d8Srobert m_continuous_executions_per_thread; 99*f6aab3d8Srobert llvm::DenseMap<lldb::tid_t, DecodedThreadSP> m_decoded_threads; 100*f6aab3d8Srobert /// This variable will not be std::nullopt if a severe error happened during 101*f6aab3d8Srobert /// the setup of the decoder and we don't want decoding to be reattempted. 102*f6aab3d8Srobert std::optional<std::string> m_setup_error; 103*f6aab3d8Srobert uint64_t m_unattributed_psb_blocks = 0; 104*f6aab3d8Srobert uint64_t m_total_psb_blocks = 0; 105*f6aab3d8Srobert }; 106*f6aab3d8Srobert 107*f6aab3d8Srobert } // namespace trace_intel_pt 108*f6aab3d8Srobert } // namespace lldb_private 109*f6aab3d8Srobert 110*f6aab3d8Srobert #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H 111