diff options
Diffstat (limited to 'simpleperf/ETMDecoder.cpp')
-rw-r--r-- | simpleperf/ETMDecoder.cpp | 128 |
1 files changed, 37 insertions, 91 deletions
diff --git a/simpleperf/ETMDecoder.cpp b/simpleperf/ETMDecoder.cpp index 62fe997c..546f2988 100644 --- a/simpleperf/ETMDecoder.cpp +++ b/simpleperf/ETMDecoder.cpp @@ -24,14 +24,12 @@ #include <llvm/Support/MemoryBuffer.h> #include <opencsd.h> -#include "ETMConstants.h" - namespace simpleperf { namespace { class DecoderLogStr : public ocsdMsgLogStrOutI { public: - void printOutStr(const std::string& out_str) override { LOG(DEBUG) << out_str; } + void printOutStr(const std::string& out_str) override { LOG(INFO) << out_str; } }; class DecodeErrorLogger : public ocsdDefaultErrorLogger { @@ -71,10 +69,10 @@ class ETMV4IDecodeTree { frame_decoder_.getErrLogAttachPt()->attach(&error_logger_); } - bool CreateDecoder(const EtmV4Config* config) { - uint8_t trace_id = config->getTraceID(); + bool CreateDecoder(const EtmV4Config& config) { + uint8_t trace_id = config.getTraceID(); auto packet_decoder = std::make_unique<TrcPktProcEtmV4I>(trace_id); - packet_decoder->setProtocolConfig(config); + packet_decoder->setProtocolConfig(&config); packet_decoder->getErrorLogAttachPt()->replace_first(&error_logger_); frame_decoder_.getIDStreamAttachPt(trace_id)->attach(packet_decoder.get()); auto result = packet_decoders_.emplace(trace_id, packet_decoder.release()); @@ -101,13 +99,7 @@ class ETMV4IDecodeTree { frame_decoder_.getTrcRawFrameAttachPt()->replace_first(&frame_printer); } - ITrcDataIn& GetFormattedDataIn() { return frame_decoder_; } - - ITrcDataIn& GetUnformattedDataIn(uint8_t trace_id) { - auto& decoder = packet_decoders_[trace_id]; - CHECK(decoder); - return *decoder; - } + ITrcDataIn& GetDataIn() { return frame_decoder_; } void ProcessError(const ocsdError& error) { if (error.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR) { @@ -191,10 +183,8 @@ class MapLocator : public PacketCallback { const EtmV4ITrcPacket* pkt) override { TraceData& data = trace_data_[trace_id]; if (op == OCSD_OP_DATA) { - if (pkt != nullptr && ((!data.use_vmid && pkt->getContext().updated_c) || - (data.use_vmid && pkt->getContext().updated_v))) { - int32_t new_tid = - static_cast<int32_t>(data.use_vmid ? pkt->getContext().VMID : pkt->getContext().ctxtID); + if (pkt != nullptr && pkt->getContext().updated_c) { + int32_t new_tid = static_cast<int32_t>(pkt->getContext().ctxtID); if (data.tid != new_tid) { data.tid = new_tid; data.thread = nullptr; @@ -232,14 +222,11 @@ class MapLocator : public PacketCallback { return thread_tree_.GetKernelMaps().FindMapByAddr(addr); } - void SetUseVmid(uint8_t trace_id, bool value) { trace_data_[trace_id].use_vmid = value; } - private: struct TraceData { int32_t tid = -1; // thread id, -1 if invalid const ThreadEntry* thread = nullptr; const MapEntry* userspace_map = nullptr; - bool use_vmid = false; // use vmid for PID }; ThreadTree& thread_tree_; @@ -341,16 +328,15 @@ struct ElementCallback { // Decode packets into elements. class PacketToElement : public PacketCallback, public ITrcGenElemIn { public: - PacketToElement(MapLocator& map_locator, - const std::unordered_map<uint8_t, std::unique_ptr<EtmV4Config>>& configs, + PacketToElement(MapLocator& map_locator, const std::unordered_map<uint8_t, EtmV4Config>& configs, DecodeErrorLogger& error_logger) : PacketCallback(PacketCallback::PACKET_TO_ELEMENT), mem_access_(map_locator) { for (auto& p : configs) { uint8_t trace_id = p.first; - const EtmV4Config* config = p.second.get(); + const EtmV4Config& config = p.second; element_decoders_.emplace(trace_id, trace_id); auto& decoder = element_decoders_[trace_id]; - decoder.setProtocolConfig(config); + decoder.setProtocolConfig(&config); decoder.getErrorLogAttachPt()->replace_first(&error_logger); decoder.getInstrDecodeAttachPt()->replace_first(&instruction_decoder_); decoder.getMemoryAccessAttachPt()->replace_first(&mem_access_); @@ -396,7 +382,7 @@ class DataDumper : public ElementCallback { frame_printer_.setMessageLogger(&stdout_logger_); } - void DumpPackets(const std::unordered_map<uint8_t, std::unique_ptr<EtmV4Config>>& configs) { + void DumpPackets(const std::unordered_map<uint8_t, EtmV4Config>& configs) { for (auto& p : configs) { uint8_t trace_id = p.first; auto result = packet_printers_.emplace(trace_id, trace_id); @@ -520,16 +506,16 @@ class BranchListParser : public PacketCallback { BranchListParser(MapLocator& map_locator, const ETMDecoder::BranchListCallbackFn& callback) : PacketCallback(BRANCH_LIST_PARSER), map_locator_(map_locator), callback_(callback) {} - void CheckConfigs(std::unordered_map<uint8_t, std::unique_ptr<EtmV4Config>>& configs) { + void CheckConfigs(std::unordered_map<uint8_t, EtmV4Config>& configs) { // TODO: Current implementation doesn't support non-zero speculation length and return stack. for (auto& p : configs) { - if (p.second->MaxSpecDepth() > 0) { + if (p.second.MaxSpecDepth() > 0) { LOG(WARNING) << "branch list collection isn't accurate with non-zero speculation length"; break; } } for (auto& p : configs) { - if (p.second->enabledRetStack()) { + if (p.second.enabledRetStack()) { LOG(WARNING) << "branch list collection will lose some data with return stack enabled"; break; } @@ -642,45 +628,21 @@ class ETMDecoderImpl : public ETMDecoder { ETMDecoderImpl(ThreadTree& thread_tree) : thread_tree_(thread_tree) {} void CreateDecodeTree(const AuxTraceInfoRecord& auxtrace_info) { - uint8_t trace_id = 0; - uint64_t* info = auxtrace_info.data->info; for (int i = 0; i < auxtrace_info.data->nr_cpu; i++) { - if (info[0] == AuxTraceInfoRecord::MAGIC_ETM4) { - auto& etm4 = *reinterpret_cast<AuxTraceInfoRecord::ETM4Info*>(info); - ocsd_etmv4_cfg cfg; - memset(&cfg, 0, sizeof(cfg)); - cfg.reg_idr0 = etm4.trcidr0; - cfg.reg_idr1 = etm4.trcidr1; - cfg.reg_idr2 = etm4.trcidr2; - cfg.reg_idr8 = etm4.trcidr8; - cfg.reg_configr = etm4.trcconfigr; - cfg.reg_traceidr = etm4.trctraceidr; - cfg.arch_ver = ARCH_V8; - cfg.core_prof = profile_CortexA; - trace_id = cfg.reg_traceidr & 0x7f; - trace_ids_.emplace(etm4.cpu, trace_id); - configs_.emplace(trace_id, new EtmV4Config(&cfg)); - info = reinterpret_cast<uint64_t*>(&etm4 + 1); - } else { - CHECK_EQ(info[0], AuxTraceInfoRecord::MAGIC_ETE); - auto& ete = *reinterpret_cast<AuxTraceInfoRecord::ETEInfo*>(info); - ocsd_ete_cfg cfg; - memset(&cfg, 0, sizeof(cfg)); - cfg.reg_idr0 = ete.trcidr0; - cfg.reg_idr1 = ete.trcidr1; - cfg.reg_idr2 = ete.trcidr2; - cfg.reg_idr8 = ete.trcidr8; - cfg.reg_devarch = ete.trcdevarch; - cfg.reg_configr = ete.trcconfigr; - cfg.reg_traceidr = ete.trctraceidr; - cfg.arch_ver = ARCH_AA64; - cfg.core_prof = profile_CortexA; - trace_id = cfg.reg_traceidr & 0x7f; - trace_ids_.emplace(ete.cpu, trace_id); - configs_.emplace(trace_id, new ETEConfig(&cfg)); - info = reinterpret_cast<uint64_t*>(&ete + 1); - } - decode_tree_.CreateDecoder(configs_[trace_id].get()); + auto& etm4 = auxtrace_info.data->etm4_info[i]; + ocsd_etmv4_cfg cfg; + memset(&cfg, 0, sizeof(cfg)); + cfg.reg_idr0 = etm4.trcidr0; + cfg.reg_idr1 = etm4.trcidr1; + cfg.reg_idr2 = etm4.trcidr2; + cfg.reg_idr8 = etm4.trcidr8; + cfg.reg_configr = etm4.trcconfigr; + cfg.reg_traceidr = etm4.trctraceidr; + cfg.arch_ver = ARCH_V8; + cfg.core_prof = profile_CortexA; + uint8_t trace_id = cfg.reg_traceidr & 0x7f; + configs_.emplace(trace_id, &cfg); + decode_tree_.CreateDecoder(configs_[trace_id]); auto result = packet_sinks_.emplace(trace_id, trace_id); CHECK(result.second); decode_tree_.AttachPacketSink(trace_id, result.first->second); @@ -714,36 +676,28 @@ class ETMDecoderImpl : public ETMDecoder { InstallPacketCallback(branch_list_parser_.get()); } - bool ProcessData(const uint8_t* data, size_t size, bool formatted, uint32_t cpu) override { + bool ProcessData(const uint8_t* data, size_t size) override { // Reset decoders before processing each data block. Because: // 1. Data blocks are not continuous. So decoders shouldn't keep previous states when // processing a new block. // 2. The beginning part of a data block may be truncated if kernel buffer is temporarily full. // So we may see garbage data, which can cause decoding errors if we don't reset decoders. - LOG(DEBUG) << "Processing " << (!formatted ? "un" : "") << "formatted data with size " << size; - auto& decoder = formatted ? decode_tree_.GetFormattedDataIn() - : decode_tree_.GetUnformattedDataIn(trace_ids_[cpu]); - - auto resp = decoder.TraceDataIn(OCSD_OP_RESET, data_index_, 0, nullptr, nullptr); + auto resp = + decode_tree_.GetDataIn().TraceDataIn(OCSD_OP_RESET, data_index_, 0, nullptr, nullptr); if (IsRespError(resp)) { LOG(ERROR) << "failed to reset decoder, resp " << resp; return false; } size_t left_size = size; - const size_t MAX_RESET_RETRY_COUNT = 3; - size_t reset_retry_count = 0; while (left_size > 0) { uint32_t processed; - auto resp = decoder.TraceDataIn(OCSD_OP_DATA, data_index_, left_size, data, &processed); + auto resp = decode_tree_.GetDataIn().TraceDataIn(OCSD_OP_DATA, data_index_, left_size, data, + &processed); if (IsRespError(resp)) { // A decoding error shouldn't ruin all data. Reset decoders to recover from it. - // But some errors may not be recoverable by resetting decoders. So use a max retry limit. - if (++reset_retry_count > MAX_RESET_RETRY_COUNT) { - break; - } - LOG(DEBUG) << "reset etm decoders for seeing a decode failure, resp " << resp - << ", reset_retry_count is " << reset_retry_count; - decoder.TraceDataIn(OCSD_OP_RESET, data_index_ + processed, 0, nullptr, nullptr); + LOG(INFO) << "reset etm decoders for seeing a decode failure, resp " << resp; + decode_tree_.GetDataIn().TraceDataIn(OCSD_OP_RESET, data_index_ + processed, 0, nullptr, + nullptr); } data += processed; left_size -= processed; @@ -766,12 +720,6 @@ class ETMDecoderImpl : public ETMDecoder { void InstallMapLocator() { if (!map_locator_) { map_locator_.reset(new MapLocator(thread_tree_)); - for (auto& cfg : configs_) { - int64_t configr = (*(const ocsd_etmv4_cfg*)*cfg.second).reg_configr; - map_locator_->SetUseVmid(cfg.first, - configr & (1U << ETM4_CFG_BIT_VMID | 1U << ETM4_CFG_BIT_VMID_OPT)); - } - InstallPacketCallback(map_locator_.get()); } } @@ -796,10 +744,8 @@ class ETMDecoderImpl : public ETMDecoder { ThreadTree& thread_tree_; // handle to build OpenCSD decoder ETMV4IDecodeTree decode_tree_; - // map from cpu to trace id - std::unordered_map<uint64_t, uint8_t> trace_ids_; // map from the trace id of an etm device to its config - std::unordered_map<uint8_t, std::unique_ptr<EtmV4Config>> configs_; + std::unordered_map<uint8_t, EtmV4Config> configs_; // map from the trace id of an etm device to its PacketSink std::unordered_map<uint8_t, PacketSink> packet_sinks_; std::unique_ptr<PacketToElement> packet_to_element_; |