1*288bf522SAndroid Build Coastguard Worker /*
2*288bf522SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*288bf522SAndroid Build Coastguard Worker *
4*288bf522SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*288bf522SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*288bf522SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*288bf522SAndroid Build Coastguard Worker *
8*288bf522SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*288bf522SAndroid Build Coastguard Worker *
10*288bf522SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*288bf522SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*288bf522SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*288bf522SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*288bf522SAndroid Build Coastguard Worker * limitations under the License.
15*288bf522SAndroid Build Coastguard Worker */
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include "ETMRecorder.h"
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
20*288bf522SAndroid Build Coastguard Worker #include <sys/sysinfo.h>
21*288bf522SAndroid Build Coastguard Worker
22*288bf522SAndroid Build Coastguard Worker #include <limits>
23*288bf522SAndroid Build Coastguard Worker #include <memory>
24*288bf522SAndroid Build Coastguard Worker #include <string>
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker #include <android-base/expected.h>
27*288bf522SAndroid Build Coastguard Worker #include <android-base/file.h>
28*288bf522SAndroid Build Coastguard Worker #include <android-base/logging.h>
29*288bf522SAndroid Build Coastguard Worker #include <android-base/parseint.h>
30*288bf522SAndroid Build Coastguard Worker #include <android-base/properties.h>
31*288bf522SAndroid Build Coastguard Worker #include <android-base/strings.h>
32*288bf522SAndroid Build Coastguard Worker
33*288bf522SAndroid Build Coastguard Worker #include "ETMConstants.h"
34*288bf522SAndroid Build Coastguard Worker #include "environment.h"
35*288bf522SAndroid Build Coastguard Worker #include "utils.h"
36*288bf522SAndroid Build Coastguard Worker
37*288bf522SAndroid Build Coastguard Worker namespace simpleperf {
38*288bf522SAndroid Build Coastguard Worker
39*288bf522SAndroid Build Coastguard Worker using android::base::expected;
40*288bf522SAndroid Build Coastguard Worker using android::base::unexpected;
41*288bf522SAndroid Build Coastguard Worker
42*288bf522SAndroid Build Coastguard Worker static const std::string ETM_DIR = "/sys/bus/event_source/devices/cs_etm/";
43*288bf522SAndroid Build Coastguard Worker
44*288bf522SAndroid Build Coastguard Worker // from coresight_get_trace_id(int cpu) in include/linux/coresight-pmu.h
GetTraceId(int cpu)45*288bf522SAndroid Build Coastguard Worker static int GetTraceId(int cpu) {
46*288bf522SAndroid Build Coastguard Worker return 0x10 + cpu * 2;
47*288bf522SAndroid Build Coastguard Worker }
48*288bf522SAndroid Build Coastguard Worker
49*288bf522SAndroid Build Coastguard Worker template <typename T>
ReadValueInEtmDir(const std::string & file,T * value,bool report_error=true,const std::string & prefix="")50*288bf522SAndroid Build Coastguard Worker static bool ReadValueInEtmDir(const std::string& file, T* value, bool report_error = true,
51*288bf522SAndroid Build Coastguard Worker const std::string& prefix = "") {
52*288bf522SAndroid Build Coastguard Worker std::string s;
53*288bf522SAndroid Build Coastguard Worker uint64_t v;
54*288bf522SAndroid Build Coastguard Worker if (!android::base::ReadFileToString(ETM_DIR + file, &s) ||
55*288bf522SAndroid Build Coastguard Worker !android::base::StartsWith(s, prefix) ||
56*288bf522SAndroid Build Coastguard Worker !android::base::ParseUint(&android::base::Trim(s)[prefix.size()], &v)) {
57*288bf522SAndroid Build Coastguard Worker if (report_error) {
58*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "failed to read " << ETM_DIR << file;
59*288bf522SAndroid Build Coastguard Worker }
60*288bf522SAndroid Build Coastguard Worker return false;
61*288bf522SAndroid Build Coastguard Worker }
62*288bf522SAndroid Build Coastguard Worker *value = static_cast<T>(v);
63*288bf522SAndroid Build Coastguard Worker return true;
64*288bf522SAndroid Build Coastguard Worker }
65*288bf522SAndroid Build Coastguard Worker
GetBits(uint32_t value,int start,int end)66*288bf522SAndroid Build Coastguard Worker static uint32_t GetBits(uint32_t value, int start, int end) {
67*288bf522SAndroid Build Coastguard Worker return (value >> start) & ((1U << (end - start + 1)) - 1);
68*288bf522SAndroid Build Coastguard Worker }
69*288bf522SAndroid Build Coastguard Worker
GetMajorVersion() const70*288bf522SAndroid Build Coastguard Worker int ETMPerCpu::GetMajorVersion() const {
71*288bf522SAndroid Build Coastguard Worker return GetBits(trcidr1, 8, 11);
72*288bf522SAndroid Build Coastguard Worker }
73*288bf522SAndroid Build Coastguard Worker
IsContextIDSupported() const74*288bf522SAndroid Build Coastguard Worker bool ETMPerCpu::IsContextIDSupported() const {
75*288bf522SAndroid Build Coastguard Worker return GetBits(trcidr2, 5, 9) >= 4;
76*288bf522SAndroid Build Coastguard Worker }
77*288bf522SAndroid Build Coastguard Worker
IsTimestampSupported() const78*288bf522SAndroid Build Coastguard Worker bool ETMPerCpu::IsTimestampSupported() const {
79*288bf522SAndroid Build Coastguard Worker return GetBits(trcidr0, 24, 28) > 0;
80*288bf522SAndroid Build Coastguard Worker }
81*288bf522SAndroid Build Coastguard Worker
IsCycAccSupported() const82*288bf522SAndroid Build Coastguard Worker bool ETMPerCpu::IsCycAccSupported() const {
83*288bf522SAndroid Build Coastguard Worker return GetBits(trcidr0, 7, 7);
84*288bf522SAndroid Build Coastguard Worker }
85*288bf522SAndroid Build Coastguard Worker
IsEnabled() const86*288bf522SAndroid Build Coastguard Worker bool ETMPerCpu::IsEnabled() const {
87*288bf522SAndroid Build Coastguard Worker return GetBits(trcauthstatus, 0, 3) == 0xc;
88*288bf522SAndroid Build Coastguard Worker }
89*288bf522SAndroid Build Coastguard Worker
GetInstance()90*288bf522SAndroid Build Coastguard Worker ETMRecorder& ETMRecorder::GetInstance() {
91*288bf522SAndroid Build Coastguard Worker static ETMRecorder etm;
92*288bf522SAndroid Build Coastguard Worker return etm;
93*288bf522SAndroid Build Coastguard Worker }
94*288bf522SAndroid Build Coastguard Worker
GetEtmEventType()95*288bf522SAndroid Build Coastguard Worker int ETMRecorder::GetEtmEventType() {
96*288bf522SAndroid Build Coastguard Worker if (event_type_ == 0) {
97*288bf522SAndroid Build Coastguard Worker if (!IsDir(ETM_DIR) || !ReadValueInEtmDir("type", &event_type_, false)) {
98*288bf522SAndroid Build Coastguard Worker event_type_ = -1;
99*288bf522SAndroid Build Coastguard Worker }
100*288bf522SAndroid Build Coastguard Worker }
101*288bf522SAndroid Build Coastguard Worker return event_type_;
102*288bf522SAndroid Build Coastguard Worker }
103*288bf522SAndroid Build Coastguard Worker
BuildEventType()104*288bf522SAndroid Build Coastguard Worker std::unique_ptr<EventType> ETMRecorder::BuildEventType() {
105*288bf522SAndroid Build Coastguard Worker int etm_event_type = GetEtmEventType();
106*288bf522SAndroid Build Coastguard Worker if (etm_event_type == -1) {
107*288bf522SAndroid Build Coastguard Worker return nullptr;
108*288bf522SAndroid Build Coastguard Worker }
109*288bf522SAndroid Build Coastguard Worker return std::make_unique<EventType>("cs-etm", etm_event_type, 0,
110*288bf522SAndroid Build Coastguard Worker "CoreSight ETM instruction tracing", "arm");
111*288bf522SAndroid Build Coastguard Worker }
112*288bf522SAndroid Build Coastguard Worker
IsETMDriverAvailable()113*288bf522SAndroid Build Coastguard Worker bool ETMRecorder::IsETMDriverAvailable() {
114*288bf522SAndroid Build Coastguard Worker return IsDir(ETM_DIR);
115*288bf522SAndroid Build Coastguard Worker }
116*288bf522SAndroid Build Coastguard Worker
CheckEtmSupport()117*288bf522SAndroid Build Coastguard Worker expected<bool, std::string> ETMRecorder::CheckEtmSupport() {
118*288bf522SAndroid Build Coastguard Worker if (GetEtmEventType() == -1) {
119*288bf522SAndroid Build Coastguard Worker return unexpected("etm event type isn't supported on device");
120*288bf522SAndroid Build Coastguard Worker }
121*288bf522SAndroid Build Coastguard Worker if (!ReadEtmInfo()) {
122*288bf522SAndroid Build Coastguard Worker return unexpected("etm devices are not available");
123*288bf522SAndroid Build Coastguard Worker }
124*288bf522SAndroid Build Coastguard Worker for (const auto& p : etm_info_) {
125*288bf522SAndroid Build Coastguard Worker if (p.second.GetMajorVersion() < 4) {
126*288bf522SAndroid Build Coastguard Worker return unexpected("etm device version is less than 4.0");
127*288bf522SAndroid Build Coastguard Worker }
128*288bf522SAndroid Build Coastguard Worker if (!p.second.IsContextIDSupported()) {
129*288bf522SAndroid Build Coastguard Worker return unexpected("etm device doesn't support contextID");
130*288bf522SAndroid Build Coastguard Worker }
131*288bf522SAndroid Build Coastguard Worker if (!p.second.IsEnabled()) {
132*288bf522SAndroid Build Coastguard Worker return unexpected("etm device isn't enabled by the bootloader");
133*288bf522SAndroid Build Coastguard Worker }
134*288bf522SAndroid Build Coastguard Worker }
135*288bf522SAndroid Build Coastguard Worker if (!FindSinkConfig()) {
136*288bf522SAndroid Build Coastguard Worker // Trigger a manual probe of etr. Then wait and recheck.
137*288bf522SAndroid Build Coastguard Worker std::string prop_name = "profcollectd.etr.probe";
138*288bf522SAndroid Build Coastguard Worker bool res = android::base::SetProperty(prop_name, "1");
139*288bf522SAndroid Build Coastguard Worker if (!res) {
140*288bf522SAndroid Build Coastguard Worker LOG(ERROR) << "fails to setprop" << prop_name;
141*288bf522SAndroid Build Coastguard Worker }
142*288bf522SAndroid Build Coastguard Worker usleep(200000); // Wait for 200ms.
143*288bf522SAndroid Build Coastguard Worker if (!FindSinkConfig()) {
144*288bf522SAndroid Build Coastguard Worker return unexpected("can't find etr device, which moves etm data to memory");
145*288bf522SAndroid Build Coastguard Worker }
146*288bf522SAndroid Build Coastguard Worker }
147*288bf522SAndroid Build Coastguard Worker etm_supported_ = true;
148*288bf522SAndroid Build Coastguard Worker return true;
149*288bf522SAndroid Build Coastguard Worker }
150*288bf522SAndroid Build Coastguard Worker
ReadEtmInfo()151*288bf522SAndroid Build Coastguard Worker bool ETMRecorder::ReadEtmInfo() {
152*288bf522SAndroid Build Coastguard Worker int contextid_value;
153*288bf522SAndroid Build Coastguard Worker use_contextid2_ = ReadValueInEtmDir("/format/contextid", &contextid_value, false, "config:") &&
154*288bf522SAndroid Build Coastguard Worker contextid_value == ETM_OPT_CTXTID2;
155*288bf522SAndroid Build Coastguard Worker
156*288bf522SAndroid Build Coastguard Worker std::vector<int> online_cpus = GetOnlineCpus();
157*288bf522SAndroid Build Coastguard Worker for (const auto& name : GetEntriesInDir(ETM_DIR)) {
158*288bf522SAndroid Build Coastguard Worker int cpu;
159*288bf522SAndroid Build Coastguard Worker if (sscanf(name.c_str(), "cpu%d", &cpu) == 1) {
160*288bf522SAndroid Build Coastguard Worker // We can't read ETM registers for offline cpus. So skip them.
161*288bf522SAndroid Build Coastguard Worker if (std::find(online_cpus.begin(), online_cpus.end(), cpu) == online_cpus.end()) {
162*288bf522SAndroid Build Coastguard Worker continue;
163*288bf522SAndroid Build Coastguard Worker }
164*288bf522SAndroid Build Coastguard Worker ETMPerCpu& cpu_info = etm_info_[cpu];
165*288bf522SAndroid Build Coastguard Worker bool success = ReadValueInEtmDir(name + "/trcidr/trcidr0", &cpu_info.trcidr0) &&
166*288bf522SAndroid Build Coastguard Worker ReadValueInEtmDir(name + "/trcidr/trcidr1", &cpu_info.trcidr1) &&
167*288bf522SAndroid Build Coastguard Worker ReadValueInEtmDir(name + "/trcidr/trcidr2", &cpu_info.trcidr2) &&
168*288bf522SAndroid Build Coastguard Worker ReadValueInEtmDir(name + "/trcidr/trcidr4", &cpu_info.trcidr4) &&
169*288bf522SAndroid Build Coastguard Worker ReadValueInEtmDir(name + "/trcidr/trcidr8", &cpu_info.trcidr8) &&
170*288bf522SAndroid Build Coastguard Worker ReadValueInEtmDir(name + "/mgmt/trcauthstatus", &cpu_info.trcauthstatus);
171*288bf522SAndroid Build Coastguard Worker
172*288bf522SAndroid Build Coastguard Worker if (!ReadValueInEtmDir(name + "/mgmt/trcdevarch", &cpu_info.trcdevarch, false)) {
173*288bf522SAndroid Build Coastguard Worker cpu_info.trcdevarch = 0;
174*288bf522SAndroid Build Coastguard Worker }
175*288bf522SAndroid Build Coastguard Worker if (!success) {
176*288bf522SAndroid Build Coastguard Worker return false;
177*288bf522SAndroid Build Coastguard Worker }
178*288bf522SAndroid Build Coastguard Worker }
179*288bf522SAndroid Build Coastguard Worker }
180*288bf522SAndroid Build Coastguard Worker return (etm_info_.size() == online_cpus.size());
181*288bf522SAndroid Build Coastguard Worker }
182*288bf522SAndroid Build Coastguard Worker
FindSinkConfig()183*288bf522SAndroid Build Coastguard Worker bool ETMRecorder::FindSinkConfig() {
184*288bf522SAndroid Build Coastguard Worker bool has_etr = false;
185*288bf522SAndroid Build Coastguard Worker bool has_trbe = false;
186*288bf522SAndroid Build Coastguard Worker for (const auto& name : GetEntriesInDir(ETM_DIR + "sinks")) {
187*288bf522SAndroid Build Coastguard Worker if (!has_etr && name.find("etr") != -1) {
188*288bf522SAndroid Build Coastguard Worker if (ReadValueInEtmDir("sinks/" + name, &sink_config_)) {
189*288bf522SAndroid Build Coastguard Worker has_etr = true;
190*288bf522SAndroid Build Coastguard Worker }
191*288bf522SAndroid Build Coastguard Worker }
192*288bf522SAndroid Build Coastguard Worker if (name.find("trbe") != -1) {
193*288bf522SAndroid Build Coastguard Worker has_trbe = true;
194*288bf522SAndroid Build Coastguard Worker break;
195*288bf522SAndroid Build Coastguard Worker }
196*288bf522SAndroid Build Coastguard Worker }
197*288bf522SAndroid Build Coastguard Worker if (has_trbe) {
198*288bf522SAndroid Build Coastguard Worker // When TRBE is present, let the driver choose the most suitable
199*288bf522SAndroid Build Coastguard Worker // configuration.
200*288bf522SAndroid Build Coastguard Worker sink_config_ = 0;
201*288bf522SAndroid Build Coastguard Worker }
202*288bf522SAndroid Build Coastguard Worker return has_trbe || has_etr;
203*288bf522SAndroid Build Coastguard Worker }
204*288bf522SAndroid Build Coastguard Worker
SetEtmPerfEventAttr(perf_event_attr * attr)205*288bf522SAndroid Build Coastguard Worker void ETMRecorder::SetEtmPerfEventAttr(perf_event_attr* attr) {
206*288bf522SAndroid Build Coastguard Worker CHECK(etm_supported_);
207*288bf522SAndroid Build Coastguard Worker BuildEtmConfig();
208*288bf522SAndroid Build Coastguard Worker attr->config = etm_event_config_;
209*288bf522SAndroid Build Coastguard Worker attr->config2 = sink_config_;
210*288bf522SAndroid Build Coastguard Worker attr->config3 = cc_threshold_config_;
211*288bf522SAndroid Build Coastguard Worker }
212*288bf522SAndroid Build Coastguard Worker
BuildEtmConfig()213*288bf522SAndroid Build Coastguard Worker void ETMRecorder::BuildEtmConfig() {
214*288bf522SAndroid Build Coastguard Worker if (etm_event_config_ == 0) {
215*288bf522SAndroid Build Coastguard Worker if (use_contextid2_) {
216*288bf522SAndroid Build Coastguard Worker etm_event_config_ |= 1ULL << ETM_OPT_CTXTID2;
217*288bf522SAndroid Build Coastguard Worker etm_config_reg_ |= 1U << ETM4_CFG_BIT_VMID;
218*288bf522SAndroid Build Coastguard Worker etm_config_reg_ |= 1U << ETM4_CFG_BIT_VMID_OPT;
219*288bf522SAndroid Build Coastguard Worker } else {
220*288bf522SAndroid Build Coastguard Worker etm_event_config_ |= 1ULL << ETM_OPT_CTXTID;
221*288bf522SAndroid Build Coastguard Worker etm_config_reg_ |= 1U << ETM4_CFG_BIT_CTXTID;
222*288bf522SAndroid Build Coastguard Worker }
223*288bf522SAndroid Build Coastguard Worker
224*288bf522SAndroid Build Coastguard Worker if (record_timestamp_) {
225*288bf522SAndroid Build Coastguard Worker bool ts_supported = true;
226*288bf522SAndroid Build Coastguard Worker for (auto& p : etm_info_) {
227*288bf522SAndroid Build Coastguard Worker ts_supported &= p.second.IsTimestampSupported();
228*288bf522SAndroid Build Coastguard Worker }
229*288bf522SAndroid Build Coastguard Worker if (ts_supported) {
230*288bf522SAndroid Build Coastguard Worker etm_event_config_ |= 1ULL << ETM_OPT_TS;
231*288bf522SAndroid Build Coastguard Worker etm_config_reg_ |= 1U << ETM4_CFG_BIT_TS;
232*288bf522SAndroid Build Coastguard Worker }
233*288bf522SAndroid Build Coastguard Worker }
234*288bf522SAndroid Build Coastguard Worker
235*288bf522SAndroid Build Coastguard Worker if (record_cycles_) {
236*288bf522SAndroid Build Coastguard Worker bool cycles_supported = true;
237*288bf522SAndroid Build Coastguard Worker for (auto& p : etm_info_) {
238*288bf522SAndroid Build Coastguard Worker cycles_supported &= p.second.IsCycAccSupported();
239*288bf522SAndroid Build Coastguard Worker }
240*288bf522SAndroid Build Coastguard Worker if (cycles_supported) {
241*288bf522SAndroid Build Coastguard Worker etm_event_config_ |= 1ULL << ETM_OPT_CYCACC;
242*288bf522SAndroid Build Coastguard Worker etm_config_reg_ |= 1U << ETM4_CFG_BIT_CCI;
243*288bf522SAndroid Build Coastguard Worker
244*288bf522SAndroid Build Coastguard Worker if (cycle_threshold_) {
245*288bf522SAndroid Build Coastguard Worker cc_threshold_config_ |= cycle_threshold_;
246*288bf522SAndroid Build Coastguard Worker }
247*288bf522SAndroid Build Coastguard Worker }
248*288bf522SAndroid Build Coastguard Worker }
249*288bf522SAndroid Build Coastguard Worker }
250*288bf522SAndroid Build Coastguard Worker }
251*288bf522SAndroid Build Coastguard Worker
CreateAuxTraceInfoRecord()252*288bf522SAndroid Build Coastguard Worker AuxTraceInfoRecord ETMRecorder::CreateAuxTraceInfoRecord() {
253*288bf522SAndroid Build Coastguard Worker AuxTraceInfoRecord::DataType data;
254*288bf522SAndroid Build Coastguard Worker memset(&data, 0, sizeof(data));
255*288bf522SAndroid Build Coastguard Worker data.aux_type = AuxTraceInfoRecord::AUX_TYPE_ETM;
256*288bf522SAndroid Build Coastguard Worker data.version = 1;
257*288bf522SAndroid Build Coastguard Worker data.nr_cpu = etm_info_.size();
258*288bf522SAndroid Build Coastguard Worker data.pmu_type = GetEtmEventType();
259*288bf522SAndroid Build Coastguard Worker std::vector<AuxTraceInfoRecord::ETEInfo> ete(etm_info_.size());
260*288bf522SAndroid Build Coastguard Worker size_t pos = 0;
261*288bf522SAndroid Build Coastguard Worker for (auto& p : etm_info_) {
262*288bf522SAndroid Build Coastguard Worker auto& e = ete[pos++];
263*288bf522SAndroid Build Coastguard Worker if (p.second.trcdevarch == 0) {
264*288bf522SAndroid Build Coastguard Worker e.magic = AuxTraceInfoRecord::MAGIC_ETM4;
265*288bf522SAndroid Build Coastguard Worker e.nrtrcparams = sizeof(AuxTraceInfoRecord::ETM4Info) / sizeof(uint64_t) - 3;
266*288bf522SAndroid Build Coastguard Worker } else {
267*288bf522SAndroid Build Coastguard Worker e.magic = AuxTraceInfoRecord::MAGIC_ETE;
268*288bf522SAndroid Build Coastguard Worker e.nrtrcparams = sizeof(AuxTraceInfoRecord::ETEInfo) / sizeof(uint64_t) - 3;
269*288bf522SAndroid Build Coastguard Worker }
270*288bf522SAndroid Build Coastguard Worker e.cpu = p.first;
271*288bf522SAndroid Build Coastguard Worker e.trcconfigr = etm_config_reg_;
272*288bf522SAndroid Build Coastguard Worker e.trctraceidr = GetTraceId(p.first);
273*288bf522SAndroid Build Coastguard Worker e.trcidr0 = p.second.trcidr0;
274*288bf522SAndroid Build Coastguard Worker e.trcidr1 = p.second.trcidr1;
275*288bf522SAndroid Build Coastguard Worker e.trcidr2 = p.second.trcidr2;
276*288bf522SAndroid Build Coastguard Worker e.trcidr8 = p.second.trcidr8;
277*288bf522SAndroid Build Coastguard Worker e.trcauthstatus = p.second.trcauthstatus;
278*288bf522SAndroid Build Coastguard Worker e.trcdevarch = p.second.trcdevarch;
279*288bf522SAndroid Build Coastguard Worker }
280*288bf522SAndroid Build Coastguard Worker return AuxTraceInfoRecord(data, ete);
281*288bf522SAndroid Build Coastguard Worker }
282*288bf522SAndroid Build Coastguard Worker
GetAddrFilterPairs()283*288bf522SAndroid Build Coastguard Worker size_t ETMRecorder::GetAddrFilterPairs() {
284*288bf522SAndroid Build Coastguard Worker CHECK(etm_supported_);
285*288bf522SAndroid Build Coastguard Worker size_t min_pairs = std::numeric_limits<size_t>::max();
286*288bf522SAndroid Build Coastguard Worker for (auto& p : etm_info_) {
287*288bf522SAndroid Build Coastguard Worker min_pairs = std::min<size_t>(min_pairs, GetBits(p.second.trcidr4, 0, 3));
288*288bf522SAndroid Build Coastguard Worker }
289*288bf522SAndroid Build Coastguard Worker if (min_pairs > 0) {
290*288bf522SAndroid Build Coastguard Worker --min_pairs; // One pair is used by the kernel to set default addr filter.
291*288bf522SAndroid Build Coastguard Worker }
292*288bf522SAndroid Build Coastguard Worker return min_pairs;
293*288bf522SAndroid Build Coastguard Worker }
294*288bf522SAndroid Build Coastguard Worker
SetRecordTimestamp(bool record)295*288bf522SAndroid Build Coastguard Worker void ETMRecorder::SetRecordTimestamp(bool record) {
296*288bf522SAndroid Build Coastguard Worker record_timestamp_ = record;
297*288bf522SAndroid Build Coastguard Worker }
298*288bf522SAndroid Build Coastguard Worker
SetRecordCycles(bool record)299*288bf522SAndroid Build Coastguard Worker void ETMRecorder::SetRecordCycles(bool record) {
300*288bf522SAndroid Build Coastguard Worker record_cycles_ = record;
301*288bf522SAndroid Build Coastguard Worker }
302*288bf522SAndroid Build Coastguard Worker
SetCycleThreshold(size_t threshold)303*288bf522SAndroid Build Coastguard Worker void ETMRecorder::SetCycleThreshold(size_t threshold) {
304*288bf522SAndroid Build Coastguard Worker cycle_threshold_ = threshold;
305*288bf522SAndroid Build Coastguard Worker }
306*288bf522SAndroid Build Coastguard Worker
307*288bf522SAndroid Build Coastguard Worker } // namespace simpleperf
308