summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2021-10-15 19:47:11 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-10-15 19:47:11 +0000
commit8918090d772da97c4505cb1e28aec785e3cc2bd5 (patch)
tree15c95395a63ad7a3bdb04f295123a7585cac5e30
parent99c3c81f9291791e7b77f466c1983f2fa2e371b1 (diff)
parent587fd04b590ef1c02dc90fdda0e2e833d15bf976 (diff)
downloadextras-8918090d772da97c4505cb1e28aec785e3cc2bd5.tar.gz
Merge "simpleperf: Add support for new perf ETE files."
-rw-r--r--simpleperf/ETMDecoder.cpp80
-rw-r--r--simpleperf/ETMRecorder.cpp20
-rw-r--r--simpleperf/ETMRecorder.h1
-rw-r--r--simpleperf/record.cpp75
-rw-r--r--simpleperf/record.h20
-rw-r--r--simpleperf/testdata/etm/perf_with_unformatted_trace.databin23018 -> 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
index dcd4c624..ee7ee3f6 100644
--- a/simpleperf/testdata/etm/perf_with_unformatted_trace.data
+++ b/simpleperf/testdata/etm/perf_with_unformatted_trace.data
Binary files differ