From 1d301dbe31ad8106f6c710bb4a1e00ba5d3269c3 Mon Sep 17 00:00:00 2001 From: Davidson K Date: Fri, 10 Dec 2021 13:18:32 +0530 Subject: [PATCH] Apply backported patches for simpleperf The ETE/TRBE support for the simpleperf is backported from the upstream master branch. Change-Id: Ie5599c7cf29f311b0cbfc597379944571994663b Signed-off-by: Davidson K --- ...Add-ETE-decoder-to-the-Android-build.patch | 29 + ...e-ETM-PID-tracing-when-the-kernel-is.patch | 200 +++++++ ...port-decoding-unformatted-ETM-traces.patch | 271 +++++++++ ...e-enabling-events-after-truncated-au.patch | 84 +++ ...f-Add-support-for-new-perf-ETE-files.patch | 554 ++++++++++++++++++ tc/vendorsetup.sh | 12 + 6 files changed, 1150 insertions(+) create mode 100644 tc/patches/0001-Add-ETE-decoder-to-the-Android-build.patch create mode 100644 tc/patches/0001-simpleperf-Enable-ETM-PID-tracing-when-the-kernel-is.patch create mode 100644 tc/patches/0002-simpleperf-Support-decoding-unformatted-ETM-traces.patch create mode 100644 tc/patches/0003-simpleperf-try-re-enabling-events-after-truncated-au.patch create mode 100644 tc/patches/0004-simpleperf-Add-support-for-new-perf-ETE-files.patch diff --git a/tc/patches/0001-Add-ETE-decoder-to-the-Android-build.patch b/tc/patches/0001-Add-ETE-decoder-to-the-Android-build.patch new file mode 100644 index 0000000..dfbc0c3 --- /dev/null +++ b/tc/patches/0001-Add-ETE-decoder-to-the-Android-build.patch @@ -0,0 +1,29 @@ +From 0c17b43af601cbdc435d07904d264b4d8704eb00 Mon Sep 17 00:00:00 2001 +From: Branislav Rankov +Date: Thu, 30 Sep 2021 22:11:55 +0100 +Subject: [PATCH] Add ETE decoder to the Android build. + +test: m simpleperf + +Change-Id: I120c1894b8300476f575342b03b8f3946b599f3e + +Upstream-Status: Backport [https://android.googlesource.com/platform/external/OpenCSD/+/335af7af5a36f802aac14b663d54a7005c8a1536] +--- + Android.bp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Android.bp b/Android.bp +index 448a8b4..6e8884c 100644 +--- a/Android.bp ++++ b/Android.bp +@@ -75,6 +75,7 @@ cc_library_static { + "decoder/source/*.cpp", + "decoder/source/etmv3/*.cpp", + "decoder/source/etmv4/*.cpp", ++ "decoder/source/ete/*.cpp", + "decoder/source/i_dec/*.cpp", + "decoder/source/mem_acc/*.cpp", + "decoder/source/pkt_printers/*.cpp", +-- +2.34.1 + diff --git a/tc/patches/0001-simpleperf-Enable-ETM-PID-tracing-when-the-kernel-is.patch b/tc/patches/0001-simpleperf-Enable-ETM-PID-tracing-when-the-kernel-is.patch new file mode 100644 index 0000000..fb2d27d --- /dev/null +++ b/tc/patches/0001-simpleperf-Enable-ETM-PID-tracing-when-the-kernel-is.patch @@ -0,0 +1,200 @@ +From e847f450c1ec2a200ab10fb621e83dcd9bcea4a3 Mon Sep 17 00:00:00 2001 +From: Tamas Zsoldos +Date: Wed, 5 May 2021 14:42:09 +0200 +Subject: [PATCH 1/4] simpleperf: Enable ETM PID tracing when the kernel is + running in EL2 + +When the kernel was booted in EL2, the PID of the traced processes +will be written to the VMIDs instead of the context IDs. This change +detects if this is the case and sets up recording and decoding to +handle it appropriately. + +Change-Id: Ia3ccefa97ca4e30d1d37715f7372f570d2999ec0 + +Upstream-Status: Backport [https://android.googlesource.com/platform/system/extras/+/68fa61e27db05972daf10903a33d575b00cb96be] +--- + simpleperf/ETMConstants.h | 30 ++++++++++++++++++++++++++++++ + simpleperf/ETMDecoder.cpp | 18 ++++++++++++++++-- + simpleperf/ETMRecorder.cpp | 29 +++++++++++++++++------------ + simpleperf/ETMRecorder.h | 2 ++ + 4 files changed, 65 insertions(+), 14 deletions(-) + create mode 100644 simpleperf/ETMConstants.h + +diff --git a/simpleperf/ETMConstants.h b/simpleperf/ETMConstants.h +new file mode 100644 +index 00000000..c0897193 +--- /dev/null ++++ b/simpleperf/ETMConstants.h +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2021 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#pragma once ++ ++namespace simpleperf { ++// Config bits from include/linux/coresight-pmu.h in the kernel ++// For etm_event_config: ++static constexpr int ETM_OPT_CTXTID = 14; ++static constexpr int ETM_OPT_CTXTID2 = 15; ++static constexpr int ETM_OPT_TS = 28; ++// For etm_config_reg: ++static constexpr int ETM4_CFG_BIT_CTXTID = 6; ++static constexpr int ETM4_CFG_BIT_VMID = 7; ++static constexpr int ETM4_CFG_BIT_TS = 11; ++static constexpr int ETM4_CFG_BIT_VMID_OPT = 15; ++} // namespace simpleperf +diff --git a/simpleperf/ETMDecoder.cpp b/simpleperf/ETMDecoder.cpp +index 546f2988..f2bec388 100644 +--- a/simpleperf/ETMDecoder.cpp ++++ b/simpleperf/ETMDecoder.cpp +@@ -24,6 +24,8 @@ + #include + #include + ++#include "ETMConstants.h" ++ + namespace simpleperf { + namespace { + +@@ -183,8 +185,10 @@ class MapLocator : public PacketCallback { + const EtmV4ITrcPacket* pkt) override { + TraceData& data = trace_data_[trace_id]; + if (op == OCSD_OP_DATA) { +- if (pkt != nullptr && pkt->getContext().updated_c) { +- int32_t new_tid = static_cast(pkt->getContext().ctxtID); ++ if (pkt != nullptr && ((!data.use_vmid && pkt->getContext().updated_c) || ++ (data.use_vmid && pkt->getContext().updated_v))) { ++ int32_t new_tid = ++ static_cast(data.use_vmid ? pkt->getContext().VMID : pkt->getContext().ctxtID); + if (data.tid != new_tid) { + data.tid = new_tid; + data.thread = nullptr; +@@ -222,11 +226,14 @@ 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_; +@@ -720,6 +727,13 @@ class ETMDecoderImpl : public ETMDecoder { + void InstallMapLocator() { + if (!map_locator_) { + map_locator_.reset(new MapLocator(thread_tree_)); ++ ++ for (auto& cfg : configs_) { ++ map_locator_->SetUseVmid( ++ cfg.first, ++ (*cfg.second).reg_configr & (1U << ETM4_CFG_BIT_VMID | 1U << ETM4_CFG_BIT_VMID_OPT)); ++ } ++ + InstallPacketCallback(map_locator_.get()); + } + } +diff --git a/simpleperf/ETMRecorder.cpp b/simpleperf/ETMRecorder.cpp +index c9119d0e..486e4f05 100644 +--- a/simpleperf/ETMRecorder.cpp ++++ b/simpleperf/ETMRecorder.cpp +@@ -28,6 +28,7 @@ + #include + #include + ++#include "ETMConstants.h" + #include "environment.h" + #include "utils.h" + +@@ -35,14 +36,6 @@ namespace simpleperf { + + static constexpr bool ETM_RECORD_TIMESTAMP = false; + +-// Config bits from include/linux/coresight-pmu.h in the kernel +-// For etm_event_config: +-static constexpr int ETM_OPT_CTXTID = 14; +-static constexpr int ETM_OPT_TS = 28; +-// For etm_config_reg: +-static constexpr int ETM4_CFG_BIT_CTXTID = 6; +-static constexpr int ETM4_CFG_BIT_TS = 11; +- + static const std::string ETM_DIR = "/sys/bus/event_source/devices/cs_etm/"; + + // from coresight_get_trace_id(int cpu) in include/linux/coresight-pmu.h +@@ -51,11 +44,13 @@ static int GetTraceId(int cpu) { + } + + template +-static bool ReadValueInEtmDir(const std::string& file, T* value, bool report_error = true) { ++static bool ReadValueInEtmDir(const std::string& file, T* value, bool report_error = true, ++ const std::string& prefix = "") { + std::string s; + uint64_t v; + if (!android::base::ReadFileToString(ETM_DIR + file, &s) || +- !android::base::ParseUint(android::base::Trim(s), &v)) { ++ !android::base::StartsWith(s, prefix) || ++ !android::base::ParseUint(&android::base::Trim(s)[prefix.size()], &v)) { + if (report_error) { + LOG(ERROR) << "failed to read " << ETM_DIR << file; + } +@@ -140,6 +135,10 @@ bool ETMRecorder::CheckEtmSupport() { + } + + bool ETMRecorder::ReadEtmInfo() { ++ int contextid_value; ++ use_contextid2_ = ReadValueInEtmDir("/format/contextid", &contextid_value, false, "config:") && ++ contextid_value == ETM_OPT_CTXTID2; ++ + std::vector online_cpus = GetOnlineCpus(); + for (const auto& name : GetEntriesInDir(ETM_DIR)) { + int cpu; +@@ -194,8 +193,14 @@ void ETMRecorder::SetEtmPerfEventAttr(perf_event_attr* attr) { + + void ETMRecorder::BuildEtmConfig() { + if (etm_event_config_ == 0) { +- etm_event_config_ |= 1ULL << ETM_OPT_CTXTID; +- etm_config_reg_ |= 1U << ETM4_CFG_BIT_CTXTID; ++ if (use_contextid2_) { ++ etm_event_config_ |= 1ULL << ETM_OPT_CTXTID2; ++ etm_config_reg_ |= 1U << ETM4_CFG_BIT_VMID; ++ etm_config_reg_ |= 1U << ETM4_CFG_BIT_VMID_OPT; ++ } else { ++ etm_event_config_ |= 1ULL << ETM_OPT_CTXTID; ++ etm_config_reg_ |= 1U << ETM4_CFG_BIT_CTXTID; ++ } + + if (ETM_RECORD_TIMESTAMP) { + bool ts_supported = true; +diff --git a/simpleperf/ETMRecorder.h b/simpleperf/ETMRecorder.h +index 33c0f726..b5596364 100644 +--- a/simpleperf/ETMRecorder.h ++++ b/simpleperf/ETMRecorder.h +@@ -68,6 +68,8 @@ class ETMRecorder { + bool etm_supported_ = false; + // select ETR device, setting in perf_event_attr->config2 + uint32_t sink_config_ = 0; ++ // use EL2 PID tracing or not ++ bool use_contextid2_ = false; + // select etm options (timestamp, context_id, ...), setting in perf_event_attr->config + uint64_t etm_event_config_ = 0; + // record etm options in AuxTraceInfoRecord +-- +2.17.1 + diff --git a/tc/patches/0002-simpleperf-Support-decoding-unformatted-ETM-traces.patch b/tc/patches/0002-simpleperf-Support-decoding-unformatted-ETM-traces.patch new file mode 100644 index 0000000..ce1ae1c --- /dev/null +++ b/tc/patches/0002-simpleperf-Support-decoding-unformatted-ETM-traces.patch @@ -0,0 +1,271 @@ +From 4c1d473daeed586feb339aad7cf7037867a27f63 Mon Sep 17 00:00:00 2001 +From: Tamas Zsoldos +Date: Fri, 23 Apr 2021 17:25:00 +0200 +Subject: [PATCH 2/4] simpleperf: Support decoding unformatted ETM traces. + +Some devices, like TRBE, produce unformatted traces. These cannot be +decoded by the formatted frame decoder, the underlying packet decoders +have to be used. This change recognizes unformatted traces and uses +the correct decoder to handle them. + +Test: simpleperf_unit_test + +Change-Id: I7e1a0c81a34c07a6f9e8cf6bceca6bf2592be0d9 + +Upstream-Status: Backport [https://android.googlesource.com/platform/system/extras/+/dd9ff55089608758d0a424612e41dea18c866eb8] +--- + simpleperf/ETMDecoder.cpp | 26 ++++++++++++------ + simpleperf/ETMDecoder.h | 2 +- + simpleperf/cmd_dumprecord.cpp | 2 +- + simpleperf/cmd_inject.cpp | 3 +- + simpleperf/cmd_inject_test.cpp | 10 +++++++ + simpleperf/perf_event.h | 4 +++ + simpleperf/record.h | 2 ++ + .../etm/perf_with_unformatted_trace.data | Bin 0 -> 23018 bytes + 8 files changed, 38 insertions(+), 11 deletions(-) + create mode 100644 simpleperf/testdata/etm/perf_with_unformatted_trace.data + +diff --git a/simpleperf/ETMDecoder.cpp b/simpleperf/ETMDecoder.cpp +index f2bec388..463a62f1 100644 +--- a/simpleperf/ETMDecoder.cpp ++++ b/simpleperf/ETMDecoder.cpp +@@ -101,7 +101,13 @@ class ETMV4IDecodeTree { + frame_decoder_.getTrcRawFrameAttachPt()->replace_first(&frame_printer); + } + +- ITrcDataIn& GetDataIn() { return frame_decoder_; } ++ ITrcDataIn& GetFormattedDataIn() { return frame_decoder_; } ++ ++ ITrcDataIn& GetUnformattedDataIn(uint8_t trace_id) { ++ auto& decoder = packet_decoders_[trace_id]; ++ CHECK(decoder); ++ return *decoder; ++ } + + void ProcessError(const ocsdError& error) { + if (error.getErrorCode() == OCSD_ERR_INVALID_PCKT_HDR) { +@@ -648,6 +654,7 @@ class ETMDecoderImpl : public ETMDecoder { + 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]); + auto result = packet_sinks_.emplace(trace_id, trace_id); +@@ -683,14 +690,17 @@ class ETMDecoderImpl : public ETMDecoder { + InstallPacketCallback(branch_list_parser_.get()); + } + +- bool ProcessData(const uint8_t* data, size_t size) override { ++ bool ProcessData(const uint8_t* data, size_t size, bool formatted, uint32_t cpu) 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. +- auto resp = +- decode_tree_.GetDataIn().TraceDataIn(OCSD_OP_RESET, data_index_, 0, nullptr, nullptr); ++ 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); + if (IsRespError(resp)) { + LOG(ERROR) << "failed to reset decoder, resp " << resp; + return false; +@@ -698,13 +708,11 @@ class ETMDecoderImpl : public ETMDecoder { + size_t left_size = size; + while (left_size > 0) { + uint32_t processed; +- auto resp = decode_tree_.GetDataIn().TraceDataIn(OCSD_OP_DATA, data_index_, left_size, data, +- &processed); ++ auto resp = decoder.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. + 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); ++ decoder.TraceDataIn(OCSD_OP_RESET, data_index_ + processed, 0, nullptr, nullptr); + } + data += processed; + left_size -= processed; +@@ -758,6 +766,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 trace_ids_; + // map from the trace id of an etm device to its config + std::unordered_map configs_; + // map from the trace id of an etm device to its PacketSink +diff --git a/simpleperf/ETMDecoder.h b/simpleperf/ETMDecoder.h +index f8cec366..5f9daebd 100644 +--- a/simpleperf/ETMDecoder.h ++++ b/simpleperf/ETMDecoder.h +@@ -74,7 +74,7 @@ class ETMDecoder { + using BranchListCallbackFn = std::function; + virtual void RegisterCallback(const BranchListCallbackFn& callback) = 0; + +- virtual bool ProcessData(const uint8_t* data, size_t size) = 0; ++ virtual bool ProcessData(const uint8_t* data, size_t size, bool formatted, uint32_t cpu) = 0; + virtual bool FinishData() = 0; + }; + +diff --git a/simpleperf/cmd_dumprecord.cpp b/simpleperf/cmd_dumprecord.cpp +index 9d8cba90..f67c411c 100644 +--- a/simpleperf/cmd_dumprecord.cpp ++++ b/simpleperf/cmd_dumprecord.cpp +@@ -423,7 +423,7 @@ bool DumpRecordCommand::DumpAuxData(const AuxRecord& aux) { + if (!record_file_reader_->ReadAuxData(aux.Cpu(), aux.data->aux_offset, data.get(), size)) { + return false; + } +- return etm_decoder_->ProcessData(data.get(), size); ++ return etm_decoder_->ProcessData(data.get(), size, !aux.Unformatted(), aux.Cpu()); + } + return true; + } +diff --git a/simpleperf/cmd_inject.cpp b/simpleperf/cmd_inject.cpp +index d90bd517..bbc26028 100644 +--- a/simpleperf/cmd_inject.cpp ++++ b/simpleperf/cmd_inject.cpp +@@ -266,7 +266,8 @@ class InjectCommand : public Command { + LOG(ERROR) << "failed to read aux data"; + return false; + } +- return etm_decoder_->ProcessData(aux_data_buffer_.data(), aux_size); ++ return etm_decoder_->ProcessData(aux_data_buffer_.data(), aux_size, !aux->Unformatted(), ++ aux->Cpu()); + } + } else if (r->type() == PERF_RECORD_MMAP && r->InKernel()) { + auto& mmap_r = *static_cast(r); +diff --git a/simpleperf/cmd_inject_test.cpp b/simpleperf/cmd_inject_test.cpp +index 8668174c..dbe742c7 100644 +--- a/simpleperf/cmd_inject_test.cpp ++++ b/simpleperf/cmd_inject_test.cpp +@@ -148,3 +148,13 @@ TEST(cmd_inject, inject_kernel_data) { + ASSERT_TRUE(android::base::ReadFileToString(tmpfile2.path, &output)); + ASSERT_EQ(output, autofdo_output); + } ++ ++TEST(cmd_inject, unformatted_trace) { ++ std::string data; ++ std::string perf_with_unformatted_trace = ++ GetTestData(std::string("etm") + OS_PATH_SEPARATOR + "perf_with_unformatted_trace.data"); ++ ASSERT_TRUE(RunInjectCmd({"-i", perf_with_unformatted_trace}, &data)); ++ // Test that we can find instr range in etm_test_loop binary. ++ ASSERT_NE(data.find("etm_test_loop"), std::string::npos); ++ CheckMatchingExpectedData(data); ++} +diff --git a/simpleperf/perf_event.h b/simpleperf/perf_event.h +index 7e7e48d7..45a00a7a 100644 +--- a/simpleperf/perf_event.h ++++ b/simpleperf/perf_event.h +@@ -23,4 +23,8 @@ + #include + #endif + ++#if !defined(PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW) ++#define PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW 0x0100 ++#endif ++ + #endif // SIMPLE_PERF_PERF_EVENT_H_ +diff --git a/simpleperf/record.h b/simpleperf/record.h +index 0ba8d4aa..f3bfb2f3 100644 +--- a/simpleperf/record.h ++++ b/simpleperf/record.h +@@ -427,6 +427,8 @@ struct AuxRecord : public Record { + + AuxRecord(const perf_event_attr& attr, char* p); + ++ bool Unformatted() const { return data->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW; } ++ + 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 +new file mode 100644 +index 0000000000000000000000000000000000000000..dcd4c6245b8d08dfb3d2bb4dd59f577648e00147 +GIT binary patch +literal 23018 +zcmd6v3zQSp8OLXlDxzXk4poi^2itP+vAfxo<)vsup@=L-UezLGv&jVF<}oDM<&6;) +zR-u>zMXjO%k4IV`-D6uVs2C|#sZ^sP$U|K`^}#u{t`?ChM>>=HeY1BabLWvvuyfAt +zoyVQ~|K0EV=H5G#JL4TQY3y|q#?;T|$kNV8T~*}3rU{TilT7K=Q?;juYK!9@hV4fn +z%|f~X(q2+JPhL;U|2PihxL0B26tbHOoU=?@G#p_kSe9N6tTzt_<-Ao~6L(x%$gWde +zIeFvwkuR=-JaRID`+kBgja!to=Ja7;fJ +zCi)pDSnOL|32Kky_4nRN^m!2JGS)u{vXxi=`@8+`&VPBETxK3i1_4H*)ZZ@(^J)X} +zXpKJ>OvJ;%nnY_X6^;tEk#O_SAyQn#W8r|j5vWPViwo0_3yO=|MY!DZl_@PId`etY +zn#+BFaCr(;(!bMjMK?WR_7Z`M2Mo6{7kaz4BKB(Uj<4JmUlrm@)HP4hPQ_l(zL02= +z!>BbCjwE$sNiIY`o+u9YD8i8jNfRC=o}A|B01h5Fx*%mF6|+YkI9w=`$4;xX^+T)sGl7k=HrtN;OGPe6CP%Kl*^I%fY<~5(qw$QTQPfN?Qt;U +zqa=G!_s4GGNTL7rY9m2^n{AKyEWPm1Z#O9YH0WnQ&xC^=7bWVuLZto}51sn;#=VZ$ +zpSP#ajsrXOr|v`Dvq}9;`tzdtTfVP~>V*ZPy`Z?fVTenc-Wbc`Y|6>+e>YpqAmOO3P$t-OuyZs;;U1`h1Y)(5!s=%JC^-eB3GA& +zi)R4A?#kMWYNstVkCDd^&Vhypz +z>J*O_jVnv8zde2B`Yx;f)cC$LMe3h39xtI4nDuXs%?-zb$&^3Pq8ADJ*Db}7oeO>d +z51a5Xa=3^a4lBHB@fS&)$+;~GcL-thwFC2kyfM(SD5x# +z5ElK3!0d3F{?iK6_{ac92INh6nDJ3A2ftM97yN;bVU>#6gIi8Gc!scMHJKM44~O`)*jSz*p3y>_$4UJ3xy+sFWD-J@dWb; +zj=p~=o;>iB>mR3hIyF3{`pGGtE_*!8cGf8#?@AIsUR2Tqu4dCHj#KgG)=+go6ssfQ +zlzy|zxW1|Q$=(a?9X#hU;WE0u9pUL%qrSeHO6;Gd_QnyOJn-Q4B^vXfSBu7vW${qs +z>HJz^pN#QyNem-q`~)t!M6XNGZ*M65rU!_A9wNbngBdTS>boBy`Xbb@NuD{vUL3D~ +z7W6S5a>n}1c(7G}Y8>7445`0KyNVWJ);}hsg1$f`%=q;{KMp943~+cr$%Ka)2jz0) +zfdl;^V$Jo_irJ&n9tSfnO0tL8{kyg6^KS~zh0z}RW>EH`U#7POlkpkKZe>M34ygWv +z2R)PLX;`3Qf9CTTdFECm9Fyje4IP4Kb*H90nJ!X)z7ILcgbVA>ex6n)PsjI!Ck=JT +zoYh?!owbVF$9){^gW_l7if*dJsYCuE<$08NHJYO*18My|wm>Wl!v@zmWK!SQVAFa&;RTb{qqaFe7E0)RMeLek||## +z9+#VJJb&qiJ-YgZ`Jp`3|0wfADHd2AB&B#=uidrk26?xP+2dS}s}1^7{@O@9;E&X% +zqGBzJW8J`gx*S&R;2p7F_k1$Xm8wS*%yY%S#8l$dt4B|p^;ovhfP=QDsNvuxAz1V{ +zWPjSR=YS0d*!JLc`jbw)!U)9oz!HHJ6UDC<+b4{(MAiFj9**K+^d~GHIqnK}vB~pr +z`v+_u+CGf_gvF!y$tKUZ%RaQm!{|?(=GoV$lg-14O8dc;F#hQwU2{18!T6|u?;u;R +z41bgwuLJzOF4Jq5NxPWtuD|D9a(_UzBl5L^{y2sm2V6h}9w~3p{VLp_pgpGa9^YU| +zziSuK=RqJ(?vKjVAH3V5eqN)Wbw>aEzyxdc?|hNeKPy{STHyEja_fJ%U!#FO_4{ZJ +z>d)~19fV5xulS$YK9HHL+IjOB7ccamVvVaq!<9X=z<_pfnrnc6nl-K*_=^XV@ML6E +zDX#73++>YQ1THUdg}%xCNK)cA~llGGo@h1i^7{hjVV&leW4xj2f;^AzFo +z!V@3OxK+!g#HHnNqq<*TIcPDPi?&zh59)X^=|7ctEs^W!q9xY2vL}}7vz@oGxqd)D +z4)EW>=A!-R>OANT5U_M-0$xM+LjG+cZEi^*j_zSLZ2PhIza +zX|F2|KEUQG~pEdRo;bBYg{(3Gy7cX>uh$9xB(aSdszNoy7L#XU7FdGvmSM_pi|YNIx+Y7N--+|lM9CZ7i0}klF&Eiz) +zFD-Jc+pyglN4~NgJGocb94F8(zxTh!<|xB2cH6P~_5aZ2(9Tbo0O85W0@8x*;OH5X +zhUxXIq5X{35`AwQmv+u1^?^0&Ll^7BIC=De`2O)wv()bVr`*YhsU +zP39qpve5DMznpS*;d1YJ*H7pJyI}cb|8Fk(X8l~qB$qXKA}MhQOa{7T8ri;Cw`LxE5CoFH?a!=6z;qHfatlTu{S_7 +zG)&&F!t*etH737)-uSKU$(7H3x-9zK1!sJSd5SbFzH5Q!(;5f%j{0ik_EmeuO*n9>?EFOM#Wjrw-;UvHoD+}qc$eiHK(*(##{jRMTC +zO=*qDrgQIke94VV4%IHbYMy`6bC|bS!}vQTcpj#-#+n=3W`-8Gt?$2a%qe>tp7;{; +z6ls`zs}0Y?l-3wL__4;(hlU>h-HLHfEZBM7i +zeEsIk;8uCaSXhcQOuog0=V3}~OuRdgd+=ums-HQ(YR>LEe{}@&6ls`zzXs34l-3x1 +z{o6Nxy7iJ#<5o>vl^Jkn7v?F_u=uSlJfGG$bYJJ(ceWlob>SatcJ14DAN11F?_@Ub +z=do-|X^k^K_MP#Ij$gksW6$I_KfU(-jhF}PVfKwt%&$#7(vF6jI(JRo@M^bv#AS8W +zv+5fBL){}r1cwa^g{p($L~6eFB+a&5hF^Z+R&SELCNFDK?yNl0pA+>-2!VJa$Wk)j +zFLP82=J||r$YlhQ)zXySk*!AgjE>1=R9E|h!9=z6dS*&U7-eQ0lgl6{^EE{ij2Y)> +zcgtmzd@>X!fA&;*VLvKzbwlfhk7(e?w|RZicX^xRk)+Sx<_|~w%@Ki1C0Ye8AkB(y +z2?x1oJSM$5Cw(QABTfy+X8Gi|cZFn6;r43cf%*5)lF^=@YDQ5Wb7(YZDSld2d}ECn*J611VWiOmeNU +zmRNjlY~j1}ps!w0OUZ + +literal 0 +HcmV?d00001 + +-- +2.17.1 + diff --git a/tc/patches/0003-simpleperf-try-re-enabling-events-after-truncated-au.patch b/tc/patches/0003-simpleperf-try-re-enabling-events-after-truncated-au.patch new file mode 100644 index 0000000..ffe448d --- /dev/null +++ b/tc/patches/0003-simpleperf-try-re-enabling-events-after-truncated-au.patch @@ -0,0 +1,84 @@ +From e473bacf6d4a96b63a262f06d5b35064532a14b5 Mon Sep 17 00:00:00 2001 +From: Tamas Zsoldos +Date: Mon, 12 Jul 2021 11:07:18 +0200 +Subject: [PATCH 3/4] simpleperf: try re-enabling events after truncated aux + record + +A truncated aux record means the aux buffer most likely got full and +the kernel has disabled the perf event. Userspace needs to enable the +event again. We mark the kernel record reader disabled when we receive +a truncated record and try re-enabling its event once we have +collected everything from the kernel. + +This imporves the amount of trace collected using TRBE significantly. + +Test: simpleperf_unit_test +Change-Id: I470bfbedc145a7a29126b3e4bd4be731ae9edd10 + +Upstream-Status: Backport [https://android.googlesource.com/platform/system/extras/+/128f95184fd9a2c4060fcd55fc3f84e5118dd9b3] +--- + simpleperf/RecordReadThread.cpp | 19 +++++++++++++++++++ + simpleperf/RecordReadThread.h | 3 +++ + 2 files changed, 22 insertions(+) + +diff --git a/simpleperf/RecordReadThread.cpp b/simpleperf/RecordReadThread.cpp +index 16af9292..bbdf4897 100644 +--- a/simpleperf/RecordReadThread.cpp ++++ b/simpleperf/RecordReadThread.cpp +@@ -487,6 +487,13 @@ bool RecordReadThread::ReadRecordsFromKernelBuffer() { + if (!has_data) { + break; + } ++ // Having collected everything available, this is a good time to ++ // try to re-enabled any events that might have been disabled by ++ // the kernel. ++ for (auto event_fd : event_fds_disabled_by_kernel_) { ++ event_fd->SetEnableEvent(true); ++ } ++ event_fds_disabled_by_kernel_.clear(); + if (!SendDataNotificationToMainThread()) { + return false; + } +@@ -568,6 +575,18 @@ void RecordReadThread::PushRecordToRecordBuffer(KernelRecordReader* kernel_recor + char* p = record_buffer_.AllocWriteSpace(header.size); + if (p != nullptr) { + kernel_record_reader->ReadRecord(0, header.size, p); ++ if (header.type == PERF_RECORD_AUX) { ++ AuxRecord r{attr_, p}; ++ if (r.data->flags & PERF_AUX_FLAG_TRUNCATED) { ++ // When the kernel sees aux output flagged with PERF_AUX_FLAG_TRUNCATED, ++ // it sets a pending disable on the event: ++ // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/events/ring_buffer.c?h=v5.13#n516 ++ // The truncated flag is set by the Coresight driver when some trace was lost, ++ // which can be caused by a full buffer. Therefore, try to re-enable the event ++ // only after we have collected the aux data. ++ event_fds_disabled_by_kernel_.insert(kernel_record_reader->GetEventFd()); ++ } ++ } + record_buffer_.FinishWrite(); + } else { + if (header.type == PERF_RECORD_SAMPLE) { +diff --git a/simpleperf/RecordReadThread.h b/simpleperf/RecordReadThread.h +index 321dc8c5..2c3ddeee 100644 +--- a/simpleperf/RecordReadThread.h ++++ b/simpleperf/RecordReadThread.h +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -208,6 +209,8 @@ class RecordReadThread { + std::vector kernel_record_readers_; + pid_t exclude_pid_ = -1; + ++ std::unordered_set event_fds_disabled_by_kernel_; ++ + RecordStat stat_; + }; + +-- +2.17.1 + diff --git a/tc/patches/0004-simpleperf-Add-support-for-new-perf-ETE-files.patch b/tc/patches/0004-simpleperf-Add-support-for-new-perf-ETE-files.patch new file mode 100644 index 0000000..6cf815a --- /dev/null +++ b/tc/patches/0004-simpleperf-Add-support-for-new-perf-ETE-files.patch @@ -0,0 +1,554 @@ +From 74fc83de8adb3501cc877bfdea0df149d0d72e3c Mon Sep 17 00:00:00 2001 +From: Branislav Rankov +Date: Tue, 28 Sep 2021 21:45:45 +0100 +Subject: [PATCH 4/4] simpleperf: Add support for new perf ETE files. + +With the addition of ETE, perf files have changed the format of +the AUXTRACE_INFO record. This patch adds support for the new format. +The old format is no longer supported. + +Also initialize ETE decoder properly now that ETE records can be +distinguished from ETM4. + +Replaced test file for unformatted_trace (ETE). Command used to record: +simpleperf record -e cs-etm:u --addr-filter "filter ./etm_test_loop" ./etm_test_loop + +test: simpleperf_unit_test --gtest_filter="cmd_inject.unformatted_trace" + +Change-Id: Ic48401ecd32357602056b5b4eb652a505d4aab9e + +Upstream-Status: Backport [https://android.googlesource.com/platform/system/extras/+/587fd04b590ef1c02dc90fdda0e2e833d15bf976] +--- + simpleperf/ETMDecoder.cpp | 80 ++++++++++++------ + simpleperf/ETMRecorder.cpp | 20 ++++- + simpleperf/ETMRecorder.h | 1 + + simpleperf/record.cpp | 75 ++++++++++++---- + simpleperf/record.h | 20 ++++- + .../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(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& configs, ++ PacketToElement(MapLocator& map_locator, ++ const std::unordered_map>& 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& configs) { ++ void DumpPackets(const std::unordered_map>& 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& configs) { ++ void CheckConfigs(std::unordered_map>& 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(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(&etm4 + 1); ++ } else { ++ CHECK_EQ(info[0], AuxTraceInfoRecord::MAGIC_ETE); ++ auto& ete = *reinterpret_cast(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(&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 trace_ids_; + // map from the trace id of an etm device to its config +- std::unordered_map configs_; ++ std::unordered_map> configs_; + // map from the trace id of an etm device to its PacketSink + std::unordered_map packet_sinks_; + std::unique_ptr 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 etm4_v(etm_info_.size()); ++ std::vector 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(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(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& etm4_info) { ++ const std::vector& 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(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(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(&e + 1); ++ } else { ++ CHECK_EQ(info[0], MAGIC_ETE); ++ ETEInfo &e = *reinterpret_cast(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(&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& etm4_info); ++ AuxTraceInfoRecord(const DataType& data, const std::vector& 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 dcd4c6245b8d08dfb3d2bb4dd59f577648e00147..ee7ee3f6dfdceca585f72701d022297369a0f1a5 100644 +GIT binary patch +literal 21967 +zcmd6v3yd4Z8GttrAPs4_5-3n1*n%iT!Drti$K{~l5E2SX8Yh7OA&t*x?1`0)#C{95UP)ZFU5H8R&q9sK%#5~$Uq14b9qM|wpBv5FR?(Y2m-gtIr +zAAa1i(%tN1X8!Mg%wyNH8(O-0*=5U@wr>*1mWOmRb3AJrIdRLk-~y9eF>7YkndwzW +zf`C_#g7dS~G^g$B{{#W57xu%>G1@hCi_W{5t%_W*`HywkWD!u`7RWSPO{c3c7paA{ +zKOyw)Raa`)f=I3%@Hdp{&kSd>Qo`RSC;b^Yp~NLcO81+~v9+4y=ievti$LhWfp%?} +z{NTq#egW9WPcSP%ooTrK6_Ae(%AH6_Gw;rTQ}yY8%Y^^SqsIgM>7 +zYWHHPw)lea$B6U3NJg@ZBw}ytc%nFh&l8Tk$9QTqNBM>7_$i_%s^bQajQD9ZN5vZl +zQkwd~di_%VEwM)qHMUQ=_85_sNIJSn95Qj +zXskWx{`Vzfk1~4RrC(h4zfsH9Z0#qCtM>rm>eXi6>gK>__^H`kr9Tj^piU(SfjO{a +zofv*=Hka^6!X*MnuRRxf+x@uU#g9~fEVRwh=cReHgteXUEao!xKhltt%vy$$Uer3C +zD2{wP;Rt}{4m?IYvF*NIj?zNHA%eywmK-fX(x%y?0vy=?lk +zT5sMF*BVTG5pqOj*yRV^n!mvFpuH5t7-Nq0td!# +z!JdQLzH9PJe&YEDXk(rM%>sxnBm4vT|88~7S|J=oTWKTC%N{C +zk0c^i9ShW8Jzt_N>VOAiuz6j%?M +zLPI~nwMTTp0;}*~Yc +z90x9LJT!`@Fh+Ppus|=aBtVN)r%ks{33!ZnwdX;vHr8KMe_DKn*vFy&LMw6Yla#Wt +za5OG+o+4WJBNRskID#O_frlG6^>T;@A%1~FLCvkxrr9Ilje{E}HQ7U%xUUpvAFtmx +zVZ2(K!8nV4xppX)NqxsSZR}Xb0o8v5Kwb_tGKyO6820Brf6-Rn#O36GlDj4kxg0rz&12`$xpTBL<41(WT6#;1P|{M|eh)kI)?Ih0 +zwu|+mT$G9RqBXtNOMaaS7kmiUfg&NRw4($$VYsaM{0OoZ0(_;u-%c;bHoB9*@?)*TNI(iCMNg;wOqnISY8u +z5Tpm-@fd#cXdl-+>V5A^So%A+p2M868X5I@+S&`g|E_m`R%=Ob7TPk*=l;O6gI +z`;*u2^72o%yn5r!=x05~+o5Uwmhtaa|B+MUmgRZ&UcV$^ncuCvmItiM^W_;~J4i)z~ +zu$KsuVZC>=xW)@Ex$=y?z9?M1jJ?2aQ*N&iaB;@3tr%F4dXF!%ZU^IQ-65BL3^H5+ +z0)Y0KGOmEVAE%5V^7Z>awJkPGejemw`-b0{n=79hCxkN5pIHur@*6#VwLX0t +zfBX_CF7Z{u#k@zw<1*sH^}MZmT(#vADX!kv2^adyVf-@UrP*A{()Ox6 +zu|vQAV%~Q^KQ?-v8|ty)qT{Rh6yajt$KY{!kFVUo{L~$n +z$8pa)SM_-O{!W)%9^=_NS9Ltwb5ZduT0b|(c6L|wbXzdE*f?U=6X1PXXykqyzfl}Y +z1?G3qF)AdTbdDCr9u4MD#$DPY#MpxwFY5J+YmVS)1$|x=0D#Hl5a{>-jvxR44=+B9 +zamrq`AMEcn%fTIb2c_;~|C7JtLCf-_ +zTMO#>E>xkk{920noyzNr3)DpjA(ZPr%}o<#ZWT@@zq>1%pd;JE7d@>{r)O?GlfLi< +zZ2x@w?)jf?ABIf2sLP4K_%V>eYc!VtN0B-H1dc1JIBgrdlB5{MZ>%B5|Ay=2XyX48 +zb$7ZD6OO3c{<{}_Y29<37C(U(lX}UCyw1OY@hq>+s1bM +za)$62mT_9gf%$kTEo0MlH(oIC{cm(Ve|}5X`@7bDh-FNAxLk9JegB0|9XRLpt8VyESicYRnDpShM}Ya+l-A?mYquZsn-8{KJmam^XZ&}6;YrME +zlHu^q3YNo^mhtY@PlO+eymskm*POsNclkcXJSG_~-=D(rw2a? +zWqm`>U>=hUhj;t19Hz94Yi@Y-*@x0UpE(d+yXw}Dl$S9N-{gj2Pyh49wEmzb@;{r){QAG}zj@+Omz=(1<+9Di_?0f& +zAnOn7?>Nyi-n!_Mz55^kY;eQqoo^0*qHISF_dX~0R9FsETE>BA77V?2`O05xSmV#U +zBW*ej^O*d>c`pI;vnefO{}cPR?wOxD_Je(=@1DE2unqH?WH@{i4a;Fl%Q&Tc^YdGV +zmOOaoy@eI8%unpWJSfBIyL*_QO=%gQ-I06bmGygjx4+hYe&RoW`U>Vn8OFDj9KKnD +z+b99T-eDo|RR2()T5YD)k(Q#VbWGi;aSN*Dd`9n3TP0c@(Tq=B`q`u3($rFmR)^0QiN(^s +zemS0%(lu0~)jU#L36c1;H +z6Md<8CL9@x$ni*DToU>t@r)!y)g`n8a!g31lInXw>L=*1z>t*AsNbY>5xDRYdAM&- +zj>p3Na&n`TR?>1ZD=a3Ty7TuBDdB{il(ikL-|x9XPDc`QX3)QQ<(g3Iip6WLSi0IT +zB{#PAr6cJ`vb8eLYs^r0cFl?`ieDMB2b+kI|8$fhGvDV*x>k1B&;rHR$%MjdUf +zy1uP^YJuD$hOd`nQaGB5$E9divnVkytg2iNsV= +TT(&mUgN77ZE+akzMXjO%k4IV`-D6uVs2C|#sZ^sP$U|K`^}#u{t`?ChM>>=HeY1BabLWvvuyfAt +zoyVQ~|K0EV=H5G#JL4TQY3y|q#?;T|$kNV8T~*}3rU{TilT7K=Q?;juYK!9@hV4fn +z%|f~X(q2+JPhL;U|2PihxL0B26tbHOoU=?@G#p_kSe9N6tTzt_<-Ao~6L(x%$gWde +zIeFvwkuR=-JaRID`+kBgja!to=Ja7;fJ +zCi)pDSnOL|32Kky_4nRN^m!2JGS)u{vXxi=`@8+`&VPBETxK3i1_4H*)ZZ@(^J)X} +zXpKJ>OvJ;%nnY_X6^;tEk#O_SAyQn#W8r|j5vWPViwo0_3yO=|MY!DZl_@PId`etY +zn#+BFaCr(;(!bMjMK?WR_7Z`M2Mo6{7kaz4BKB(Uj<4JmUlrm@)HP4hPQ_l(zL02= +z!>BbCjwE$sNiIY`o+u9YD8i8jNfRC=o}A|B01h5Fx*%mF6|+YkI9w=`$4;xX^+T)sGl7k=HrtN;OGPe6CP%Kl*^I%fY<~5(qw$QTQPfN?Qt;U +zqa=G!_s4GGNTL7rY9m2^n{AKyEWPm1Z#O9YH0WnQ&xC^=7bWVuLZto}51sn;#=VZ$ +zpSP#ajsrXOr|v`Dvq}9;`tzdtTfVP~>V*ZPy`Z?fVTenc-Wbc`Y|6>+e>YpqAmOO3P$t-OuyZs;;U1`h1Y)(5!s=%JC^-eB3GA& +zi)R4A?#kMWYNstVkCDd^&Vhypz +z>J*O_jVnv8zde2B`Yx;f)cC$LMe3h39xtI4nDuXs%?-zb$&^3Pq8ADJ*Db}7oeO>d +z51a5Xa=3^a4lBHB@fS&)$+;~GcL-thwFC2kyfM(SD5x# +z5ElK3!0d3F{?iK6_{ac92INh6nDJ3A2ftM97yN;bVU>#6gIi8Gc!scMHJKM44~O`)*jSz*p3y>_$4UJ3xy+sFWD-J@dWb; +zj=p~=o;>iB>mR3hIyF3{`pGGtE_*!8cGf8#?@AIsUR2Tqu4dCHj#KgG)=+go6ssfQ +zlzy|zxW1|Q$=(a?9X#hU;WE0u9pUL%qrSeHO6;Gd_QnyOJn-Q4B^vXfSBu7vW${qs +z>HJz^pN#QyNem-q`~)t!M6XNGZ*M65rU!_A9wNbngBdTS>boBy`Xbb@NuD{vUL3D~ +z7W6S5a>n}1c(7G}Y8>7445`0KyNVWJ);}hsg1$f`%=q;{KMp943~+cr$%Ka)2jz0) +zfdl;^V$Jo_irJ&n9tSfnO0tL8{kyg6^KS~zh0z}RW>EH`U#7POlkpkKZe>M34ygWv +z2R)PLX;`3Qf9CTTdFECm9Fyje4IP4Kb*H90nJ!X)z7ILcgbVA>ex6n)PsjI!Ck=JT +zoYh?!owbVF$9){^gW_l7if*dJsYCuE<$08NHJYO*18My|wm>Wl!v@zmWK!SQVAFa&;RTb{qqaFe7E0)RMeLek||## +z9+#VJJb&qiJ-YgZ`Jp`3|0wfADHd2AB&B#=uidrk26?xP+2dS}s}1^7{@O@9;E&X% +zqGBzJW8J`gx*S&R;2p7F_k1$Xm8wS*%yY%S#8l$dt4B|p^;ovhfP=QDsNvuxAz1V{ +zWPjSR=YS0d*!JLc`jbw)!U)9oz!HHJ6UDC<+b4{(MAiFj9**K+^d~GHIqnK}vB~pr +z`v+_u+CGf_gvF!y$tKUZ%RaQm!{|?(=GoV$lg-14O8dc;F#hQwU2{18!T6|u?;u;R +z41bgwuLJzOF4Jq5NxPWtuD|D9a(_UzBl5L^{y2sm2V6h}9w~3p{VLp_pgpGa9^YU| +zziSuK=RqJ(?vKjVAH3V5eqN)Wbw>aEzyxdc?|hNeKPy{STHyEja_fJ%U!#FO_4{ZJ +z>d)~19fV5xulS$YK9HHL+IjOB7ccamVvVaq!<9X=z<_pfnrnc6nl-K*_=^XV@ML6E +zDX#73++>YQ1THUdg}%xCNK)cA~llGGo@h1i^7{hjVV&leW4xj2f;^AzFo +z!V@3OxK+!g#HHnNqq<*TIcPDPi?&zh59)X^=|7ctEs^W!q9xY2vL}}7vz@oGxqd)D +z4)EW>=A!-R>OANT5U_M-0$xM+LjG+cZEi^*j_zSLZ2PhIza +zX|F2|KEUQG~pEdRo;bBYg{(3Gy7cX>uh$9xB(aSdszNoy7L#XU7FdGvmSM_pi|YNIx+Y7N--+|lM9CZ7i0}klF&Eiz) +zFD-Jc+pyglN4~NgJGocb94F8(zxTh!<|xB2cH6P~_5aZ2(9Tbo0O85W0@8x*;OH5X +zhUxXIq5X{35`AwQmv+u1^?^0&Ll^7BIC=De`2O)wv()bVr`*YhsU +zP39qpve5DMznpS*;d1YJ*H7pJyI}cb|8Fk(X8l~qB$qXKA}MhQOa{7T8ri;Cw`LxE5CoFH?a!=6z;qHfatlTu{S_7 +zG)&&F!t*etH737)-uSKU$(7H3x-9zK1!sJSd5SbFzH5Q!(;5f%j{0ik_EmeuO*n9>?EFOM#Wjrw-;UvHoD+}qc$eiHK(*(##{jRMTC +zO=*qDrgQIke94VV4%IHbYMy`6bC|bS!}vQTcpj#-#+n=3W`-8Gt?$2a%qe>tp7;{; +z6ls`zs}0Y?l-3wL__4;(hlU>h-HLHfEZBM7i +zeEsIk;8uCaSXhcQOuog0=V3}~OuRdgd+=ums-HQ(YR>LEe{}@&6ls`zzXs34l-3x1 +z{o6Nxy7iJ#<5o>vl^Jkn7v?F_u=uSlJfGG$bYJJ(ceWlob>SatcJ14DAN11F?_@Ub +z=do-|X^k^K_MP#Ij$gksW6$I_KfU(-jhF}PVfKwt%&$#7(vF6jI(JRo@M^bv#AS8W +zv+5fBL){}r1cwa^g{p($L~6eFB+a&5hF^Z+R&SELCNFDK?yNl0pA+>-2!VJa$Wk)j +zFLP82=J||r$YlhQ)zXySk*!AgjE>1=R9E|h!9=z6dS*&U7-eQ0lgl6{^EE{ij2Y)> +zcgtmzd@>X!fA&;*VLvKzbwlfhk7(e?w|RZicX^xRk)+Sx<_|~w%@Ki1C0Ye8AkB(y +z2?x1oJSM$5Cw(QABTfy+X8Gi|cZFn6;r43cf%*5)lF^=@YDQ5Wb7(YZDSld2d}ECn*J611VWiOmeNU +zmRNjlY~j1}ps!w0OUZ + +-- +2.17.1 + diff --git a/tc/vendorsetup.sh b/tc/vendorsetup.sh index fac02e5..b9c6f1e 100644 --- a/tc/vendorsetup.sh +++ b/tc/vendorsetup.sh @@ -34,3 +34,15 @@ ANDROID_TOP_DIR=$(pwd) PATCHES_DIR=$ANDROID_TOP_DIR/device/arm/tc/patches apply_patch "external/drm_hwcomposer" "0001-Add-include-of-fcntl.h.patch" + +# Backported patches for simpleperf from the Upstream master branch +# 0001 and 0002 are part of android-s-beta-3 tag +# 0003 is part of android-s-beta-5 tag +# 0004 is part of android-s-v2-preview-1 tag +apply_patch "system/extras" "0001-simpleperf-Enable-ETM-PID-tracing-when-the-kernel-is.patch" +apply_patch "system/extras" "0002-simpleperf-Support-decoding-unformatted-ETM-traces.patch" +apply_patch "system/extras" "0003-simpleperf-try-re-enabling-events-after-truncated-au.patch" +apply_patch "system/extras" "0004-simpleperf-Add-support-for-new-perf-ETE-files.patch" + +# Backported patch to enable ETE in OpenCSD +apply_patch "external/OpenCSD" "0001-Add-ETE-decoder-to-the-Android-build.patch" -- GitLab