diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2021-10-15 19:47:11 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-10-15 19:47:11 +0000 |
commit | 8918090d772da97c4505cb1e28aec785e3cc2bd5 (patch) | |
tree | 15c95395a63ad7a3bdb04f295123a7585cac5e30 | |
parent | 99c3c81f9291791e7b77f466c1983f2fa2e371b1 (diff) | |
parent | 587fd04b590ef1c02dc90fdda0e2e833d15bf976 (diff) | |
download | extras-8918090d772da97c4505cb1e28aec785e3cc2bd5.tar.gz |
Merge "simpleperf: Add support for new perf ETE files."
-rw-r--r-- | simpleperf/ETMDecoder.cpp | 80 | ||||
-rw-r--r-- | simpleperf/ETMRecorder.cpp | 20 | ||||
-rw-r--r-- | simpleperf/ETMRecorder.h | 1 | ||||
-rw-r--r-- | simpleperf/record.cpp | 75 | ||||
-rw-r--r-- | simpleperf/record.h | 20 | ||||
-rw-r--r-- | simpleperf/testdata/etm/perf_with_unformatted_trace.data | bin | 23018 -> 21967 bytes |
6 files changed, 144 insertions, 52 deletions
diff --git a/simpleperf/ETMDecoder.cpp b/simpleperf/ETMDecoder.cpp index 463a62f1..4c72331e 100644 --- a/simpleperf/ETMDecoder.cpp +++ b/simpleperf/ETMDecoder.cpp @@ -71,10 +71,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()); @@ -341,15 +341,16 @@ struct ElementCallback { // Decode packets into elements. class PacketToElement : public PacketCallback, public ITrcGenElemIn { public: - PacketToElement(MapLocator& map_locator, const std::unordered_map<uint8_t, EtmV4Config>& configs, + PacketToElement(MapLocator& map_locator, + const std::unordered_map<uint8_t, std::unique_ptr<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; + const EtmV4Config* config = p.second.get(); 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_); @@ -395,7 +396,7 @@ class DataDumper : public ElementCallback { frame_printer_.setMessageLogger(&stdout_logger_); } - void DumpPackets(const std::unordered_map<uint8_t, EtmV4Config>& configs) { + void DumpPackets(const std::unordered_map<uint8_t, std::unique_ptr<EtmV4Config>>& configs) { for (auto& p : configs) { uint8_t trace_id = p.first; auto result = packet_printers_.emplace(trace_id, trace_id); @@ -519,16 +520,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, EtmV4Config>& configs) { + void CheckConfigs(std::unordered_map<uint8_t, std::unique_ptr<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; } @@ -641,22 +642,45 @@ 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++) { - 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; - trace_ids_.emplace(etm4.cpu, trace_id); - configs_.emplace(trace_id, &cfg); - decode_tree_.CreateDecoder(configs_[trace_id]); + 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 result = packet_sinks_.emplace(trace_id, trace_id); CHECK(result.second); decode_tree_.AttachPacketSink(trace_id, result.first->second); @@ -735,11 +759,11 @@ 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, - (*cfg.second).reg_configr & (1U << ETM4_CFG_BIT_VMID | 1U << ETM4_CFG_BIT_VMID_OPT)); + configr & (1U << ETM4_CFG_BIT_VMID | 1U << ETM4_CFG_BIT_VMID_OPT)); } InstallPacketCallback(map_locator_.get()); @@ -769,7 +793,7 @@ class ETMDecoderImpl : public ETMDecoder { // 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, EtmV4Config> configs_; + std::unordered_map<uint8_t, std::unique_ptr<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_; diff --git a/simpleperf/ETMRecorder.cpp b/simpleperf/ETMRecorder.cpp index 486e4f05..7bef4f21 100644 --- a/simpleperf/ETMRecorder.cpp +++ b/simpleperf/ETMRecorder.cpp @@ -154,6 +154,10 @@ bool ETMRecorder::ReadEtmInfo() { ReadValueInEtmDir(name + "/trcidr/trcidr4", &cpu_info.trcidr4) && ReadValueInEtmDir(name + "/trcidr/trcidr8", &cpu_info.trcidr8) && ReadValueInEtmDir(name + "/mgmt/trcauthstatus", &cpu_info.trcauthstatus); + + if (!ReadValueInEtmDir(name + "/mgmt/trcdevarch", &cpu_info.trcdevarch, false)) { + cpu_info.trcdevarch = 0; + } if (!success) { return false; } @@ -219,13 +223,20 @@ AuxTraceInfoRecord ETMRecorder::CreateAuxTraceInfoRecord() { AuxTraceInfoRecord::DataType data; memset(&data, 0, sizeof(data)); data.aux_type = AuxTraceInfoRecord::AUX_TYPE_ETM; + data.version = 1; data.nr_cpu = etm_info_.size(); data.pmu_type = GetEtmEventType(); - std::vector<AuxTraceInfoRecord::ETM4Info> etm4_v(etm_info_.size()); + std::vector<AuxTraceInfoRecord::ETEInfo> ete(etm_info_.size()); size_t pos = 0; for (auto& p : etm_info_) { - auto& e = etm4_v[pos++]; - e.magic = AuxTraceInfoRecord::MAGIC_ETM4; + auto& e = ete[pos++]; + if (p.second.trcdevarch == 0) { + e.magic = AuxTraceInfoRecord::MAGIC_ETM4; + e.nrtrcparams = sizeof(AuxTraceInfoRecord::ETM4Info) / sizeof(uint64_t) - 3; + } else { + e.magic = AuxTraceInfoRecord::MAGIC_ETE; + e.nrtrcparams = sizeof(AuxTraceInfoRecord::ETEInfo) / sizeof(uint64_t) - 3; + } e.cpu = p.first; e.trcconfigr = etm_config_reg_; e.trctraceidr = GetTraceId(p.first); @@ -234,8 +245,9 @@ AuxTraceInfoRecord ETMRecorder::CreateAuxTraceInfoRecord() { e.trcidr2 = p.second.trcidr2; e.trcidr8 = p.second.trcidr8; e.trcauthstatus = p.second.trcauthstatus; + e.trcdevarch = p.second.trcdevarch; } - return AuxTraceInfoRecord(data, etm4_v); + return AuxTraceInfoRecord(data, ete); } size_t ETMRecorder::GetAddrFilterPairs() { diff --git a/simpleperf/ETMRecorder.h b/simpleperf/ETMRecorder.h index b5596364..1e33ed80 100644 --- a/simpleperf/ETMRecorder.h +++ b/simpleperf/ETMRecorder.h @@ -34,6 +34,7 @@ struct ETMPerCpu { uint32_t trcidr4; uint32_t trcidr8; uint32_t trcauthstatus; + uint32_t trcdevarch; int GetMajorVersion() const; bool IsContextIDSupported() const; diff --git a/simpleperf/record.cpp b/simpleperf/record.cpp index 4e8a8822..218147b1 100644 --- a/simpleperf/record.cpp +++ b/simpleperf/record.cpp @@ -924,25 +924,43 @@ AuxTraceInfoRecord::AuxTraceInfoRecord(char* p) : Record(p) { p += header_size(); data = reinterpret_cast<DataType*>(p); CHECK_EQ(data->aux_type, AUX_TYPE_ETM); - CHECK_EQ(data->version, 0); + CHECK_EQ(data->version, 1); + p += sizeof(DataType); for (uint32_t i = 0; i < data->nr_cpu; ++i) { - CHECK_EQ(data->etm4_info[i].magic, MAGIC_ETM4); + uint64_t magic = *reinterpret_cast<uint64_t*>(p); + if (magic == MAGIC_ETM4) { + p += sizeof(ETM4Info); + } else { + CHECK_EQ(magic, MAGIC_ETE); + p += sizeof(ETEInfo); + } } - p += sizeof(DataType) + data->nr_cpu * sizeof(ETM4Info); CHECK_EQ(p, end); } AuxTraceInfoRecord::AuxTraceInfoRecord(const DataType& data, - const std::vector<ETM4Info>& etm4_info) { + const std::vector<ETEInfo>& ete_info) { SetTypeAndMisc(PERF_RECORD_AUXTRACE_INFO, 0); - SetSize(header_size() + sizeof(DataType) + sizeof(ETM4Info) * etm4_info.size()); - char* new_binary = new char[size()]; + + uint32_t size = header_size() + sizeof(DataType); + for (auto& ete : ete_info) { + size += (ete.trcdevarch == 0) ? sizeof(ETM4Info) : sizeof(ETEInfo); + } + SetSize(size); + char* new_binary = new char[size]; char* p = new_binary; MoveToBinaryFormat(header, p); this->data = reinterpret_cast<DataType*>(p); MoveToBinaryFormat(data, p); - for (auto& etm4 : etm4_info) { - MoveToBinaryFormat(etm4, p); + for (auto& ete : ete_info) { + if (ete.trcdevarch == 0) { + ETM4Info etm4; + static_assert(sizeof(ETM4Info) + sizeof(uint64_t) == sizeof(ETEInfo)); + memcpy(&etm4, &ete, sizeof(ETM4Info)); + MoveToBinaryFormat(etm4, p); + } else { + MoveToBinaryFormat(ete, p); + } } UpdateBinary(new_binary); } @@ -954,17 +972,38 @@ void AuxTraceInfoRecord::DumpData(size_t indent) const { PrintIndented(indent, "pmu_type %u\n", data->pmu_type); PrintIndented(indent, "snapshot %" PRIu64 "\n", data->snapshot); indent++; + uint64_t *info = data->info; + for (int i = 0; i < data->nr_cpu; i++) { - const ETM4Info& e = data->etm4_info[i]; - PrintIndented(indent, "magic 0x%" PRIx64 "\n", e.magic); - PrintIndented(indent, "cpu %" PRIu64 "\n", e.cpu); - PrintIndented(indent, "trcconfigr 0x%" PRIx64 "\n", e.trcconfigr); - PrintIndented(indent, "trctraceidr 0x%" PRIx64 "\n", e.trctraceidr); - PrintIndented(indent, "trcidr0 0x%" PRIx64 "\n", e.trcidr0); - PrintIndented(indent, "trcidr1 0x%" PRIx64 "\n", e.trcidr1); - PrintIndented(indent, "trcidr2 0x%" PRIx64 "\n", e.trcidr2); - PrintIndented(indent, "trcidr8 0x%" PRIx64 "\n", e.trcidr8); - PrintIndented(indent, "trcauthstatus 0x%" PRIx64 "\n", e.trcauthstatus); + if (info[0] == MAGIC_ETM4) { + ETM4Info &e = *reinterpret_cast<ETM4Info *>(info); + PrintIndented(indent, "magic 0x%" PRIx64 "\n", e.magic); + PrintIndented(indent, "cpu %" PRIu64 "\n", e.cpu); + PrintIndented(indent, "nrtrcparams %" PRIu64 "\n", e.nrtrcparams); + PrintIndented(indent, "trcconfigr 0x%" PRIx64 "\n", e.trcconfigr); + PrintIndented(indent, "trctraceidr 0x%" PRIx64 "\n", e.trctraceidr); + PrintIndented(indent, "trcidr0 0x%" PRIx64 "\n", e.trcidr0); + PrintIndented(indent, "trcidr1 0x%" PRIx64 "\n", e.trcidr1); + PrintIndented(indent, "trcidr2 0x%" PRIx64 "\n", e.trcidr2); + PrintIndented(indent, "trcidr8 0x%" PRIx64 "\n", e.trcidr8); + PrintIndented(indent, "trcauthstatus 0x%" PRIx64 "\n", e.trcauthstatus); + info = reinterpret_cast<uint64_t *>(&e + 1); + } else { + CHECK_EQ(info[0], MAGIC_ETE); + ETEInfo &e = *reinterpret_cast<ETEInfo *>(info); + PrintIndented(indent, "magic 0x%" PRIx64 "\n", e.magic); + PrintIndented(indent, "cpu %" PRIu64 "\n", e.cpu); + PrintIndented(indent, "nrtrcparams %" PRIu64 "\n", e.nrtrcparams); + PrintIndented(indent, "trcconfigr 0x%" PRIx64 "\n", e.trcconfigr); + PrintIndented(indent, "trctraceidr 0x%" PRIx64 "\n", e.trctraceidr); + PrintIndented(indent, "trcidr0 0x%" PRIx64 "\n", e.trcidr0); + PrintIndented(indent, "trcidr1 0x%" PRIx64 "\n", e.trcidr1); + PrintIndented(indent, "trcidr2 0x%" PRIx64 "\n", e.trcidr2); + PrintIndented(indent, "trcidr8 0x%" PRIx64 "\n", e.trcidr8); + PrintIndented(indent, "trcauthstatus 0x%" PRIx64 "\n", e.trcauthstatus); + PrintIndented(indent, "trcdevarch 0x%" PRIx64 "\n", e.trcdevarch); + info = reinterpret_cast<uint64_t *>(&e + 1); + } } } diff --git a/simpleperf/record.h b/simpleperf/record.h index f3bfb2f3..fad3a886 100644 --- a/simpleperf/record.h +++ b/simpleperf/record.h @@ -452,10 +452,12 @@ struct AuxTraceInfoRecord : public Record { // magic values to be compatible with linux perf static const uint32_t AUX_TYPE_ETM = 3; static const uint64_t MAGIC_ETM4 = 0x4040404040404040ULL; + static const uint64_t MAGIC_ETE = 0x5050505050505050ULL; struct ETM4Info { uint64_t magic; uint64_t cpu; + uint64_t nrtrcparams; uint64_t trcconfigr; uint64_t trctraceidr; uint64_t trcidr0; @@ -465,6 +467,20 @@ struct AuxTraceInfoRecord : public Record { uint64_t trcauthstatus; }; + struct ETEInfo { + uint64_t magic; + uint64_t cpu; + uint64_t nrtrcparams; + uint64_t trcconfigr; + uint64_t trctraceidr; + uint64_t trcidr0; + uint64_t trcidr1; + uint64_t trcidr2; + uint64_t trcidr8; + uint64_t trcauthstatus; + uint64_t trcdevarch; + }; + struct DataType { uint32_t aux_type; uint32_t reserved; @@ -472,11 +488,11 @@ struct AuxTraceInfoRecord : public Record { uint32_t nr_cpu; uint32_t pmu_type; uint64_t snapshot; - ETM4Info etm4_info[0]; + uint64_t info[0]; } * data; explicit AuxTraceInfoRecord(char* p); - AuxTraceInfoRecord(const DataType& data, const std::vector<ETM4Info>& etm4_info); + AuxTraceInfoRecord(const DataType& data, const std::vector<ETEInfo>& ete_info); protected: void DumpData(size_t indent) const override; diff --git a/simpleperf/testdata/etm/perf_with_unformatted_trace.data b/simpleperf/testdata/etm/perf_with_unformatted_trace.data Binary files differindex dcd4c624..ee7ee3f6 100644 --- a/simpleperf/testdata/etm/perf_with_unformatted_trace.data +++ b/simpleperf/testdata/etm/perf_with_unformatted_trace.data |